Game Development Community

Get terrain texture?

by Christian · in Torque Game Engine · 11/02/2007 (11:03 pm) · 3 replies

Is there a way to get terrain texture that the player is standing on, such as getTerrainHeigh()?

#1
11/02/2007 (11:25 pm)
Someone asked this just two days ago on the RTS-SK private forums, funny.
Some time ago I found this C++ code, that is part of James Holmes's Terrain path following Resource

//--------------------------------------------
// Get the terrain texture under an x,y coord
//
// This fills an array with the alpha value of each of the
// textures under that point. The actual texture names can be
// obtained from the TextureHandle array in the terrain block.
//
// distance - How far to look down for the terrain block
// pt - Point in world space
// alphas - U8 array of size TerrainBlock::materialGroups
//
// JH
//
bool Player::getTerrainTextures(float distance, Point3F& pt, U8 *alphas) {
    RayInfo rInfo;
    if (gClientContainer.castRay(pt, 
            Point3F(pt.x, pt.y, pt.z - distance ),
            TerrainObjectType, &rInfo)) {
         
		TerrainBlock* ter = static_cast<TerrainBlock*>(rInfo.object);
		Point2I gPos;
		const MatrixF & mat = ter->getTransform();
		Point3F origin;
		mat.getColumn(3, &origin);
		F32 squareSize = (F32) ter->getSquareSize();
		F32 halfSquareSize = squareSize / 2;

		float x = (pt.x - origin.x + halfSquareSize) / squareSize;
		float y = (pt.y - origin.y + halfSquareSize) / squareSize;

		ter->getMaterialAlpha(Point2I(x,y), alphas);
		return true;
	}
	return false;
}

You could use it directly in C++ or make a console function to use it from script (if you do do, show us what you have done ;)
#2
11/03/2007 (2:03 am)
That is brilliant. I'm sure this question has been asked a million times, but that's the most coherent answer I've seen.
It's a bit tricky putting it into a console method, though - probably the C++ language barrier in my case :P. I think the easiest way would be to have it return a string with space-delineated alpha values, but I'm having trouble reading from the U8 into a string.

EDIT: *snip*

EDIT: All right, nearly there:
const char* ShapeBase::cGetTerrainTextures(float dist,Point3F pos)
{
	U8* terrainAlphas = new U8[TerrainBlock::MaterialGroups];
	if(getTerrainTextures(dist,pos,terrainAlphas))
	{
		int i;
		float alpha;
		char* calpha;
		char* buff = Con::getReturnBuffer(256);
		for(i = 0; i < TerrainBlock::MaterialGroups; i++)
		{
			alpha = terrainAlphas[i];
			dSprintf(calpha,sizeof(calpha),"%g",alpha);
			buff = buff + calpha;
		}
		return buff;
	}
	return "";
}

ConsoleMethod(ShapeBase,getTerrainTextures,const char*,3,3,"getTerrainTextures(distance, [position]) returns space-delineated alpha values")
{
	float dist = dAtof(argv[2]);
	Point3F pos;
	if(!argv[3])
	   pos = object->getPosition();
	else
		dSscanf(argv[3],"%g %g %g",pos.x,pos.y,pos.z);

	return object->cGetTerrainTextures(dist,pos);
}
On compile, I get an error saying you can't add two pointers on the line buff = buff + calpha. I understand that, but I don't know what to do about it.
For the record, I've never had any formal C++ training - this is all guess-and-compile :P...
#3
11/05/2007 (12:57 am)
You can also look at the footprint decal code in the Player class as it does what you want.