Moving a Body with forces... Smoothly

CagedFury

15-03-2007 17:58:02

Ok so i have managed to get a physics body andragdoll etc moving around with forces however i am trying to get the camera to stay with that collision body at all times and it tends to jump and skip a bit.

Im simply doign this in process unbuffered mouse input


mCamera->setPosition(mNode_CollisionBody->getPosition());


If i have the camera in a set position the the collsion body moves fine without skipping but if the camera follows it like that then it looks like its missing frames and the collision body gets closer or furher from the camera each frame which just looks messy.

Any ideas on how to handle this?

nikhil

17-03-2007 08:08:28

I guess you can take a look at the Ogre Wiki for a sample Camera implementation. It's quite comprehensive and gives you the exact approach one should implement a basic camera..

abecam

20-03-2007 13:05:26

You can simply push the camera as a child of your mesh. In the example I wrote (accessible here : http://mmroserver.hgo.se/PistonTutorial.html ), you can change the camera position by pressing 'c', and one is "inside the box" (the container in the example):


Ogre::Quaternion orientBox(Ogre::Vector3(0,-1,0),Ogre::Vector3(1,0,0),Ogre::Vector3(0,0,1));
orientBox.FromAngleAxis(Ogre::Radian(Ogre::Degree(-90)),Ogre::Vector3(1,0,0));
orientBox.normalise();
container->getOgreNode()->attachObject( mCamera );

mCamera->setPosition(0.0, 0.0, 0.0);
mCamera->setAutoTracking(false);

mCamera->setOrientation(orientBox);
cameraMode=2;
LogManager::getSingleton().logMessage(" Camera in the box ");


You might have to change the position of the camera (here it is really inside the box), it will move it relatively to the object you attach it with(here the container).

For better solutions you can find a lot of threads, and StuntPlayground as a very good approach, and thanks to our master here, you can download the sources 8) .

Oooh, and if you only want the camera to follow one object 8auto tracking), that's simply (following the container here):


mCamera->setAutoTracking(true,container->getOgreNode());

CagedFury

28-03-2007 19:47:34

Actually worked out this isnt really to do with the camera, its the way the body is moving with forces, the forces being applied are pushing it off the position which it actually is. Then its jumping back to this position so when the body is moving it looks liek its jumping around.

Bah maybe i will try creating a separate body that the forces act upon which moves this body around, it would be fine if it werent connected to a node which has a mesh connected to it, but then how do other objects move around with forces without this happening maybe ill look at my custom force callback again.

CagedFury

28-03-2007 20:52:34

Yes basically the problem is with the way Newton moves the bodys with forces (local, Global, or Velocitys).

It doesnt just affect the body with a given force, it actually moves it with the force while still registering with Ogre that its position is the previous position.

I have an OgreNewt Cylinder moving with forces, this in turn moves teh node it is attached to which moves the mesh that is attached to it. However when i update things to be at that mesh location or that node location they always appear to be a physics frame behind.

Although having said that it then jumps back to being correct (and back to being off a frame), its probably the frame listeners as the events happen at different times or some such.

I wouldnt mind if it were consistently incorrect as that would at least make it look like smooth movement the problem is with it jumping back and forth and making it look like an earthquake or something.

CagedFury

28-03-2007 21:33:08

Bah ok so i created anouther collision body that has a joint which pulls the original collision body around with it and it works slightly better but it still does the same thing starts to twitch.

Ill provide some of my code maybe that will help with pointing out a mistake theGame->getPhysicsManager etc is just my link to mWorld


mNode_CollisionBody = mNode_Root->createChildSceneNode();
mNode_CollisionBody->setPosition(startPos+ Vector3(0,10,0));
mNode_Ragdoll = mNode_CollisionBody->createChildSceneNode();

mRag_Entity = theGame->getSceneManager()->createEntity( "ENTITY", "zombie.mesh" );
mNode_Ragdoll->attachObject( mRag_Entity );

//Setup values
size = Ogre::Vector3( 2, 3, 0 );
position = mNode_CollisionBody->getPosition();
rotation = Quaternion(Ogre::Math::Sqrt(0.5),0,0,Ogre::Math::Sqrt(0.5));//Rotation 90 Degrees around the Z axis
mNode_Ragdoll->setOrientation(Quaternion(Ogre::Math::Sqrt(0.5),0,0,-Ogre::Math::Sqrt(0.5)) * Quaternion(0,0,1,0)); //Compensate for rotation, -90 Degrees around the Z axis
mass = 2;
inertia = OgreNewt::MomentOfInertia::CalcCylinderSolid( mass, size.x, size.y);
col = new OgreNewt::CollisionPrimitives::Cylinder(theGame->getPhysicsManager()->getPhysicsWorld(), size.x,size.y);

//Create body and assign values
mCollision_Body = new OgreNewt::Body( theGame->getPhysicsManager()->getPhysicsWorld(), col );
mCollision_Body->setPositionOrientation( position, rotation );
mCollision_Body->attachToNode( mNode_CollisionBody );
mCollision_Body->setAutoFreeze(0);
mCollision_Body->setContinuousCollisionMode(1);
mCollision_Body->setMassMatrix( mass, inertia );

//Interaction between Ragdoll and Collision Body
OgreNewt::MaterialID * matRag = new OgreNewt::MaterialID(theGame->getPhysicsManager()->getPhysicsWorld());
OgreNewt::MaterialID * matCyl = new OgreNewt::MaterialID(theGame->getPhysicsManager()->getPhysicsWorld());
OgreNewt::MaterialPair * pair = new OgreNewt::MaterialPair(theGame->getPhysicsManager()->getPhysicsWorld(), matRag, matCyl);
pair->setDefaultCollidable(0);
pair = new OgreNewt::MaterialPair(theGame->getPhysicsManager()->getPhysicsWorld(), matCyl, matCyl);
pair->setDefaultCollidable(0);
pair = new OgreNewt::MaterialPair(theGame->getPhysicsManager()->getPhysicsWorld(), matRag, matRag);
pair->setDefaultCollidable(0);
OgreNewt::MaterialPair * pair2 = new OgreNewt::MaterialPair(theGame->getPhysicsManager()->getPhysicsWorld(), theGame->getPhysicsManager()->getPhysicsWorld()->getDefaultMaterialID(), matCyl);
pair2->setDefaultCollidable(1);
pair2->setDefaultFriction(0.8f,0.8f);

//Assign Materials and force callbacks
mCollision_Body->setMaterialGroupID(matCyl);
mCollision_Body->setCustomForceAndTorqueCallback(boost::bind(&RagCharacter::ForceCallback_CollisionBody,this,_1));

mRag_Upvector = new OgreNewt::BasicJoints::UpVector( theGame->getPhysicsManager()->getPhysicsWorld(),
mCollision_Body,
Vector3::UNIT_Y);



void RagCharacter::ForceCallback_CollisionBody(OgreNewt::Body * me)
{
mForce = Vector3(0,0,0);
mForce.x += adjForce->x;
mForce.z += adjForce->z;
me->addForce(mForce);
}


I have considered creating a sphere and enacting torque on it with some sort of joint attaching it to the cylinder but surely this will still have a similar effect?

Really not sure what else to try, going to have a look at the frame listeners now because thats the only thing i can think that it might be to do with however i just create a basic OgreNewt frame listener and a basic ogre frame listener so i dont know what eh problem could be there.

CagedFury

28-03-2007 21:49:20

Ok so i even went to the extent of creating a sphere that pulls the cylinder around using torque but it still twicthes.

Why does it twitch!!?!?? :)

My other other option i suppose is to create a vechicle that moves the mesh of a character around, but that really doesnt seem like the right way to go about things.

CagedFury

28-03-2007 23:12:47

Ok ive worked the whole way back around to guessing it must be something to do with the camera location.. lol

Its just strange that nothing else twicthes, just eh body im moving with physics, and i have it twitch when it wasnt being followed by the camera.

Ill look at camera stuff again i suppose.


mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
mCamera->yaw(mRotX);
mCamera->pitch(mRotY);

//Get camera rotation arond the y axis as a Quaternion
Camera_Rotation = Quaternion(mCamera->getRealOrientation());
Camera_Rotation.x = 0;
Camera_Rotation.z = 0;

//Create a vector location for behind the player character
Vector3 behindActor = Camera_Rotation * Vector3(0,0,30);
//Set the camera to be behind said Character
mCamera->setPosition(mNode_CollisionBody->getPosition() + behindActor);

CagedFury

28-03-2007 23:36:11

Ok yes it was the camera, the way i was positioning the camera, really i should have been just attaching it to a node and letting ogrenewt handle the movement of nodes and child nodes etc.

Basically its something to do with when the framestarted function executed and when the ogrenewt moved things, i think that is the reason why i couldnt directly reposition the camera every frame instead what i can do is repositin the node which it is attached to, however i can then only change where it is place relative to where the original collision body is placed (as it is a child of its scene node). Which is fine for what i need.

Finally i hope now i can make this work in the main application and not jus the little one i made to fiddle with this.