• 9
• 10
• 10
• 11
• 17

# Smooth moving on terrain

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

## Recommended Posts

Right now I'm checking my collision detection between a point and a polygon/terrain. The way I test to see if the point needs to be moved is if it flys through the polygon and then I send it back to the point it was before the collision. This collision detection is pretty rough and I sometimes get my point to warp at the edges of each polygon and fly off in weird directions. Is there any way to get the point to follow the polygons smoother than flying through stopping and then changing the direction of the speed vector? Is there some kind of terrain avoidance or something that I could use?

##### Share on other sites
Here are a few options:

1. Just set the z component of the object's position to the height of the terrain at the object's (x,y) position (assuming z up). There are a couple of fairly easy ways to do this.

2. If it's an object that would tend to align itself with the terrain (such as a tank), do number 1 above, but also maintain its orientation incrementally and align it towards the normal of the plane below it.

3. The above aren't really collision detection methods per se, so if you're looking for something more realistic, you could try a discrete and/or swept sphere or ellipsoid test.

There are other possibilities, but those are just some quick suggestions. Of those three, number 1 would be by far the easiest to implement.

##### Share on other sites
Quote:
 Original post by jyk2. If it's an object that would tend to align itself with the terrain (such as a tank), do number 1 above, but also maintain its orientation incrementally and align it towards the normal of the plane below it.

I'm no expert and I'm not sure what assumptions you're making, but it seems to me that, assuming the direction of alignment for the tank is it's forward vector, then you would want to align the object perpendicular to the normal of plane below it. I may just be confused, so would you mind clearing up what you were trying to say? [smile]

-AJ

##### Share on other sites
Quote:
 Original post by u235I'm no expert and I'm not sure what assumptions you're making, but it seems to me that, assuming the direction of alignment for the tank is it's forward vector, then you would want to align the object perpendicular to the normal of plane below it.
Oops, I should have been more specific: it's the up vector (not the foward vector) that you align towards the normal.

##### Share on other sites
Well I'm confused now. Can someone please explain some ways to improve the code I already have so I don't get weird results. I'm writing in a different code language but below it's written in kind of pseudocode/C which should be easier to read. I also just use one square in the code but if you want to see the weird results add an array of squares. Here's the code I'm using:

#define kGravity 3.0char keyboardCommand;BOOL keyUp, collision;float xSpeed, ySpeed, zSpeed;float xPoint, yPoint, zPoint;float xOldPoint, yOldPoint, zOldPoint;float lastDistance, normalForce;float vectorDistance(float x1Vert, float y1Vert, float z1Vert, float x2Vert, float y2Vert, float z2Vert, 	float x3Vert, float y3Vert, float z3Vert, float xP, float yP, float zP);void keyboardDown(void);void keyPressed(char command){	keyUp = NO;		// Sometimes this doesn't fire when the key is held down for a long time.	// So I update it in the timer	keyboardCommand = command;}void keyboardUp(char command){	keyUp = YES;	xSpeed = 0.0;	ySpeed = 0.0;	zSpeed = 0.0;        switch(command)    {        case 'w':        case 's':	      zSpeed = 0.0;	break;    }}// this is where everything is updatedvoid timer(void){	float x1Vert =-1.0;	float y1Vert = 1.0;	float z1Vert = 0.0;	float x2Vert = 1.0;	float y2Vert = 3.0;	float z2Vert = 0.0;	float x3Vert = 1.0;	float y3Vert = 3.0;	float z3Vert =-1.0;	float x4Vert =-1.0;	float y4Vert = 1.0;	float z4Vert =-1.0;	float A = y1Vert * (z2Vert - z3Vert) + y2Vert * (z3Vert -  z1Vert) + y3Vert * (z1Vert - z2Vert);	float B = z1Vert * (x2Vert - x3Vert) + z2Vert * (x3Vert -  x1Vert) + z3Vert * (x1Vert - x2Vert);	float C = x1Vert * (y2Vert - y3Vert) + x2Vert * (y3Vert -  y1Vert) + x3Vert * (y1Vert - y2Vert);	float D = x1Vert * (y2Vert * z3Vert - y3Vert * z2Vert) 			+ x2Vert * (y3Vert * z1Vert - y1Vert * z3Vert)			+ x3Vert * (y1Vert * z2Vert - y2Vert * z1Vert);			float vectorMagnitude = sqrt(A * A + B * B + C * C);	float s;	// This has more code but I don't want to write it out 	// All it does is count the time between when the timer(); was last called	float theTimeSegment;	xPoint += (xSpeed * theTimeSegment);	yPoint += ((ySpeed - kGravity + normalForce) * theTimeSegment);	zPoint += (zSpeed * theTimeSegment);		// this needs to be after the speed	keyboardDown();		if (s > 0.1)	{		xOldPoint = xPoint;		yOldPoint = yPoint;		zOldPoint = zPoint;	}		s = A * xPoint + B * yPoint + C * zPoint - D;		if (lastDistance >=-0.1 && s <= 0.1)	{		// Normalize and finding the unit length of the normal		float xPlanePoint = xPoint - ((s / vectorMagnitude) * (A / vectorMagnitude));		float yPlanePoint = yPoint - ((s / vectorMagnitude) * (B / vectorMagnitude));		float zPlanePoint = zPoint - ((s / vectorMagnitude) * (C / vectorMagnitude));				// This is for a square but it can be done for any polygon		float distance1 = vectorDistance(x1Vert, y1Vert, z1Vert, x2Vert, y2Vert, z2Vert, 			(x1Vert - A), (y1Vert - B), (z1Vert - C), xPlanePoint, yPlanePoint, zPlanePoint);				float distance2 = vectorDistance(x2Vert, y2Vert, z2Vert, x3Vert, y3Vert, z3Vert, 			(x2Vert - A), (y2Vert - B), (z2Vert - C), xPlanePoint, yPlanePoint, zPlanePoint);		float distance3 = vectorDistance(x3Vert, y3Vert, z3Vert, x4Vert, y4Vert, z4Vert, 			(x3Vert - A), (y3Vert - B), (z3Vert - C), xPlanePoint, yPlanePoint, zPlanePoint);		float distance4 = vectorDistance(x4Vert, y4Vert, z4Vert, x1Vert, y1Vert, z1Vert, 			(x4Vert - A), (y4Vert - B), (z4Vert - C), xPlanePoint, yPlanePoint, zPlanePoint);		// Since the planes are pointing inward we check for a positive distance		if (distance1 >= 0.0 && distance2 >= 0.0 && distance3 >= 0.0 && distance4 >= 0.0)		{						// Normalize			float xNorm = A / vectorMagnitude;			float yNorm = B / vectorMagnitude;			float zNorm = C / vectorMagnitude;			float dotProduct = (xSpeed * xNorm + ySpeed * yNorm + zSpeed * zNorm);						xSpeed -= xNorm * dotProduct;			ySpeed -= yNorm * dotProduct;			zSpeed -= zNorm * dotProduct;			xPoint = xOldPoint;			yPoint = yOldPoint;			zPoint = zOldPoint;						normalForce = kGravity;			collision = YES;		}	}		lastDistance = s;}float vectorDistance(float x1Vert, float y1Vert, float z1Vert, float x2Vert, float y2Vert, float z2Vert, 	float x3Vert, float y3Vert, float z3Vert, float xP, float yP, float zP){	float A = y1Vert * (z2Vert - z3Vert) + y2Vert * (z3Vert -  z1Vert) + y3Vert * (z1Vert - z2Vert);	float B = z1Vert * (x2Vert - x3Vert) + z2Vert * (x3Vert -  x1Vert) + z3Vert * (x1Vert - x2Vert);	float C = x1Vert * (y2Vert - y3Vert) + x2Vert * (y3Vert -  y1Vert) + x3Vert * (y1Vert - y2Vert);	float D = x1Vert * (y2Vert * z3Vert - y3Vert * z2Vert) + x2Vert * (y3Vert * z1Vert - y1Vert * z3Vert)		+ x3Vert * (y1Vert * z2Vert - y2Vert * z1Vert);	return ((A * xP) + (B * yP) + (C * zP) - D);}void keyboardDown(void){	if (keyUp == NO)	{		switch(keyboardCommand)		{			case 'w':				if (collision)				{					xSpeed = 0.0;					ySpeed = 0.0;					zSpeed = 0.0;					if (normalForce == kGravity)						normalForce = 0.0;					zSpeed =-2.0;					collision = NO;				}			break;			case 's':				if (collision)				{					xSpeed = 0.0;					ySpeed = 0.0;					zSpeed = 0.0;					if (normalForce == kGravity)						normalForce = 0.0;					zSpeed = 2.0;					collision = NO;				}			break;		}	}}

[Edited by - Jonathan2006 on May 23, 2006 9:11:35 PM]

##### Share on other sites
We'd be more than happy to take a look at your code, but could you please surround your code with [ source] [ /source] tags without the spaces.

It keeps the formatting of your code and puts it in a nifty textbox type thing like this sentence is in.

[smile]

-AJ