Kinematic RigidBodyControl slower than it's Node

Hello,

I have 3 physical objects in my scene:

  • A player character (the blue “blobby”) which i made kinematic. It has a collision shape made of one sphere on top of another.
  • A white ball which i copied from the Hello Physics tutorial.
  • A floor (2DPlane)

The the (kinematic) player character .move()s in direction of the mouse (red sphere, aligned to the floor). So the vector from the player character towards the mouse (multiplied by sth.) is the actual movement of the player character (mouse far = more speed).

Now the issue I have:

When the player doesnt move, everything is great:

But when the player moves, the collision shape moves a bit slower and doesn’t catch up until the player gets slower or stops. When I use the player character to accelerate the ball the same issue appears on the ball.

Is this the tribute for using kinematic RigidBodyControls? What could I else use? With the CharacterControl my character rolls over the field and BetterCharacterControl isn’t applicable because theres no way to use my own collision shape.

Or am I doing something wrong? Here is the code (stripped away mouse movement, camera and materials):

[java]
public void simpleInitApp() {
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
bulletAppState.setDebugEnabled(true);
bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0, 0, -9.81f));

    short width = 30;
    short height = 50;
    
    // Floor Creation
    Quad q = new Quad(height, width);
    Geometry geom = new Geometry("Field", q);
    geom.setMaterial(grassMat);
    geom.move(-height/2f, -width/2f, 0);
    
    PlaneCollisionShape floorCS = new PlaneCollisionShape(new Plane(Vector3f.UNIT_Z, 0f));
    geom.addControl(new RigidBodyControl(floorCS, 0f));
    bulletAppState.getPhysicsSpace().add(geom);
    rootNode.attachChild(geom);
    
    
    // Football Creation
    Geometry ball_geo = new Geometry("Football", new Sphere(16, 16, 0.3f));
    ball_geo.setMaterial(ballMat);
    rootNode.attachChild(ball_geo);
    ball_geo.setLocalTranslation(cam.getLocation());
    RigidBodyControl ball_phy = new RigidBodyControl(1f);
    ball_geo.addControl(ball_phy);
    bulletAppState.getPhysicsSpace().add(ball_phy);
    ball_phy.setLinearVelocity(cam.getDirection().mult(25));
    
    Node playerNode = new Node("Player");
    playerNode.addControl(new BlobbyMoveControl());
    CompoundCollisionShape playerCS = new CompoundCollisionShape();
    playerCS.addChildShape(new SphereCollisionShape(0.49f), new Vector3f(0, 0, 0.491f));
    playerCS.addChildShape(new SphereCollisionShape(0.356f), new Vector3f(0, 0, 1.18195f));
    playerNode.addControl(new RigidBodyControl(playerCS, 5f));
    playerNode.getControl(RigidBodyControl.class).setKinematic(true);
    rootNode.attachChild(playerNode);
    bulletAppState.getPhysicsSpace().add(playerNode);
    
    Spatial playerGeo = assetManager.loadModel("Models/blobby.j3o");
    playerGeo.setName("PlayerGeometry");
    playerGeo.setMaterial(playerMat);
    playerGeo.rotate(FastMath.HALF_PI, 0, FastMath.PI);
    playerGeo.move(0, 1, 0);
    playerNode.attachChild(playerGeo);

    // Mouse
    Sphere b = new Sphere(16, 16, 0.25f);
    Geometry g = new Geometry("MouseBox", b);
    g.setMaterial(mouseMat);
    playerNode.attachChild(g);
}

// the BlobbyMoveControl:
public class BlobbyMoveControl extends AbstractControl {
@Override
protected void controlUpdate(float tpf) {
Vector3f movement = ((Node)spatial).getChild(“MouseBox”).getLocalTranslation().mult(1.2f*tpf);
spatial.move(movement);
}
//…
[/java]

My guess would that this is because the physics space runs at a steady 60fps, but your app is probably running much faster. The physics space is always going to be playing catch up if your render update rate is faster.

I never really understood how to continuously move kinematic objects because of this issue. Seems to me they should be only moved from the physics space, not the render space. But the JME docs say otherwise.

Its actual the other way around! The screenshots were taken at 59/60 FPS (Vsync on) but when I switch Vsync off (and the framerate goes up) the gap between RigidBody and Geometry gets smaller although it still exists.

Weird… Well anyway I still think the difference between the physics and render space’s update rate is still the root cause.

I personally don’t use kinematic=true for anything that is going to move a lot. I use a regular rigid body and damp the forces I don’t want.

For characters that probably means all angular forces.

In your case I might just make a new class that inherits BetterCharacterControl and overrides the getShape() method with your own custom shape.

Thanks a lot! Could you explain the whole “damp forces I don’t want”-process? How do you do that?

Overriding getShape() in BetterCharacterControl sounds like a good idea, I will read the code of it. If this wont help me maybe I just use a GhostControl and do it all by myself cause I want to be able to “kick” the ball either way…

@jejay said: Thanks a lot! Could you explain the whole "damp forces I don't want"-process? How do you do that?

.setAngularFactor(0) on the physics control.

edit

A little more explanation. This makes it so that any physical interactions the RidgidBody has will not cause a change in angular momentum i.e. tip over. This simulates an object that can keep it’s balance… like a person…

There is a list of other options in the docs: here

1 Like

I responded to this once and it seems it got lost…

Shorter version: this sounds like a classic frame-update-delay issue. I don’t know how far off the visualization is but it sounds like it’s at least a frame or two behind.

Is it only the visualization that looks wrongs or does the physics act wrong too?

I could easily see something like this happening:
-control updates spatial
-rigid body control updates physics object (in same frame)
-physics sees it in its next frame
-debug shape sees it in the following visualization frame

I’m not really familiar enough with bullet or how you’ve set it up to know anything more specific… but if it’s just a visualization lag issue then switching how you move the body may not fix the “issue”.

I think its not (only) a (debug) visualization issue, look at this screenshots:
(fast ball pushing:)

(slow ball pushing:)

Edit:
I just moved the colision shape the distance the player moves at highspeed in one frame (at 60 FPS) to the left and then I ran in the same direction… and voilà: Its exactly compensating it. So it’s really exactly one frame late, but according to the screens above its the whole physics and not just the debug visualization :-?

Physics update happens in render, then in update its applied. Depending on where you look from (before or after the control update) its always a frame late of course.

So whats your advice I should do when I dont want the ball to dip into my character at high velocity? :-? And I dont understand… You say physics in general? So not a single sulution of the mentioned ones will help me?

@jejay said: So whats your advice I should do when I dont want the ball to dip into my character at high velocity? :-? And I dont understand... You say physics in general? So not a single sulution of the mentioned ones will help me?

Actually, if I read normen’s reply right, the issue shouldn’t be caused be the physics stuff. I think he was discounting that not really agreeing with the possibility.

render happens after all updates are performed so Physics would get the latest data from that frame. The next frame would see the new data.

Hmmm… actually, thinking about it… because you move the spatial directly, that’s the issue. If you somehow moved the rigidbody control instead then you won’t have this issue. By moving the spatial directly, you make it out of sync with the physical state of the objects. Do you see what I mean?

This looks the same problem as in my thread from 2,5 years ago. :smiley:
http://hub.jmonkeyengine.org/forum/topic/kinematic-problems/

EDIT: Although no solution was found at that time. Would be definitely good to try @pspeed’s approach with moving the control. But in my opinion this should be done automatically … It is obviously a bug in the engine; or missing documentation to not do it in this way. :slight_smile:

Just don’t mix spatial locations and physics locations, use the same all the way. Either get your locations from the spatials or the physics objects.

@normen: Uhhm? Where exactly am I mixing spatial locations and physics locations? In my example I’m not using physics locations at all?
Edit: If you mean that I shouldn’t use spatial locations when I attached my spatial to a physic space (which makes totally sense at least for non kinematic RigidBodies) then why is https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:physics advising to use .setLocalTranslation() on (the spatials of) kinematic RigidBodyControls?

I’ve tried two approaches from this thread:

[movement is the movement vector calculated from the mouse position relative to center of mouse axes. It (possibly) changes every frame.]

Approach One (@pspeed’s):
.setKinematicSpatial(false) in simpleInitApp() (the control remains kinematic, it just lets me translate the control instead of the spatial) and move the control (not the spatial) with .setPhysicsLocation(.getPhysicsLocation().add(movement)) every update. First of all in debug mode the result is looking the same. But when you look at the geometries you can see that no more dipping occurs. Now its just a debug visualization issue. But I’m afraid the physics don’t run as smoth as before. The ball flickers often and even gets faster than the player who pushed it. It feels like the ball is exploding a tiny bit out of the incorrect state I’ve set every frame.

Approach Two (@aaronperkins’):
.setKinematic(false) on the RigidControl of the character (so its no more kinematic), also .setAngularFactor(0) for it (damps force driven rotation), and every update I reset .setLinearVelocity(movement). The debug visualization gap is still there, but now it looks like it is a bit smaller than before :-? Nevermind, this is working like it should. No dipping, no flickering, balls speed max at player speed.

So thank you all guys! Pardon me that I’m not as lucky as I hoped to be, the epiphany is stil missing :S It just seems that kinematic RidigBodyControls arent good for what they’re promised. To quote the Hello Physics tutorial: “you can use a kinematic node like a billard queue”. I think this would result in either impaling the balls before hitting them or making the balls flicker.

@jejay: Can you explain please again what is the proper solution?
I still think that it should be fixed in the engine though … :slight_smile:

The solution seems to be don’t use kinematic objects for anything that moves regularly. Searching the regular bullet forums, there are lots of people reporting the same problem. So it’s not just a JME or jbullet issue.

If you think logically about it… Being able to warp objects around in a physical simulation just seems like a bad idea. Kinematic or not, it’s bound to cause inconsistent states.

@InShadow: I rewrote the approaches a bit (hope it helps), but its just the solution to my case. You just have to find a constellation of forces, velocities (etc.) on a non kinematic RigidBody that helps you out.

@aaronperkins: Yep it makes sense, thank you a lot!

@InShadow said: @jejay: Can you explain please again what is the proper solution? I still think that it should be fixed in the engine though ... :)

I’m not even sure how it could be fixed. If I’m following right, what happens is:
-physics engine moves the objects around
-update pass will make the Spatials be the same location as the objects
-your code subverts this and moves them somewhere else and now they don’t look like they are in the right place.

Something has to be authoritative. The same thing would happen, for example, if you were getting locations from a game server and then decided to move one spatial to a different place anyway. It seems unfair to then wonder why the spatial doesn’t match everything else… since it was specifically moved to not match anymore.

@aaronperkins said: The solution seems to be don't use kinematic objects for anything that moves regularly. Searching the regular bullet forums, there are lots of people reporting the same problem. So it's not just a JME or jbullet issue.

If you think logically about it… Being able to warp objects around in a physical simulation just seems like a bad idea. Kinematic or not, it’s bound to cause inconsistent states.

Ok, but what can then be used for objects that move regularly and should affect other physics objects? It seems like a pretty harsh limitation … :slight_smile:

@InShadow said: Ok, but what can then be used for objects that move regularly and should affect other physics objects? It seems like a pretty harsh limitation ... :)

Use a regular non kinematic RidgidBodyControl. Use setAngularFactor(0) to stop it from “tipping over”. Use setLinearVelocity() and setAngularVelocity() to control its direction of movement.

You give up being able to absolutely position and rotate the object … but that’s really the sacrifice you make when using a physics engine anyway.