- WIP Sinbad Ragdoll can now stand up after beeing whacked
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7309 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
ea9e60d099
commit
2f1f2e7e54
@ -31,10 +31,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.bullet.control;
|
package com.jme3.bullet.control;
|
||||||
|
|
||||||
|
import com.jme3.animation.AnimChannel;
|
||||||
import com.jme3.bullet.control.ragdoll.RagdollPreset;
|
import com.jme3.bullet.control.ragdoll.RagdollPreset;
|
||||||
import com.jme3.bullet.control.ragdoll.HumanoidRagdollPreset;
|
import com.jme3.bullet.control.ragdoll.HumanoidRagdollPreset;
|
||||||
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.animation.Skeleton;
|
import com.jme3.animation.Skeleton;
|
||||||
import com.jme3.animation.SkeletonControl;
|
import com.jme3.animation.SkeletonControl;
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
@ -90,12 +92,16 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
protected Spatial targetModel;
|
protected Spatial targetModel;
|
||||||
protected Vector3f initScale;
|
protected Vector3f initScale;
|
||||||
protected boolean control = false;
|
protected boolean control = false;
|
||||||
|
protected boolean blendedControl = false;
|
||||||
|
protected float blendTime = 1.0f;
|
||||||
|
protected float blendStart = 0.0f;
|
||||||
protected List<RagdollCollisionListener> listeners;
|
protected List<RagdollCollisionListener> listeners;
|
||||||
protected float eventDispatchImpulseThreshold = 10;
|
protected float eventDispatchImpulseThreshold = 10;
|
||||||
protected float eventDiscardImpulseThreshold = 3;
|
protected float eventDiscardImpulseThreshold = 3;
|
||||||
protected RagdollPreset preset = new HumanoidRagdollPreset();
|
protected RagdollPreset preset = new HumanoidRagdollPreset();
|
||||||
protected List<String> boneList = new LinkedList<String>();
|
protected List<String> boneList = new LinkedList<String>();
|
||||||
protected Vector3f modelPosition = new Vector3f();
|
protected Vector3f modelPosition = new Vector3f();
|
||||||
|
protected Quaternion modelRotation = new Quaternion();
|
||||||
protected float rootMass = 15;
|
protected float rootMass = 15;
|
||||||
private float totalMass = 0;
|
private float totalMass = 0;
|
||||||
|
|
||||||
@ -121,10 +127,11 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
}
|
}
|
||||||
TempVars vars = TempVars.get();
|
TempVars vars = TempVars.get();
|
||||||
assert vars.lock();
|
assert vars.lock();
|
||||||
|
Quaternion q2 = vars.quat1;
|
||||||
|
Quaternion q3 = vars.quat2;
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
|
|
||||||
Quaternion q2 = vars.quat1;
|
|
||||||
Quaternion q3 = vars.quat2;
|
|
||||||
|
|
||||||
for (PhysicsBoneLink link : boneLinks.values()) {
|
for (PhysicsBoneLink link : boneLinks.values()) {
|
||||||
|
|
||||||
@ -140,7 +147,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
q2.normalize();
|
q2.normalize();
|
||||||
if (link.bone.getParent() == null) {
|
if (link.bone.getParent() == null) {
|
||||||
modelPosition.set(p).subtractLocal(link.bone.getInitialPos());
|
modelPosition.set(p).subtractLocal(link.bone.getInitialPos());
|
||||||
|
modelRotation.set(q).multLocal(link.bone.getInitialRot().inverse());
|
||||||
targetModel.setLocalTranslation(modelPosition);
|
targetModel.setLocalTranslation(modelPosition);
|
||||||
|
targetModel.setLocalRotation(modelRotation);
|
||||||
link.bone.setUserControl(true);
|
link.bone.setUserControl(true);
|
||||||
link.bone.setUserTransformsWorld(position, q2);
|
link.bone.setUserTransformsWorld(position, q2);
|
||||||
|
|
||||||
@ -154,6 +163,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
for (PhysicsBoneLink link : boneLinks.values()) {
|
for (PhysicsBoneLink link : boneLinks.values()) {
|
||||||
//the ragdoll does not control the skeleton
|
//the ragdoll does not control the skeleton
|
||||||
link.bone.setUserControl(false);
|
link.bone.setUserControl(false);
|
||||||
@ -161,6 +172,32 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
link.rigidBody.setKinematic(true);
|
link.rigidBody.setKinematic(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blendedControl) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vector3f position = vars.vect1.set(link.startBlendingPos);
|
||||||
|
Vector3f position2 = vars.vect2;
|
||||||
|
|
||||||
|
q2.set(link.startBlendingRot);
|
||||||
|
|
||||||
|
q3.set(q2).slerp(link.bone.getModelSpaceRotation(), blendStart / blendTime);
|
||||||
|
position2.set(position).interpolate(link.bone.getModelSpacePosition(), blendStart / blendTime);
|
||||||
|
q2.set(q3);
|
||||||
|
position.set(position2);
|
||||||
|
if (boneList.isEmpty()) {
|
||||||
|
link.bone.setUserControl(true);
|
||||||
|
link.bone.setUserTransformsWorld(position, q2);
|
||||||
|
} else {
|
||||||
|
setTransform(link.bone, position, q2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector3f position = vars.vect1;
|
Vector3f position = vars.vect1;
|
||||||
Quaternion rotation = vars.quat1;
|
Quaternion rotation = vars.quat1;
|
||||||
|
|
||||||
@ -175,6 +212,14 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
link.rigidBody.setPhysicsLocation(position);
|
link.rigidBody.setPhysicsLocation(position);
|
||||||
link.rigidBody.setPhysicsRotation(rotation);
|
link.rigidBody.setPhysicsRotation(rotation);
|
||||||
}
|
}
|
||||||
|
if (blendedControl) {
|
||||||
|
blendStart += tpf;
|
||||||
|
|
||||||
|
if (blendStart > blendTime) {
|
||||||
|
blendedControl = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -191,6 +236,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
setTransform(childBone, t.getTranslation(), t.getRotation());
|
setTransform(childBone, t.getTranslation(), t.getRotation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bone.setUserControl(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Control cloneForSpatial(Spatial spatial) {
|
public Control cloneForSpatial(Spatial spatial) {
|
||||||
@ -615,6 +661,44 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void blendControlToAnim(String anim, AnimChannel channel) {
|
||||||
|
blendedControl = true;
|
||||||
|
control = false;
|
||||||
|
AnimControl animControl = targetModel.getControl(AnimControl.class);
|
||||||
|
animControl.setEnabled(true);
|
||||||
|
channel.setAnim(anim, 0);
|
||||||
|
channel.setLoopMode(LoopMode.DontLoop);
|
||||||
|
|
||||||
|
TempVars vars = TempVars.get();
|
||||||
|
assert vars.lock();
|
||||||
|
//this.control = control;
|
||||||
|
for (PhysicsBoneLink link : boneLinks.values()) {
|
||||||
|
|
||||||
|
Vector3f p = link.rigidBody.getMotionState().getWorldLocation();
|
||||||
|
Vector3f position = vars.vect1;
|
||||||
|
|
||||||
|
targetModel.getWorldTransform().transformInverseVector(p, position);
|
||||||
|
|
||||||
|
Quaternion q = link.rigidBody.getMotionState().getWorldRotationQuat();
|
||||||
|
Quaternion q2 = vars.quat1;
|
||||||
|
Quaternion q3 = vars.quat2;
|
||||||
|
|
||||||
|
q2.set(q).multLocal(link.initalWorldRotation).normalize();
|
||||||
|
q3.set(targetModel.getWorldRotation()).inverseLocal().mult(q2, q2);
|
||||||
|
q2.normalize();
|
||||||
|
link.startBlendingPos.set(position);
|
||||||
|
link.startBlendingRot.set(q2);
|
||||||
|
link.rigidBody.setKinematic(true);
|
||||||
|
}
|
||||||
|
assert vars.unlock();
|
||||||
|
|
||||||
|
for (Bone bone : skeleton.getRoots()) {
|
||||||
|
setUserControl(bone, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
blendStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private void setUserControl(Bone bone, boolean bool) {
|
private void setUserControl(Bone bone, boolean bool) {
|
||||||
bone.setUserControl(bool);
|
bone.setUserControl(bool);
|
||||||
for (Bone child : bone.getChildren()) {
|
for (Bone child : bone.getChildren()) {
|
||||||
@ -643,7 +727,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
|
|||||||
PhysicsRigidBody rigidBody;
|
PhysicsRigidBody rigidBody;
|
||||||
Vector3f pivotA;
|
Vector3f pivotA;
|
||||||
Vector3f pivotB;
|
Vector3f pivotB;
|
||||||
float volume = 0;
|
Quaternion startBlendingRot = new Quaternion();
|
||||||
|
Vector3f startBlendingPos = new Vector3f();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRootMass(float rootMass) {
|
public void setRootMass(float rootMass) {
|
||||||
|
@ -33,7 +33,9 @@ package jme3test.bullet;
|
|||||||
|
|
||||||
import com.jme3.animation.AnimChannel;
|
import com.jme3.animation.AnimChannel;
|
||||||
import com.jme3.animation.AnimControl;
|
import com.jme3.animation.AnimControl;
|
||||||
|
import com.jme3.animation.AnimEventListener;
|
||||||
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;
|
||||||
@ -57,6 +59,7 @@ 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.FastMath;
|
||||||
|
import com.jme3.math.Matrix3f;
|
||||||
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;
|
||||||
@ -70,7 +73,7 @@ import com.jme3.texture.Texture;
|
|||||||
* PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
|
* PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
|
||||||
* @author normenhansen
|
* @author normenhansen
|
||||||
*/
|
*/
|
||||||
public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener {
|
public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener{
|
||||||
|
|
||||||
private BulletAppState bulletAppState;
|
private BulletAppState bulletAppState;
|
||||||
Material matBullet;
|
Material matBullet;
|
||||||
@ -135,13 +138,26 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
|
|||||||
|
|
||||||
animChannel = control.createChannel();
|
animChannel = control.createChannel();
|
||||||
animChannel.setAnim("Dance");
|
animChannel.setAnim("Dance");
|
||||||
|
control.addListener(this);
|
||||||
|
|
||||||
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);
|
|
||||||
model.setLocalTranslation(0, 0, 0);
|
Vector3f v=new Vector3f();
|
||||||
|
v.set(model.getLocalTranslation());
|
||||||
|
v.y=0;
|
||||||
|
model.setLocalTranslation(v);
|
||||||
|
Quaternion q=new Quaternion();
|
||||||
|
float[] angles=new float[3];
|
||||||
|
model.getLocalRotation().toAngles(angles);
|
||||||
|
q.fromAngleAxis(angles[1], Vector3f.UNIT_Y);
|
||||||
|
//q.lookAt(model.getLocalRotation().toRotationMatrix().getColumn(2), Vector3f.UNIT_Y);
|
||||||
|
model.setLocalRotation(q);
|
||||||
|
// animChannel.setAnim("StandUpBack");
|
||||||
|
ragdoll.blendControlToAnim("StandUpFront",animChannel);
|
||||||
|
// animChannel.setAnim("StandUpFront",0.00f);
|
||||||
}
|
}
|
||||||
if (name.equals("bullet+") && isPressed) {
|
if (name.equals("bullet+") && isPressed) {
|
||||||
bulletSize += 0.1f;
|
bulletSize += 0.1f;
|
||||||
@ -166,7 +182,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
|
|||||||
bulletCollisionShape = new SphereCollisionShape(bulletSize);
|
bulletCollisionShape = new SphereCollisionShape(bulletSize);
|
||||||
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
|
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
|
||||||
bulletNode.setCcdMotionThreshold(0.001f);
|
bulletNode.setCcdMotionThreshold(0.001f);
|
||||||
bulletNode.setLinearVelocity(cam.getDirection().mult(180));
|
bulletNode.setLinearVelocity(cam.getDirection().mult(80));
|
||||||
bulletg.addControl(bulletNode);
|
bulletg.addControl(bulletNode);
|
||||||
rootNode.attachChild(bulletg);
|
rootNode.attachChild(bulletg);
|
||||||
getPhysicsSpace().add(bulletNode);
|
getPhysicsSpace().add(bulletNode);
|
||||||
@ -295,40 +311,60 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void simpleUpdate(float tpf) {
|
public void simpleUpdate(float tpf) {
|
||||||
elTime += tpf;
|
// elTime += tpf;
|
||||||
if (elTime > 3) {
|
// if (elTime > 3) {
|
||||||
elTime = 0;
|
// elTime = 0;
|
||||||
if (dance) {
|
// if (dance) {
|
||||||
rotate.multLocal(direction);
|
// rotate.multLocal(direction);
|
||||||
}
|
// }
|
||||||
if (Math.random() > 0.80) {
|
// if (Math.random() > 0.80) {
|
||||||
dance = true;
|
// dance = true;
|
||||||
animChannel.setAnim("Dance");
|
// animChannel.setAnim("Dance");
|
||||||
} else {
|
// } else {
|
||||||
dance = false;
|
// dance = false;
|
||||||
animChannel.setAnim("RunBase");
|
// animChannel.setAnim("RunBase");
|
||||||
rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y);
|
// rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y);
|
||||||
rotate.multLocal(direction);
|
// rotate.multLocal(direction);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (!ragdoll.hasControl() && !dance) {
|
// if (!ragdoll.hasControl() && !dance) {
|
||||||
if (model.getLocalTranslation().getZ() < -10) {
|
// if (model.getLocalTranslation().getZ() < -10) {
|
||||||
direction.z = 1;
|
// direction.z = 1;
|
||||||
direction.normalizeLocal();
|
// direction.normalizeLocal();
|
||||||
} else if (model.getLocalTranslation().getZ() > 10) {
|
// } else if (model.getLocalTranslation().getZ() > 10) {
|
||||||
direction.z = -1;
|
// direction.z = -1;
|
||||||
direction.normalizeLocal();
|
// direction.normalizeLocal();
|
||||||
}
|
// }
|
||||||
if (model.getLocalTranslation().getX() < -10) {
|
// if (model.getLocalTranslation().getX() < -10) {
|
||||||
direction.x = 1;
|
// direction.x = 1;
|
||||||
direction.normalizeLocal();
|
// direction.normalizeLocal();
|
||||||
} else if (model.getLocalTranslation().getX() > 10) {
|
// } else if (model.getLocalTranslation().getX() > 10) {
|
||||||
direction.x = -1;
|
// direction.x = -1;
|
||||||
direction.normalizeLocal();
|
// direction.normalizeLocal();
|
||||||
}
|
// }
|
||||||
model.move(direction.multLocal(tpf * 8));
|
// model.move(direction.multLocal(tpf * 8));
|
||||||
direction.normalizeLocal();
|
// direction.normalizeLocal();
|
||||||
model.lookAt(model.getLocalTranslation().add(direction), Vector3f.UNIT_Y);
|
// model.lookAt(model.getLocalTranslation().add(direction), Vector3f.UNIT_Y);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
|
||||||
|
// if(channel.getAnimationName().equals("StandUpFront")){
|
||||||
|
// channel.setAnim("Dance");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(channel.getAnimationName().equals("StandUpBack") || channel.getAnimationName().equals("StandUpFront")){
|
||||||
|
channel.setLoopMode(LoopMode.DontLoop);
|
||||||
|
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…
x
Reference in New Issue
Block a user