From c407296ccbdae555b72730757ec07e8ec506f6e8 Mon Sep 17 00:00:00 2001
From: "rem..om"
Date: Fri, 29 Apr 2011 17:31:04 +0000
Subject: [PATCH] Ragdoll - made some clean up - started a draft javadoc
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7360 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
---
.../jme3/bullet/control/RagdollControl.java | 303 ++++++++++++------
.../test/jme3test/bullet/TestBoneRagdoll.java | 59 ++--
2 files changed, 237 insertions(+), 125 deletions(-)
diff --git a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
index 8fc00fa66..77e9d7f7c 100644
--- a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
+++ b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
@@ -75,8 +75,34 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
-/**
- *
+/**This control is still a WIP, use it at your own risk
+ * To use this control you need a model with an AnimControl and a SkeletonControl.
+ * This should be the case if you imported an animated model from Ogre or blender.
+ *
+ * This control creates collision shapes for each bones of the skeleton when you call spatial.addControl(ragdollControl).
+ *
+ * - The shape is HullCollision shape based on the vertices associated with each bone and based on a tweakable weight threshold (see setWeightThreshold)
+ * - If you don't want each bone to be a collision shape, you can specify what bone to use by using the addBoneName method
+ * By using this method, bone that are not used to create a shape, are "merged" to their parent to create the collision shape.
+ *
+ *
+ *
+ *
+ *There are 2 behavior for this control :
+ *
+ * - The kinematic behavior :
+ * this is the default behavior, this means that the collision shapes of the body are able to interact with physics enabled objects.
+ * in this mode physic shapes follow the moovements of the animated skeleton (for example animated by a key framed animation)
+ * this mode is enabled just by enabling the control with setEnabled(true);
+ * disabling the control removes it from the phyic space
+ *
+ * - The ragdoll behavior :
+ * To enable this behavior, you need to call setRagdollEnabled(true) method.
+ * In this mode the charater is entirely controled by physics, so it will fall under the garvity and move if any force is applied to it.
+ *
+ *
+ *
+ *
* @author Normen Hansen and Rémy Bouquet (Nehon)
*/
public class RagdollControl implements PhysicsControl, PhysicsCollisionListener {
@@ -97,14 +123,13 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
protected float blendStart = 0.0f;
protected List listeners;
protected float eventDispatchImpulseThreshold = 10;
- protected float eventDiscardImpulseThreshold = 3;
protected RagdollPreset preset = new HumanoidRagdollPreset();
protected List boneList = new LinkedList();
protected Vector3f modelPosition = new Vector3f();
protected Quaternion modelRotation = new Quaternion();
protected float rootMass = 15;
protected float totalMass = 0;
- protected boolean added=false;
+ protected boolean added = false;
public RagdollControl() {
}
@@ -128,116 +153,144 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
TempVars vars = TempVars.get();
assert vars.lock();
- Quaternion q2 = vars.quat1;
- Quaternion q3 = vars.quat2;
+ Quaternion tmpRot1 = vars.quat1;
+ Quaternion tmpRot2 = vars.quat2;
+ //if the ragdoll has the control of the skeleton, we update each bone with its position in physic world space.
if (control) {
-
-
for (PhysicsBoneLink link : boneLinks.values()) {
- Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
Vector3f position = vars.vect1;
+ //retrieving bone position in physic world space
+ Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
+ //transforming this position with inverse transforms of the model
targetModel.getWorldTransform().transformInverseVector(p, position);
+ //retrieving bone rotation in physic world space
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
- q2.set(q).multLocal(link.initalWorldRotation).normalizeLocal();
- q3.set(targetModel.getWorldRotation()).inverseLocal().mult(q2, q2);
- q2.normalizeLocal();
+ //multiplying this rotation by the initialWorld rotation of the bone,
+ //then transforming it with the inverse world rotation of the model
+ tmpRot1.set(q).multLocal(link.initalWorldRotation);
+ tmpRot2.set(targetModel.getWorldRotation()).inverseLocal().mult(tmpRot1, tmpRot1);
+ tmpRot1.normalizeLocal();
+
+ //if the bone is the root bone, we apply the physic's transform to the model, so its position and rotation are correctly updated
if (link.bone.getParent() == null) {
+ //offsetting the physic's position/rotation by the root bone inverse model space position/rotaion
modelPosition.set(p).subtractLocal(link.bone.getInitialPos());
- modelRotation.set(q).multLocal(link.bone.getInitialRot().inverse());
+ modelRotation.set(q).multLocal(tmpRot2.set(link.bone.getInitialRot()).inverseLocal());
+
+ //applying transforms to the model
targetModel.setLocalTranslation(modelPosition);
targetModel.setLocalRotation(modelRotation);
- link.bone.setUserControl(true);
- link.bone.setUserTransformsWorld(position, q2);
+
+ //Applying computed transforms to the bone
+ link.bone.setUserTransformsWorld(position, tmpRot1);
} else {
+ //if boneList is empty, this means that every bone in the ragdoll has a collision shape,
+ //so we just update the bone position
if (boneList.isEmpty()) {
- link.bone.setUserControl(true);
- link.bone.setUserTransformsWorld(position, q2);
+ link.bone.setUserTransformsWorld(position, tmpRot1);
} else {
- setTransform(link.bone, position, q2);
+ //boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
+ //So we update them recusively
+ setTransform(link.bone, position, tmpRot1, false);
}
}
}
} else {
-
-
+ //the ragdoll does not have the controll, so the keyframed animation updates the physic position of the physic bonces
for (PhysicsBoneLink link : boneLinks.values()) {
- //the ragdoll does not control the skeleton
- link.bone.setUserControl(false);
+
if (!link.rigidBody.isKinematic()) {
link.rigidBody.setKinematic(true);
}
- if (blendedControl) {
-
-
+ Vector3f position = vars.vect1;
- Vector3f position = vars.vect1.set(link.startBlendingPos);
+ //if blended control this means, keyframed animation is updating the skeleton,
+ //but to allow smooth transition, we blend this transformation with the saved position of the ragdoll
+ if (blendedControl) {
Vector3f position2 = vars.vect2;
+ //initializing tmp vars with the start position/rotation of the ragdoll
+ position.set(link.startBlendingPos);
+ tmpRot1.set(link.startBlendingRot);
- q2.set(link.startBlendingRot);
-
- q3.set(q2).slerp(link.bone.getModelSpaceRotation(), blendStart / blendTime);
+ //interpolating between ragdoll position/rotation and keyframed position/rotation
+ tmpRot2.set(tmpRot1).slerp(link.bone.getModelSpaceRotation(), blendStart / blendTime);
position2.set(position).interpolate(link.bone.getModelSpacePosition(), blendStart / blendTime);
- q2.set(q3);
+ tmpRot1.set(tmpRot2);
position.set(position2);
+
+ //updating bones transforms
if (boneList.isEmpty()) {
+ //we ensure we have the control to update the bone
link.bone.setUserControl(true);
- link.bone.setUserTransformsWorld(position, q2);
+ link.bone.setUserTransformsWorld(position, tmpRot1);
+ //we give control back to the key framed animation.
+ link.bone.setUserControl(false);
} else {
- setTransform(link.bone, position, q2);
+ setTransform(link.bone, position, tmpRot1, true);
}
}
-
-
-
-
- Vector3f position = vars.vect1;
- Quaternion rotation = vars.quat1;
-
//computing position from rotation and scale
targetModel.getWorldTransform().transformVector(link.bone.getModelSpacePosition(), position);
//computing rotation
- rotation.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation());
- targetModel.getWorldRotation().mult(rotation, rotation);
- rotation.normalize();
+ tmpRot1.set(link.bone.getModelSpaceRotation()).multLocal(link.bone.getWorldBindInverseRotation());
+ targetModel.getWorldRotation().mult(tmpRot1, tmpRot1);
+ tmpRot1.normalizeLocal();
+ //updating physic location/rotation of the physic bone
link.rigidBody.setPhysicsLocation(position);
- link.rigidBody.setPhysicsRotation(rotation);
+ link.rigidBody.setPhysicsRotation(tmpRot1);
}
+
+ //time control for blending
if (blendedControl) {
blendStart += tpf;
-
if (blendStart > blendTime) {
blendedControl = false;
}
}
}
-
-
assert vars.unlock();
}
- private void setTransform(Bone bone, Vector3f pos, Quaternion rot) {
- bone.setUserControl(true);
+ /**
+ * Updates a bone position and rotation.
+ * if the child bones are not in the bone list this means, they are not associated with a physic shape.
+ * So they have to be updated
+ * @param bone the bone
+ * @param pos the position
+ * @param rot the rotation
+ */
+ private void setTransform(Bone bone, Vector3f pos, Quaternion rot, boolean restoreBoneControl) {
+ //we ensure that we have the control
+ if (restoreBoneControl) {
+ bone.setUserControl(true);
+ }
+ //we set te user transforms of the bone
bone.setUserTransformsWorld(pos, rot);
for (Bone childBone : bone.getChildren()) {
+ //each child bone that is not in the list is updated
if (!boneList.contains(childBone.getName())) {
Transform t = childBone.getCombinedTransform(pos, rot);
- setTransform(childBone, t.getTranslation(), t.getRotation());
+ setTransform(childBone, t.getTranslation(), t.getRotation(), restoreBoneControl);
}
}
- bone.setUserControl(false);
+ //we give back the control to the keyframed animation
+ if (restoreBoneControl) {
+ bone.setUserControl(false);
+ }
+
}
public Control cloneForSpatial(Spatial spatial) {
@@ -285,7 +338,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
model.setLocalRotation(initRotation);
model.setLocalScale(initScale);
- logger.log(Level.INFO, "Create physics ragdoll for skeleton {0}", skeleton);
+ logger.log(Level.INFO, "Created physics ragdoll for skeleton {0}", skeleton);
}
public void addBoneName(String name) {
@@ -405,29 +458,36 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private void addToPhysicsSpace() {
-
+
if (baseRigidBody != null) {
space.add(baseRigidBody);
- added=true;
+ added = true;
}
for (Iterator it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.rigidBody != null) {
space.add(physicsBoneLink.rigidBody);
- added=true;
+ added = true;
}
}
for (Iterator it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.joint != null) {
space.add(physicsBoneLink.joint);
- added=true;
+ added = true;
}
}
-
+
}
- private HullCollisionShape makeShape(PhysicsBoneLink link, Spatial model) {
+ /**
+ * Create a hull collision shape from linked vertices to this bone.
+ *
+ * @param link
+ * @param model
+ * @return
+ */
+ protected HullCollisionShape makeShape(PhysicsBoneLink link, Spatial model) {
Bone bone = link.bone;
List boneIndices = null;
if (boneList.isEmpty()) {
@@ -437,12 +497,11 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
boneIndices = getBoneIndices(bone, skeleton);
}
-
ArrayList points = new ArrayList();
if (model instanceof Geometry) {
Geometry g = (Geometry) model;
for (Integer index : boneIndices) {
- points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition(), link));
+ points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition()));
}
} else if (model instanceof Node) {
Node node = (Node) model;
@@ -450,7 +509,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if (s instanceof Geometry) {
Geometry g = (Geometry) s;
for (Integer index : boneIndices) {
- points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition(), link));
+ points.addAll(getPoints(g.getMesh(), index, bone.getModelSpacePosition()));
}
}
@@ -464,7 +523,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return new HullCollisionShape(p);
}
- private List getBoneIndices(Bone bone, Skeleton skeleton) {
+ //retruns the list of bone indices of the given bone and its child(if they are not in the boneList)
+ protected List getBoneIndices(Bone bone, Skeleton skeleton) {
List list = new LinkedList();
list.add(skeleton.getBoneIndex(bone));
for (Bone chilBone : bone.getChildren()) {
@@ -475,7 +535,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return list;
}
- protected List getPoints(Mesh mesh, int boneIndex, Vector3f offset, PhysicsBoneLink link) {
+ /**
+ * returns a list of points for the given bone
+ * @param mesh
+ * @param boneIndex
+ * @param offset
+ * @param link
+ * @return
+ */
+ private List getPoints(Mesh mesh, int boneIndex, Vector3f offset) {
FloatBuffer vertices = mesh.getFloatBuffer(Type.Position);
ByteBuffer boneIndices = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
@@ -516,8 +584,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return results;
}
- private void removeFromPhysicsSpace() {
-
+ protected void removeFromPhysicsSpace() {
+
if (baseRigidBody != null) {
space.remove(baseRigidBody);
}
@@ -533,9 +601,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
space.remove(physicsBoneLink.rigidBody);
}
}
- added=false;
+ added = false;
}
+ /**
+ * 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;
@@ -548,11 +622,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
}
+ /**
+ * returns true if the control is enabled
+ * @return
+ */
public boolean isEnabled() {
return enabled;
}
- public void attachDebugShape(AssetManager manager) {
+ protected void attachDebugShape(AssetManager manager) {
for (Iterator it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next();
physicsBoneLink.rigidBody.createDebugShape(manager);
@@ -560,7 +638,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
debug = true;
}
- public void detachDebugShape() {
+ protected void detachDebugShape() {
for (Iterator it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next();
physicsBoneLink.rigidBody.detachDebugShape();
@@ -568,6 +646,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
debug = false;
}
+ /**
+ * For internal use only
+ * specific render for the ragdoll(if debugging)
+ * @param rm
+ * @param vp
+ */
public void render(RenderManager rm, ViewPort vp) {
if (enabled && space != null && space.getDebugManager() != null) {
if (!debug) {
@@ -586,6 +670,10 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
}
+ /**
+ * set the physic space to this ragdoll
+ * @param space
+ */
public void setPhysicsSpace(PhysicsSpace space) {
if (space == null) {
removeFromPhysicsSpace();
@@ -600,27 +688,48 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
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) {
PhysicsCollisionObject objA = event.getObjectA();
PhysicsCollisionObject objB = event.getObjectB();
+ //excluding collisions that do not involve the ragdoll
if (event.getNodeA() == null && event.getNodeB() == null) {
return;
}
- if (event.getAppliedImpulse() < eventDiscardImpulseThreshold) {
+ //discarding low impulse collision
+ if (event.getAppliedImpulse() < eventDispatchImpulseThreshold) {
return;
}
@@ -628,7 +737,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
Bone hitBone = null;
PhysicsCollisionObject hitObject = null;
-
+ //Computing which bone has been hit
if (objA.getUserObject() instanceof PhysicsBoneLink) {
PhysicsBoneLink link = (PhysicsBoneLink) objA.getUserObject();
if (link != null) {
@@ -648,7 +757,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
}
- if (hit && event.getAppliedImpulse() > eventDispatchImpulseThreshold) {
+ //dispatching the event if the ragdoll has been hit
+ if (hit) {
for (RagdollCollisionListener listener : listeners) {
listener.collide(hitBone, hitObject, event);
}
@@ -656,26 +766,38 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
- public void setControl(boolean control) {
+ /**
+ * Enable or disable the ragdoll behaviour.
+ * if ragdollEnabled is true, the character motion will only be powerd by physics
+ * else, the characted will be animated by the keyframe animation,
+ * but will be able to physically interact with its physic environnement
+ * @param ragdollEnabled
+ */
+ public void setRagdollEnabled(boolean ragdollEnabled) {
AnimControl animControl = targetModel.getControl(AnimControl.class);
- animControl.setEnabled(!control);
+ animControl.setEnabled(!ragdollEnabled);
- this.control = control;
+ this.control = ragdollEnabled;
for (PhysicsBoneLink link : boneLinks.values()) {
- // link.bone.setUserControl(control);
- link.rigidBody.setKinematic(!control);
+ link.rigidBody.setKinematic(!ragdollEnabled);
}
-
for (Bone bone : skeleton.getRoots()) {
- setUserControl(bone, control);
+ setUserControl(bone, ragdollEnabled);
}
-
}
- public void blendControlToAnim(String anim, AnimChannel channel) {
+ /**
+ * Blend motion between the ragdoll actual physic state to the given animation, in the given blendTime
+ * Note that this disable the ragdoll behaviour of the control
+ * @param anim the animation name to blend to
+ * @param channel the channel to use for this animation
+ * @param blendTime the blending time between ragdoll to anim.
+ */
+ public void blendRagdollToAnim(String anim, AnimChannel channel, float blendTime) {
blendedControl = true;
+ this.blendTime = blendTime;
control = false;
AnimControl animControl = targetModel.getControl(AnimControl.class);
animControl.setEnabled(true);
@@ -696,9 +818,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
Quaternion q2 = vars.quat1;
Quaternion q3 = vars.quat2;
- q2.set(q).multLocal(link.initalWorldRotation).normalize();
+ q2.set(q).multLocal(link.initalWorldRotation).normalizeLocal();
q3.set(targetModel.getWorldRotation()).inverseLocal().mult(q2, q2);
- q2.normalize();
+ q2.normalizeLocal();
link.startBlendingPos.set(position);
link.startBlendingRot.set(q2);
link.rigidBody.setKinematic(true);
@@ -719,12 +841,19 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
}
- public boolean hasControl() {
-
+ /**
+ * returns true if the ragdoll behaviour is enabled
+ * @return
+ */
+ public boolean isRagdollEnabled() {
return control;
}
+ /**
+ * add a
+ * @param listener
+ */
public void addCollisionListener(RagdollCollisionListener listener) {
if (listeners == null) {
listeners = new ArrayList();
@@ -760,14 +889,6 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
this.weightThreshold = weightThreshold;
}
- public float getEventDiscardImpulseThreshold() {
- return eventDiscardImpulseThreshold;
- }
-
- public void setEventDiscardImpulseThreshold(float eventDiscardImpulseThreshold) {
- this.eventDiscardImpulseThreshold = eventDiscardImpulseThreshold;
- }
-
public float getEventDispatchImpulseThreshold() {
return eventDispatchImpulseThreshold;
}
diff --git a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
index 4efc0938f..0be1091a6 100644
--- a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
+++ b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java
@@ -46,20 +46,16 @@ import com.jme3.bullet.collision.RagdollCollisionListener;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.control.RagdollControl;
import com.jme3.bullet.control.RigidBodyControl;
-import com.jme3.bullet.joints.SixDofJoint;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
-import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
-import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
-import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
@@ -73,7 +69,7 @@ import com.jme3.texture.Texture;
* PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
* @author normenhansen
*/
-public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener{
+public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener {
private BulletAppState bulletAppState;
Material matBullet;
@@ -131,8 +127,8 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
float eighth_pi = FastMath.PI * 0.125f;
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);
-
-
+
+
//Oto's head is almost rigid
// ragdoll.setJointLimit("head", 0, 0, eighth_pi, -eighth_pi, 0, 0);
@@ -152,21 +148,21 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("toggle") && isPressed) {
-
- Vector3f v=new Vector3f();
+
+ Vector3f v = new Vector3f();
v.set(model.getLocalTranslation());
- v.y=0;
+ v.y = 0;
model.setLocalTranslation(v);
- Quaternion q=new Quaternion();
- float[] angles=new float[3];
+ Quaternion q = new Quaternion();
+ float[] angles = new float[3];
model.getLocalRotation().toAngles(angles);
- q.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
+ q.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
//q.lookAt(model.getLocalRotation().toRotationMatrix().getColumn(2), Vector3f.UNIT_Y);
- model.setLocalRotation(q);
- if(angles[0]<0){
- ragdoll.blendControlToAnim("StandUpBack",animChannel);
- }else{
- ragdoll.blendControlToAnim("StandUpFront",animChannel);
+ model.setLocalRotation(q);
+ if (angles[0] < 0) {
+ ragdoll.blendRagdollToAnim("StandUpBack", animChannel, 1);
+ } else {
+ ragdoll.blendRagdollToAnim("StandUpFront", animChannel, 1);
}
}
@@ -190,7 +186,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletg.setMaterial(matBullet);
bulletg.setLocalTranslation(cam.getLocation());
bulletg.setLocalScale(bulletSize);
- bulletCollisionShape = new SphereCollisionShape(bulletSize);
+ bulletCollisionShape = new SphereCollisionShape(bulletSize);
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(80));
@@ -206,7 +202,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletCollisionShape = new SphereCollisionShape(bulletSize);
BombControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1);
bulletNode.setForceFactor(10);
- bulletNode.setExplosionRadius(30);
+ bulletNode.setExplosionRadius(30);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(180));
bulletg.addControl(bulletNode);
@@ -214,7 +210,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
getPhysicsSpace().add(bulletNode);
}
}
- }, "toggle", "shoot", "stop", "bullet+", "bullet-","boom");
+ }, "toggle", "shoot", "stop", "bullet+", "bullet-", "boom");
inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addMapping("boom", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
@@ -226,7 +222,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
}
private void setupLight() {
- // AmbientLight al = new AmbientLight();
+ // AmbientLight al = new AmbientLight();
// al.setColor(ColorRGBA.White.mult(1));
// rootNode.addLight(al);
@@ -260,7 +256,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
guiNode.attachChild(ch);
}
- public void collide(Bone bone, PhysicsCollisionObject object,PhysicsCollisionEvent event) {
+ public void collide(Bone bone, PhysicsCollisionObject object, PhysicsCollisionEvent event) {
if (object.getUserObject() != null && object.getUserObject() instanceof Geometry) {
Geometry geom = (Geometry) object.getUserObject();
@@ -269,10 +265,8 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
}
}
-
- if (!ragdoll.hasControl()) {
-
- ragdoll.setControl(true);
+ if (!ragdoll.isRagdollEnabled()) {
+ ragdoll.setRagdollEnabled(true);
}
}
@@ -300,10 +294,8 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
ragdoll.addBoneName("Clavicle.R");
}
-
float elTime = 0;
boolean forward = true;
-
AnimControl animControl;
AnimChannel animChannel;
Vector3f direction = new Vector3f(0, 0, 1);
@@ -353,19 +345,18 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
// if(channel.getAnimationName().equals("StandUpFront")){
// channel.setAnim("Dance");
// }
-
- if(channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")){
+
+ if (channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")) {
channel.setLoopMode(LoopMode.DontLoop);
- channel.setAnim("IdleTop",5);
+ channel.setAnim("IdleTop", 5);
channel.setLoopMode(LoopMode.Loop);
}
// if(channel.getAnimationName().equals("IdleTop")){
// channel.setAnim("StandUpFront");
// }
-
+
}
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
-
}
}