Kinematic bodies

jchmack

12-09-2007 02:42:59

In my previous iteration of my engine i was able to move around the mesh(now triangle mesh) objects by manually updating their position myself each frame. But now if i do the same thing now i get a very reduced framerate and many error messages from NxOgre about not moving triangle meshes.

I am using these to create a lift to take my characters upwards. I believe that i was told to use a kinematic actor for my lift. I tried params.kinematic=true but it still acts like a static. Are Kinematics implemented yet?

Aiursrage2k

12-09-2007 03:55:28

Triangle meshes can not move, but convex meshes can.

From the documentation...
NOTE: The maximum number of polygons for a convex mesh is limited to 256.

Concave Meshes
The best way to build dynamic objects from concave meshes is to break the concave mesh into separate convex meshes, then build the actor from a union of these convex mesh shapes. You can build dynamic objects from concave meshes, but there are many unresolved issues with collisions involving dynamic actors built in this manner. It is highly recommended that you use only box, sphere, capsule, and convex mesh shapes to construct your dynamic objects. You can, however, still construct static objects from arbitrary triangle meshes.

betajaen

12-09-2007 09:06:42

You should use a kinematic actor for lifts (although you can actually model it with proper actors using a pulley system), unfortantly there is a bug in the NxActiveTransform which NxOgre now uses to render the actors (Ageia's bug, not mine).

So when you move the kinematic actor you'll need to call the render(0) afterwards.

Auirage2k is also correct with that too, try using a compound of convexes or primitives to make up your lift.

jchmack

12-09-2007 22:11:30

hmm i don't think we are thinking on the same page here. I believe you are thinking of a lift like a cable car with pulleys and such but i am thinking more of an elevator. All i really need is a moving floor that can carry the player to the next floor.

betajaen

13-09-2007 09:17:33

Nope. I'm thinking of an elevator too, we call them "lifts" in the UK.

jchmack

19-09-2007 18:44:03

OK i am trying to get this working again.

i get this error when i make my object:

NxOgre::Error::reportError#78

Trying to collide two pmapless, nonconvex,nonheightfield meshes: this is no longer supported.


here is how i create it:

if(Kinematic)
mBody = mScene->createBody(GraphicMaterial, new ConvexShape(GraphicMaterial), NxOgre::Pose(InitialPosition+KinematicOffset,InitialDirection), Params);
else
mBody = mScene->createBody(GraphicMaterial, new TriangleMeshShape(GraphicMaterial), NxOgre::Pose(InitialPosition+KinematicOffset,InitialDirection), Params);


Shouldn't this work since i am making my body with new ConvexShape for the collision detection?

jchmack

19-09-2007 19:00:04

OK i got that working. Now i have two problems:

1)How do i move this new kinematic/convex object.

i used to move it myself each frame like this:


if(KinematicOffset!= Vector3(0,0,0))
{
if(Age < KinematicOffsetTime)
{
float TimeLeft = KinematicOffsetTime - Age;
if(TimeLeft!=0)//for safety
{
Vector3 Speed = Vector3( KinematicOffset.x / TimeLeft,
KinematicOffset.y / TimeLeft,
KinematicOffset.z / TimeLeft);
mBody->setGlobalPosition(mBody->getGlobalPosition() + (-Speed * Time));
KinematicOffset+= -Speed * Time;
}
}
else
{
mBody->setGlobalPosition(mBody->getGlobalPosition() + -KinematicOffset);
KinematicOffset= Vector3(0,0,0);
}
}

Quaternion LocalDirection = mBody->getGlobalOrientation();

Vector3 Temp= mBody->getGlobalPosition() +
(Velocity * Time) +
((LocalDirection * LocalVelocity) * Time);

mBody->setGlobalPosition(Temp);


but i don't think that setGlobalPosition is moving it at all.

2) When i run into it with my character it collides properly but i get this error message:

NxOgre::Error::reporterror#78
PhysX Error < NXE_INVALID_PARAMETER > 'Actor::addForceAtLocalPos: Actor must be (non_kinematic) dynamic! in line 394 of NpActor.cpp

edit: i believe i am creating it and making it kinematic properly:
//if(Kinematic)
//Params.kinematic=true;

mBody = mScene->createBody(GraphicMaterial, new ConvexShape(GraphicMaterial), NxOgre::Pose(InitialPosition+KinematicOffset,InitialDirection), Params);
mBody->raiseBodyFlag(NX_BF_KINEMATIC);


im pretty sure that my convex is much less than 256 polys too.

ebol

19-09-2007 19:58:16

About 1) - actor->setGlobalPosition() on kinematic actors does work, I use it it my ragdools code, although I read somewhere, that there's a bug in PhysX and you have to call actor->render(0) after doing that. Anyway, it works for me.

jchmack

19-09-2007 20:14:41

ah thank you the render bugfix worked for me. I still get the error in number2 though.

betajaen

19-09-2007 21:15:20

@Ebol

I don't think it's a bug. I was reading the PhysX SDK Documentation more carefully and there are some moveGlobalPosition, moveGlobalOrientation and moveGlobalPose functions (wrapped in NxOgre - of course).Those are supposed to be used with Kinematic Actors, not setGlobalPosition.

The reason being it's more stable on the iterator and kinematic actors would not clip another non kinematic actor causing a jump or a jiggle or two.

I assume the NxActiveTransform code would render the scene during a moveGlobalXXX function, unlike a setGlobalPosition.

ebol

19-09-2007 22:43:01

Your probably right betajaen. I was aware of those moveGlobal* functions, I though we need pass a translation vector to them, not the desired position. But after you posted this I checked it with desired position and it works.

I took another read at PhysX docs - you were referring to this I suppose:


Do not use the setGlobal*() functions to make the actor mobile; it will disable many of the advantages that kinematic objects provide, such as having the appearance of infinite mass and the ability to push regular dynamic actors out of the way.


So its probably not a bug, its just how things are done.

@jchmack
If you haven't spotted this your self yet, here's an answer to your second question.

jchmack

20-09-2007 00:43:51

hmm i don't get any different results:

// mBody->setGlobalPosition(Temp);
// mBody->render(0);

mBody->moveGlobalPosition(Temp);

I still get the error message from NxOgre and my character will(still) fall through the lift unless he is walking around.

jchmack

20-09-2007 22:25:35


@jchmack
If you haven't spotted this your self yet, here's an answer to your second question.


lol i didn't see that the "here" was a url link for a while. I thought u were refering to mBody->moveGlobalPosition(Temp). But anyways I compiled the fix and i got the error message to go away. Thank you.

One last thing. The lift works just like i need it to when my character is constantly moving around, but if he is standing there he falls through it. I believe that NxOgre doesn't perform the collision check unless he is moving to save on CPU cycles. Is there a way i can get my character to be lifted by the lift, even if he isn't moving?

betajaen

20-09-2007 22:36:21

I'm pretty sure it NxOgre hasn't anything to do with that, unless I unknowingly added filtering for that.

Can you walk through kinematic actors?

jchmack

20-09-2007 23:26:17

I'm pretty sure it NxOgre hasn't anything to do with that, unless I unknowingly added filtering for that.

Can you walk through kinematic actors?


No. But a kinematic actor can walk through me =).

edit: i should rephrase that:

No. But a kinematic actor can walk through me (unless i am walking around).

betajaen

21-09-2007 09:48:06

Around as in:

- The Kinematic Actor can go through you if your Character isn't moving
- You can walk through the Kinematic Actor, because your moving and the kinematic Actor is not.

It just narrows it down to when the Kinematic Actor isn't moving then. I suppose the solution is then to all players entering the lift to move around like a lunatic in the lift until you've reached the desired floor. ;)

I'll have a look through after I've finished with the mesh stuff. But if you can attempt to trace the bug somehow, I'd really appreciate it. My first thoughts are the Characters <-> Character collision code (there isn't any real code there) but I'm thinking PhysX may confuse that Kinematic Actor with a Character somehow.

jchmack

22-09-2007 00:49:14

Around as in:

- The Kinematic Actor can go through you if your Character isn't moving
- You can walk through the Kinematic Actor, because your moving and the kinematic Actor is not.


Ok i get on the lift and it works fine as long as i am moving. Then once i stop moving i will fall through the floor of the lift (if it is moving). I tried creating a kinematic pillar to see if i had similar results. I can never walk through the pillar/lift. But if i am sitting still and it moves it can go through me.

Basically if i am moving the collisions are perfect. If i am not moving kinematics can go through me.

Aiursrage2k

22-09-2007 07:13:37

If I understand it correctly your character is on an "elevator lift", when the elevator moves along the vertical axis he will fall through.


If so there is a thread about it in the aegiadev forum:
http://devsupport.ageia.com/ics/forum/C ... ntent50795


a workaround here is to use NxUserControllerHitReport to get the velocity of the platform. Then pass this info to NxController::move(). However it will look a little delay. The first timestep the platform moves and trigger the report. The second timestep the controller could move with the info that got from report.

But it only works when the movement of platform is slight each timestep. otherwise the controller will lose the contact with the platform and fall through.



EDIT
I got it working

Create two actorgroups, character and elevator. Enable collision between these groups using the flag start and touch.

For the elevator inherit from Body, set it to kinematic.

Inherit the Character class
Create another nxactor
->Raise its actor flag NX_AF_DISABLE_RESPONSE
->every frame move it to the characters position.
->Set its group to character


In your callback of onTouch and onStartTouch check to see if its the actors are character and elevator.
If so do not apply gravity to your character in its movement function, instead add the relative motion of the elevator.

This is move code...

if(m_onElevator && m_impulseForce.y >0)
{
out = (moveVector*4.0) * t + NxOgre::toNxVec3(m_impulseForce);
//else{
// out = ((moveVector*4.0)+g)*t + NxOgre::toNxVec3(m_impulseForce);
//}
}else{
out = (moveVector*4.0 + g) * t + NxOgre::toNxVec3(m_impulseForce);
}

OgreMage

27-04-2008 19:48:29

is the bug in PhysX and you have to call actor->render(0) fixed in the latest versions? (i.e. 2.8.x)