Jump to content
  • Advertisement
Sign in to follow this  

Heightmap + Collision detection.

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello all, I've been writing a terrain engine. All is well so far and the thing works beautifully. The only problem is collision detection with hills that are too steep. I got to think, now I could either calculate the degrees the hill is or look at the pixels in the heightmap and check the difference. If the difference would for example be 10 pixels in height, then the hill would most likely be too steep. So, after having figured that out I stumbled upon a problem. How do I figure out what tile I need to check in order to allow/disallow my entity to move. I have a 360 degrees movement system, and I have absolutely no experience on how to do collision detection with that in a tile based map. Does anyone know how to handle this ? Here's my current move entity function.
/// MoveEntity. Moves an entity from it's current position to an other position.
int EntityManager::MoveEntity(BaseEntity *entity, float speed)
	Vector cp, cr, tp, np, op, ha, hb, hc, hd, deg;
	HeightObject *object = NULL;
	frametime_t *timer = engine->GetTimer();
	curframe = timer->curtime * 0.001f;
	lastframe = timer->lasttime * 0.001f;

	if (!entity)
		return 1;

	// Retrieve entities current position and rotation.
	cp = entity->GetPosition();
	cr = entity->GetRotation();

	// Negative speed or positive speed.
	if ((cr.GetZ() > 90) && (cr.GetZ() < 270))
		speed = -speed;

	// Retrieve vertice position in the map.
	if (entities.at(0) != NULL)
		object = ((HeightObject*)(entities[0]->GetModel()));
	// Get the object's plane position.
	ha = object->GetVertice(Vector(fabs(cp.GetZ() / 20.0f), fabs(cp.GetX() / 20.0f), 0, 0));
	hb = object->GetVertice(Vector(fabs(cp.GetZ() / 20.0f) + 1, fabs(cp.GetX() / 20.0f), 0, 0));
	hc = object->GetVertice(Vector(fabs(cp.GetZ() / 20.0f) + 1, fabs(cp.GetX() / 20.0f) + 1, 0, 0));

	hd = object->GetVertice(Vector(fabs(cp.GetZ() / 20.0f), fabs(cp.GetX() / 20.0f) + 1, 0, 0));
	// Calculate new position, check if a hill is steeper than 65 degrees.
	tp = cp;

	tp.SetX( tp.GetX() + ( (sin(cr.GetZ() * ANG2RAD) * RAD2ANG) * (speed * (curframe - lastframe))));
	tp.SetZ( tp.GetZ() + ( (cos(cr.GetZ() * ANG2RAD) * RAD2ANG) * (speed * (curframe - lastframe))));

	cp.SetX( cp.GetX() + ( (sin(cr.GetZ() * ANG2RAD) * RAD2ANG) * (speed * (curframe - lastframe))));
	cp.SetZ( cp.GetZ() + ( (cos(cr.GetZ() * ANG2RAD) * RAD2ANG) * (speed * (curframe - lastframe))));

	// Perform a bilinear interpolation.
	float tx = cp.GetX() / 20.0f - float(cp.GetX() / 20.0f);
	float ty = cp.GetZ() / 20.0f - float(cp.GetZ() / 20.0f);

	float xy = tx * ty;
	float h = ha.GetY() * (1.0f - ty - tx + xy)
				+ hb.GetY() * (tx - xy)
				+ hc.GetY() * xy
				+ hd.GetY() * (ty - xy);


	// Adjust the Y value so the object is always on top of the terrain.
	cp.SetY(np.GetY() + entity->GetModel()->GetBoundingBox().GetMax().GetY());

	// Set the new position.

	return 0;

Thanks a lot.

Share this post

Link to post
Share on other sites
this is my advice:

1)You must get yours coordinates
2)if you use an heightmap for terrain, you must have a 'gap value' that identify the distance between 2 consecutives vertices. If you divide your position by this gap values, you get the vertice where you are.
3)with a very easy offset you can get from your heightmapbuffer the 4 vertices's heigh of the square where you are..
4)with these datas and your position in this square, you can calculate the exact heigh where you must be.

ok... my english is poor... so I post an example....

you have a heightmap of 256x256 --> byte* heightmapbuffer[256*256]
distances between vertices 10 --> int gap =10
so the world is 2560x2560 unit...

you are in position 1302,803
1302/10 = 130,2
803/10 = 80,3

this mean that on X axis you are between 130th and 131th vertice,
on Z axis you are between 80th and 81th vertices.

now you get the square's vertices where you are:

now you have this

_____ _____ _____
| | |\ | | /|
| | | \ | | / |
|_____| and it is divide or in this way |____\| or in this |/____|

with some operation you can know in which triangle you are, e then calculate your real high....

probably is more easy do it, that read it....


Share this post

Link to post
Share on other sites
Hmmm, that's an idea yes. But my main point was, I still don't know what square to check for the height, and how to make it so I can stop my player/entity from walking into that part of the terrain.

Share this post

Link to post
Share on other sites
Assuming you use the y coordinate for the height, then use the x and z coordinates of the player's position to find the tile that it sits on. You do this by dividing the x and z coordinate by the size of the tile. So, if each tile represents 10 units in world space, and the player's position is at (15, 11), then the entity is sitting on (1, 1) in tile space.

Share this post

Link to post
Share on other sites
you can calculate the square where you are, the square to check for the height.

Like strtok has rewrite, dividing your position by vertices's distance, you get the vertices of the square where you are.

easy and speed....

Share this post

Link to post
Share on other sites
The problem is not with finding the tile I am standing on. The problem is finding out what tiles to test for how steep a hill is. and also how to make it so that if it is too steep, X or Z won't be added.

Share this post

Link to post
Share on other sites

The problem is finding out what tiles to test for how steep a hill is. and also how to make it so that if it is too steep, X or Z won't be added.

it is not a problema, because with trigonometry and the 3 triangle vertices coordinates, you can calculate the tile slope...
if the slope is too much, you don't add X or Z.... you don't need of another tile... and otherwise you know your direction, so you can know which will be the next tile.

Share this post

Link to post
Share on other sites
Well in that case, if I need to calculate it on the tile that I am standing on. How would I go about calculating how steep it is ? And I still need to know wether I should add X or Z or if I should not add them. I hope you understand me. Thx a lot already :)

Share this post

Link to post
Share on other sites
ok... you follow above istructions, and you'll know in which tile you stay.

for example you are in this square.

A_____B _ _
|\ | |
| \ | | Z
| \ | | <---- this is a square! not a rectangle!! :)
| \ | |
|____\| _|_

| |

A B C and D are 3 vector(x,y,z), of course..

You are in ABD or in ACD??

1)check position inside tile
float coefX = B.x - position.x;
float coefZ = B.z - position.z;

if (coefX >= coefZ) <---- you are in ABD
D3DXPlaneFromPoints(Plane, A,B,D);
else <---- you are in ACD
D3DXPlaneFromPoints(Plane, A,&v3,&v4);

now you have a plane!!
This is your point height
height = (-position.x * Plane.a - position.z * Plane.c - Plane.d) / Plane.b;

now, you calculate the slope.

ok... maybe there are some errors, but the juice there is...

in this forum there is people with mathematical skill better than mine.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!