[SOLVED] Static RigidBodyControl is wrongly offsetting location of Spatial

I have a wooden pew model that I am trying to place in rows going down the aisle of a church, but it appears as though the location of the pews are being offset and are causing them to stick out into the aisle and overlap with a table with candles on it.

The issue only seems to occur when it has a RigidBodyControl.

Here is an image showing 2 screenshots:

The top screenshot shows the pews located in the incorrect location whenever they have a RigidBodyControl.
And the lower screenshot shows the correct location that they are at in my scene composer where there is no physics (and in-game after I removed the code that assigns a RigidBodyControl with mass of 0)

Also here is the code I use to generate the rigidBodyControl for this pew. I don’t think I’m doing anything incorrect here but this is my code just in case:

    mass = 0; //hardcode mass to 0 to ensure pews are static physics object for this test
    RigidBodyControl rbc = new RigidBodyControl(mass);
    item.addControl(rbc);

    app.enqueue(() ->{
        if(!bulletAppState.getPhysicsSpace().contains(rbc)){
            bulletAppState.getPhysicsSpace().add(rbc);
        }
    });

And I am also using the latest version (I think) of Minie 7.5.0.

Any ideas what could be causing this? I can also share the model that is having trouble if necessary.
Thanks :slightly_smiling_face:

2 Likes

I suspect the 3-D model has a different origin from the collision shape. One way to verify my suspicion would be to enable debug visualization using bulletAppState.setDebugEnabled(true) .

1 Like

Here’s a screenshot with the debug enabled.

https://i.imgur.com/SLuOZTX.png

It looks like the model is matching the physics shape represented by the debug wireframe.

What is also strange is that I made another sharp-edged variation of this pew model (which can be seen on the left side of the previous screenshot) and I modeled both of them in similar ways at the same time in a single blender project, and all 6 pews are also attached to the same parent node in my editor. Yet the issue only happens to the rounded pews on the right.

1 Like

If you provide me with a simple test case I can execute locally, I will figure out what’s going on.

2 Likes

I’ve tried reproducing the issue but am having some trouble.

I cannot reproduce the issue if I link a new pew model into a scene, but I can reproduce it if I copy/paste one of the 3 original corrupted pews from my screenshots. So I think I will need to strip down the scene that is having the problem so it contains only those 3 linked pews, and then upload that and hopefully it will still display the issue…

However, I am also wondering if this might not be a bug in Minie, but if it is instead a silent bug that occurred when I originally linked these objects into this scene with my custom scene editor app that corrupted those specific copies of my model?

I had a similarly strange but different issue about a month ago where I placed 6 of the same statue model all at the same time in my scene composer, and then when I loaded the scene again, the collision shape did not match the visual of my models when doing Ray collisions, it was as if the ray collisions were ignoring the 5x scale that I applied while the model was still being displayed at that 5x scale, resulting in broken ray collisions. Eventually I deleted those statues and tried placing new copies of the same models and the issue never occurred again.

I also had another time where I added one of these pew models to the same node and they were rendering as if they had a non-identity rotation, despite the scene-composer showing that they indeed had an identity rotation. And then when i ran my custom editor again I couldn’t reproduce it and the same exact model started working with the correct rotation.

All 3 of these non-reproducible bugs have happened to me in the past few months after I upgraded my custom scene edtior from Ant to Gradle and bumped my scene editor app from using JME 3.3 to the latest 3.6 version.

After upgrading that project to gradle with the latest SDK version, I also started getting some random error message when I run my custom scene editor, but it doesn’t always happen and it doesn’t cause a crash, and the error message contains illegible characters so I have no clue what it even means. (I wonder if all of these seemingly random bugs may have occurred when my scene-editor experienced this strange start-up exception without me realizing it…)

So ignoring that error was probably not a good idea, but it happens so rare and doesn’t cause a crash, and even now I can’t reproduce it despite repeatedly running/closing my scene editor for the past 10 minutes. I will keep trying and post the error as soon as I see it occur again though.

2 Likes

I’ve tried reproducing the issue but am having some trouble.

Thanks for attempting to narrow down the issue.

I am also wondering if this might not be a bug in Minie, but if it is instead a silent bug that occurred when I originally linked these objects into this scene with my custom scene editor app that corrupted those specific copies of my model?

I can’t rule out that possibility, of course.

However, over the past few years I’ve discovered and fixed quite a few serialization/cloning bugs in Minie. Assuming your scene editor relies on those features, I worry one of those bugs might’ve bitten you.

The Maud editor was a major motivation behind the creation of Minie. For this reason, I strive to maintain compatibility of serialized physics objects (i.e. J3Os) between Minie releases. It’s a struggle, however.

It shouldn’t be necessary to re-generate physics objects for each Minie release. Doing so, however, is probably the safest course.

1 Like

Sorry for the delay following up on this, it’s been a hectic week for me.

I currently do not generate the physics object in my scene editor (although that is eventually the plan in the future) so I don’t think this could be affecting me now, but this is useful to know going forward when I do reach that point. Right now, I just flag my models in my scene composer with a “physics” user data key where the value is used as the mass. Then I check every model’s userData when the game runs and re-create the rigidBodyControls at run-time for any models that are flagged accordingly.


I also haven’t managed to get my scene editor to launch with the weird illegable error since I mentioned it in my last post… of course now that I’m trying to troubleshoot it it is no longer happening and is making me double guess my sanity :upside_down_face:

Nonetheless I did manage to isolate the part of my scene that is having the problem so you can test the corrupted pew model with physics to see if you find anything strange.

I deleted everything from the problematic scene except for the corrupted pew models and the church model that they are located in. There is also a non-corrupted version of the pew that I have since added when I was unable to reproduce the issue, so you’ll notice the first 3 or 4 move when they have an RBC but the last pew doesn’t have the issue and always renders in the correct place.

You also might have to look some distance away from the origin to find the church, since it is offset almost 300 units from the center of the scene-tile that its located in (I did not want to move or change anything related to the issue to ensure it doesn’t magically disappear…)

Here’s a link to a simplified version of my assets folder that contains the pew model, the church model, and a mostly empty scene that they are linked into. (I also had to link my entire matdefs folder because all of my models that use custom forks of the pbr shader, so let me know if you have any trouble loading the models and I will fix it asap)

https://drive.google.com/drive/folders/1gVM91gYUemyCtQeARYF9BPkaj1IHX4IN?usp=share_link

I haven’t had a chance to make it into a formal test case, but here is the important code for loading the scene from the minimalized assets folder I uploaded, as well as the code I use to check which model needs an RBC:


Node sceneNode = assetManager.loadModel("Scenes/SilverShoreGorge/cliffRight.j3o");

//traverse through all children of sceneNode to check for the "physics" user data key to determine which models need an RBC:

if(childSpatial.getUserData("physics") != null){
     RigidBodyControl rbc = new RigidBodyControl(0);
     childSpatial.addControl(rbc);
     bulletAppState.getPhysicsSpace().add(rbc);
}

If putting all of that together is too much trouble I can try to pack it all into a more organized test case with a full class when I get a chance again. Thanks for your help so far :slightly_smiling_face:

1 Like

I wrote a quick app to load the model, and it failed due to missing assets:

  • Textures/slime1_metallicRoughness.jpg
  • Textures/AfflictionAlphaMaps/Silver_Shore_Gorge_AfflictionAlphaMaps/cliffRight_AfflictionAlphaMap.png
  • Textures/slime3.jpg
  • Textures/slime1_matchingNRML.png
  • Textures/TextureArrays/Silver_Shore_Gorge_Default_MetallicRoughnessAoEi_TextureArray
  • Textures/TextureArrays/Silver_Shore_Gorge_Default_Albedo_TextureArray
  • Textures/TextureArrays/Silver_Shore_Gorge_Default_NormalParallax_TextureArray
  • Textures/terrain-alpha/shoreRight-terrain_cliffRight-alphablend0.png
    … plus more textures
  • Models/Architecture_NecroRuins/skullTable/tableOfTemptation.j3o
  • Models/Decor_Church/candles/pieces/Mounted_CandleStick0_Tall.j3o
  • Models/Decor_Church/candles/pieces/Tiny_Candle.001.j3o
  • Models/Decor_Church/candles/pieces/Plated_Candle_Dish_Empty.j3o
    … and so on.
1 Like

Oops, I messed up and uploaded the wrong copy of the scene. I made a backup before deleting everything but the church and pew, and it appears I uploaded the backup by mistake.

I replaced the original assets zip with a new zip that has right copy of “cliffRight.j3o” and also uploaded an unzipped copy of that scene in case its easier for you to drop that in and not have to download the rest of the assets again. (the original j3o file I accidentally gave you was near 3000kb and the correct reduced j3o file should now only be 3kb)

Sorry for the mistake!

1 Like

I tried again with the current “assets.zip”.

I was able to load the “cliffRight.j3o” scene, but the resulting render was all black. I tried adding lights (including a LightProbe), moving the camera around, and enabling physics debug visualization, but I still don’t see anything.

I dumped the scene graph and didn’t see anything obviously wrong.

Perhaps the best thing would be for you to provide me with a complete Java application I can build and run, with good lighting and the camera properly positioned.

1 Like

I’ll post a test case soon and make sure there’s nothing else wrong with the scene.

1 Like

Sorry again for the trouble, I should have waited until I had time to make this full test case before asking you to try to troubleshoot things, I hope I didn’t waste too much of your time.

Here’s a single class app that will load the scene, and whenever you press the space bar it will toggle physics for the church and pews. So you should be able to see it in the correct location until you press space, then all but one pew suddenly shift location when they gain a RigidBodyControl

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.light.LightProbe;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.AssetLinkNode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.util.SafeArrayList;

public class Main extends SimpleApplication {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }

    public BulletAppState bas;
    public Node sceneNode;
    
    @Override
    public void simpleInitApp() {
        
        //init keybinding for space bar toggling physics
        inputManager.addMapping("TogglePhysics", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addListener(actionListener, "TogglePhysics");
        
        //init bulletAppState
        bas = new BulletAppState();
        bas.setEnabled(true);
        stateManager.attach(bas);
        
        bas.setDebugEnabled(true);
        
        //init lights
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(-0.5f, -0.5f, -0.5f)).normalizeLocal());
        sun.setColor(ColorRGBA.White);
        rootNode.addLight(sun);        

        LightProbe probe = (LightProbe)  assetManager.loadAsset("Scenes/LightProbes/quarry_Probe.j3o");    
        probe.getArea().setRadius(500);
        rootNode.addLight(probe);
        
        //load scene
        sceneNode = (Node) assetManager.loadModel("Scenes/SilverShoreGorge/cliffRight.j3o");
        rootNode.attachChild(sceneNode);
        
       //position camera inside church
        Vector3f chruchLoc = new Vector3f(-107.09586f, 70.409782f, 190.07628f);   
        getCamera().setLocation(chruchLoc);
        
        flyCam.setMoveSpeed(20);

        
        
    }
    

    private void traverseChildrenForPhysicsObjects(Spatial spatial){
        
        if(spatial instanceof AssetLinkNode){
            RigidBodyControl rbc = spatial.getControl(RigidBodyControl.class);
            
            if(rbc == null){
                rbc = new RigidBodyControl(0);
                spatial.addControl(rbc);
                bas.getPhysicsSpace().add(spatial);
            }
            else{
                spatial.removeControl(rbc);
                bas.getPhysicsSpace().remove(rbc);
            }
            
            
        }else if(spatial instanceof Node){
            
            SafeArrayList<Spatial> children = (SafeArrayList<Spatial>) ((Node) spatial).getChildren();
            
            for(int x = 0; x < children.size(); x++){
                traverseChildrenForPhysicsObjects(children.get(x));
            }
        }                
    }

    
    final private ActionListener actionListener = new ActionListener() {
        @Override
        public void onAction(String name, boolean keyPressed, float tpf) {
            if (name.equals("TogglePhysics") && !keyPressed && sceneNode != null) {
                traverseChildrenForPhysicsObjects(sceneNode);
                
            }
        }
    };
}


Let me know if there’s anymore issues, this test case runs as intended on my device, so I’m hoping it was just a positioning issue but if everything still rendres black that could mean the shaders im using are having errors for other gpus… in which case you can just edit the 3 material files for the pew, the church, and church windows to use PbrLighting.j3md in place of AfflictedPbr.j3md.

The test case also uses quarry_Probe.j3o so the app needs to include the jme test data library:
implementation "org.jmonkeyengine:jme3-testdata:3.4.0-stable"

1 Like

Even before physics controls are added, the 5 pews aren’t identical:

  • The last pew’s AssetNode has uniform local scaling (xyz=4.185) while the other 4 asset nodes have non-uniform scaling (x=4.2 yz=4.5).
  • The last pew’s AssetNode has a different local rotation (0.0, -0.20726654, 0.0, 0.9782843—a normalized quaternion representing a 23.9-degree rotation) than the other 4 asset nodes (which have 0.0, -0.1467117, 0.0, 0.6917189—a non-normalized quaternion).

I adjusted the AssetNode transforms so that all 5 pews have the same local rotation, and the issue went away. So I think there’s an issue in how non-normalized quaternions are handled.

I continue to investigate.

1 Like

This is proving to be an interesting issue. Even without physics controls, normalizing local rotations in the scene graph changes the apparent location of the pews.

Before normalizing:

After normalizing:

To me, this looks like a rendering bug in JMonkeyEngine. (Since Bullet uses rotation matrices not quaternions, adding physics controls has the side-effect of normalizing local rotations.)

Inspection of com.jme3.math.Quaternion turned up an ancient bug in getRotationColumn() for non-normalized quaternions: issue 2023. However, fixing that bug doesn’t correct the pew locations. I believe JME3 rendering uses toRotationMatrix() instead, which doesn’t have the same issue, so I suspect there’s another bug somewhere.

Until the bug is found, I think you should avoid using non-normalized quaternions with JMonkeyEngine.

3 Likes

The root cause turns out to be in Quaternion.multLocal(Vector3f), which assumes the current instance is normalized.

When this isn’t the case, multLocal() produces an incorrect result vector. This causes Transform.combineWithParent() and Geometry.updateWorldTransforms() to compute incorrect translations.

JMonkeyEngine invokes combineWithParent() often. Calculating the norm of parent.rot on every invocation (to see whether it’s 1) might cause a measurable CPU hit. I’d rather document the assumption of normality and tell people to avoid using non-normalized quaternions.

8 Likes
  • I’ve opened a pull request to document JME’s assumption that certain quaternions are normalized.
  • I’ve created safer versions of Quaternion.mult(Vector3f, Vector3f) and Transform.combineWithParent() and added them to my Heart library.
  • I’ve marked this discussion as “SOLVED”.
1 Like

That’s good to hear you found the source of the underlying issue, and I appreciate your help as always.

The only question I’m left with is how the pews got different quaternions in my editor… I knew the scale was slightly different, but the code for placing both pews and determining the rotation was exactly the same when I placed both copies of the pew, so it is weird that the one time it placed it with a different quaternion.

I finally did manage to get the strange error when running my scene editor again once:

It actually appears to point to a local branch of ParticleMonkey I copy/pasted directly into my scene editor’s src directory a while ago so I could quickly modify the source code alongside my editor’s code without having to rebuild them separately.

It looks like the package names in all of my ParticleMonkey related classes do not match where they are located, and the IDE is showing an error but it doesn’t crash my app so I likely never noticed before.

I wonder if this incorrect pacakge naming could be whats causing a weird error like this that only occurrs every 1/100 times I run the editor? And I also am curious if its possible this error could have also occurred at the same I spawned that “corrupted” pew, because otherwise I still am at a loss for an explanation as to how it got a different quaternion than the other pews.

1 Like

It appears I made a big blunder and accidentally included 2 imports of the ParticleMonkey library in my project, one being a jar in a local folder that gets included in the gradle build that I was overlooking.

So I expect that’s what’s causing the occasional error and random bugs in my editor.

I think I recall having a similar problem a long time ago when I still used ant and included duplicate jars of the same terrain library, and things started breaking in all sorts of weird ways. So it was only a matter of time before I made that mistake again with gradle since I’ve only been using it for a year or so now.

I’ll have to be more careful going forward to check for local .jar files to ensure I’m not importing duplicates in the future. But I’m glad my mistake at least uncovered a real issue that you were able to solve.

1 Like