- 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
3.0
rem..om 14 years ago
parent ea9e60d099
commit 2f1f2e7e54
  1. 91
      engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
  2. 112
      engine/src/test/jme3test/bullet/TestBoneRagdoll.java

@ -31,10 +31,12 @@
*/
package com.jme3.bullet.control;
import com.jme3.animation.AnimChannel;
import com.jme3.bullet.control.ragdoll.RagdollPreset;
import com.jme3.bullet.control.ragdoll.HumanoidRagdollPreset;
import com.jme3.animation.AnimControl;
import com.jme3.animation.Bone;
import com.jme3.animation.LoopMode;
import com.jme3.animation.Skeleton;
import com.jme3.animation.SkeletonControl;
import com.jme3.asset.AssetManager;
@ -90,12 +92,16 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
protected Spatial targetModel;
protected Vector3f initScale;
protected boolean control = false;
protected boolean blendedControl = false;
protected float blendTime = 1.0f;
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;
private float totalMass = 0;
@ -121,10 +127,11 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
TempVars vars = TempVars.get();
assert vars.lock();
Quaternion q2 = vars.quat1;
Quaternion q3 = vars.quat2;
if (control) {
Quaternion q2 = vars.quat1;
Quaternion q3 = vars.quat2;
for (PhysicsBoneLink link : boneLinks.values()) {
@ -140,7 +147,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
q2.normalize();
if (link.bone.getParent() == null) {
modelPosition.set(p).subtractLocal(link.bone.getInitialPos());
modelRotation.set(q).multLocal(link.bone.getInitialRot().inverse());
targetModel.setLocalTranslation(modelPosition);
targetModel.setLocalRotation(modelRotation);
link.bone.setUserControl(true);
link.bone.setUserTransformsWorld(position, q2);
@ -154,6 +163,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
}
} else {
for (PhysicsBoneLink link : boneLinks.values()) {
//the ragdoll does not control the skeleton
link.bone.setUserControl(false);
@ -161,6 +172,32 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
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;
Quaternion rotation = vars.quat1;
@ -175,6 +212,14 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
link.rigidBody.setPhysicsLocation(position);
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());
}
}
bone.setUserControl(false);
}
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) {
bone.setUserControl(bool);
for (Bone child : bone.getChildren()) {
@ -643,7 +727,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
PhysicsRigidBody rigidBody;
Vector3f pivotA;
Vector3f pivotB;
float volume = 0;
Quaternion startBlendingRot = new Quaternion();
Vector3f startBlendingPos = new Vector3f();
}
public void setRootMass(float rootMass) {

@ -33,7 +33,9 @@ package jme3test.bullet;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.Bone;
import com.jme3.animation.LoopMode;
import com.jme3.bullet.BulletAppState;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
@ -57,6 +59,7 @@ 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;
@ -70,7 +73,7 @@ import com.jme3.texture.Texture;
* PHYSICS RAGDOLLS ARE NOT WORKING PROPERLY YET!
* @author normenhansen
*/
public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener {
public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisionListener, AnimEventListener{
private BulletAppState bulletAppState;
Material matBullet;
@ -135,13 +138,26 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
animChannel = control.createChannel();
animChannel.setAnim("Dance");
control.addListener(this);
inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) {
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) {
bulletSize += 0.1f;
@ -166,7 +182,7 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
bulletCollisionShape = new SphereCollisionShape(bulletSize);
RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, bulletSize * 10);
bulletNode.setCcdMotionThreshold(0.001f);
bulletNode.setLinearVelocity(cam.getDirection().mult(180));
bulletNode.setLinearVelocity(cam.getDirection().mult(80));
bulletg.addControl(bulletNode);
rootNode.attachChild(bulletg);
getPhysicsSpace().add(bulletNode);
@ -295,40 +311,60 @@ public class TestBoneRagdoll extends SimpleApplication implements RagdollCollisi
@Override
public void simpleUpdate(float tpf) {
elTime += tpf;
if (elTime > 3) {
elTime = 0;
if (dance) {
rotate.multLocal(direction);
}
if (Math.random() > 0.80) {
dance = true;
animChannel.setAnim("Dance");
} else {
dance = false;
animChannel.setAnim("RunBase");
rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y);
rotate.multLocal(direction);
}
}
if (!ragdoll.hasControl() && !dance) {
if (model.getLocalTranslation().getZ() < -10) {
direction.z = 1;
direction.normalizeLocal();
} else if (model.getLocalTranslation().getZ() > 10) {
direction.z = -1;
direction.normalizeLocal();
}
if (model.getLocalTranslation().getX() < -10) {
direction.x = 1;
direction.normalizeLocal();
} else if (model.getLocalTranslation().getX() > 10) {
direction.x = -1;
direction.normalizeLocal();
}
model.move(direction.multLocal(tpf * 8));
direction.normalizeLocal();
model.lookAt(model.getLocalTranslation().add(direction), Vector3f.UNIT_Y);
// elTime += tpf;
// if (elTime > 3) {
// elTime = 0;
// if (dance) {
// rotate.multLocal(direction);
// }
// if (Math.random() > 0.80) {
// dance = true;
// animChannel.setAnim("Dance");
// } else {
// dance = false;
// animChannel.setAnim("RunBase");
// rotate.fromAngleAxis(FastMath.QUARTER_PI * ((float) Math.random() - 0.5f), Vector3f.UNIT_Y);
// rotate.multLocal(direction);
// }
// }
// if (!ragdoll.hasControl() && !dance) {
// if (model.getLocalTranslation().getZ() < -10) {
// direction.z = 1;
// direction.normalizeLocal();
// } else if (model.getLocalTranslation().getZ() > 10) {
// direction.z = -1;
// direction.normalizeLocal();
// }
// if (model.getLocalTranslation().getX() < -10) {
// direction.x = 1;
// direction.normalizeLocal();
// } else if (model.getLocalTranslation().getX() > 10) {
// direction.x = -1;
// direction.normalizeLocal();
// }
// model.move(direction.multLocal(tpf * 8));
// direction.normalizeLocal();
// 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…
Cancel
Save