- move KinematicRagdollControl to use AbstractPhysicsControl

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10370 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
nor..67 12 years ago
parent 2addc81210
commit 887c13142f
  1. 287
      engine/src/bullet-common/com/jme3/bullet/control/KinematicRagdollControl.java

@ -47,8 +47,10 @@ import com.jme3.bullet.control.ragdoll.RagdollPreset;
import com.jme3.bullet.control.ragdoll.RagdollUtils; import com.jme3.bullet.control.ragdoll.RagdollUtils;
import com.jme3.bullet.joints.SixDofJoint; import com.jme3.bullet.joints.SixDofJoint;
import com.jme3.bullet.objects.PhysicsRigidBody; import com.jme3.bullet.objects.PhysicsRigidBody;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter; import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter; import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
@ -92,31 +94,28 @@ import java.util.logging.Logger;
* *
* @author Normen Hansen and Rémy Bouquet (Nehon) * @author Normen Hansen and Rémy Bouquet (Nehon)
*/ */
public class KinematicRagdollControl implements PhysicsControl, PhysicsCollisionListener { public class KinematicRagdollControl extends AbstractPhysicsControl implements PhysicsCollisionListener {
protected static final Logger logger = Logger.getLogger(KinematicRagdollControl.class.getName()); protected static final Logger logger = Logger.getLogger(KinematicRagdollControl.class.getName());
protected Map<String, PhysicsBoneLink> boneLinks = new HashMap<String, PhysicsBoneLink>(); protected List<RagdollCollisionListener> listeners;
protected Skeleton skeleton; protected final Set<String> boneList = new TreeSet<String>();
protected PhysicsSpace space; protected final Map<String, PhysicsBoneLink> boneLinks = new HashMap<String, PhysicsBoneLink>();
protected boolean enabled = true; protected final Vector3f modelPosition = new Vector3f();
protected boolean debug = false; protected final Quaternion modelRotation = new Quaternion();
protected PhysicsRigidBody baseRigidBody; protected PhysicsRigidBody baseRigidBody;
protected float weightThreshold = -1.0f;
protected Spatial targetModel; protected Spatial targetModel;
protected Skeleton skeleton;
protected RagdollPreset preset = new HumanoidRagdollPreset();
protected Vector3f initScale; protected Vector3f initScale;
protected Mode mode = Mode.Kinematic; protected Mode mode = Mode.Kinematic;
protected boolean debug = false;
protected boolean blendedControl = false; protected boolean blendedControl = false;
protected float blendTime = 1.0f; protected float weightThreshold = -1.0f;
protected float blendStart = 0.0f; protected float blendStart = 0.0f;
protected List<RagdollCollisionListener> listeners; protected float blendTime = 1.0f;
protected float eventDispatchImpulseThreshold = 10; protected float eventDispatchImpulseThreshold = 10;
protected RagdollPreset preset = new HumanoidRagdollPreset();
protected Set<String> boneList = new TreeSet<String>();
protected Vector3f modelPosition = new Vector3f();
protected Quaternion modelRotation = new Quaternion();
protected float rootMass = 15; protected float rootMass = 15;
protected float totalMass = 0; protected float totalMass = 0;
protected boolean added = false;
public static enum Mode { public static enum Mode {
@ -166,7 +165,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
return; return;
} }
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
Quaternion tmpRot1 = vars.quat1; Quaternion tmpRot1 = vars.quat1;
Quaternion tmpRot2 = vars.quat2; Quaternion tmpRot2 = vars.quat2;
@ -270,13 +269,15 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Set the transforms of a rigidBody to match the transforms of a bone. * Set the transforms of a rigidBody to match the transforms of a bone. this
* this is used to make the ragdoll follow the skeleton motion while in Kinematic mode * is used to make the ragdoll follow the skeleton motion while in Kinematic
* mode
*
* @param link the link containing the bone and the rigidBody * @param link the link containing the bone and the rigidBody
* @param position just a temp vector for position * @param position just a temp vector for position
* @param tmpRot1 just a temp quaternion for rotation * @param tmpRot1 just a temp quaternion for rotation
*/ */
private void matchPhysicObjectToBone(PhysicsBoneLink link, Vector3f position, Quaternion tmpRot1) { protected void matchPhysicObjectToBone(PhysicsBoneLink link, Vector3f position, Quaternion tmpRot1) {
//computing position from rotation and scale //computing position from rotation and scale
targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position); targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position);
@ -291,23 +292,29 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
public Control cloneForSpatial(Spatial spatial) {
throw new UnsupportedOperationException("Not supported yet.");
}
/** /**
* rebuild the ragdoll * rebuild the ragdoll this is useful if you applied scale on the ragdoll
* this is useful if you applied scale on the ragdoll after it's been initialized * after it's been initialized, same as reattaching.
*/ */
public void reBuild() { public void reBuild() {
setSpatial(targetModel); if (added) {
addToPhysicsSpace(); removePhysics(space);
setSpatial(targetModel);
addPhysics(space);
} else {
setSpatial(targetModel);
}
} }
@Override
public void setSpatial(Spatial model) { public void setSpatial(Spatial model) {
super.setSpatial(model);
if (added) {
removePhysics(space);
}
boneLinks.clear();
baseRigidBody = null;
if (model == null) { if (model == null) {
removeFromPhysicsSpace();
clearData();
return; return;
} }
targetModel = model; targetModel = model;
@ -328,10 +335,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
SkeletonControl sc = model.getControl(SkeletonControl.class); SkeletonControl sc = model.getControl(SkeletonControl.class);
model.removeControl(sc); model.removeControl(sc);
model.addControl(sc); model.addControl(sc);
//----
removeFromPhysicsSpace();
clearData();
// put into bind pose and compute bone transforms in model space // put into bind pose and compute bone transforms in model space
// maybe dont reset to ragdoll out of animations? // maybe dont reset to ragdoll out of animations?
scanSpatial(model); scanSpatial(model);
@ -345,19 +349,23 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
model.setLocalRotation(initRotation); model.setLocalRotation(initRotation);
model.setLocalScale(initScale); model.setLocalScale(initScale);
if (added) {
addPhysics(space);
}
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton); logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
} }
/** /**
* Add a bone name to this control * Add a bone name to this control Using this method you can specify which
* Using this method you can specify which bones of the skeleton will be used to build the collision shapes. * bones of the skeleton will be used to build the collision shapes.
* @param name *
* @param name
*/ */
public void addBoneName(String name) { public void addBoneName(String name) {
boneList.add(name); boneList.add(name);
} }
private void scanSpatial(Spatial model) { protected void scanSpatial(Spatial model) {
AnimControl animControl = model.getControl(AnimControl.class); AnimControl animControl = model.getControl(AnimControl.class);
Map<Integer, List<Float>> pointsMap = null; Map<Integer, List<Float>> pointsMap = null;
if (weightThreshold == -1.0f) { if (weightThreshold == -1.0f) {
@ -377,7 +385,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
private void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) { protected void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) {
PhysicsRigidBody parentShape = parent; PhysicsRigidBody parentShape = parent;
if (boneList.isEmpty() || boneList.contains(bone.getName())) { if (boneList.isEmpty() || boneList.contains(bone.getName())) {
@ -429,6 +437,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
/** /**
* Set the joint limits for the joint between the given bone and its parent. * 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 * This method can't work before attaching the control to a spatial
*
* @param boneName the name of the bone * @param boneName the name of the bone
* @param maxX the maximum rotation on the x axis (in radians) * @param maxX the maximum rotation on the x axis (in radians)
* @param minX the minimum rotation on the x axis (in radians) * @param minX the minimum rotation on the x axis (in radians)
@ -447,8 +456,9 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Return the joint between the given bone and its parent. * Return the joint between the given bone and its parent. This return null
* This return null if it's called before attaching the control to a spatial * if it's called before attaching the control to a spatial
*
* @param boneName the name of the bone * @param boneName the name of the bone
* @return the joint between the given bone and its parent * @return the joint between the given bone and its parent
*/ */
@ -462,18 +472,24 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
private void clearData() { @Override
boneLinks.clear(); protected void setPhysicsLocation(Vector3f vec) {
baseRigidBody = null; if (baseRigidBody != null) {
baseRigidBody.setPhysicsLocation(vec);
}
} }
private void addToPhysicsSpace() { @Override
if (space == null) { protected void setPhysicsRotation(Quaternion quat) {
return; if (baseRigidBody != null) {
baseRigidBody.setPhysicsRotation(quat);
} }
}
@Override
protected void addPhysics(PhysicsSpace space) {
if (baseRigidBody != null) { if (baseRigidBody != null) {
space.add(baseRigidBody); space.add(baseRigidBody);
added = true;
} }
for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) { for (Iterator<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next(); PhysicsBoneLink physicsBoneLink = it.next();
@ -483,15 +499,13 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
space.add(physicsBoneLink.joint); space.add(physicsBoneLink.joint);
} }
added = true;
} }
} }
space.addCollisionListener(this);
} }
protected void removeFromPhysicsSpace() { @Override
if (space == null) { protected void removePhysics(PhysicsSpace space) {
return;
}
if (baseRigidBody != null) { if (baseRigidBody != null) {
space.remove(baseRigidBody); space.remove(baseRigidBody);
} }
@ -504,92 +518,13 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
} }
} }
added = false; space.removeCollisionListener(this);
}
/**
* enable or disable the control
* note that if enabled is true and that the physic space has been set on the ragdoll, the ragdoll is added to the physic space
* if enabled is false the ragdoll is removed from physic space.
* @param enabled
*/
public void setEnabled(boolean enabled) {
if (this.enabled == enabled) {
return;
}
this.enabled = enabled;
if (!enabled && space != null) {
removeFromPhysicsSpace();
} else if (enabled && space != null) {
addToPhysicsSpace();
}
} }
/** /**
* returns true if the control is enabled * For internal use only callback for collisionevent
* @return *
*/ * @param event
public boolean isEnabled() {
return enabled;
}
/**
* For internal use only
* specific render for the ragdoll(if debugging)
* @param rm
* @param vp
*/
public void render(RenderManager rm, ViewPort vp) {
}
/**
* set the physic space to this ragdoll
* @param space
*/
public void setPhysicsSpace(PhysicsSpace space) {
if (space == null) {
removeFromPhysicsSpace();
this.space = space;
} else {
if (this.space == space) {
return;
}
this.space = space;
addToPhysicsSpace();
this.space.addCollisionListener(this);
}
}
/**
* returns the physic space
* @return
*/
public PhysicsSpace getPhysicsSpace() {
return space;
}
/**
* serialize this control
* @param ex
* @throws IOException
*/
public void write(JmeExporter ex) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* de-serialize this control
* @param im
* @throws IOException
*/
public void read(JmeImporter im) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* For internal use only
* callback for collisionevent
* @param event
*/ */
public void collision(PhysicsCollisionEvent event) { public void collision(PhysicsCollisionEvent event) {
PhysicsCollisionObject objA = event.getObjectA(); PhysicsCollisionObject objA = event.getObjectA();
@ -639,11 +574,12 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Enable or disable the ragdoll behaviour. * Enable or disable the ragdoll behaviour. if ragdollEnabled is true, the
* if ragdollEnabled is true, the character motion will only be powerd by physics * character motion will only be powerd by physics else, the characted will
* else, the characted will be animated by the keyframe animation, * be animated by the keyframe animation, but will be able to physically
* but will be able to physically interact with its physic environnement * interact with its physic environnement
* @param ragdollEnabled *
* @param ragdollEnabled
*/ */
protected void setMode(Mode mode) { protected void setMode(Mode mode) {
this.mode = mode; this.mode = mode;
@ -652,7 +588,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
baseRigidBody.setKinematic(mode == Mode.Kinematic); baseRigidBody.setKinematic(mode == Mode.Kinematic);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
link.rigidBody.setKinematic(mode == Mode.Kinematic); link.rigidBody.setKinematic(mode == Mode.Kinematic);
if (mode == Mode.Ragdoll) { if (mode == Mode.Ragdoll) {
@ -671,8 +607,9 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Smoothly blend from Ragdoll mode to Kinematic mode * Smoothly blend from Ragdoll mode to Kinematic mode This is useful to
* This is useful to blend ragdoll actual position to a keyframe animation for example * blend ragdoll actual position to a keyframe animation for example
*
* @param blendTime the blending time between ragdoll to anim. * @param blendTime the blending time between ragdoll to anim.
*/ */
public void blendToKinematicMode(float blendTime) { public void blendToKinematicMode(float blendTime) {
@ -686,7 +623,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
animControl.setEnabled(true); animControl.setEnabled(true);
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
@ -715,9 +652,9 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Set the control into Kinematic mode * Set the control into Kinematic mode In theis mode, the collision shapes
* In theis mode, the collision shapes follow the movements of the skeleton, * follow the movements of the skeleton, and can interact with physical
* and can interact with physical environement * environement
*/ */
public void setKinematicMode() { public void setKinematicMode() {
if (mode != Mode.Kinematic) { if (mode != Mode.Kinematic) {
@ -726,8 +663,8 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
/** /**
* Sets the control into Ragdoll mode * Sets the control into Ragdoll mode The skeleton is entirely controlled by
* The skeleton is entirely controlled by physics. * physics.
*/ */
public void setRagdollMode() { public void setRagdollMode() {
if (mode != Mode.Ragdoll) { if (mode != Mode.Ragdoll) {
@ -737,15 +674,17 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
/** /**
* retruns the mode of this control * retruns the mode of this control
* @return *
* @return
*/ */
public Mode getMode() { public Mode getMode() {
return mode; return mode;
} }
/** /**
* add a * add a
* @param listener *
* @param listener
*/ */
public void addCollisionListener(RagdollCollisionListener listener) { public void addCollisionListener(RagdollCollisionListener listener) {
if (listeners == null) { if (listeners == null) {
@ -780,8 +719,9 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
/** /**
* Set the CcdMotionThreshold of all the bone's rigidBodies of the ragdoll * Set the CcdMotionThreshold of all the bone's rigidBodies of the ragdoll
* @see PhysicsRigidBody#setCcdMotionThreshold(float) *
* @param value * @see PhysicsRigidBody#setCcdMotionThreshold(float)
* @param value
*/ */
public void setCcdMotionThreshold(float value) { public void setCcdMotionThreshold(float value) {
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
@ -791,8 +731,9 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
/** /**
* Set the CcdSweptSphereRadius of all the bone's rigidBodies of the ragdoll * Set the CcdSweptSphereRadius of all the bone's rigidBodies of the ragdoll
* @see PhysicsRigidBody#setCcdSweptSphereRadius(float) *
* @param value * @see PhysicsRigidBody#setCcdSweptSphereRadius(float)
* @param value
*/ */
public void setCcdSweptSphereRadius(float value) { public void setCcdSweptSphereRadius(float value) {
for (PhysicsBoneLink link : boneLinks.values()) { for (PhysicsBoneLink link : boneLinks.values()) {
@ -802,6 +743,7 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
/** /**
* return the rigidBody associated to the given bone * return the rigidBody associated to the given bone
*
* @param boneName the name of the bone * @param boneName the name of the bone
* @return the associated rigidBody. * @return the associated rigidBody.
*/ */
@ -812,4 +754,39 @@ public class KinematicRagdollControl implements PhysicsControl, PhysicsCollision
} }
return null; return null;
} }
/**
* For internal use only specific render for the ragdoll(if debugging)
*
* @param rm
* @param vp
*/
public void render(RenderManager rm, ViewPort vp) {
}
public Control cloneForSpatial(Spatial spatial) {
throw new UnsupportedOperationException("Not supported yet.");
}
/**
* serialize this control
*
* @param ex
* @throws IOException
*/
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
}
/**
* de-serialize this control
*
* @param im
* @throws IOException
*/
public void read(JmeImporter im) throws IOException {
super.read(im);
InputCapsule ic = im.getCapsule(this);
}
} }

Loading…
Cancel
Save