diff --git a/engine/src/core/com/jme3/animation/Bone.java b/engine/src/core/com/jme3/animation/Bone.java
index 15438d21b..b242e4d5d 100644
--- a/engine/src/core/com/jme3/animation/Bone.java
+++ b/engine/src/core/com/jme3/animation/Bone.java
@@ -235,7 +235,7 @@ public final class Bone implements Savable {
/**
* Updates the world transforms for this bone, and, possibly the attach node if not null.
*/
- final void updateWorldVectors() {
+ public final void updateWorldVectors() {
if (parent != null) {
//rotation
@@ -381,7 +381,16 @@ public final class Bone implements Savable {
worldPos.set(translation);
worldRot.set(rotation);
}
-
+
+ protected Vector3f tmpVec=new Vector3f();
+ protected Quaternion tmpQuat=new Quaternion();
+ public Quaternion getTmpQuat() {
+ return tmpQuat;
+ }
+ public Vector3f getTmpVec() {
+ return tmpVec;
+ }
+
/**
* Returns the attachment node.
* Attach models and effects to this node to make
diff --git a/engine/src/core/com/jme3/scene/Spatial.java b/engine/src/core/com/jme3/scene/Spatial.java
index f22b73a45..2475b4f87 100644
--- a/engine/src/core/com/jme3/scene/Spatial.java
+++ b/engine/src/core/com/jme3/scene/Spatial.java
@@ -150,8 +150,8 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
refreshFlags |= RF_BOUND;
}
-
- /**
+
+ /**
* Constructor instantiates a new Spatial
object setting the
* rotation, translation and scale value to defaults.
*
@@ -487,7 +487,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
}
private void runControlUpdate(float tpf) {
- if (controls.size() == 0) {
+ if (controls.isEmpty()) {
return;
}
@@ -507,7 +507,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable {
* @see Spatial#getControl(java.lang.Class)
*/
public void runControlRender(RenderManager rm, ViewPort vp) {
- if (controls.size() == 0) {
+ if (controls.isEmpty()) {
return;
}
diff --git a/engine/src/core/com/jme3/util/TempVars.java b/engine/src/core/com/jme3/util/TempVars.java
index ebd828a3d..7bc569c53 100644
--- a/engine/src/core/com/jme3/util/TempVars.java
+++ b/engine/src/core/com/jme3/util/TempVars.java
@@ -167,6 +167,7 @@ public class TempVars {
* General quaternions.
*/
public final Quaternion quat1 = new Quaternion();
+ public final Quaternion quat2 = new Quaternion();
/**
* Eigen
diff --git a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
index 3c755eedc..b242fb5a4 100644
--- a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
+++ b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
@@ -1,5 +1,7 @@
package com.jme3.bullet.control;
+import com.jme3.bullet.control.radoll.RagdollPreset;
+import com.jme3.bullet.control.radoll.HumanoidRagdollPreset;
import com.jme3.animation.AnimControl;
import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
@@ -12,12 +14,10 @@ import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.RagdollCollisionListener;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.HullCollisionShape;
-import com.jme3.bullet.joints.PhysicsJoint;
import com.jme3.bullet.joints.SixDofJoint;
import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
-import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
@@ -35,6 +35,7 @@ import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@@ -61,6 +62,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
protected float eventDispatchImpulseThreshold = 10;
protected float eventDiscardImpulseThreshold = 3;
protected RagdollPreset preset = new HumanoidRagdollPreset();
+ protected List boneList = new LinkedList();
public RagdollControl() {
}
@@ -78,6 +80,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if (control) {
Quaternion q2 = vars.quat1;
+ Quaternion q3 = vars.quat2;
+ Vector3f p2 = vars.vect2;
// skeleton.reset();
for (PhysicsBoneLink link : boneLinks.values()) {
@@ -101,9 +105,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
- link.bone.setUserControl(true);
- link.bone.setUserTransformsWorld(position, q2);
-
+ if (boneList.isEmpty()) {
+ link.bone.setUserControl(true);
+ link.bone.setUserTransformsWorld(position, q2);
+ } else {
+ setTransform(link.bone, position, q2);
+ }
}
@@ -112,6 +119,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
for (PhysicsBoneLink link : boneLinks.values()) {
//the ragdoll does not control the skeleton
link.bone.setUserControl(false);
+ if (!link.rigidBody.isKinematic()) {
+ link.rigidBody.setKinematic(true);
+ }
Vector3f position = vars.vect1;
Quaternion rotation = vars.quat1;
@@ -134,6 +144,21 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
+ private void setTransform(Bone bone, Vector3f pos, Quaternion rot) {
+ bone.setUserControl(true);
+ bone.setUserTransformsWorld(pos, rot);
+ for (Bone childBone : bone.getChildren()) {
+ if (!boneList.contains(childBone.getName())) {
+ Vector3f tmpVec = childBone.getTmpVec();
+ Quaternion tmpQuat = childBone.getTmpQuat();
+ rot.mult(childBone.getLocalPosition(), tmpVec).addLocal(pos);
+ tmpQuat.set(rot).multLocal(childBone.getLocalRotation());
+ setTransform(childBone, tmpVec, tmpQuat);
+
+ }
+ }
+ }
+
public Control cloneForSpatial(Spatial spatial) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -165,7 +190,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
// maybe dont reset to ragdoll out of animations?
scanSpatial(model);
-
+
if (parent != null) {
parent.attachChild(model);
@@ -178,7 +203,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
public void addBoneName(String name) {
- throw new UnsupportedOperationException("Not supported yet.");
+ boneList.add(name);
}
private void scanSpatial(Spatial model) {
@@ -204,53 +229,60 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount) {
-
- //get world space position of the bone
- Vector3f pos = bone.getModelSpacePosition().add(model.getLocalTranslation());
+ PhysicsRigidBody parentShape = parent;
+ if (boneList.isEmpty() || boneList.contains(bone.getName())) {
+ //get world space position of the bone
+ Vector3f pos = bone.getModelSpacePosition().add(model.getLocalTranslation());
// Quaternion rot = bone.getModelSpaceRotation().mult(initRotation);
- //creating the collision shape from the bone's associated vertices
- PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model), 10.0f / (float) reccount);
+ //creating the collision shape from the bone's associated vertices
+ PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model), 10.0f / (float) reccount);
- // shapeNode.setPhysicsRotation(rot);
+ // shapeNode.setPhysicsRotation(rot);
- PhysicsBoneLink link = new PhysicsBoneLink();
- link.bone = bone;
- link.rigidBody = shapeNode;
- link.initalWorldRotation = bone.getModelSpaceRotation().clone();
- // link.mass = 10.0f / (float) reccount;
+ PhysicsBoneLink link = new PhysicsBoneLink();
+ link.bone = bone;
+ link.rigidBody = shapeNode;
- //TODO: ragdoll mass 1
- if (parent != null) {
- //get joint position for parent
- Vector3f posToParent = new Vector3f();
- if (bone.getParent() != null) {
- bone.getModelSpacePosition().subtract(bone.getParent().getModelSpacePosition(), posToParent);
- }
+ link.initalWorldRotation = bone.getModelSpaceRotation().clone();
+ // link.mass = 10.0f / (float) reccount;
- //Joint local position from parent
- link.pivotA = posToParent;
- //joint local position from current bone
- link.pivotB = new Vector3f(0, 0, 0f);
+ //TODO: ragdoll mass 1
+ if (parent != null) {
+ //get joint position for parent
+ Vector3f posToParent = new Vector3f();
+ if (bone.getParent() != null) {
+ bone.getModelSpacePosition().subtract(bone.getParent().getModelSpacePosition(), posToParent);
+ }
+
+ //Joint local position from parent
+ link.pivotA = posToParent;
+ //joint local position from current bone
+ link.pivotB = new Vector3f(0, 0, 0f);
- SixDofJoint joint = new SixDofJoint(parent, shapeNode, link.pivotA, link.pivotB, true);
- //TODO find a way to correctly compute/import joints (maybe based on their names)
- preset.setupJointForBone(bone.getName(), joint);
- //setJointLimit(joint, 0, 0, 0, 0, 0, 0);
+ SixDofJoint joint = new SixDofJoint(parent, shapeNode, link.pivotA, link.pivotB, true);
+ joint.getTranslationalLimitMotor().setUpperLimit(new Vector3f(0, 0, 0));
+ joint.getTranslationalLimitMotor().setLowerLimit(new Vector3f(0, 0, 0));
+ //TODO find a way to correctly compute/import joints (maybe based on their names)
+ preset.setupJointForBone(bone.getName(), joint);
+ //setJointLimit(joint, 0, 0, 0, 0, 0, 0);
- link.joint = joint;
- joint.setCollisionBetweenLinkedBodys(false);
+ link.joint = joint;
+ joint.setCollisionBetweenLinkedBodys(false);
+ }
+ boneLinks.put(bone.getName(), link);
+ shapeNode.setUserObject(link);
+ parentShape = shapeNode;
}
- boneLinks.put(bone.getName(), link);
- shapeNode.setUserObject(link);
for (Iterator it = bone.getChildren().iterator(); it.hasNext();) {
Bone childBone = it.next();
- boneRecursion(model, childBone, shapeNode, reccount++);
+ boneRecursion(model, childBone, parentShape, reccount++);
}
+
}
/**
@@ -323,17 +355,31 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private HullCollisionShape makeShape(Bone bone, Spatial model) {
- int boneIndex = skeleton.getBoneIndex(bone);
+
+ List boneIndices = null;
+ if (boneList.isEmpty()) {
+ boneIndices = new LinkedList();
+ boneIndices.add(skeleton.getBoneIndex(bone));
+ } else {
+ boneIndices = getBoneIndices(bone, skeleton);
+ }
+
+
ArrayList points = new ArrayList();
if (model instanceof Geometry) {
Geometry g = (Geometry) model;
- points.addAll(getPoints(g.getMesh(), boneIndex, bone.getModelSpacePosition()));
+ for (Integer index : boneIndices) {
+ points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition()));
+ }
} else if (model instanceof Node) {
Node node = (Node) model;
for (Spatial s : node.getChildren()) {
if (s instanceof Geometry) {
Geometry g = (Geometry) s;
- points.addAll(getPoints(g.getMesh(), boneIndex, bone.getModelSpacePosition()));
+ for (Integer index : boneIndices) {
+ points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition()));
+ }
+
}
}
}
@@ -345,6 +391,17 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return new HullCollisionShape(p);
}
+ private List getBoneIndices(Bone bone, Skeleton skeleton) {
+ List list = new LinkedList();
+ list.add(skeleton.getBoneIndex(bone));
+ for (Bone chilBone : bone.getChildren()) {
+ if (!boneList.contains(chilBone.getName())) {
+ list.addAll(getBoneIndices(chilBone, skeleton));
+ }
+ }
+ return list;
+ }
+
protected List getPoints(Mesh mesh, int boneIndex, Vector3f offset) {
FloatBuffer vertices = mesh.getFloatBuffer(Type.Position);
@@ -529,10 +586,22 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
this.control = control;
for (PhysicsBoneLink link : boneLinks.values()) {
- link.bone.setUserControl(control);
+ // link.bone.setUserControl(control);
link.rigidBody.setKinematic(!control);
}
+
+ for (Bone bone : skeleton.getRoots()) {
+ setUserControl(bone, control);
+ }
+
+ }
+
+ private void setUserControl(Bone bone, boolean bool) {
+ bone.setUserControl(bool);
+ for (Bone child : bone.getChildren()) {
+ setUserControl(child, bool);
+ }
}
public boolean hasControl() {
diff --git a/engine/src/jbullet/com/jme3/bullet/control/HumanoidRagdollPreset.java b/engine/src/jbullet/com/jme3/bullet/control/radoll/HumanoidRagdollPreset.java
similarity index 98%
rename from engine/src/jbullet/com/jme3/bullet/control/HumanoidRagdollPreset.java
rename to engine/src/jbullet/com/jme3/bullet/control/radoll/HumanoidRagdollPreset.java
index c3455760c..3d9207081 100644
--- a/engine/src/jbullet/com/jme3/bullet/control/HumanoidRagdollPreset.java
+++ b/engine/src/jbullet/com/jme3/bullet/control/radoll/HumanoidRagdollPreset.java
@@ -2,7 +2,7 @@
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
-package com.jme3.bullet.control;
+package com.jme3.bullet.control.radoll;
import com.jme3.math.FastMath;
diff --git a/engine/src/jbullet/com/jme3/bullet/control/RagdollPreset.java b/engine/src/jbullet/com/jme3/bullet/control/radoll/RagdollPreset.java
similarity index 98%
rename from engine/src/jbullet/com/jme3/bullet/control/RagdollPreset.java
rename to engine/src/jbullet/com/jme3/bullet/control/radoll/RagdollPreset.java
index 415b719fa..460cfc369 100644
--- a/engine/src/jbullet/com/jme3/bullet/control/RagdollPreset.java
+++ b/engine/src/jbullet/com/jme3/bullet/control/radoll/RagdollPreset.java
@@ -2,7 +2,7 @@
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
-package com.jme3.bullet.control;
+package com.jme3.bullet.control.radoll;
import com.jme3.bullet.joints.SixDofJoint;
import java.util.HashMap;
diff --git a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
index 359a3711a..368907991 100644
--- a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
+++ b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
@@ -91,11 +91,11 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletAppState = new BulletAppState();
bulletAppState.setEnabled(true);
stateManager.attach(bulletAppState);
- // bulletAppState.getPhysicsSpace().enableDebug(assetManager);
+ //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
setupLight();
- model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
+ model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
// model.setLocalTranslation(5, 0, 5);
// model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X));
@@ -109,24 +109,26 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
skeletonDebug.setLocalTranslation(model.getLocalTranslation());
//Note: PhysicsRagdollControl is still TODO, constructor will change
- ragdoll = new RagdollControl(1.0f);
+ ragdoll = new RagdollControl(0.7f);
+ setupSinbad(ragdoll);
ragdoll.addCollisionListener(this);
model.addControl(ragdoll);
float eighth_pi = FastMath.PI * 0.125f;
//Oto's head is almost rigid
- ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0);
+ // ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0);
getPhysicsSpace().add(ragdoll);
speed = 1.3f;
rootNode.attachChild(model);
+ // rootNode.attachChild(skeletonDebug);
flyCam.setMoveSpeed(50);
final AnimChannel channel = control.createChannel();
- channel.setAnim("Walk");
+ channel.setAnim("Dance");
inputManager.addListener(new ActionListener() {
@@ -137,6 +139,10 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
if (name.equals("shoot") && isPressed) {
timer = 0;
+ }
+ if (name.equals("stop") && isPressed) {
+ bulletAppState.setEnabled(!bulletAppState.isEnabled());
+
}
if (name.equals("shoot") && !isPressed) {
Geometry bulletg = new Geometry("bullet", bullet);
@@ -144,7 +150,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletg.setLocalTranslation(cam.getLocation());
bulletg.setLocalScale(timer);
bulletCollisionShape = new SphereCollisionShape(timer);
- // RigidBodyControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
+ // RigidBodyControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, timer * 10);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(80));
@@ -155,16 +161,17 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
}
}
- }, "toggle", "shoot");
+ }, "toggle", "shoot","stop");
inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
+ inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_H));
}
private void setupLight() {
AmbientLight al = new AmbientLight();
- // al.setColor(ColorRGBA.White.mult(1));
- // rootNode.addLight(al);
+ // al.setColor(ColorRGBA.White.mult(1));
+ // rootNode.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
@@ -208,22 +215,115 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
public void collide(Bone bone, PhysicsCollisionObject object) {
- if(object.getUserObject()!=null && object.getUserObject() instanceof Geometry){
- Geometry geom=(Geometry)object.getUserObject();
- if ("Floor".equals(geom.getName())) {
+ if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) {
+ Geometry geom = (Geometry) object.getUserObject();
+ if ("Floor".equals(geom.getName())) {
return;
}
}
-
-
+
+
if (!ragdoll.hasControl()) {
- // bulletTime();
+ //bulletTime();
ragdoll.setControl(true);
}
}
+ private void setupSinbad(RagdollControl ragdoll) {
+ ragdoll.addBoneName("Ulna.L");
+ ragdoll.addBoneName("Ulna.R");
+ ragdoll.addBoneName("Chest");
+ ragdoll.addBoneName("Foot.L");
+ ragdoll.addBoneName("Foot.R");
+ ragdoll.addBoneName("Hand.R");
+ ragdoll.addBoneName("Hand.L");
+ ragdoll.addBoneName("Neck");
+ ragdoll.addBoneName("Head");
+ ragdoll.addBoneName("Root");
+ ragdoll.addBoneName("Stomach");
+ ragdoll.addBoneName("Waist");
+ ragdoll.addBoneName("Humerus.L");
+ ragdoll.addBoneName("Humerus.R");
+ ragdoll.addBoneName("Thigh.L");
+ ragdoll.addBoneName("Thigh.R");
+ ragdoll.addBoneName("Calf.L");
+ ragdoll.addBoneName("Calf.R");
+ ragdoll.addBoneName("Clavicle.L");
+ ragdoll.addBoneName("Clavicle.R");
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+ }
+
private void bulletTime() {
speed = 0.1f;
elTime = 0;