Character Movement

CaseyB

06-05-2006 02:56:47

I have read that the best way to do character movement is to have the bottom part of the collision model be a sphere and then simply add a torque to the sphere to roll it along and then another forse to keep the character upright. Is this the proper way to do it? And if so can I describe it simply as an OgreNewt::CollisionPromitives::CompoundCollision() or do I need to use joints?

DarkCoder

06-05-2006 03:27:18

I think it depends on the type of game you want to create.
And the type of project you'r working on.

For a MMORPG type game i would use.

Either a Cylinder or an Ellipsoid.
You could use:
* OgreNewt::CollisionPrimitives::Box
* OgreNewt::CollisionPrimitives::Capsule
* OgreNewt::CollisionPrimitives::ChamferCylinder
* OgreNewt::CollisionPrimitives::Cone
* OgreNewt::CollisionPrimitives::ConvexHull
* OgreNewt::CollisionPrimitives::Cylinder
* OgreNewt::CollisionPrimitives::Ellipsoid
* OgreNewt::CollisionPrimitives::Pyramid

And add an UpVector so it allways points in the X,Y or Z without falling other.

OgreNewt::Joint* joint;
joint = new OgreNewt::BasicJoints::UpVector( m_World, body, Vector3(Vector3::UNIT_Y));


Many people use this to collide with your level & objects etc.
And combine it with a material pair to remove Elasticity & Friction while moving.

You may also find this interesting from this topic.
http://www.ogre3d.org/phpBB2addons/view ... c&start=15

I went a step further than that. I wanted to use the ragdoll to create an accurate hitbox as well. Problem is you cant walk a ragdoll around really. For this reason I use a Biped Class that has a collide box (Spherical Character controller moved by forces) to walk my zombies (soon to be guards whenever my artist finishes modelling them...) around the game world and I also have a ragdoll, which is attached to all the bones.

Spend some tiem to make the ragdoll more functional. Put in a few functions that loop through the bones and do things like: apply newton materials, freeze and unfreeze, get root bone, update ragbones to match ogrebones etc. This lets me have a fully animated character with a VERY accuarate series of hitboxes. I have also changed OgreNewts body class to have a "shootable" flag so that I can shoot only what I flag as shootable (this could have been done with a few checks or the 'userdata' tho).

So heres how it works:

1) Hitbox (with an up-joint to stop it tipping over) attaches to entitys sceneNode. Attach a null material (until newton can turn physics objects on and off this is the best way to make physics items NOT hit anything) to the ragdoll and attach the entity. Make all the bones in the entities skeliton automatic (so the ragdoll doesnt cause drama), also make a function taht loops your ragdoll bones and updates them to match your skeliton (VERY easy).

2) When you fire a bullet, do your raytrace. If you set up a "shootable" flag, make a custom raytrace callback that returns only shootable objects. If that object is a ragdoll (I use a combo of a 'world object' flag in the body class so that it knows what type of object it is (ragdoll) and I also have a function int he ragdoll taht queries if any of the bones have the body I shot).

3) Set the ragdoll to a normal physics material (so it hits stuff now), add an impulse for the bullet hit, set a null material to the hitbox, put the bones on manual etc.

4) Ragdoll falls to ground


And tahts how I have a biped that walks around but can be ragged and it doesnt use creating objects during runtime (you should NEVER allocate memory DURING the game, only at load). If walaber is at all keen on using this kind of system in a demo or anything I can give him the code to my biped controller class (basically, I use it for guards, allies etc. Anything tahts human and walks around). Its not really 100% perfect though but theres ALWAYS people asking how to do ragdolls and this is the best way ive found.

For those interested in a visual look at this:



Notice the ragdoll hitboxes and its collide box (you can see my players collide box too). Now if you look at it AFTER I shoot it:



you can see the hitbox is not really used anymore (unless I ressurect the enemy to be used again). For those curious what the hand icon is in the second pic, its for dragging bodies. Its another reason why you should modify your ragdoll class (for dragging, I just find what body the ragdoll belongs to and use simelar code to whats in walabers demo for raytracing that comes with OgreNewt to move that body around (and it drags the rest of the doll with it)

CaseyB

06-05-2006 04:57:15

Wow! Very informative! Thank you! /me runs off to play!

CaseyB

06-05-2006 06:22:22

Ok, so I have tried three different set ups and I can't seem to get it to work! Firstly I added the UpVector that you suggested then I had a box on top of a ellipsoid connected with a Hinge, then connected with a ball and socket and then I tried just one solid body, but when I try to add a force to it using the keys it just sits there. I tried adding the force directly in the keyPressed() event handler and then I just added force to a vector in the event handler and applied it in the frameStarted handler. Here's how I left it.void keyPressed(KeyEvent* e)
{
switch(e->getKey())
{
...
case KC_W:
guyRoll.z += MOVEMENT_SPEED;
break;
}
}

frameStarted(const FrameEvent& evt)
{
...
Dog->addForce(guyRoll);
newtWorld->update( m_elapsed );
...
}

and nothing happens!

DarkCoder

06-05-2006 14:48:50

To make it move you need to add a Custom callback.

body->setCustomForceAndTorqueCallback(forceCallback);

forceCallback will be a function like this.

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

//Get object mass & inertia
me->getMassMatrix( mass, inertia );

me->addLocalForce( Vector3(PMove,Gravity,PStryfe) * mass, Vector3(0.0,0.0,0.0) );
me->setTorque( torque ) ;

}

//You can get its Position & Orientation like this
Ogre::Vector3 positstatus;
Ogre::Quaternion orienstatus;
me->getPositionOrientation(positstatus, orienstatus);



Take a look at Demo05_SimpleVehicle, Demo06_SimpleBuoyancy, Demo03_CollisionCallbacks

BergBoy

06-05-2006 14:56:11

You can only apply forces in an callback. Every physics object has a physics callback and this is where you apply forces and whatnot. You cant just do it anywhere in your code. this can be annoying when ur starting out but you get the hang of it after a while. Search the forum for info on it, its fairly common to find this problem solved and also check out the OgreNewt demo for dragging (it uses a 'dragging' callback which shows you how its done).

For the character controller in the qoute of mine, use a "movement" callback that uses your stored change in movement and applies it (so you know where to start and I dont just say "make yon callback!").

edit: damn, beaten by 8 minutes, I must be slow...

CaseyB

06-05-2006 15:50:47

Awesome!! Thank you guys very much! :oops: I guess I should have looked at the demos closer!

CaseyB

13-05-2006 00:12:24

Ok, I got the force callback working, but now my guy just sits there and rocks a little bit. What I am trying to do is something like this. I want to have a ball with a box hooked to the top with a joint of somekind and kept upright using an up-vector joint. And then I could apply a torque to the ball to cause it to roll along, thus moving the character. I have tried the BallAndSocket joint and the Hinge joint but neither of these act like what I am describing. Does anyone have somthing like this workin? Am I making it harder than it needs to be? ___
| | /|\
| | | Up Vector
| | |
|___| --------------> Direction of Travel
/ \ \
| | | Torque
\___/ |
<--/

DarkCoder

14-05-2006 18:04:08

You can just use an Ellipsoid for your character instead.

Using a force & torgue callback on an Ellipsoid with an upvector should work fine.

It will turn left & right, & move around.
Thats the way i do it.

maxwave

17-05-2006 08:29:55

How to quit rotate my ellipsoid-character on degrees, when I want to yaw my character? How to use performance Torque?

jtpsoft

02-06-2006 00:56:13

OgreNewt::Joint* joint;
joint = new OgreNewt::BasicJoints::UpVector( m_World, body, Vector3(Vector3::UNIT_Y));

how can i get body instance from ragdoll??

or more clear question:
how is the best way to keep up the ragdoll??

CaseyB

03-06-2006 05:19:00

I STILL cannot get this to work! I have the character bounded by an ellipseoid, but he won't slide along the ground! If I start him in the air then I can move him while he's falling, but as soon as he hits the ground it's like he's stuck there! Do I need to reduce the friction or something?! :?

walaber

03-06-2006 08:05:18

yes. remove friction between the player body's material, and the world material (when moving).

also be sure to setAutoFreeze(0) so the body doesn't fall asleep.

jtpsoft

03-06-2006 23:51:30

Can we take a look to the famous biped class written above??

CaseyB

05-06-2006 07:17:22

Ok, I can't seem to disable friction. I do thisnewtWorld = new OgreNewt::World();
defaultMaterial = newtWorld->getDefaultMaterialID();
dogMaterial = new OgreNewt::MaterialID(newtWorld);
materialPair = new OgreNewt::MaterialPair(newtWorld, defaultMaterial, dogMaterial);
materialPair->setDefaultFriction(0, 0);

... // Ogre Stuff

OgreNewt::Collision* col = new OgreNewt::CollisionPrimitives::TreeCollision(newtWorld, node, true);
OgreNewt::Body* floor = new OgreNewt::Body(newtWorld, col);
floor->attachToNode(node);
floor->setPositionOrientation(Ogre::Vector3(0.0f, 0.0f, 0.0f), Ogre::Quaternion::IDENTITY);
floor->setMaterialGroupID(defaultMaterial);
floor->setUserData(this);

... // Ogre Stuff

col = new OgreNewt::CollisionPrimitives::Ellipsoid(newtWorld, Ogre::Vector3(0.1555f, 0.3485f, 0.4115),
Ogre::Quaternion::IDENTITY, Ogre::Vector3(0, 0.3485, -0.1625f));
dog = new OgreNewt::Body(newtWorld, col, 1);
dog->attachToNode(node);
Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid(10.0f, Ogre::Vector3(0.1555f, 0.3485f, 0.4115));
dog->setMassMatrix(10.0f, inertia);
dog->setCenterOfMass(Ogre::Vector3(0.0f, 0.433f, -0.322f));
dog->setPositionOrientation(Ogre::Vector3(0, 4, 0), Ogre::Quaternion::IDENTITY);
dog->setMaterialGroupID(dogMaterial);
dog->setUserData(this);
OgreNewt::Joint *joint = new OgreNewt::BasicJoints::UpVector(newtWorld, dog, Ogre::Vector3::UNIT_Y);
But there is still the same behavior where I can move it while it's falling, but sticks to the ground.

Also what does mBody->setUserData(this); do?

persoontje

05-06-2006 08:49:36



Also what does mBody->setUserData(this); do?


You can set your own data in the Body. In the callback then you can do:

void CPlayer::playerForceandTorqueCallback(OgreNewt::Body *me)
{

CPlayer* player = (CPlayer*)me->getUserData();


So *me is still a pointer to the body, but in the body is a pointer to your own data (in this example to a player object), and you can get the pointer back using me->getUserData(). You also need a cast because you get a void pointer back.

I don't know about rest. I have now also self problems with movement. :twisted: