Camera collision

greyWiz

31-03-2006 03:33:08

Hi, I'm having some problems trying to set a collision object to my camera.

Actually, I'm using a customized camera that inherits Ogre::Camera. It has an independent gravity system that relies on OgreNewt::BasicRaycast to test downward collision. Until here, everything's working fine, but now I'm trying to include this code to the class:

OgreNewt::Collision* col = new OgreNewt::CollisionPrimitives::Ellipsoid(mWorld, Vector3(1.0, 1.0, 1.0));
OgreNewt::Body* body = new OgreNewt::Body(mWorld, col);
delete col;
Vector3 pos = mCameraNode->getPosition();
body->setPositionOrientation(pos, mCameraNode->getOrientation());
body->attachToNode(mCameraNode);


mCameraNode is the scene node where the camera is attached. The problem here is that I don't know how to test the collision of this body with other bodies inside the world. I've read in another post that there's a function called CollisionCollide() inside namespace CollisionTools, but I haven't found it.

Is there a way of using a Body for collision test only, without applying forces to it? Os should I use a Collision object to do the job? I'm really lost here... :oops:

Thanks in advance!
Edgard

BergBoy

31-03-2006 11:14:26

The way I pulled off using a camera with collision was having a physics body (an elipsoid) with a second node attached near the top with a camera on it. You can look up and down with the cameras standard controls but you use torque to look left and right. Forces translate the physics body around the enviroment and an upJoint holds the body upright.

If I just wanted collision, I would think a collide callback that rejects collisions and lets you do what you want instead (im no master but im under the impression you can do that).

greyWiz

04-04-2006 23:05:29

Hi, I tried BergBoy's suggestion (using an ellipsoid) and it worked partially... When I'm on air, I can move camera up and down and apply forces normally; but, when the ellipsoid touches the ground, it simply gets stuck and I can't move the camera up or down anymore, and the forces applied doesn't have effect! I already tried to reduce the linear damping, but nothing changed.

Here are the OgreNewt's settings related to my camera class:

OgreNewt::Collision* col = new OgreNewt::CollisionPrimitives::Ellipsoid(mWorld, Vector3(1.0, 1.0, 1.0));
OgreNewt::Body* body = new OgreNewt::Body(mWorld, col);
delete col;

Real mass = 70.0;
Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid( mass, Vector3(1.0, 1.0, 1.0) );
body->setMassMatrix(mass, inertia);

body->setLinearDamping(0.001f);
body->setAngularDamping(Vector3(0.001f, 0.001f, 0.001f));

Vector3 pos = mCameraNode->getPosition();
body->setPositionOrientation(pos, mCameraNode->getOrientation());
body->attachToNode(mCameraNode);

body->setCustomForceAndTorqueCallback(forceCallback);
mUpVec = new OgreNewt::BasicJoints::UpVector(mWorld, body, Ogre::Vector3::UNIT_Y);


mCameraNode is the parent node and holds the ellipsoid. It has a child node, called mPitchNode, which is the one who owns the camera.
Here's the code for forceCallback:

void forceCallback( OgreNewt::Body* me )
{
Real mass;
Vector3 inertia;

me->getMassMatrix(mass, inertia);
Ogre::Vector3 gravity = Vector3(0,-9.8,0) * mass;
me->addForce( gravity );

//Capture input states
mInputDevice->capture();

//Still not happy with this implementation...
if(mInputDevice->getMouseRelY() != 0)
{
mCurrentPitch += Degree(-mInputDevice->getMouseRelY() / 2.0);

if(mCurrentPitch > mMaximumPitch)
{
mCurrentPitch = mMaximumPitch;
}
else if(mCurrentPitch < -mMaximumPitch)
{
mCurrentPitch = -mMaximumPitch;
}
else
{
mPitchNode->pitch(Degree(mInputDevice->getMouseRelY() / 2.0));
}
}

//Walk Ahead
if (mInputDevice->isKeyDown(KC_UP))
{
me->addForce( Vector3(0.0, 0.0, 100.0) * mass );
}

//Walk back
if (mInputDevice->isKeyDown(KC_DOWN))
{
me->addForce( Vector3(0.0, 0.0, -100.0) * mass );
}
}


As I said before, it works fine when I'm free falling. When the camera finishes bouncing, it becomes completely frozen and I can't move it anymore. What am I missing? :oops:

Thanks in advance! :D
Edgard

PS: by the way, is there some trick to reduce camera's bouncing?

BergBoy

05-04-2006 05:06:22

is the object falling asleep? (this is when an object stops moving and will not become active in the physics world again until a collision). Try turning the autofreeze off:

body->setAutoFreeze(0)

that means it never falls asleep. Good for character controllers, not good for ragdolls or crates and stuff. Objects falling asleep helps conserve precious CPU...

sdragou

05-04-2006 11:21:13

You have to assign a new material to the body and then make a new material pair between this material and default material and set elasticity to zero
e.g.
const OgreNewt::MaterialID* mMatDefault = m_World->getDefaultMaterialID();
const OgreNewt::MaterialID* mMatCamera = new OgreNewt::MaterialID( m_World );

OgreNewt::MaterialPair *mMatPairDefaultCamera = new OgreNewt::MaterialPair( m_World, mMatDefault, mMatCamera );
mMatPairDefaultAssil->setDefaultFriction( 0.4, 0.4 );
mMatPairDefaultAssil->setDefaultSoftness(0.1);
mMatPairDefaultAssil->setDefaultElasticity(0.0);
mMatPairDefaultAssil->setContinuousCollisionMode(1);
body->setMaterialGroupID(mMatCamera);

greyWiz

05-04-2006 19:18:49

I mixed BergBoy and sdragou's answers and both of you were right! :wink:

Indeed, my object was freezing when hitting the ground, and the material pair made the camera stop bouncing and receiving forces correctly. But still there are two weird things happening:

1. When apply torque to turn the camera, it takes a lot of time until it stops... I already set the angular damping to 100000, but nothing changed;
2. I created a crab camera! :shock: When I press up it goes to the right and not to the front... I'm not an expert in quaternions, so I don't know if I'm missing something. Anyway, here's the code to the up key (inside forceCallback, 'me' is a pointer to a Body):

Real mass;
Vector3 inertia;
me->getMassMatrix(mass, inertia);

//Walk Ahead
if (mInputDevice->isKeyDown(KC_UP))
{
Vector3 position, axes;
Quaternion orientation;
me->getPositionOrientation(position, orientation);
orientation.normalise();
orientation.ToAxes(&axes);
Real forceAhead = 10 * mass;
axes *= forceAhead;
me->addForce( axes );
}


I haven't rotated any of the elements - SceneNodes, Camera and Body - so I don't know why is it happening...

I know that issue 2 isn't OgreNewt related, but any light here would be really appreciated...

Once again, thanks in advance! :)
Edgard

sdragou

06-04-2006 08:39:56

1) Have you tryied to increase the kinetic friction factor ?
e.g.
mMatPairDefaultAssil->setDefaultFriction( 1, 1 );

2) What I have done is to have a Vector3 (mDirection) that describes the desired speed in local coordinates.

Then in the force callback


Ogre::Real mass;
Ogre::Vector3 inertia;
Vector3 postition;
Quaternion orientation;
me->getMassMatrix(mass, inertia);
Ogre::Vector3 force;
me->getPositionOrientation(postition,orientation);
Vector3 V0 = me->getVelocity();
Vector3 V1=orientation*(mDirection);
Ogre::Real deltatime = me->getWorld()->getTimeStep();
Vector3 acel ((V1 - V0) / deltatime);
force = (Vector3(acel.x,-9.81,acel.z))*mass;

praetor

10-04-2006 15:58:22

The position and orientation OgreNewt gives back probably is for the scene node. You should take the "local" direction want to travel (which is usually -Z for forward, +Y for up, etc.) and multiply it with the camera's derived orientation (cam->getDerivedOrientation). This will force the node to move in the coordinate space of the camera (relative to what you see) as opposed to the system of the node.