Incline Rotation and Height-Based Positioning

Started by
8 comments, last by JulianSpillane 20 years, 9 months ago
Hey guys. I''ve got a problem (..don''t we all. XD). I''m working on a kart-style racing game, and I''ve come to a roadblock in my coding. For my worlds, I''m using a 3DS format exported base and adding my interactive objects separately through an editor. Now, I can collide with the separate objects easily (bounding box), but I''m not sure how to go about positioning my main "kart" object based on the height of the level and rotating it based on the incline. Now, I can do it when it comes to terrain (since I have a heightmap), but the only solution I can think of for my problem is to compare the y position of the vertex corresponding with the object''s position and positioning the object at that height, but that involves sorting through the entire world''s vertices each frame and won''t help me with incline rotation at all. Sorry if this question''s been asked before, I just really didn''t know what to search for. ^^; Any help would be greatly appreciated. Many Thanks, Julian Spillane
Advertisement
The solution to your problem requires a damn a lot of math code but i believe your capable if you''ve written a half game.Here is how to do it:collide each of the kart wheels with the terrain separately.Then rotate and invert the kart so it can fit the wheels.That''s it!

"You losers better learn...NOONE CONTROLS OUR GOD DAMN LIFE!!!" - MANOWAR
Thanks for replying, but the problem is, my terrain isn''t done through heightmap, it''s in fact done through a modeling program, so the hard part for me is finding the correct height to collide with.

I''ll continue to mess around. Hopefully I''ll find something. Thanks anyways.
Hi JulianSpillane,

you can cast a ray (0, -1, 0) from the Center of Mass or simply from the position of your kart.
Then you''ll have to check which triangle it hits on your road; the intersection point is the new position of your car.

To orientate your car get the triangle collider normal and orientate your car defined with normal vector(0, 1, 0) taking the cross-product of these two vectors. You''ll get the axis of rotation. a little dot product between the triangle normal and (0, 1, 0), you get the angle of rotation. voila

The ray-triangle test can be done easily in two steps:
- intersection ray-plane
bool intersectLinePlane(Vector rayStart, Vector rayEnd,				        Vector vertex, Vector triangleNormal, Vector *intersection){	Vector direction, L1;	float rayLength, distFromPlane, percentage;	//calculate the ray''s direction vector	direction = rayEnd - rayStart;	Vector normDir = direction;	normDir.Normalize();	//this gives us the ray length	rayLength = direction.Dot(normal); 	//check it does not = 0 with tolerance for floating point rounding errors	if (fabsf(rayLength) < 0.00001){		return false; //0 means the ray is parallel to the plane so can not intersect it	}	L1 = vertex - rayStart;	//gives the distance from the plane	distFromPlane = L1.Dot(normal);	//how far from RayStart, intersection is as a percentage of 0 to 1 	percentage = distFromPlane / rayLength;	if(percentage < 0){ //the plane is behind the start of the line		return false;	}	else if(percentage > 1){ //the line does not reach the plane		return false;	}	//add the percentage of the ray to ray start	intersection->x1 = rayStart.x1 + direction.x1 * percentage;	intersection->x2 = rayStart.x2 + direction.x2 * percentage;	intersection->x3 = rayStart.x3 + direction.x3 * percentage;	return true; //we have hit a plane; }

- point in triangle
bool pointInTriangle(Vector point, Vector triangle[3]){	Vector Lines[3];	float total_angles;	//loop through all the vertices in triangle	for (int i = 0; i < 3; i++)        {			//get direction Vector from intersection to vertex[a]		Lines[i] = point - triangle[i]; 		Lines[i].Normalize();	}	double ang1 = acos(Lines[0].Dot(Lines[1]));	double ang2 = acos(Lines[1].Dot(Lines[2]));	double ang3 = acos(Lines[2].Dot(Lines[0]));	if(ang1 < 0 || ang2 < 0 || ang3 < 0)		return false;	float ang1deg = (float)RAD_TO_DEG(ang1);	float ang2deg = (float)RAD_TO_DEG(ang2);	float ang3deg = (float)RAD_TO_DEG(ang3);	total_angles = (float)(ang1 + ang2 + ang3);	//lets take 6.28 radians(360 degrees) away from total_angles	//if its Zero (with tolerence) we''ve hit it	if (fabsf(total_angles - PI_2X) < 0.00001f)        {			return true; 		}	}	}	return false; //we have not hit the polygon}


Cheers
Of course, that''s just part of it. To save time, you might want to have a subset of just the polys that you can actually drive on. Also you''ll want to have collision detect for running into walls and trees and stuff.

Good luck!
-solo (my site)
Thanks a lot guys. That actually seems a lot more sound than the method a bunch of us came up with tonight at my local IGDA meeting. I didn''t even THINK of casting a ray. ^_^ Thanks a lot!

I''ll tell y''all if I get it running nicely. ^_-

Thanks a lot,
Julian
I''ve been wondering about this for a while now.
Would you have to test for a collision from the center of the mass, or every single wheel and then take the average of the reflected normals?
I guess it depends on the terrain. With a plain road one ray should be ok. If the terrain is too rough and detailed, orienting the kart based on the triangle normals of the terrain will make it bounce around like hell... I''d probably take 4 ground samples at each tire, orient the car above the average plane through these points, and adjust the height of the wheels so they actually all touch the ground (shock absorbers). That of course still doesn''t work if you are hanging over a cliff with part of your car
Hey all,
Sorry for the late reply. I''ve been working and as such, been exhausted.

I finally got around to toying with this code, but I''ve run into some theoretical problems.

To obtain the axis of rotation you cross the triangle''s normal vector with (0,1,0), correct? So:

Axis of Rotation = V1 x V2

And the angle of rotation is equal to the triangle''s normal dot (0,1,0)?

Angle of Rotation = V1.V2

So if my kart is traveling along and hits a triangle at an angle, who''s normal is (0.5,0.5,0), the following should be true:

Axis of Rotation = V1 x V2
AoR.x = ((1 * 0) - (0 * 1))
AoR.x = 0 - 0
AoR.x = 0
AoR.y = ((0*0.5) - (0*0))
AoR.y = 0 - 0
AoR.y = 0
AoR.z = ((0 * 0.5) - (1 * 0.5))
AoR.z = 0 - 0.5
AoR.z = -0.5

Angle of Rotation = V1.V2
AxoR = (0*0.5)+(1*0.5)+(0*0)
AxoR = 0+0.5+0
AxoR = 0.5

For some reason that doesn''t seem right. Am I doing something wrong?

Sorry to be a bother. >_<
Hehe...well, I''m an idiot. I forgot to divide the result of the dot by the magnitudes of both vectors and acos that. ^^;;

The angle is 45, as it should be.

Me = idiot. XD

Sorry about that!

This topic is closed to new replies.

Advertisement