#52 - C++ Terrain Class

Date: 2019-03-16 12:00 - C++

C++ class to create a terrain mesh. This generates meshes without a third dimension. The third dimension should be added in a shader with a heightmap texture.

// Terrain.h
#pragma once

#include <memory>

#define TERRAIN_POSITIONS 0
#define TERRAIN_TEXTURE_COORDS 1

class Terrain {
    static std::shared_ptr<Mesh> createPatch(float size, float resolution);
private:
    int _sizeX;
    int _sizeY;
    float _patchSize;
    float _patchResolution;
    std::shared_ptr<Meshes::Mesh> _terrainPatch;
public:
    Terrain(int sizeX, int sizeY, float patchSize, float patchResolution);
    void render();
};

// Terrain.cpp
#include "Terrain.h"


#include "Mesh.h"
#include "MeshBuilder.h"

std::shared_ptr<Mesh> Terrain::createPatch(float size, float resolution) {
	const int numVerticesPerAxis = (int)(size * resolution) + 1;
	const float ds = 1.0f / numVerticesPerAxis;
	const float dx = 1.0f / resolution;

	const int numVertices = numVerticesPerAxis * numVerticesPerAxis;
	float* vertices = new float[numVertices * 2];
	float* texCoords = new float[numVertices * 2];

	const int numEdgesAxis = numVerticesPerAxis - 1;
	const int numIndices = numEdgesAxis * numEdgesAxis * 3 * 2;
	unsigned int* indices = new unsigned int[numIndices];

	for (int i = 0, x = 0; x < numVerticesPerAxis; x++) {
		for (int z = 0; z < numVerticesPerAxis; z++) {
			vertices[i] = x * dx;
			vertices[i + 1] = z * dx;
			texCoords[i] = x * ds;
			texCoords[i + 1] = z * ds;
			i += 2;
		}
	}

	for (int i = 0, index = 0, x = 0; x < numEdgesAxis; x++) {
		for (int z = 0; z < numEdgesAxis; z++) {
			indices[i] = index;
			indices[i + 1] = index + 1;
			indices[i + 2] = index + numVerticesPerAxis + 1;
			indices[i + 3] = index + numVerticesPerAxis + 1;
			indices[i + 4] = index + numVerticesPerAxis;
			indices[i + 5] = index;
			i += 6;
			index++;
		}
		index++;
	}

	MeshBuilder builder;
	builder.generateVBO(GL_ARRAY_BUFFER, numVertices * 2 * sizeof(float), vertices, GL_STATIC_DRAW);
	builder.attribPointer(TERRAIN_POSITIONS, 2, GL_FLOAT, 0, 0);

	builder.generateVBO(GL_ARRAY_BUFFER, numVertices * 2 * sizeof(float), texCoords, GL_STATIC_DRAW);
	builder.attribPointer(TERRAIN_TEXTURE_COORDS, 2, GL_FLOAT, 0, 0);

	builder.generateVBO(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned int), indices, GL_STATIC_DRAW);

	delete[] vertices;
	delete[] texCoords;
	delete[] indices;

	return builder.build(numIndices);
}

Terrain::Terrain(int sizeX, int sizeY, float patchSize, float patchResolution) : _sizeX(sizeX), _sizeY(sizeY), _patchSize(patchSize), _patchResolution(patchResolution) {
	_terrainPatch = Terrain::createPatch(patchSize, patchResolution);
}

void Terrain::render() {
	_terrainPatch->render();
}

Previous snippet | Next snippet