From 2f1f2e7e548d5c057ccaa68ed91be1029f283d53 Mon Sep 17 00:00:00 2001 From: "rem..om" Date: Tue, 26 Apr 2011 20:42:44 +0000 Subject: [PATCH] - 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 --- .../jme3/bullet/control/RagdollControl.java | 91 +++++++++++++- .../test/jme3test/bullet/TestBoneRagdoll.java | 112 ++++++++++++------ 2 files changed, 162 insertions(+), 41 deletions(-) diff --git a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java index 1d0a63d88..62835cf70 100644 --- a/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java +++ b/engine/src/jbullet/com/jme3/bullet/control/RagdollControl.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 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; 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) { diff --git a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java index 03fcd8fce..9336c9ba6 100644 --- a/engine/src/test/jme3test/bullet/TestBoneRagdoll.java +++ b/engine/src/test/jme3test/bullet/TestBoneRagdoll.java @@ -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) { + } }