Page 1 of 1

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

Posted: Thu Jun 25, 2015 12:01 am
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?

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

Posted: Thu Jun 25, 2015 6:30 am
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)

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

Posted: Thu Jun 25, 2015 4:46 pm
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.

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

Posted: Fri Jun 26, 2015 11:19 pm
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.

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

Posted: Mon Jun 29, 2015 1:51 am
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.

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

Posted: Sun Apr 23, 2017 9:40 pm
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?

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

Posted: Mon Apr 24, 2017 11:34 pm
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.

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

Posted: Tue Apr 25, 2017 12:00 am
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.

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

Posted: Tue Apr 25, 2017 3:12 pm
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.

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

Posted: Tue Apr 25, 2017 3:19 pm
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?

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

Posted: Tue Apr 25, 2017 3:39 pm
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.

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

Posted: Tue Apr 25, 2017 5:05 pm
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.

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

Posted: Tue Apr 25, 2017 6:10 pm
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);

}

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

Posted: Tue Apr 25, 2017 6:40 pm
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?