Is there an example of how to use KinematicRagdollControl anywhere?

Hi,



I’m trying to make an articulated physics object, and after digging around in the forums I’ve come to two conclusions:



1.) While GImpactCollisionShape is the most accurate way to add a mesh to physics space, a GImpactCollisionShape cannot deform-- You must create a new GImpactCollisionShape for each animation frame.



2.) KinematicRagdollControl is supposed to be a fast way to estimate a deforming dynamic mesh which works by attaching simple physical objects to bones. However, TestBoneRagdoll is the best example I can find that uses KinematicRagdollControl (one of the developers has referenced something called KinematicRagdollTest in the past, but I don’t think this example exists). I get a NullPointerException if I try to implement KinematicRagdollControl as is done in TestBoneRagdoll:



[java]

Node walkChar = (Node)assetManager.loadModel(“Models/WalkCharDecimateBone/WalkCharDecimateBone.j3o”);

//walkChar.scale(1.0f, 1.0f, 1.0f);



bulletAppState = new BulletAppState();

bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);

stateManager.attach(bulletAppState);



walkChar_phy = new KinematicRagdollControl(0.5f);

walkChar_phy.setKinematicMode();

walkChar_phy.addBoneName(“Thigh.L”);

walkChar_phy.addBoneName(“Thigh.R”);

walkChar_phy.addBoneName(“Shin.L”);

walkChar_phy.addBoneName(“Shin.R”);

walkChar_phy.addBoneName(“Foot.L”);

walkChar_phy.addBoneName(“Foot.R”);

walkChar_phy.addBoneName(“Shoulder.L”);

walkChar_phy.addBoneName(“Shoulder.R”);

bulletAppState.getPhysicsSpace().add(walkChar_phy);



walkChar.addControl(walkChar_phy);

[/java]



The last line generates the following exception:



[java]

java.lang.NullPointerException

at com.jme3.scene.Spatial.addControl(Spatial.java:591)

at com.jme3.bullet.control.KinematicRagdollControl.setSpatial(KinematicRagdollControl.java:331)

at com.jme3.scene.Spatial.addControl(Spatial.java:591)

[/java]



Any idea what could be happening?



Thanks.

In line 591 something is null, find out what.

Fixed by adding the control to the object I find down in the model hierarchy that has a Skeleton and Animation controls attached:



[java]

walkChar_phy = new KinematicRagdollControl(0.5f);

walkChar_phy.setKinematicMode();

walkChar_phy.addBoneName(“Thigh.L”);

walkChar_phy.addBoneName(“Thigh.R”);

walkChar_phy.addBoneName(“Shin.L”);

walkChar_phy.addBoneName(“Shin.R”);

walkChar_phy.addBoneName(“Foot.L”);

walkChar_phy.addBoneName(“Foot.R”);

walkChar_phy.addBoneName(“Shoulder.L”);

walkChar_phy.addBoneName(“Shoulder.R”);

bulletAppState.getPhysicsSpace().add(walkChar_phy);

walkChar_phy.setEnabled(true);



((Node)walkChar.getChild(“Armature”)).getChild(“Cylinder”).addControl(walkChar_phy);

[/java]



This appears to make a kinematic ragdoll-- But the model no longer responds to gravity, and instead just floats in space where it was instantiated. I’m trying to realize a deformable mesh that exists in physics space; what’s the best way to do this?



Should I parent the model to a simple spatial with RigidBodyControl? KinematicRagdollControl appears to be giving me the collision shape that I want, but I can’t actually make it tumble around in the world.

I don’t think you want that, much too complicated. Think more like how you can fake what you want to be seen.

I’m trying to make a simple game for some research I’m doing. The goal of the game is to articulate the legs of a two-legged model to make it stand, walk around, climb simple obstacles, etcetera. It doesn’t need to be an accurate simulation that has relevance to the real world-- It only needs to be possible to control the character. Think 3D QWOP.



To this end, I need to make a deformable mesh that exists in physics space. The first thing I tried was GImpactCollisionShape, but I’m pretty sure now that you can’t deform those. Next, I tried KinematciRagdollControl, which seemed to give me a deformable collision shape, but I can’t figure out how to make that shape react to gravity.



Maybe what I need to do is make a regular Ragdoll, and impose control via torque forces on the bones? What’s the best way to go about this task?

I believe there are two mysteries at work here. Maybe someone (normen?) can help me work through these. Before I try, though, I’d mostly like to know if what I’m trying to do is even possible in JMonkeyEnigne. I’ve sunk a good number of hours into learning how to use this software, and I’d like to avoid putting any more in if my goals are simply impossible on this platform. If they are, then maybe the two examples below will give people enough information to help.



First, if I replace my model with Sinbad from the test data, the Sinbad model still floats in midair even after KinematicRagdollControl is set to Ragdoll mode. Something is wrong with my code (see below).



Second, TestBoneRagdoll.java works after some fiddling with textures. My JME can make a ragdoll Sinbad with this test program. However, if I replace Sinbad with my model, then adding the KinematicRagdollControl to the model results in a NullPointerException.



Here is my simpleInitApp, which produces a Sinbad model which does not respond to gravity:



[java]

map.load();

map.normalizeTerrain(20.0f);



flyCam.setMoveSpeed(50);



// TERRAIN TEXTURE material

matRock = new Material(assetManager, “Common/MatDefs/Terrain/Terrain.j3md”);

matRock.setBoolean(“useTriPlanarMapping”, false);



// ALPHA map (for splat textures)

matRock.setTexture(“Alpha”, assetManager.loadTexture(“Textures/Terrain/splat/alphamap.png”));



// GRASS texture

Texture grass = assetManager.loadTexture(“Textures/Terrain/splat/grass.jpg”);

grass.setWrap(WrapMode.Repeat);

matRock.setTexture(“Tex1”, grass);

matRock.setFloat(“Tex1Scale”, grassScale);



// DIRT texture

Texture dirt = assetManager.loadTexture(“Textures/Terrain/splat/dirt.jpg”);

dirt.setWrap(WrapMode.Repeat);

matRock.setTexture(“Tex2”, dirt);

matRock.setFloat(“Tex2Scale”, dirtScale);



// ROCK texture

Texture rock = assetManager.loadTexture(“Textures/Terrain/splat/road.jpg”);

rock.setWrap(WrapMode.Repeat);

matRock.setTexture(“Tex3”, rock);

matRock.setFloat(“Tex3Scale”, rockScale);



// WIREFRAME material

matWire = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

matWire.setColor(“Color”, ColorRGBA.Green);





terrain = new TerrainQuad(“terrain”, 65, mapSize + 1, map.getHeightMap());//, new LodPerspectiveCalculatorFactory(getCamera(), 4)); // add this in to see it use entropy for LOD calculations

List<Camera> cameras = new ArrayList<Camera>();

cameras.add(getCamera());

TerrainLodControl control = new TerrainLodControl(terrain, cameras);

terrain.addControl(control);

terrain.setMaterial(matRock);

terrain.setModelBound(new BoundingBox());

terrain.updateModelBound();

terrain.setLocalTranslation(0, -100, 0);

terrain.setLocalScale(2f, 1f, 2f);

rootNode.attachChild(terrain);





Node walkChar = (Node) assetManager.loadModel(“Models/Sinbad/Sinbad.mesh.xml”);



bulletAppState = new BulletAppState();

bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);

stateManager.attach(bulletAppState);



floor_phy = new RigidBodyControl(0.0f);

terrain.addControl(floor_phy);

bulletAppState.getPhysicsSpace().add(floor_phy);



DirectionalLight light = new DirectionalLight();

light.setDirection((new Vector3f(-0.5f, -1f, -0.5f)).normalize());

rootNode.addLight(light);



flyCam.setEnabled(false);

chaseCam = new ChaseCamera(cam, walkChar, inputManager);



getCamera().getLocation().y = 10;



walkChar_phy = new KinematicRagdollControl(0.5f);

setupSinbad(walkChar_phy);

bulletAppState.getPhysicsSpace().add(walkChar_phy);



walkChar.addControl(walkChar_phy);

bulletAppState.getPhysicsSpace().enableDebug(assetManager);

rootNode.attachChild(walkChar);

walkChar_phy.setEnabled(true);

[/java]





…And here is the modified portion of TestBoneRagdoll, which produces an NPE when KinematicRagdollControl is added to the model I made in Blender:



[java]

//model = (Node) assetManager.loadModel(“Models/Sinbad/Sinbad.mesh.xml”);

model = (Node)assetManager.loadModel(“Models/WalkCharDecimateBone/WalkCharDecimateBone.j3o”);



// model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X));



//debug view

//AnimControl control = model.getControl(AnimControl.class);

AnimControl control = ((Node)model.getChild(“Armature”)).getChild(“Cylinder”).getControl(AnimControl.class);

SkeletonDebugger skeletonDebug = new SkeletonDebugger(“skeleton”, control.getSkeleton());



Material mat2 = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat2.setColor(“Color”, ColorRGBA.Green);

mat2.getAdditionalRenderState().setDepthTest(false);

skeletonDebug.setMaterial(mat2);

skeletonDebug.setLocalTranslation(model.getLocalTranslation());



//Note: PhysicsRagdollControl is still TODO, constructor will change

ragdoll = new KinematicRagdollControl(0.5f);

setupSinbad(ragdoll);

ragdoll.addCollisionListener(this);

model.addControl(ragdoll);

[/java]

Everything is possible, it just depends on your programming skill. If you want to do a 3d QWOP, do what the KinematicRagDollControl does and then let the user control the motors of the SixDofJoints.