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.


