فهرست منبع

- 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
rem..om 14 سال پیش
والد
کامیت
2f1f2e7e54
2فایلهای تغییر یافته به همراه162 افزوده شده و 41 حذف شده
  1. 88 3
      engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java
  2. 74 38
      engine/src/test/jme3test/bullet/TestBoneRagdoll.java

+ 88 - 3
engine/src/jbullet/com/jme3/bullet/control/RagdollControl.java

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

+ 74 - 38
engine/src/test/jme3test/bullet/TestBoneRagdoll.java

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