- made some clean up
- started a draft javadoc

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

@ -75,8 +75,34 @@ import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
/**<strong>This control is still a WIP, use it at your own risk</strong><br>
* To use this control you need a model with an AnimControl and a SkeletonControl.<br>
* This should be the case if you imported an animated model from Ogre or blender.<br>
* <p>
* This control creates collision shapes for each bones of the skeleton when you call spatial.addControl(ragdollControl).
* <ul>
* <li>The shape is HullCollision shape based on the vertices associated with each bone and based on a tweakable weight threshold (see setWeightThreshold)</li>
* <li>If you don't want each bone to be a collision shape, you can specify what bone to use by using the addBoneName method<br>
* By using this method, bone that are not used to create a shape, are "merged" to their parent to create the collision shape.
* </li>
* </ul>
*</p>
*<p>
*There are 2 behavior for this control :
* <ul>
* <li><strong>The kinematic behavior :</strong><br>
* 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
* </li>
* <li><strong>The ragdoll behavior :</strong><br>
* 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.
* </li>
* </ul>
*</p>
*
* @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<RagdollCollisionListener> listeners;
protected float eventDispatchImpulseThreshold = 10;
protected float eventDiscardImpulseThreshold = 3;
protected RagdollPreset preset = new HumanoidRagdollPreset();
protected List<String> boneList = new LinkedList<String>();
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<PhysicsBoneLink> it = boneLinks.values().iterator(); it.hasNext();) {
PhysicsBoneLink physicsBoneLink = it.next();
if (physicsBoneLink.rigidBody != null) {
space.add(physicsBoneLink.rigidBody);
added=true;
added = true;
}
}
for (Iterator<PhysicsBoneLink> 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<Integer> boneIndices = null;
if (boneList.isEmpty()) {
@ -437,12 +497,11 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
boneIndices = getBoneIndices(bone, skeleton);
}
ArrayList<Float> points = new ArrayList<Float>();
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<Integer> 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<Integer> getBoneIndices(Bone bone, Skeleton skeleton) {
List<Integer> list = new LinkedList<Integer>();
list.add(skeleton.getBoneIndex(bone));
for (Bone chilBone : bone.getChildren()) {
@ -475,7 +535,15 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return list;
}
protected List<Float> 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<Float> 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<PhysicsBoneLink> 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<PhysicsBoneLink> 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<RagdollCollisionListener>();
@ -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;
}

@ -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) {
}
}

Loading…
Cancel
Save