Problem with hkpWorld::rayCast (or my usage of it)

Problem with hkpWorld::rayCast (or my usage of it)

Kryogenik's picture

I'm in the early stages of making a game where you control a hover craft (just a box graphically at this point) that follows the "terrain" you are on. I put terrain in quotes because it won't be terrain, but 3d shapes, like spheres, toruses, bowls, helixes, tubes etc. put together to make a level. It will be sort of like this [url]http://www.youtube.com/watch?v=KY9FsXHPsTg[/url], but instead of just a sphere, you will be able to use any 3d model.

I made a torus to use for testing purposes and exported as a .mesh for the visual model and as a .hkt for the Havok rigid body.

I figured this is what I would have to do to get the box to "follow" the terrain

1 Position the box at the edge of the torus

2 Do a raycast from 20 spaces up its y-axis to 20 spaces down its y-axis, get the collision position and normal from it, and position the box at the collision position

3 Add the position and collision normal vectors together into a vector and point the box towards it along the y axis so the box has the correct pitch and roll

4 Set the yaw to zero so that the box doesn't turn randomly

5 Position the camera 100 away from the box along its y-axis and point the camera toward it

6 Repeat steps 2-5 whenever you move around

But it doesn't work, whenever the box goes above a different polygon from the torus, it freezes when I try to move it and spins around. I think that for some reason, the normal flips sometimes. Like if the normal is 0, 0, 1, it can sometimes return 0, 0, -1. I have my commented game loop here, it uses some of my functions and classes, but you'll get the idea:

void Engine::MainGameLoop()
{
	//Variable that will be set to true when any of the arrow keys are pressed, so we know when to perform raycasting
	bool moving = false;
	//These lines make a visual box and positions it near the edge of the torus so the raycasting will hit the torus
	Objects[0] = new ObjectClass(0, Ogre::Vector3(20, 20, 20), lRootSceneNode, lScene, "Box");
	Objects[0]->Position(Ogre::Vector3(200, 0 , 30));
	Objects[0]->Point(Ogre::Vector3(0, 0, 0), 2);
	//This line makes the visual torus from Torus.mesh, a model I made
	Objects[ObjectNum-1] = new ObjectClass("Torus.mesh", lRootSceneNode, lScene, "Torus");
	//This line makes the physical torus in havok form Torus .hkt, a havok tagfile I made
	HavokObject->LoadHavokObject(Objects[ObjectNum-1], "C:/Torus.hkt", "Torus");
	//Self Explanatory
	PositionCamera(Ogre::Vector3(420, 500, 0));
	PointCamera(Ogre::Vector3(0, 0, 0));
	//Initializes the Havok Viusal Debugger, not really used here, but whatever
	HavokObject->InitVisualDebugger();
	//Initializes some variables used later
	Ogre::Vector3 ColPos;
	Ogre::Vector3 Added;
	Ogre::Vector4 ColNorm;
	Ogre::Vector4 OldNorm;
	//The start of the main loop
	while (!lWindow->isClosed())
	{
		//Sets moving to false so that when you let go of the arrow keys, the program doesn't think you're still moving
		moving=false;
		//Gets the elapsed time in milliseconds, used for timer based movement (although it isn't really that necessary here)
		float Elapsed=TimeSinceLast()*.001;
		//Steps Havok and positions/orients the visual objects the same ways as their rigid bodies in Havok
		HavokObject->StepHavok(Elapsed);
		PositionRigidBodies();
		//Ends the loop when escape is pressed
		if (GetKey(int(VK_ESCAPE))==true)
		{
			lWindow->destroy();
		}
		//Moves the box forward along the z-axis 8 units every second and sets moving to true
		if (GetKey(int(VK_UP))==true)
		{
			Objects[0]->Move(Ogre::Vector3(0, 0, 8*Elapsed));moving=true;
		}
		//Moves the box backward along the z-axis 8 units every second and sets moving to true
		if (GetKey(int(VK_DOWN))==true)
		{
			Objects[0]->Move(Ogre::Vector3(0, 0, -8*Elapsed));moving=true;
		}
		//Moves the box backward along the x-axis 8 units every second and sets moving to true
		if (GetKey(int(VK_LEFT))==true)
		{
			Objects[0]->Move(Ogre::Vector3(-8*Elapsed, 0, 0));moving=true;
		}
		//Moves the box forward along the x-axis 8 units every second and sets moving to true
		if (GetKey(int(VK_RIGHT))==true)
		{
			Objects[0]->Move(Ogre::Vector3(8*Elapsed, 0, 0));moving=true;
		}
		//Checks to see if we are moving so we can start raycasting and stuff
		if (moving==true)
		{
			//Gets the normalized y axis vector for the box
			Ogre::Vector3 yaxis = Objects[0]->GetAxis(1);
			//Sets the Old Collision Normal to the current one, we do this so that when the New Collision Normal from the raycast is the same as the old one, we won't do reorient the object
			OldNorm=ColNorm;
			//Performs a Raycast from 2 spaces above the box on the its y-axis, to 50 units down its y-axis
			HavokObject->RayCast(Objects[0]->getPosition()+(yaxis*2), -yaxis, &ColPos, &ColNorm, 50);
			//Checks to see if the new collision normal is different from the old one
			if (OldNorm!=ColNorm)
			{
				//Adds the collision normal to the collision position and puts it in 'Added' so we can point the box toward it and get the right x and z rotations
				Added = Ogre::Vector3(ColPos.x+ColNorm.x, ColPos.y+ColNorm.y, ColPos.z+ColNorm.z);
				//Positions the box at the Collision Position
				Objects[0]->Position(ColPos);
				//Points the box towards 'Added' along the y axis (instead of the default z axis)
				Objects[0]->Point(Added, 1);
				//Sets the yaw of the box to zero so you can rotate the box on the y-axis and turn it
				Objects[0]->Yaw(Ogre::Radian(0), false);
			}
			//Positions the Camera at the box plus 100 of its y-axes (if that makes sense) and points it toward the box
			PositionCamera(Ogre::Vector3(Objects[0]->getPosition()+(yaxis*100)));PointCamera(Objects[0]->getPosition());
		}
		//Prints out some debug info
		mText->text(Ogre::StringConverter::toString(ColNorm)+" X-Axis: "+Ogre::StringConverter::toString(Objects[0]->GetAxis(0))+" Y-Axis: "+Ogre::StringConverter::toString(Objects[0]->GetAxis(1))+" Z-Axis: "+Ogre::StringConverter::toString(Objects[0]->GetAxis(2))+" Rotation: "+Ogre::StringConverter::toString(Objects[0]->getRotation()));
		//Updates the window, swaps the buffers, renders the scene, and handles the windows message pump
		lWindow->update(false);
		bool vsync = true;
		lWindow->swapBuffers(vsync);
		OgreRoot->renderOneFrame();
		Ogre::WindowEventUtilities::messagePump();
	}
	return;
}

Has anyone ever tried doing something like this before? I don't know what could be going wrong. Thanks for any help.

2 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
havokcormac's picture

Hi,

Haven't had time to analyze exactly what you're doing but from a quick readthrough it doesn't sound very robust.
In any case, setting the position of the box directly doesn't leverage any of the possibly interesting hovercraft dynamics you could be playing with.

Take a look at the Physics/UseCase/PlanetGravity demo as a starting point, it might give you some ideas.

Cheers,
Cormac

EDIT: Sounds interesting, by the way. I'm keen to see some results on this one.

Login to leave a comment.