Sign in to follow this  
Jonathan2006

Smooth moving on terrain

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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by jyk
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.


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 this post


Link to post
Share on other sites
Quote:
Original post by u235
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.
Oops, I should have been more specific: it's the up vector (not the foward vector) that you align towards the normal.

Share this post


Link to post
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.0

char 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 updated
void 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 this post


Link to post
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this