Kinematic body motion -- how to make "smooth"?

Post Reply
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

I'm using 2.83.

Let's say I have a dynamic sphere on top of a kinematic triangle mesh. I want this triangle mesh to move smoothly every step as "velocity" so that the sphere moves along with it, smoothly, as if it were everything else moving and the mesh were stationary (think Newtonian relativity).

Currently, I'm trying to do this as follows:
  • I set mass to 0 and set CF_KINEMATIC_OBJECT when the mesh is created.
  • I keep track of what the mesh's velocity should be.
  • In a substep callback, I use getMotionState()->setWorldTransform() to set the new position after computing it from the velocity and time step.
This appears to move the mesh in discrete steps, such that the sphere's motion looks jittery; it's being impulsed several small times instead of a constant force being applied. How can I achieve the desired effect?
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: Kinematic body motion -- how to make "smooth"?

Post by Basroil »

You should really be setting the velocity rather than setting the position. It should move to the desired position, and also not mess with constraints solving.

EDIT: That should read "You should really be setting the velocity rather than just setting the position"

As stated below, you need the velocity for collision constraints to work optimally (especially if you're rolling a ball)
Last edited by Basroil on Mon Jun 29, 2015 7:37 am, edited 1 time in total.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic body motion -- how to make "smooth"?

Post by drleviathan »

The body's active/inactive state is influenced by its world-frame velocity, which never goes to zero when it is sitting on a moving kinematic object -- the DynamicsWorld will never allow the object to settle and it will always bounce and jitter a little bit.

You might be able to do what you want using a custom "action" (derived from btActionInterface) that watches for when an object is settling down relative to what it is sitting on (basically duplicating the normal activate/settle logic already in the DynamicsEngine) and then makes the object kinematic (where it is moved to follow its floor) when it settles in the local-frame. You'd also need to collect and handle collision events on the object so that when something else hits it it can be changed back to a dynamic object. Also, you'd want to compute the effective acceleration of the object's frame of reference such that if its floor moves in a way that would make it slide or fly off then the object would go dynamic. Hrm... it's starting to sound complicated.
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

Basroil wrote:You should really be setting the velocity rather than setting the position. It should move to the desired position, and also not mess with constraints solving.
... Setting the velocity doesn't appear to do anything on kinematic bodies.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic body motion -- how to make "smooth"?

Post by drleviathan »

Kinematic objects are supposed to be controlled by a custom class derived from btMotionState. The DynamicsWorld will call the MotionState's getWorldTransform() every frame, expecting the MotionState to provide the new transform (and maybe setting the object's correct velocity). Setting the velocity is not required for the object to move (that's done by setting its transform) but it is important for keeping the collision responses correct for dynamic objects that are bumped by the kinematic one.
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

Apologies for raising this thread from the grave, but I'm still having problems. Here's my current setup:
  • I have at least two rigid bodies in my world: one is a kinematic triangle mesh, and one is a dynamic sphere.
  • The first rigid body is associated with a custom C++ class called a BodyMovement, which defines how it moves. This class does not inherit from any Bullet class.
  • The BodyMovement stores information concerning the body's velocity and angular velocity.
  • I have a function called tickCallback, which I set as the world's internal tick callback.
  • In tickCallback, every BodyMovement sets the transform (through the motion state), velocity, and angular velocity of its kinematic body.
I still get choppy movement; if the sphere is rolling across the triangle mesh as it moves, every second or two there is a "skip" and the sphere bounces into the air inexplicably. Does anyone know what I'm doing wrong?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic body motion -- how to make "smooth"?

Post by drleviathan »

The popping you're seeing is probably the penetration resolution code kicking in every so many frames.

The first thing I wold wonder is: what is the collision margin of your kinematic object? You say it uses a "triangle mesh"? Which mesh shape exactly? btGImpactShape, btBvhTriangleMeshShape, or something else?

Looking at the Bullet code I see that btDynamicsWorld::m_internalTickCallback is called every substep. Your callback should take a timeStep argument and should use that to compute the new transform + velocities. If your function is updating its transforms using a different timeStep (e.g. the time since the last main loop or something) then that would be bad and could see how it might cause the popping.
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

The triangle mesh is a btBvhTriangleMeshShape. The time step used to compute the new transform is passed in from tickCallback and comes from Bullet's internal tick timer.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic body motion -- how to make "smooth"?

Post by drleviathan »

Bullet does not support btBvhTriangleMeshShape having velocity during collisions, which means you should only use it for static objects. The system does not prevent you from trying to use it for kinematic, but you'll tend to get more penetrations, tunneling and other glitches. Also, the btBvhTriangleMeshShape doesn't have much of a collision margin so it is pretty easy to get tunneling anyway, even when the object is static.

For better results take the time to compute a convex decomposition of your mesh and build a btCompoundShape of btConvexShapes. Alternatively I think the btGImpactShape can be used for kinematic, but I've never played with it.
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

Ahhh, okay. I knew that Bullet didn't support dynamic btBvhTriangleMeshShapes, but I didn't know that kinematic bodies also had issues. Can Bullet do convex decomposition itself, or do I have to bring in code from elsewhere for that?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic body motion -- how to make "smooth"?

Post by drleviathan »

Bullet comes with a library called VHACD which has utilities for computing the convex decomposition. That is, it comes with the Bullet install but it is its own separate library and you need to link it in separately. Running VHACD is not something you would want to do real-time. Depending on the parameters given to the algorithm and the mesh model submitted it can take anywhere from a fraction of a second to a few minutes to come up with an answer. Also, using the library takes a bit of knowledge/experience -- it has its own API that requires some study before you know how to use it effectively, and it sometimes fails for problematic models or bad parameters.

Alternatively I think Blender has a VHACD plugin or tool. You could load your mesh into that, generate the convex decomposition, and export to a separate model file. You would then load the original triangle mesh for your render object and the convex mesh for your collision shape.
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

Okay, I replaced the triangle mesh with a btCompoundShape of btConvexHullShapes. The "glitches" seem less drastic, but they definitely still happen, about once a second it seems, though it's erratic. Any other idea as to what's happening here?

EDIT: It looks like the glitches occur precisely when Bullet takes more than one step in a frame, i.e. when the game's overall FPS drops below Bullet's fixed time step. My tick callback code is reporting that the timestep is 1/60 s every time.
ktfh
Posts: 44
Joined: Thu Apr 14, 2016 3:44 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by ktfh »

Im not sure if this is the problem, but if you don't clear forces in your pre tick callback and have a variable frame rate the applied force can be doubled or more when frames are dropped.

Code: Select all

void preTickCallback(btDynamicsWorld *world, btScalar timeStep) {
world->clearForces();
world->applyGravity();

myRigidbody->applyForce(someforce);

myKinematicBody->setWorldTransform(newposition);
myKinematicBody->saveKinematicState(timestep);

}
whirligig231
Posts: 7
Joined: Wed Jun 24, 2015 11:55 pm

Re: Kinematic body motion -- how to make "smooth"?

Post by whirligig231 »

Well, I came up with a solution, though I'm still not sure exactly what the issue was. It turns out that everything runs okay if instead of calling stepSimulation with the appropriate timestep and let Bullet figure out how many steps to take, I keep track of the accumulating time myself and then call stepSimulation for one step the appropriate number of times. I'm not sure why this would make a difference, but for now, it looks like my issue is solved?
Post Reply