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