[SOLVED] Ghost collision detected incorrectly (over-sensitive)

Hi,

I have some objects with GhostControl added. I found the collisions are reported even when two ghosts are not collided (though they’re close to each other). Screenshot:

I carefully put more debugging in collision detection to make sure those ghosts indeed belong to the objects I focused. In above screenshot, I’m pretty sure the collision happens between the attachment and the black display.

I tried CollisionShape.setDefaultMargin(0f) but it seems not work. It makes sense as the yellow debugging wire is not changed.

Any idea? Thanks!

UPDATE: Issue is solved by replacing jBullet with Minie and calling physicsSpace.contactTest() to actively detect ghost collision.

1 Like

GhostControl uses axis-aligned bounding boxes (AABBs). If your boxes are not axis-aligned, then the AABBs could be much larger than the boxes themselves.

If you’re using Minie with BulletAppState, there’s a debug visualization option to render the AABBs. That should clarify what’s going on:

        bulletAppState.setDebugEnabled(true);
        bulletAppState.setDebugBoundingBoxFilter(new FilterAll(true));

Thanks for the information…I believe my ghost boxes are axis-aligned but will double check.

I’m using default jBullet engine so there’s no way to enable bounding box filter. Before I switch to Minie, a simple question: does Minie work generally better than the default jBullet?

The answer might start with ‘it depends…’, but from the homepage I can see Minie has more complex physics simulation that I might not need for now. However I do expect a better physics engine for basic shape collision as I found the default jBullet has many weird behaviors, for example I set a velocity (not very high, 1 or 2 length/sec) to a dynamic object, it can easily pass a kinematic object which has a fair thickness unless I set the kinematic object to static.

I’m new to jBullet (and JME!) engine so there’s a great chance the weird thing is caused by wrong setup or poor choice. Learning is satisfying but less pain is always welcome. :smiley:

1 Like

Yes!

I set a velocity (not very high, 1 or 2 length/sec) to a dynamic object, it can easily pass a kinematic object which has a fair thickness unless I set the kinematic object to static.

That’s what continuous collision detection is for. Both Minie and jme3-jbullet have this feature.

@sgold switched to Minie now! I can observe some improvement but the original issue still persists. AABBs debugging shows they’re axis-aligned.

For the CCD issue, there’s no improvement even I set the params. After some tests, I think it may be related with my arbitrary rigid control on the player:

  1. I have a rigid cylinder and a mass for the player, so it’s dynamic;
  2. I use setLinearVelocity to control player movement;
  3. I force the player rotation to (HALF_PI, 0f, 0f) to keep cylinder vertical in update loop.

The problem seems in 3. If I don’t force the rotation. The player cylinder will start rolling once velocity is applied and it hit something. In this case, the cylinder won’t pass any static body, like wall. However, if I force the rotation, the cylinder will pass the static body easily with a little tilt. The overall feeling is the cylinder is struggling in keep vertical and will slowly merged into wall if the velocity to the wall persists.

Any idea how I may improve this?

1 Like

I found a good solution on the CCD issue. By setting angular factor to zero, the player rigid body never rotates or rolls and have perfect collision with walls:

rbc.setAngularFactor(Vector3f.ZERO);

1 Like

@sgold I have a few questions after switching to Minie but first thank you for your advice as I found Minie works much better than the default jBullet!

  1. The jBullet doc says no objects should be overlapped, even for static object. What I found is that I can override update() to always copy world translation/rotation to physical ones to make them stable. But in Minie, it looks stable automatically as long as I set setKinematic() and setKinematicSpatial() to true. I took a look into the source code, it seems the RigidBodyControl does what I did in default whenever above flags are set in both engines. The improvement in Minie is some additional case check.
    a) So is it ok to overlap static objects in initialization in Minie?
    b) What’s setKinematicSpatial() for? I can only find doc talking about setKinematic();
    c) The jBullet doc states we need to set a non-zero mass for kinematic objects. However, in the above case, I don’t have mass set but everything looks good. So is the statement not true, at least partially, in Minie that kinematic object must have a non-zero mass?

  2. In the jBullet doc, it says setApplyLocal(true) can be used in situations like physics inside a running train or spacecraft (hey, that’s the game I’m working on!) by adding another physics space onto the running node. However I can’t find example code on how to do this. Could you mind show me some? Minie is preferred if there’s some difference between jBullet and Minie here.

  3. I’m using PhysicsTickListener to read any ghost collision on the object player is trying to place. That’s what the doc say it’s the correct way to have a reliable result from ghost.getOverlappingObjects(). Generally it works fine (except the original issue in this post which I still have no clue) but I can observe some delays in getOverlappingObjects(). Same delays in Minie so is there a better way in Minie for this? For example, is it possible to call get all collisions from a ghost on-demand? The reason is that my game only needs to detect GhostControl collision when player is trying to place the object. In-game collision and contact are all left to RigidBodyControl.

Sorry for throwing tons of question without more code details. Although I’m still in early prototype stage, the code is already well-structured in OOP style so I decide to describe the issue instead of pasting a long long list of code, which is daunting to anyone except the author.

1 Like

1b:

JavaDoc:
Enable or disable kinematic mode for this Control. If both the rigid body and controlled spatial are kinematic, the spatial's location and rotation will be applied to the body during each update. Kinematic mode has noeffect when the body isn't kinematic.

RigidBodyControl.java:
    /**
     * true→ kinematic body follows Spatial, false→Spatial follows
     * kinematic body
     */
    private boolean kinematicSpatial = true;

    public void setKinematicSpatial(boolean kinematicSpatial) {
        this.kinematicSpatial = kinematicSpatial;
    }

1c: A kinematic object “sends” impulses on collision. The impulse force is calculated from the masses (physically: power = mass * speed). So are you sure, it is not static? See RigidBodyControl#isStatic().

3: To test on demand, you can call contactTest(PhysicsCollisionObject, PhysicsCollisionListener) on PhysicsSpace. But it make sense to do this, after the Physics update is done.
PS: If you mean by “delays”, the TickListener is called delayed: The Physics engine runs with only 60 FPS. When the application runs with more than 60 FPS, steps between becomes interpolated.

@Nakano, thanks for the help.

If you mean by “delays”, the TickListener is called delayed: The Physics engine runs with only 60 FPS. When the application runs with more than 60 FPS, steps between becomes interpolated.

Nope. I drew a picture here:

Note in my game, both boxes (the black displays in the picture) are static. I use setLocalTranslation() directly to move them. The collision is detected by the GhostControl added to both of them.

@Nakano good news, after switching to contactTest(obj, listener), the collision detection works fine. Thank you very much!

A minor question: if I set thread mode to PARALLEL, will the listener be called in another thread? I tried to do the test myself but application crashed with error that executor is null. I didn’t look into details but it seems I need to set a thread pool to enable parallel mode. I can only confirm in SINGLE mode, listener is indeed called in the caller thread.

Never used parallel physics, just tested it. In my case becomes the Listener called from the jME3 Main Thread (which also calls contactTest).

The BulletAppstate creates the Thread executor in startPhysics, when the type is parallel:

app.getStateManager().getState(BulletAppState.class).setThreadingType(ThreadingType.PARALLEL);
app.getStateManager().getState(BulletAppState.class).stopPhysics();
app.getStateManager().getState(BulletAppState.class).startPhysics();

Or set Threading type before adding to the AppStateManager, since startPhysics become called in initialize.


Are you sure, your boxes are static? Because static objects should only placable if you use the setPhysics…-Method on RigidBodyControl, else location and rotation become overwritten. See this table:

Or do you mean by “static”, they have no RigidBodyControl?

1 Like

That depends what you mean by “ok”.

  • It shouldn’t cause a crash or violent motion.
  • In debug versions of Minie, it should generate a warning message.
  • It might be somewhat inefficient.

What’s setKinematicSpatial() for? I can only find doc talking about setKinematic();

Although the JME physics tutorials will help you understand Minie, I recommend following the Minie tutorials instead.

Your question is answered in the Minie tutorial on RigidBodyControl: An introduction to RigidBodyControl :: The Minie project

So is the statement not true, at least partially, in Minie that kinematic object must have a non-zero mass?

Indeed. Prior to version 7.6, Minie required kinematic rigid bodies to have positive mass. Since v7.6, zero mass is also allowed.

it says setApplyLocal(true) can be used in situations like physics inside a running train or spacecraft (hey, that’s the game I’m working on!) by adding another physics space onto the running node. However I can’t find example code on how to do this. Could you mind show me some? Minie is preferred if there’s some difference between jBullet and Minie here.

First off, you don’t need multiple physics spaces to simulate the interior of a train or spacecraft.

The original intent of local physics (as I understand it) was that you would have a specific Node in your scene graph that represents an inertial reference frame. You attach rigid-body controls to that Node and set their local-physics flags. Everything else in the scene (including the interior geometries, the world coordinate system, and the camera) is moving with the vehicle; their coordinates aren’t affected by vehicle motion. To produce the illusion of motion, the coordinates of the inertial node change in the direction opposite the vehicle’s motion.

I’ll admit I’ve never actually seen it used this way. I’ve seen example apps that use local physics, but none of them includes a train or spacecraft. The HelloLocalPhysics tutorial app has a reference-frame node that moves in a circle.

There are obvious challenges involved in simulating physics on a moving vehicle. One is that if the reference frame and the camera get too far apart, you lose precision in one or both coordinate systems. Minie comes with a double-precision build you can use, but that’s not a complete solution. For one thing, you’d need a double-precision version of RigidBodyControl.

  1. I’m using PhysicsTickListener to read any ghost collision on the object player is trying to place. That’s what the doc say it’s the correct way to have a reliable result from ghost.getOverlappingObjects(). Generally it works fine (except the original issue in this post which I still have no clue) but I can observe some delays in getOverlappingObjects(). Same delays in Minie so is there a better way in Minie for this? For example, is it possible to call get all collisions from a ghost on-demand? The reason is that my game only needs to detect GhostControl collision when player is trying to place the object. In-game collision and contact are all left to RigidBodyControl.

I’m unsure what’s causing the delays you’re seeing with getOverlappingObjects(). The method never blocks, so it ought to return promptly unless the list is huge.

If you tell me in detail what you’re trying to do, perhaps I could suggest alternative ways to do it.

2 Likes

In my project I figure that a single precision float has 6 highly accurate digits which, under the assumption that 1 unit = 1 meter, gives a high-precision zone of +/- 999.999 if millimeter accuracy is desired. I’ve not had a chance to stress test this idea in practice, especially with the physics engine. Does this sound like it’s consistent with what you’re describing above? I.e, within these coordinate ranges would you expect to see much loss of accuracy in the physics simulation?

1 Like

Are you sure, your boxes are static? Because static objects should only placable if you use the setPhysics

Yes, they’re static. I think the reason it works is I set kinematic and kinematicSpatial to true. If you look into the source code in RigidBodyControl, you may notice when both flags are true, it copies world (or local depends on whether applyPhysicsLocal is set) translation and rotation to physics ones. The behavior exists both in jBullet and Minie while the later has more checking logic.

1 Like
  • It might be somewhat inefficient.

That’s a thing I will do some experiment later.

Since v7.6, zero mass is also allowed.

Thanks for the confirmation! Anything I need to take extra care? As the doc states kinematic object needs mass to calculate contact force to dynamic objects so how this calculation can be done without mass? In my test, things just look ok. A dynamic object hit it and bounce back with a minor velocity loose (hasn’t get a chance to look carefully though).

I’ll admit I’ve never actually seen it used this way.

I will continue my experiment on this. In my game, it’s ok if I cannot make the moving vehicle interior works perfectly as the most part of game focus on the interior so I can simply do some manual simulation to the outside object, like a passing meteoroid.

If you tell me in detail what you’re trying to do, perhaps I could suggest alternative ways to do it.

In my game, player can attach an object, for example a display or a bed, onto the interior wall of the spacecraft. In this process, I need to keep checking if the object overlaps with another object which is already on the wall. I’m using GhostControl to do the job. I mentioned TickListener before as doc states the result from getOverlappingObjects() is reliable only when the method is called in physics loop. After I switch to Minie, I found the collision detection delay still exist in the PhysicsCollisionListener so it’s probably has nothing to do with TickListener.

Anyway, as @Nakano pointed out, I can use physicsSpace.contactTest() to do on-demand collision check. It works fine now. The contactTest() always return a reliable result without any delay.

In my project I figure that a single precision float has 6 highly accurate digits which, under the assumption that 1 unit = 1 meter, gives a high-precision zone of +/- 999.999 if millimeter accuracy is desired. I’ve not had a chance to stress test this idea in practice, especially with the physics engine. Does this sound like it’s consistent with what you’re describing above? I.e, within these coordinate ranges would you expect to see much loss of accuracy in the physics simulation?

I expect single-precision physics to work well for objects 8 cm in diameter in world that’s 2 km in diameter.

The bad news is that a train going 72 km/hr could cross that world in 100 seconds.

1 Like

Yes, they’re static. I think the reason it works is I set kinematic and kinematicSpatial to true.

If you create a rigid body with mass = 0, it’s static. But after you setKinematic(true), it’s no longer a static rigid body. It’s a kinematic one.

Where 32 bit floating point will really get you is in the time-step math… especially for smaller speeds. There ends up being a large number versus small number disparity at some point that makes movement feel weird (at best)… up high enough and you won’t be able to move at all.

But:
v = v + a * t
p = p + v * t

can accumulate errors very fast considering t usually already small.

sgold is right that +/- 2000 is probably pretty safe from issues. I don’t think the size of the object matters for the math I’m talking about (though note that mass to mass comes into play as well for collisions)

I think when I used to do physics in 32 bit, I would start to have noticeable feel issues at ~6,500 and really really weird movement at 65,000 or so.

2 Likes

If you create a rigid body with mass = 0, it’s static. But after you setKinematic(true) , it’s no longer a static rigid body. It’s a kinematic one.

Got it. Thanks!

1 Like

In Bullet, mass = 0 is always treated as a special case, used to encode infinite mass.

I don’t know why Bullet was written that way. Perhaps the creator(s) didn’t realize that IEEE floating point has its own way of encoding infinity? Just a guess…

The contactTest() always return a reliable result without any delay.

I’m glad you found a reliable solution. Personally, I love contactTest() because it uses real collision shapes instead axis-aligned boxes.

It occurs to me maybe the delay you saw was because GhostControl overlaps get updated only during a simulation step, whereas contactTest() gives immediate results.

1 Like