Terrain data from array

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
larztheloser
Posts: 13
Joined: Thu Oct 08, 2009 8:58 pm
Location: New Zealand

Terrain data from array

Post by larztheloser »

Hi all,

I'm working at extending the CTerrainSceneNode class to add a method with loads a heightmap from an array of values. Right now my function looks like this:

Code: Select all

	bool CTerrainSceneNode::loadHeightMapFromArray(irr::f32* heights[], int width, video::SColor vertexColor, s32 smoothFactor)
	{
        const u32 startTime = os::Timer::getTime();
		Mesh.MeshBuffers.clear();
		TerrainData.Size = width;
		switch (TerrainData.PatchSize)
		{
			case ETPS_9:
				if (TerrainData.MaxLOD > 3)
				{
					TerrainData.MaxLOD = 3;
				}
			break;
			case ETPS_17:
				if (TerrainData.MaxLOD > 4)
				{
					TerrainData.MaxLOD = 4;
				}
			break;
			case ETPS_33:
				if (TerrainData.MaxLOD > 5)
				{
					TerrainData.MaxLOD = 5;
				}
			break;
			case ETPS_65:
				if (TerrainData.MaxLOD > 6)
				{
					TerrainData.MaxLOD = 6;
				}
			break;
			case ETPS_129:
				if (TerrainData.MaxLOD > 7)
				{
					TerrainData.MaxLOD = 7;
				}
			break;
		}
		scene::CDynamicMeshBuffer *mb=0;
		const u32 numVertices = TerrainData.Size * TerrainData.Size;
		if (numVertices <= 65536)
		{
			mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT);
			RenderBuffer->getIndexBuffer().setType(video::EIT_16BIT);
		}
		else
		{
			mb=new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_32BIT);
			RenderBuffer->getIndexBuffer().setType(video::EIT_32BIT);
		}
		mb->getVertexBuffer().reallocate(numVertices);
		video::S3DVertex2TCoords vertex;
		vertex.Normal.set(0.0f, 1.0f, 0.0f);
		vertex.Color = vertexColor;
		const f32 tdSize = 1.0f/(f32)(TerrainData.Size-1);
		float fx=0.f;
		float fx2=0.f;
		for (s32 x = 0; x < TerrainData.Size; ++x)
		{
			float fz=0.f;
			float fz2=0.f;
			for (s32 z = 0; z < TerrainData.Size; ++z)
			{
			    vertex.Pos.Y = heights[x*width+z];
				vertex.Pos.Z = fz;
				vertex.TCoords.X = vertex.TCoords2.X = 1.f-fx2;
				vertex.TCoords.Y = vertex.TCoords2.Y = fz2;
				mb->getVertexBuffer().push_back(vertex);
				++fz;
				fz2 += tdSize;
			}
			++fx;
			fx2 += tdSize;
		}
		smoothTerrain(mb, smoothFactor);
		calculateNormals(mb);
		Mesh.addMeshBuffer(mb);
		const u32 vertexCount = mb->getVertexCount();
		RenderBuffer->getVertexBuffer().set_used(vertexCount);

		for (u32 i = 0; i < vertexCount; i++)
		{
			RenderBuffer->getVertexBuffer()[i] = mb->getVertexBuffer()[i];
			RenderBuffer->getVertexBuffer()[i].Pos *= TerrainData.Scale;
			RenderBuffer->getVertexBuffer()[i].Pos += TerrainData.Position;
		}

		mb->drop();

		// calculate all the necessary data for the patches and the terrain
		calculateDistanceThresholds();
		createPatches();
		calculatePatchData();

		// set the default rotation pivot point to the terrain nodes center
		TerrainData.RotationPivot = TerrainData.Center;

		// Rotate the vertices of the terrain by the rotation specified. Must be done
		// after calculating the terrain data, so we know what the current center of the
		// terrain is.
		setRotation(TerrainData.Rotation);

		// Pre-allocate memory for indices
		RenderBuffer->getIndexBuffer().set_used(
				TerrainData.PatchCount*TerrainData.PatchCount*
				TerrainData.CalcPatchSize*TerrainData.CalcPatchSize*6);

		const u32 endTime = os::Timer::getTime();

		c8 tmp[255];
		snprintf(tmp, 255, "Generated terrain data (%dx%d) in %.4f seconds",
			TerrainData.Size, TerrainData.Size, (endTime - startTime) / 1000.0f);
		os::Printer::log(tmp);

		return true;
	}
Unfortunately this line:

Code: Select all

vertex.Pos.Y = heights[x*width+z];
Is being problematic, because of course I can't convert `irr::f32*' to `irr::f32'! Can anybody think of a way around this?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Re: Terrain data from array

Post by vitek »

The type of the parameter heights is array of f32 pointer. I'm pretty sure you just want array of f32 or pointer to f32...

Code: Select all

// pointer to f32
bool CTerrainSceneNode::loadHeightMapFromArray(irr::f32* heights, int width, video::SColor vertexColor, s32 smoothFactor)

// array of f32
bool CTerrainSceneNode::loadHeightMapFromArray(irr::f32 heights[], int width, video::SColor vertexColor, s32 smoothFactor)
Travis
larztheloser
Posts: 13
Joined: Thu Oct 08, 2009 8:58 pm
Location: New Zealand

Post by larztheloser »

Thanks vitec! That was a very silly mistake of mine!
kingdutch
Posts: 76
Joined: Tue Sep 02, 2008 7:01 am

Post by kingdutch »

This has been exactly what I've been looking for :O Is it ok if I use this? :D
if (msg.getRubbishFactor() > rubbishLimit) { ignorePost(); cout << how it should be done << "\n"; }
Post Reply