/** * Create a shallow clone for the JME cloner. * * @return a new control (not null) */ @Override public Object jmeClone() { KinematicRagdollControl control = new KinematicRagdollControl(preset, weightThreshold); control.setMode(mode); control.setRootMass(rootMass); control.setWeightThreshold(weightThreshold); control.setApplyPhysicsLocal(applyLocal); control.spatial = this.spatial; return control; }
/** * Ensure that user control is enabled for any bones used by inverse * kinematics and disabled for any other bones. */ public void applyUserControl() { for (Bone bone : skeleton.getRoots()) { RagdollUtils.setUserControl(bone, false); } if (ikTargets.isEmpty()) { setKinematicMode(); } else { Iterator iterator = ikTargets.keySet().iterator(); TempVars vars = TempVars.get(); while (iterator.hasNext()) { Bone bone = (Bone) iterator.next(); while (bone.getParent() != null) { Quaternion tmpRot1 = vars.quat1; Vector3f position = vars.vect1; matchPhysicObjectToBone(boneLinks.get(bone.getName()), position, tmpRot1); bone.setUserControl(true); bone = bone.getParent(); } } vars.release(); } }
/** * Remove all inverse-kinematics targets. */ public void removeAllIKTargets(){ ikTargets.clear(); ikChainDepth.clear(); applyUserControl(); }
/** * Rebuild the ragdoll. This is useful if you applied scale on the ragdoll * after it was initialized. Same as re-attaching. */ public void reBuild() { if (spatial == null) { return; } removeSpatialData(spatial); createSpatialData(spatial); }
/** * Update this control. Invoked once per frame during the logical-state * update, provided the control is added to a scene. Do not invoke directly * from user code. * * @param tpf the time interval between frames (in seconds, ≥0) */ @Override public void update(float tpf) { if (!enabled) { return; } if(mode == Mode.IK){ ikUpdate(tpf); } else if (mode == mode.Ragdoll && targetModel.getLocalTranslation().equals(modelPosition)) { //if the ragdoll has the control of the skeleton, we update each bone with its position in physics world space. ragDollUpdate(tpf); } else { kinematicUpdate(tpf); } }
/** * Put the control into Kinematic mode. In this mode, the collision shapes * follow the movements of the skeleton while interacting with the physics * environment. */ public void setKinematicMode() { if (mode != Mode.Kinematic) { setMode(Mode.Kinematic); } }
filterBoneList(sc); scanSpatial(model); addPhysics(space);
updateBone(boneLinks.get(bone.getName()), tpf * (float) FastMath.sqrt(distance), vars, tmpRot1, tmpRot2, bone, ikTargets.get(boneName), depth, maxDepth); matchPhysicObjectToBone(link, position, tmpRot1);
/** * Generate physics shapes and bone links for the skeleton. * * @param model the spatial with the model's SkeletonControl (not null) */ protected void scanSpatial(Spatial model) { AnimControl animControl = model.getControl(AnimControl.class); Map<Integer, List<Float>> pointsMap = null; if (weightThreshold == -1.0f) { pointsMap = RagdollUtils.buildPointMap(model); } skeleton = animControl.getSkeleton(); skeleton.resetAndUpdate(); for (int i = 0; i < skeleton.getRoots().length; i++) { Bone childBone = skeleton.getRoots()[i]; if (childBone.getParent() == null) { logger.log(Level.FINE, "Found root bone in skeleton {0}", skeleton); boneRecursion(model, childBone, baseRigidBody, 1, pointsMap); } } }
Vector3f position = vars.vect1; matchPhysicObjectToBone(link, position, tmpRot1);
ragdoll = new KinematicRagdollControl(0.5f); setupSinbad(ragdoll); ragdoll.addCollisionListener(this); model.addControl(ragdoll); ragdoll.setJointLimit("Waist", eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi, eighth_pi); ragdoll.setJointLimit("Chest", eighth_pi, eighth_pi, 0, 0, eighth_pi, eighth_pi);
scanSpatial(model); addPhysics(space);
KinematicRagdollControl ragdoll = new KinematicRagdollControl(0.5f); sinbad.addControl(ragdoll);
public void setSpatial(Spatial model) { if (model == null) { removeFromPhysicsSpace(); clearData(); return; removeFromPhysicsSpace(); clearData(); scanSpatial(model);
@Override public synchronized void setKinematicMode() { // theLogger.info("setKinematicMode()"); super.setKinematicMode(); }
/** * Update this control. Invoked once per frame during the logical-state * update, provided the control is added to a scene. Do not invoke directly * from user code. * * @param tpf the time interval between frames (in seconds, ≥0) */ @Override public void update(float tpf) { if (!enabled) { return; } if(mode == Mode.IK){ ikUpdate(tpf); } else if (mode == mode.Ragdoll && targetModel.getLocalTranslation().equals(modelPosition)) { //if the ragdoll has the control of the skeleton, we update each bone with its position in physics world space. ragDollUpdate(tpf); } else { kinematicUpdate(tpf); } }
/** * Sets the control into Ragdoll mode The skeleton is entirely controlled by * physics. */ public void setRagdollMode() { if (mode != Mode.Ragdoll) { setMode(Mode.Ragdoll); } }
filterBoneList(sc); scanSpatial(model); addPhysics(space);
updateBone(boneLinks.get(bone.getName()), tpf * (float) FastMath.sqrt(distance), vars, tmpRot1, tmpRot2, bone, ikTargets.get(boneName), depth, maxDepth); matchPhysicObjectToBone(link, position, tmpRot1);
/** * Rebuild the ragdoll. This is useful if you applied scale on the ragdoll * after it was initialized. Same as re-attaching. */ public void reBuild() { if (spatial == null) { return; } removeSpatialData(spatial); createSpatialData(spatial); }