# Terrain Following Bug

This topic is 3821 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ive got a strange bug with my terrain following, it follows roughly but certain cells dont seem to be calculating right. This is being done in OpenGL. An entity checks its x and z position against a certain piece of terrain like so:
m_position.y = terrain->getHeight(m_position.x, m_position.z) + (m_pModel->getRadius() * 2);


Get radius is definetly right, heres the terrain checking code. Im un-necessarily calculating triangle normals here because i could figure out an algorithm to see which triangles are in a specific cell, i do have all surface normals pre calculated so if you guys know that it'd be great:
float CTerrain::getHeight(float x, float z)
{
int cellX = (x - m_pos.x) / MAP_SCALE; // Find cellX which entity point lies within
int cellZ = -(z - m_pos.z) / MAP_SCALE; // Find cellZ which entity point lies within, negative because the way terrain verts are created

int currentCell = (( cellZ * MAP_X ) + cellX ); // Find exact cell point lies within

CVector bottomLeftVert = m_vTerrain[ currentCell ] + m_pos; // Vertices around current cell
CVector bottomRightVert = m_vTerrain[ currentCell + 1 ] + m_pos;
CVector topLeftVert = m_vTerrain[ (currentCell + MAP_X) ] + m_pos;
CVector topRightVert = m_vTerrain[ (currentCell + MAP_X) + 1 ] + m_pos;

float dx = x - bottomLeftVert.x; // x distance is cell
float dz = -(z - bottomLeftVert.z); // z distance in cell

if( dx > dz )
{
CVector normal = (topLeftVert - bottomLeftVert).CrossProduct( bottomRightVert - bottomLeftVert ); // Get normal of triangle

// height = bottomLeftVert + ((dx * triNorm.x) + (dz * triNorm.z)) / -triNorm.y
float height = bottomLeftVert.y + ( normal.x * dx + normal.z * dz ) / -normal.y;
}

else // dz > dx
{
CVector normal = (topLeftVert - topRightVert).CrossProduct( bottomRightVert - topRightVert );
float height = topRightVert.y + ( normal.z * dz + normal.x * dx ) / -normal.y;

return height;
}


} m_pos = Vector of position in space, refers to first point. MAP_SCALE = Distance between vertices MAP_X = num verts in grid I used toymaker as reference for this, heres the exact guide i used: http://www.toymaker.info/Games/html/terrain_follow.html The specific bit is halfway down. Heres the vid:
Any ideas how to sort this? [Edited by - Infinite_Daremo on July 28, 2008 2:41:56 PM]

##### Share on other sites
Your problem seems to be that you're calculating one normal in the opposite direction from the other. Try changing "/ -normal.y" to just "/ normal.y" in the dz > dx case, and see what happens.

Use the right-hand rule. For "A cross B equals C", point your index down A and your middle finger down B. Put your thumb at a right angle to your index finger, and your thumb is pointing in the direction of C.

If you do this for your math, you'll see that your thumb should point up in one case and down in the other case.

##### Share on other sites
Thanks for the reply, i re did some of the code and found how to get which triangles are in a specific cell. Its just currentCell * 2 for the bottom triangle and currentCell * 2 + 1 for the top, but its even weirder now so im guessing either the normals are wrong or its the way im doing it. Now i precalculate all my surface normals at creation like this:

void CTerrain::calculateSurfaceNormals(){	int currentVertex = 0;	// Tri Normal calculations	for( int z = 0; z < MAP_Z-1; z++ )	{		for( int x = 0; x < MAP_X-1; x++ )		{			currentVertex = z * MAP_X + x;			m_vTriNormals[currentVertex * 2] = UTILITY.calculateNormal( &m_vTerrain[currentVertex], &m_vTerrain[currentVertex + 1], &m_vTerrain[currentVertex + MAP_Z]);			m_vTriNormals[(currentVertex * 2) +1] = UTILITY.calculateNormal( &m_vTerrain[currentVertex + MAP_Z + 1], &m_vTerrain[currentVertex + MAP_Z], &m_vTerrain[currentVertex + 1]);		}	}}

And that code is here:

CVector CUtility::calculateNormal(CVector *p1, CVector *p2, CVector *p3){	CVector a, b, result;	float length;	a.x = (p1->x - p2->x);	a.y = (p1->y - p2->y);	a.z = (p1->z - p2->z);	b.x= ( p1->x - p3->x );	b.y= ( p1->y - p3->y );	b.z= ( p1->z - p3->z );	result.x = ( a.y * b.z ) - ( b.y * a.z ); 	result.y = ( b.x * a.z ) - ( a.x * b.z );	result.z = ( a.x * b.y ) - ( b.x * a.y );	length = (float)sqrt(result.x * result.x + result.y * result.y + result.z * result.z);	result.x /= length; 	result.y /= length;	result.z /= length;	return result;}

Then all that has changed in the terrain following bit is this:

int currentCell = (( cellZ * MAP_X ) + cellX ); // Find exact cell point lies within	int xTriangle = (currentCell * 2);	int zTriangle = (currentCell * 2) + 1;	if( dx > dz )	{		// height = bottomLeftVert + ((dx * triNorm.x) + (dz * triNorm.z)) / -triNorm.y		float height = bottomLeftVert.y + ( (m_vTriNormals[ xTriangle ].x * dx) + (m_vTriNormals[ xTriangle ].z * dz) ) / -m_vTriNormals[ xTriangle ].y;		return height;	}	else // dz > dx	{     	float height = bottomLeftVert.y + ( (m_vTriNormals[ zTriangle ].x * dx) + (m_vTriNormals[ zTriangle ].z * dz) ) / m_vTriNormals[ zTriangle ].y;		return height;	}

I tried your suggestion about the normal being in the opposite direction, it just made the model go under the map. One thing to note though is that if i force dz to be always less than dx it looks believable-ish except when the two triangles dont correlate at all so im assuming the calculating for the z triangle is messed up.

[Edited by - Infinite_Daremo on July 29, 2008 9:24:23 AM]

##### Share on other sites
If your model is consistently under the map after that change, then it was the wrong case I changed; probably your up axis was the opposite direction to what I assumed. So, apply my suggestion to the dx>dz case instead of the dz>dx one.

##### Share on other sites
Thanks for the help so far, i did your suggestion but did it for both values and it works on some test terrain that mimics stairs, heres the result:

- Seems to work

But with irregular terrain the result is like in the other video. The heigh calculation code seems to be fine. No i dont know if im calculating the normals incorrectly or im using the wrong cell to figure out the height.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 14
• 46
• 22
• 27
• ### Forum Statistics

• Total Topics
634046
• Total Posts
3015224
×