|
|
@ -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,11 +127,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener |
|
|
|
} |
|
|
|
} |
|
|
|
TempVars vars = TempVars.get(); |
|
|
|
TempVars vars = TempVars.get(); |
|
|
|
assert vars.lock(); |
|
|
|
assert vars.lock(); |
|
|
|
if (control) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Quaternion q2 = vars.quat1; |
|
|
|
Quaternion q2 = vars.quat1; |
|
|
|
Quaternion q3 = vars.quat2; |
|
|
|
Quaternion q3 = vars.quat2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (control) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (PhysicsBoneLink link : boneLinks.values()) { |
|
|
|
for (PhysicsBoneLink link : boneLinks.values()) { |
|
|
|
|
|
|
|
|
|
|
|
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); |
|
|
|
Vector3f p = link.rigidBody.getMotionState().getWorldLocation(); |
|
|
@ -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) { |
|
|
|