[SOLVED] Porting to Minie 1.6.1 Issues & Questions

Hello Guys,
I’m porting my project to Minie and I have a few issues & questions which I would like to post in this thread -
First regarding CharacterControl I have made this 2 changes in code for getViewDirection and setGravity. I hope it’s OK and would also would like to know if it’s still best practice to use CharacterControl or you suggest replacing it with another class?

//need to supply null for getViewDirection:
CharacterControl.getViewDirection(null);

//character control provide float instead of vector3f for setGravity:
CharacterControl.setGravity( -9.8f);// was new Vector3f(0,-9.8f,0)

Second, regarding PhysicsCollisionEvent I’m providing nulls for the functions :getLocalPointA & getLocalPointB
Again I hope it’s OK and will provide the same functionality as the previous version.

And last issue is a crash I’m having at the very beginning:

java.lang.NoSuchFieldError: hitNormalLocal
	at com.jme3.bullet.PhysicsSpace.createPhysicsSpace(Native Method)
	at com.jme3.bullet.PhysicsSpace.create(PhysicsSpace.java:811)
	at com.jme3.bullet.CollisionSpace.<init>(CollisionSpace.java:148)
	at com.jme3.bullet.PhysicsSpace.<init>(PhysicsSpace.java:254)
	at com.jme3.bullet.BulletAppState.createPhysicsSpace(BulletAppState.java:627)
	at com.jme3.bullet.BulletAppState.startPhysics(BulletAppState.java:567)
	at com.jme3.bullet.BulletAppState.stateAttached(BulletAppState.java:795)
	at com.jme3.app.state.AppStateManager.attach(AppStateManager.java:148)
	at com.scenemaxeng.projector.SceneMaxApp.simpleInitApp(SceneMaxApp.java:248)
	at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:240)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:211)
	at java.lang.Thread.run(Thread.java:745)

it happens when attaching the BulletAppState:

// bullet init
        if(bulletAppState==null) {
            bulletAppState = new BulletAppState();

        }

        stateManager.attach(bulletAppState);

What am I doing wrong?

1 Like

Hum are you sure you remove all the other librairy like writen into the Minie documentation ?

Remove any existing physics libraries

Minie replaces (and is therefore incompatible with) the following jMonkeyEngine libraries:

  • jme3-bullet
  • jme3-bullet-native
  • jme3-bullet-native-android
  • jme3-jbullet

Before adding Minie, you should remove these libraries from your project so they won’t interfere with Minie.

1 Like

I double-checked - no jme3-bullet jars in the libs folder

1 Like

If you pass null to getViewDirection(), it allocates a Vector3f object for the result. That’s fine if you don’t mind generating a little garbage each time.

If you pass a negative value to setGravity(), the character should fall upwards, which would be … unconventional. The Javadoc says:

    public void setGravity(float downwardAcceleration)
    Alter the character's gravitational acceleration.
    Parameters:
        downwardAcceleration - the desired downward acceleration (in physics-space units per second squared, not null, default=29.4)

You probably want setGravity(9.8f) instead.

Best practice for character physics depends on the effect you’re trying to achieve and how much effort you’re willing to spend. CharacterControl has many quirks, and because its functionality comes mostly from Bullet’s btKinematicCharacterController class, it’s not easily customized.

I regard CharacterControl and BetterCharacterControl as examples, analogous to FlyCamAppState and ChaseCameraAppState—fine for learners and demo apps. I expect major game projects to write their own physics controls, just as they write their own camera-control appstates.

It’s fine if you don’t mind a little garbage.

Probably you’re combining jme3-bullet-native with Minie. One of the first things jme3-bullet-native does is to look up the field ID for hitNormalLocal in the PhysicsRayTestResult class. In Minie, that field is called normal.

What build tool are you using: Gradle, Ant, or something else?

1 Like

I’m just putting the jars in the lib folder and I removed jme3-bullet jars from that folder and now just using Minie & Heart jars But I understand that it somehow cached those jme3-bullet jars and I will find a way to make it work

@sgold Now I’m having issue with static models. Here is the relevant code (loading a simple box):

        float mass = 1;
        boolean isPhysical = inst.massExpr!=null || inst.varDef.isStatic;
        if(isPhysical) {
            if(inst.varDef.isStatic) {
                mass=0;
            } else {
                mass = Float.parseFloat(inst.massExpr.evaluate(this).toString());
            }

        }

        CollisionShape modelShape;
        if(inst.varDef.isStatic) {
            modelShape = new MeshCollisionShape(boxGeo.getMesh());
        } else {
            modelShape = CollisionShapeFactory.createBoxShape(boxGeo);
        }

        RigidBodyControl modelCtl = new RigidBodyControl(modelShape,mass);
        modelCtl.setKinematic(!isPhysical);//

        boxGeo.addControl(modelCtl);
        bulletAppState.getPhysicsSpace().add(modelCtl);
        List<java.lang.Object> ctls = new ArrayList<>();
        ctls.add(modelCtl);
        collisionControlsCache.put(boxName,ctls);

        this.enqueue(new Runnable() {
            @Override
            public void run() {
                rootNode.attachChild(boxGeo);
            }
        });

And I’m getting this exception when trying to load a static Box:

java.lang.IllegalStateException: Cannot set/clear kinematic mode on a static body!
	at com.jme3.bullet.objects.PhysicsRigidBody.setKinematic(PhysicsRigidBody.java:701)
	at com.scenemaxeng.projector.SceneMaxApp.loadBox(SceneMaxApp.java:1070)
	at com.scenemaxeng.projector.SceneMaxApp.instantiateVariable(SceneMaxApp.java:985)
	at com.scenemaxeng.projector.InstantiateGraphicEntityController.run(InstantiateGraphicEntityController.java:22)
	at com.scenemaxeng.projector.CompositeController.run(CompositeController.java:68)
	at com.scenemaxeng.projector.SceneMaxApp.simpleUpdate(SceneMaxApp.java:2121)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:259)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:197)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
	at java.lang.Thread.run(Thread.java:745)

By “static” I mean models which are used as roads / cities / walls etc. and for those objects I’m using the MeshCollisionShape

What do you think Stephen?

1 Like

A rigid body is either static OR dynamic OR kinematic. The error message is reminding you that it can’t be both static and kinematic at the same time. When creating a kinematic rigid body, please specify mass > 0. Roads and walls should have static bodies, not kinematic ones.

The RigidBodyControl has 2 unrelated methods with similar names: setKinematic() and setKinematicSpatial(). This sometimes causes confusion.

Thanks! I’m fixing things and now it looks fine. Regarding the crash in Finalize - I’m still seeing issue there:

Stack: [0x0000000016950000,0x0000000016a50000],  sp=0x0000000016a4ec68,  free space=1019k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [bulletjme.dll+0x9076a]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.jme3.bullet.collision.PhysicsCollisionObject.getSpaceId(J)J+0
j  com.jme3.bullet.collision.PhysicsCollisionObject.spaceId()J+5
j  com.jme3.bullet.collision.PhysicsCollisionObject.getCollisionSpace()Lcom/jme3/bullet/CollisionSpace;+3
j  com.jme3.bullet.collision.PhysicsCollisionObject.finalize()V+13
J 6068 C2 java.lang.ref.Finalizer.access$100(Ljava/lang/ref/Finalizer;Lsun/misc/JavaLangAccess;)V (6 bytes) @ 0x0000000003afcd94 [0x0000000003afcbc0+0x1d4]
j  java.lang.ref.Finalizer$FinalizerThread.run()V+45
v  ~StubRoutines::call_stub

But this is less a problem for me now since I moved to running my program in a different process so now the main app is not crashing.

1 Like

The crash occurred with Minie v1.6.1, correct?

I’ll review the relevant sourcecode and see if I can spot the bug.

If you create a simple test that demonstrates the crash, I’d love to see it!

Yes 1.6.1
does a Zoom meeting for observing the crash is an option? if not, I’ll do my best to create a test program. Basically is happens when i’m using large models specifically in this case I’m using this model: https://sketchfab.com/3d-models/game-pirate-adventure-map-696dfa212fda4240817615bdccb373d0. after 3-10 times of opening my app using those models the garbage collector starts cleaning and the crash occurs

1 Like

You can trigger garbage collection by invoking System.gc(). Doing so may help you reproduce the issue with a smaller collision shape.

1 Like

I’ll try

1 Like

The good news is that now I have Minie in my project!
I was sure that I will need to upgrade Advance Vehicles as well because of that but somehow it works… (I have an old version of advance vehicles) so less pressure from this side.
Next I’m going to explore Minie tests and see what nice features can be added to my project :slight_smile:
One thing I would like to add is updating the collision shape for some models while they perform an animation. Is there any Minie test doing it so I can observe the code?

1 Like

For physics that follows bone animations, use DynamicAnimControl. For best results, you’ll need to tune it to your models.

I suggest starting with the tutorial:

TestDac is a very feature-rich test app that’s fun to play with:

For model-specific tuning, I use DacWizard:

2 Likes

Amazing! I’ll do that

1 Like

I’m learning to do things with DAC from TestDac.java. One simple thing I’m struggling with how to reset my model to its initial state after performing the setRagdollMode()?
I tried blendToKinematicMode() and resetLocalTransform() but something is missing for the model to “stand” back on his feet (I’m using Ninja for my tests)

1 Like

It’s somewhat tricky because 2 things both need to be reset: the model’s armature and the model’s root spatial or controlled spatial. You can see this in TestDac, which has a separate action for each:

  • Pressing the K key begins blending all links to purely kinematic, which resets the Armature.
  • Pressing the Home key resets the Spatial.

DacWizard provides an even clearer example. The toggleRagdoll() method in the TestMode class saves the local transform of the controlled spatial before invoking setRagdollMode(). When it comes time to reset the model, it passes the saved transform to torso.blendToKinematicMode().

The TestBoneRagdoll app in jme3-examples provides a more sophisticated example. Here the model (Sinbad) has stand-up animations to be played during the transition back to purely kinematic mode. The code has to determine which animation to use and what the final orientation should be.

2 Likes

Thanks! I’m testing the code. What is the difference between this:

TorsoLink torso = dac.getTorsoLink();
            KinematicSubmode bindPose = KinematicSubmode.Bound;
            float blendInterval = 1f; // in seconds
            torso.blendToKinematicMode(bindPose, blendInterval, am.resetTransform);
            Collection<BoneLink> boneLinks = dac.listLinks(BoneLink.class);
            for (BoneLink boneLink : boneLinks) {
                boneLink.blendToKinematicMode(bindPose, blendInterval);
            }

And this?

dac.blendToKinematicMode(2f,am.resetTransform);

They both yields the same result - the NInja is reset back up on his legs (Good!) but one problem - it is reset to its original scale (very big). What am I missing here?

I’m puzzled by your first question. Minie is an open-source project. blendToKinematicMode() is a dozen lines of code. It should not be difficult for you to analyze it yourself.

Anyway…

  1. The top code specifies a 1-second blend interval, and the bottom specifies a 2-second inverval.
  2. The top code blends to bind pose, and the bottom blends to the current (kinematic) animation.
  3. The top code blends attachment links; the bottom doesn’t.

Regarding your scaling question, I don’t know what you’re missing. I suppose it has something to do with how you scaled the Ninja in the first place. Perhaps that initial scaling isn’t reflected in am.resetTransform.