- RagdollControl now uses SixDofJoints instead of ConeJoints.

- Ragdoll joints are now fully tweakable by user
- Changed controls in TestBoneRagdoll : keep left click pressed longer to throw bigger bullets.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7223 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent c5ac1c8bfe
commit 6417263674
  1. 227
      engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
  2. 69
      engine/src/test/jme3test/bullet/TestBoneRagdoll.java

@ -12,8 +12,8 @@ import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.RagdollCollisionListener; import com.jme3.bullet.collision.RagdollCollisionListener;
import com.jme3.bullet.collision.shapes.BoxCollisionShape; import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.HullCollisionShape; import com.jme3.bullet.collision.shapes.HullCollisionShape;
import com.jme3.bullet.joints.ConeJoint;
import com.jme3.bullet.joints.PhysicsJoint; import com.jme3.bullet.joints.PhysicsJoint;
import com.jme3.bullet.joints.SixDofJoint;
import com.jme3.bullet.objects.PhysicsRigidBody; import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
@ -33,16 +33,17 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class RagdollControl implements PhysicsControl, PhysicsCollisionListener { public class RagdollControl implements PhysicsControl, PhysicsCollisionListener {
protected static final Logger logger = Logger.getLogger(RagdollControl.class.getName()); protected static final Logger logger = Logger.getLogger(RagdollControl.class.getName());
protected List<PhysicsBoneLink> boneLinks = new LinkedList<PhysicsBoneLink>(); protected Map<String, PhysicsBoneLink> boneLinks = new HashMap<String, PhysicsBoneLink>();
protected Skeleton skeleton; protected Skeleton skeleton;
protected PhysicsSpace space; protected PhysicsSpace space;
protected boolean enabled = true; protected boolean enabled = true;
@ -53,20 +54,11 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
protected Spatial targetModel; protected Spatial targetModel;
protected Vector3f initPosition; protected Vector3f initPosition;
protected Quaternion initRotation; protected Quaternion initRotation;
protected Quaternion invInitRotation;
protected Vector3f initScale; protected Vector3f initScale;
protected boolean control = false; protected boolean control = false;
protected List<RagdollCollisionListener> listeners; protected List<RagdollCollisionListener> listeners;
//Normen: Think you have the system you want, with movement
//Normen: but the rootBone movement and translation is also accessible like getRootBoneLocation()
//Normen: and you can disable the applying of it
//Normen: setApplyRootBoneMovement(false)
//Normen: when you add a RigidBodyControl..
//Normen: it does this in setSpatial:
//Normen: if (spatial.getcontrol(AnimControl.class)){animControl.setApplyRootBoneMovement(false)
//Normen: and instead reads the current location and sets it to the RigidBody
//Normen: simply said
//Normen: update(){setPhysicsLocation(animControl.getRootBoneLocation())
public RagdollControl() { public RagdollControl() {
} }
@ -84,33 +76,51 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
Quaternion q2 = vars.quat1; Quaternion q2 = vars.quat1;
// skeleton.reset(); // skeleton.reset();
for (PhysicsBoneLink link : boneLinks) { for (PhysicsBoneLink link : boneLinks.values()) {
// if(link.bone==skeleton.getRoots()[0]){
// Vector3f loc=vars.vect1;
// loc.set(baseRigidBody.getMotionState().getWorldLocation());//.subtractLocal(rootBoneInit);
// ((Geometry)targetModel).setLocalTranslation(loc);
//
// }
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
Vector3f position = vars.vect1;
//.multLocal(invInitRotation)
// invInitRotation.mult(p,position);
position.set(p).subtractLocal(initPosition);
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat(); Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
q2.set(q).multLocal(link.initalWorldRotation).normalize(); q2.set(q).multLocal(link.initalWorldRotation).normalize();
if (link.bone.getParent() == null) {
// targetModel.getLocalTransform().setTranslation(position);
// Vector3f loc=vars.vect1;
// loc.set(baseRigidBody.getMotionState().getWorldLocation());//.subtractLocal(rootBoneInit);
// (targetModel).setLocalTranslation(loc);
//
}
link.bone.setUserControl(true); link.bone.setUserControl(true);
link.bone.setUserTransformsWorld(p, q2); link.bone.setUserTransformsWorld(position, q2);
} }
targetModel.updateModelBound();
} else { } else {
for (PhysicsBoneLink link : boneLinks) { for (PhysicsBoneLink link : boneLinks.values()) {
//the ragdoll does not control the skeleton
link.bone.setUserControl(false); link.bone.setUserControl(false);
Vector3f position = vars.vect1; Vector3f position = vars.vect1;
Quaternion rotation = vars.quat1; Quaternion rotation = vars.quat1;
Vector3f scale = vars.vect2; //Vector3f pos2 = vars.vect2;
//computing position from rotation and scale
initRotation.mult(link.bone.getModelSpacePosition(), position);
position.addLocal(initPosition);
//computing rotation
rotation.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation()).multLocal(initRotation);
position.set(link.bone.getModelSpacePosition()); // scale.set(link.bone.getModelSpaceScale());
rotation.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation());
scale.set(link.bone.getModelSpaceScale());
link.rigidBody.setPhysicsLocation(position); link.rigidBody.setPhysicsLocation(position);
link.rigidBody.setPhysicsRotation(rotation); link.rigidBody.setPhysicsRotation(rotation);
} }
@ -118,7 +128,6 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
assert vars.unlock(); assert vars.unlock();
//baseRigidBody.getMotionState().applyTransform(targetModel);
} }
@ -128,7 +137,17 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
public void setSpatial(Spatial model) { public void setSpatial(Spatial model) {
targetModel = model; targetModel = model;
Node parent = model.getParent();
initPosition = model.getLocalTranslation().clone();
initRotation = model.getLocalRotation().clone();
invInitRotation = initRotation.inverse();
initScale = model.getLocalScale().clone();
model.removeFromParent();
model.setLocalTranslation(Vector3f.ZERO);
model.setLocalRotation(Quaternion.ZERO);
model.setLocalScale(1);
//HACK ALERT change this //HACK ALERT change this
//I remove the skeletonControl and readd it to the spatial to make sure it's after the ragdollControl in the stack //I remove the skeletonControl and readd it to the spatial to make sure it's after the ragdollControl in the stack
//Find a proper way to order the controls. //Find a proper way to order the controls.
@ -143,6 +162,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
// maybe dont reset to ragdoll out of animations? // maybe dont reset to ragdoll out of animations?
scanSpatial(model); scanSpatial(model);
System.out.println("parent " + parent);
if (parent != null) {
parent.attachChild(model);
}
model.setLocalTranslation(initPosition);
model.setLocalRotation(initRotation);
model.setLocalScale(initScale);
logger.log(Level.INFO, "Create physics ragdoll for skeleton {0}", skeleton); logger.log(Level.INFO, "Create physics ragdoll for skeleton {0}", skeleton);
} }
@ -153,10 +181,6 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
private void scanSpatial(Spatial model) { private void scanSpatial(Spatial model) {
AnimControl animControl = model.getControl(AnimControl.class); AnimControl animControl = model.getControl(AnimControl.class);
initPosition = model.getLocalTranslation();
initRotation = model.getLocalRotation();
initScale = model.getLocalScale();
skeleton = animControl.getSkeleton(); skeleton = animControl.getSkeleton();
skeleton.resetAndUpdate(); skeleton.resetAndUpdate();
for (int i = 0; i < skeleton.getRoots().length; i++) { for (int i = 0; i < skeleton.getRoots().length; i++) {
@ -164,44 +188,35 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
// childBone.setUserControl(true); // childBone.setUserControl(true);
if (childBone.getParent() == null) { if (childBone.getParent() == null) {
Vector3f parentPos = childBone.getModelSpacePosition().add(initPosition); Vector3f parentPos = childBone.getModelSpacePosition().add(initPosition);
// Quaternion parentRot= childBone.getModelSpaceRotation().mult(initRotation); // Quaternion parentRot= childBone.getModelSpaceRotation().mult(initRotation);
logger.log(Level.INFO, "Found root bone in skeleton {0}", skeleton); logger.log(Level.INFO, "Found root bone in skeleton {0}", skeleton);
baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(.1f)), 1); baseRigidBody = new PhysicsRigidBody(new BoxCollisionShape(Vector3f.UNIT_XYZ.mult(.1f)), 1);
baseRigidBody.setPhysicsLocation(parentPos); baseRigidBody.setPhysicsLocation(parentPos);
// baseRigidBody.setPhysicsRotation(parentRot); // baseRigidBody.setPhysicsRotation(parentRot);
boneLinks = boneRecursion(model, childBone, baseRigidBody, boneLinks, 1); boneLinks = boneRecursion(model, childBone, baseRigidBody, boneLinks, 1);
return; return;
} }
} }
// BoneAnimation myAnimation = new BoneAnimation("boneAnimation", 1000000);
// myAnimation.setTracks(new BoneTrack[0]);
// animControl.addAnim(myAnimation);
// animControl.createChannel().setAnim("boneAnimation");
} }
private List<PhysicsBoneLink> boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, List<PhysicsBoneLink> list, int reccount) { private Map<String, PhysicsBoneLink> boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, Map<String, PhysicsBoneLink> list, int reccount) {
//Allow bone's transformation change outside of animation
// bone.setUserControl(true);
//get world space position of the bone //get world space position of the bone
Vector3f pos = bone.getModelSpacePosition().add(model.getLocalTranslation()); Vector3f pos = bone.getModelSpacePosition().add(model.getLocalTranslation());
Quaternion rot = bone.getModelSpaceRotation().mult(initRotation); // Quaternion rot = bone.getModelSpaceRotation().mult(initRotation);
//creating the collision shape from the bone's associated vertices //creating the collision shape from the bone's associated vertices
PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model),10.0f / (float) reccount); PhysicsRigidBody shapeNode = new PhysicsRigidBody(makeShape(bone, model), 10.0f / (float) reccount);
shapeNode.setPhysicsLocation(pos); shapeNode.setPhysicsLocation(pos);
// shapeNode.setPhysicsRotation(rot);
// shapeNode.setPhysicsRotation(rot);
PhysicsBoneLink link = new PhysicsBoneLink(); PhysicsBoneLink link = new PhysicsBoneLink();
link.bone = bone; link.bone = bone;
link.rigidBody = shapeNode; link.rigidBody = shapeNode;
link.initalWorldRotation = bone.getModelSpaceRotation().clone(); link.initalWorldRotation = bone.getModelSpaceRotation().clone();
link.mass=10.0f / (float) reccount; // link.mass = 10.0f / (float) reccount;
//TODO: ragdoll mass 1 //TODO: ragdoll mass 1
if (parent != null) { if (parent != null) {
@ -216,14 +231,14 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
//joint local position from current bone //joint local position from current bone
link.pivotB = new Vector3f(0, 0, 0f); link.pivotB = new Vector3f(0, 0, 0f);
ConeJoint joint = new ConeJoint(parent, shapeNode, link.pivotA, link.pivotB); SixDofJoint joint = new SixDofJoint(parent, shapeNode, link.pivotA, link.pivotB, true);
//TODO make joints editable by user or find a way to correctly compute/import them //TODO find a way to correctly compute/import joints (maybe based on their names)
joint.setLimit(FastMath.HALF_PI, FastMath.HALF_PI, 0.01f); setJointLimit(joint, 0, 0, 0, 0, 0, 0);
link.joint = joint; link.joint = joint;
joint.setCollisionBetweenLinkedBodys(false); joint.setCollisionBetweenLinkedBodys(false);
} }
list.add(link); list.put(bone.getName(), link);
for (Iterator<Bone> it = bone.getChildren().iterator(); it.hasNext();) { for (Iterator<Bone> it = bone.getChildren().iterator(); it.hasNext();) {
Bone childBone = it.next(); Bone childBone = it.next();
@ -232,6 +247,52 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return list; return list;
} }
/**
* Set the joint limits for the joint between the given bone and its parent.
* This method can't work before attaching the control to a spatial
* @param boneName the name of the bone
* @param maxX the maximum rotation on the x axis (in radians)
* @param minX the minimum rotation on the x axis (in radians)
* @param maxY the maximum rotation on the y axis (in radians)
* @param minY the minimum rotation on the z axis (in radians)
* @param maxZ the maximum rotation on the z axis (in radians)
* @param minZ the minimum rotation on the z axis (in radians)
*/
public void setJointLimit(String boneName, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
PhysicsBoneLink link = boneLinks.get(boneName);
if (link != null) {
setJointLimit(link.joint, maxX, minX, maxY, minY, maxZ, minZ);
} else {
logger.log(Level.WARNING, "Not joint was found for bone {0}. make sure you call spatial.addControl(ragdoll) before setting joints limit", boneName);
}
}
/**
* Return the joint between the given bone and its parent.
* This return null if it's called before attaching the control to a spatial
* @param boneName the name of the bone
* @return the joint between the given bone and its parent
*/
public SixDofJoint getJoint(String boneName) {
PhysicsBoneLink link = boneLinks.get(boneName);
if (link != null) {
return link.joint;
} else {
logger.log(Level.WARNING, "Not joint was found for bone {0}. make sure you call spatial.addControl(ragdoll) before setting joints limit", boneName);
return null;
}
}
private void setJointLimit(SixDofJoint joint, float maxX, float minX, float maxY, float minY, float maxZ, float minZ) {
joint.getRotationalLimitMotor(0).setHiLimit(maxX);
joint.getRotationalLimitMotor(0).setLoLimit(minX);
joint.getRotationalLimitMotor(1).setHiLimit(maxY);
joint.getRotationalLimitMotor(1).setLoLimit(minY);
joint.getRotationalLimitMotor(2).setHiLimit(maxZ);
joint.getRotationalLimitMotor(2).setLoLimit(minZ);
}
private void clearData() { private void clearData() {
boneLinks.clear(); boneLinks.clear();
baseRigidBody = null; baseRigidBody = null;
@ -241,13 +302,13 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if (baseRigidBody != null) { if (baseRigidBody != null) {
space.add(baseRigidBody); space.add(baseRigidBody);
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.rigidBody != null) { if (physicsBoneLink.rigidBody != null) {
space.add(physicsBoneLink.rigidBody); space.add(physicsBoneLink.rigidBody);
} }
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.joint != null) { if (physicsBoneLink.joint != null) {
space.add(physicsBoneLink.joint); space.add(physicsBoneLink.joint);
@ -320,13 +381,13 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if (baseRigidBody != null) { if (baseRigidBody != null) {
space.remove(baseRigidBody); space.remove(baseRigidBody);
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.joint != null) { if (physicsBoneLink.joint != null) {
space.remove(physicsBoneLink.joint); space.remove(physicsBoneLink.joint);
} }
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.rigidBody != null) { if (physicsBoneLink.rigidBody != null) {
space.remove(physicsBoneLink.rigidBody); space.remove(physicsBoneLink.rigidBody);
@ -348,7 +409,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
} }
public void attachDebugShape(AssetManager manager) { public void attachDebugShape(AssetManager manager) {
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
physicsBoneLink.rigidBody.attachDebugShape(manager); physicsBoneLink.rigidBody.attachDebugShape(manager);
} }
@ -356,7 +417,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
} }
public void detachDebugShape() { public void detachDebugShape() {
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
physicsBoneLink.rigidBody.detachDebugShape(); physicsBoneLink.rigidBody.detachDebugShape();
} }
@ -368,7 +429,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if (!debug) { if (!debug) {
attachDebugShape(space.getDebugManager()); attachDebugShape(space.getDebugManager());
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
Spatial debugShape = physicsBoneLink.rigidBody.debugShape(); Spatial debugShape = physicsBoneLink.rigidBody.debugShape();
if (debugShape != null) { if (debugShape != null) {
@ -410,32 +471,25 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
public void collision(PhysicsCollisionEvent event) { public void collision(PhysicsCollisionEvent event) {
PhysicsCollisionObject objA = event.getObjectA(); PhysicsCollisionObject objA = event.getObjectA();
PhysicsCollisionObject objB = event.getObjectB(); PhysicsCollisionObject objB = event.getObjectB();
// System.out.println("----------------------------");
// System.out.println("NodeA "+event.getNodeA());
// System.out.println("NodeB "+event.getNodeB());
if (event == null) {
return;
}
if (event.getNodeA() != null && "Floor".equals(event.getNodeA().getName())) { if (event.getNodeA() != null && "Floor".equals(event.getNodeA().getName())) {
return; return;
} }
if (event.getNodeB() != null && "Floor".equals(event.getNodeB().getName())) { if (event.getNodeB() != null && "Floor".equals(event.getNodeB().getName())) {
return; return;
} }
// if(event.getNodeB() == null && event.getNodeA() ==null){
// return;
// }
if (event.getAppliedImpulse() < 3.0) { if (event.getAppliedImpulse() < 3.0) {
return; return;
} }
boolean hit = false; boolean hit = false;
Bone hitBone=null; Bone hitBone = null;
PhysicsCollisionObject hitObject=null; PhysicsCollisionObject hitObject = null;
if (objA instanceof PhysicsRigidBody) { if (objA instanceof PhysicsRigidBody) {
PhysicsRigidBody prb = (PhysicsRigidBody) objA; PhysicsRigidBody prb = (PhysicsRigidBody) objA;
for (PhysicsBoneLink physicsBoneLink : boneLinks) { for (PhysicsBoneLink physicsBoneLink : boneLinks.values()) {
if (physicsBoneLink.rigidBody == prb) { if (physicsBoneLink.rigidBody == prb) {
hit = true; hit = true;
hitBone = physicsBoneLink.bone; hitBone = physicsBoneLink.bone;
@ -447,7 +501,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
} }
if (objB instanceof PhysicsRigidBody) { if (objB instanceof PhysicsRigidBody) {
PhysicsRigidBody prb = (PhysicsRigidBody) objB; PhysicsRigidBody prb = (PhysicsRigidBody) objB;
for (PhysicsBoneLink physicsBoneLink : boneLinks) { for (PhysicsBoneLink physicsBoneLink : boneLinks.values()) {
if (physicsBoneLink.rigidBody == prb) { if (physicsBoneLink.rigidBody == prb) {
hit = false; hit = false;
hitBone = physicsBoneLink.bone; hitBone = physicsBoneLink.bone;
@ -468,28 +522,14 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
} }
public void setControl(boolean control) { public void setControl(boolean control) {
this.control = control;
AnimControl animControl = targetModel.getControl(AnimControl.class); AnimControl animControl = targetModel.getControl(AnimControl.class);
animControl.setEnabled(!control); animControl.setEnabled(!control);
//
for (PhysicsBoneLink link : boneLinks) { this.control = control;
link.bone.setUserControl(control); for (PhysicsBoneLink link : boneLinks.values()) {
// TempVars vars=TempVars.get(); link.bone.setUserControl(control);
// assert vars.lock(); }
// Vector3f position = vars.vect1;
// Quaternion rotation = vars.quat1;
// Vector3f scale = vars.vect2;
// position.set(link.bone.getModelSpacePosition());
// rotation.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation());
// scale.set(link.bone.getModelSpaceScale());
// link.rigidBody.setPhysicsLocation(position);
// link.rigidBody.setPhysicsRotation(rotation);
// assert vars.unlock();
// link.bone.setUserControl(control);
//
//
// link.rigidBody.setMass(control?link.mass:0);
}
} }
@ -511,13 +551,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
} }
protected static class PhysicsBoneLink { protected static class PhysicsBoneLink {
Bone bone; Bone bone;
Quaternion initalWorldRotation; Quaternion initalWorldRotation;
PhysicsJoint joint; SixDofJoint joint;
PhysicsRigidBody rigidBody; PhysicsRigidBody rigidBody;
Vector3f pivotA; Vector3f pivotA;
Vector3f pivotB; Vector3f pivotB;
float mass; // float mass;
} }
} }

@ -31,10 +31,8 @@
*/ */
package jme3test.bullet; package jme3test.bullet;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl; import com.jme3.animation.AnimControl;
import com.jme3.animation.Bone; import com.jme3.animation.Bone;
import com.jme3.animation.LoopMode;
import com.jme3.bullet.BulletAppState; import com.jme3.bullet.BulletAppState;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey; import com.jme3.asset.TextureKey;
@ -45,7 +43,6 @@ import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.RagdollControl; import com.jme3.bullet.control.RagdollControl;
import com.jme3.bullet.control.RigidBodyControl; import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.font.BitmapText; import com.jme3.font.BitmapText;
import com.jme3.input.ChaseCamera;
import com.jme3.input.KeyInput; import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput; import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.ActionListener;
@ -54,6 +51,7 @@ import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
@ -73,6 +71,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
Material matBullet; Material matBullet;
Node model; Node model;
RagdollControl ragdoll; RagdollControl ragdoll;
float timer = 0;
public static void main(String[] args) { public static void main(String[] args) {
TestBoneRagdoll app = new TestBoneRagdoll(); TestBoneRagdoll app = new TestBoneRagdoll();
@ -90,12 +89,12 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletAppState = new BulletAppState(); bulletAppState = new BulletAppState();
bulletAppState.setEnabled(true); bulletAppState.setEnabled(true);
stateManager.attach(bulletAppState); stateManager.attach(bulletAppState);
// bulletAppState.getPhysicsSpace().enableDebug(assetManager); // bulletAppState.getPhysicsSpace().enableDebug(assetManager);
PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace()); PhysicsTestHelper.createPhysicsTestWorld(rootNode, assetManager, bulletAppState.getPhysicsSpace());
setupLight(); setupLight();
model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml"); model = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
// model.setLocalTranslation(5,5,5); // model.setLocalTranslation(5, 0, 5);
// model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X)); // model.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_X));
//debug view //debug view
@ -114,39 +113,66 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
//Note: PhysicsRagdollControl is still TODO, constructor will change //Note: PhysicsRagdollControl is still TODO, constructor will change
ragdoll = new RagdollControl(); ragdoll = new RagdollControl(1.0f);
ragdoll.addCollisionListener(this); ragdoll.addCollisionListener(this);
// ragdoll.setEnabled(true); model.addControl(ragdoll);
// ragdoll.attachDebugShape(assetManager);
ragdoll.setJointLimit("head", FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("spinehigh", FastMath.QUARTER_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("hip.right", FastMath.PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("hip.left", FastMath.PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("leg.left", 0, -FastMath.PI, 0, 0, 0, 0);
ragdoll.setJointLimit("leg.right", 0, -FastMath.PI, 0, 0, 0, 0);
ragdoll.setJointLimit("foot.right", 0, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("foot.left", 0, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("uparm.right", FastMath.HALF_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.QUARTER_PI, -FastMath.HALF_PI);
ragdoll.setJointLimit("uparm.left", FastMath.HALF_PI, -FastMath.QUARTER_PI, 0, 0, FastMath.QUARTER_PI, -FastMath.HALF_PI);
ragdoll.setJointLimit("arm.right", FastMath.PI, 0, 0, 0, 0, 0);
ragdoll.setJointLimit("arm.left", FastMath.PI, 0, 0, 0, 0, 0);
ragdoll.setJointLimit("hand.right", FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
ragdoll.setJointLimit("hand.left", FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI, FastMath.QUARTER_PI, -FastMath.QUARTER_PI);
// ragdoll.setSpatial(model);
// ragdoll.setPhysicsSpace(getPhysicsSpace());
// control.setRagdoll(ragdoll);
model.addControl(ragdoll);
getPhysicsSpace().add(ragdoll); getPhysicsSpace().add(ragdoll);
speed = 1f; speed = 1.3f;
rootNode.attachChild(model); rootNode.attachChild(model);
// rootNode.attachChild(skeletonDebug); // rootNode.attachChild(skeletonDebug);
//flyCam.setEnabled(false); //flyCam.setEnabled(false);
flyCam.setMoveSpeed(50); flyCam.setMoveSpeed(50);
// ChaseCamera chaseCamera=new ChaseCamera(cam, inputManager); // ChaseCamera chaseCamera=new ChaseCamera(cam, inputManager);
// chaseCamera.setLookAtOffset(Vector3f.UNIT_Y.mult(4)); // chaseCamera.setLookAtOffset(Vector3f.UNIT_Y.mult(4));
// model.addControl(chaseCamera); // model.addControl(chaseCamera);
inputManager.addListener(new ActionListener() { inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) { public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("toggle") && isPressed) { if (name.equals("toggle") && isPressed) {
ragdoll.setControl(false); ragdoll.setControl(false);
} }
if (name.equals("shoot") && isPressed) {
timer = 0;
}
if (name.equals("shoot") && !isPressed) { if (name.equals("shoot") && !isPressed) {
Geometry bulletg = new Geometry("bullet", bullet); Geometry bulletg = new Geometry("bullet", bullet);
bulletg.setMaterial(matBullet); bulletg.setMaterial(matBullet);
bulletg.setLocalTranslation(cam.getLocation()); 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, 50); RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, timer * 10);
bulletNode.setLinearVelocity(cam.getDirection().mult(80)); bulletNode.setLinearVelocity(cam.getDirection().mult(80));
bulletg.addControl(bulletNode); bulletg.addControl(bulletNode);
rootNode.attachChild(bulletg); rootNode.attachChild(bulletg);
@ -174,12 +200,12 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
Material mat; Material mat;
Material mat3; Material mat3;
private static final Sphere bullet; private static final Sphere bullet;
private static final SphereCollisionShape bulletCollisionShape; private static SphereCollisionShape bulletCollisionShape;
static { static {
bullet = new Sphere(32, 32, 0.4f, true, false); bullet = new Sphere(32, 32, 1.0f, true, false);
bullet.setTextureMode(TextureMode.Projected); bullet.setTextureMode(TextureMode.Projected);
bulletCollisionShape = new SphereCollisionShape(0.4f); bulletCollisionShape = new SphereCollisionShape(1.0f);
} }
public void initMaterial() { public void initMaterial() {
@ -203,9 +229,12 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
} }
public void collide(Bone bone, PhysicsCollisionObject object) { public void collide(Bone bone, PhysicsCollisionObject object) {
if (!ragdoll.hasControl()) { if (!ragdoll.hasControl()) {
bulletTime();
// bulletTime();
ragdoll.setControl(true); ragdoll.setControl(true);
} }
} }
@ -217,9 +246,11 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
@Override @Override
public void simpleUpdate(float tpf) { public void simpleUpdate(float tpf) {
// System.out.println(model.getLocalTranslation());
elTime += tpf; elTime += tpf;
if (elTime > 0.05f && speed < 1.0f) { if (elTime > 0.05f && speed < 1.0f) {
speed += tpf * 8; speed += tpf * 8;
} }
timer += tpf;
} }
} }

Loading…
Cancel
Save