nickgravelyn
11-07-2006 21:57:40
I'm trying to create a single collision detection system between my character and other Newton bodies. I used Ogre's code to get the AABB to create the size vector for my collision box. Problem is that my moving code directly alters the Ogre::SceneNode's position. How can I then update the OgreNewt::Body's position to reflect this? Here's how I'm creating the box (just in case this is actually the problem) :
Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode( "PlayerNode" );
node->attachObject( ent );
node->scale( Ogre::Vector3( 1 / ent->getBoundingRadius(), 1 / ent->getBoundingRadius(), 1 / ent->getBoundingRadius() ) );
node->scale( Ogre::Vector3( 6, 6, 6 ) );
ent->setNormaliseNormals( true );
ent->setCastShadows( true );
Ogre::AxisAlignedBox characterBB= ent->getBoundingBox();
collision = new OgreNewt::CollisionPrimitives::Box( mWorld, characterBB.getMaximum() - characterBB.getCenter() );
body = new OgreNewt::Body( mWorld, collision );
body->attachToNode( node );
praetor
11-07-2006 22:38:02
First off, have your move code update the newton body, not the scene node. The physics should receive the physical updates (like moving) first, and have the graphics updated from its state, not the other way around.
The simplest and worst way is simply to use the setPosition calls for the body. I've seen it work, especially with a higher physics frame rate. The other way to do it is "inverse kinematics." You know where the body needs to be, where it was, how fast it was going, and how long it has to get to its destination.
Get the position and velocity from the body.
p0 = Current position
p1 = Next position (where you're going)
v0 = Current velocity
t = time body has to go from p0 to p1
a = acceleration
f = force to apply to update body's position
f = m * (1/t) * ( ((p1 - p0)/t) - v0)
Just apply this force to the body in the force/torque callback. Then in the transform callback, update the related scene node. After all that, render in Ogre.
nickgravelyn
12-07-2006 06:48:44
Is there anyway to get the OgreNewt body from the scene node? I currently have a frame listener with a pointer to the scene node and would rather not jumble things around to pass the OgreNewt body to the frame listener. I assume this is possible somehow, is it not?
nickgravelyn
12-07-2006 08:14:36
Ok. I decided to just pass the body to the frame listener. Now my body is moving around with my character. Now for collisions...
I need to make sure my player does not walk through buildings (obviously). I understand I need to create two MaterialIDs and then use a MaterialPair to connect the two and select a collision callback. I even have a basic callback class set up. How do I simply code the callback so that my player is not allowed to go inside the buildings?
walaber
12-07-2006 10:55:16
you don't need a collision callback if you just want regular collision. you only need the callback if you want to do something special, like apply acceleration, or other special effects.
standard collision will happen automatically if you let Newton move the objects instaed of moving them manually. you need to apply forces to move the objects, instead of moving the position manually... search the forum, there are a lot of topics about this.
nickgravelyn
12-07-2006 20:07:44
Will setting the velocity in a callback work as well? I want my character to have constant motion (i.e. no acceleration when moving). I tried doing this in a force callback, but I can't move him around at all. Any ideas why this isn't working?
void SpyscrollerFrameListener::playerPhysicsCallback( OgreNewt::Body *pBody )
{
if( pBody != mPlayerBody ||
pBody == NULL )
return;
Ogre::Real mass;
Ogre::Vector3 inertia;
pBody->getMassMatrix( mass, inertia );
pBody->addForce( Ogre::Vector3( 0, -9.8 * mass, 0 ) );
Ogre::Vector3 currentVelocity = pBody->getVelocity();
Ogre::Vector3 velocity = Ogre::Vector3::ZERO;
if( mButton[ UP ] && !( mButton[ RIGHT ] || mButton[ LEFT ] ) )
{
velocity.z = 1;
}
else if( mButton[ UP ] && mButton[ RIGHT ] )
{
velocity.x = -1;
velocity.z = 1;
}
else if( mButton[ UP ] && mButton[ LEFT ] )
{
velocity.x = 1;
velocity.z = 1;
}
else if( mButton[ DOWN ] && !( mButton[ RIGHT ] || mButton[ LEFT ] ) )
{
velocity.z = -1;
}
else if( mButton[ DOWN ] && mButton[ RIGHT ] )
{
velocity.x = -1;
velocity.z = -1;
}
else if( mButton[ DOWN ] && mButton[ LEFT ] )
{
velocity.x = 1;
velocity.z = -1;
}
else if( mButton[ RIGHT ] )
{
velocity.x = -1;
}
else if( mButton[ LEFT ] )
{
velocity.x = 1;
}
velocity.normalise();
velocity *= mMoveSpeed;
velocity.y = currentVelocity.y;
pBody->setVelocity( velocity );
}