@ -1,5 +1,7 @@
package com.jme3.bullet.control ;
import com.jme3.bullet.control.radoll.RagdollPreset ;
import com.jme3.bullet.control.radoll.HumanoidRagdollPreset ;
import com.jme3.animation.AnimControl ;
import com.jme3.animation.Bone ;
import com.jme3.animation.Skeleton ;
@ -12,12 +14,10 @@ import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.bullet.collision.RagdollCollisionListener ;
import com.jme3.bullet.collision.shapes.BoxCollisionShape ;
import com.jme3.bullet.collision.shapes.HullCollisionShape ;
import com.jme3.bullet.joints.PhysicsJoint ;
import com.jme3.bullet.joints.SixDofJoint ;
import com.jme3.bullet.objects.PhysicsRigidBody ;
import com.jme3.export.JmeExporter ;
import com.jme3.export.JmeImporter ;
import com.jme3.math.FastMath ;
import com.jme3.math.Quaternion ;
import com.jme3.math.Vector3f ;
import com.jme3.renderer.RenderManager ;
@ -35,6 +35,7 @@ import java.nio.FloatBuffer;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.LinkedList ;
import java.util.List ;
import java.util.Map ;
import java.util.logging.Level ;
@ -61,6 +62,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
protected float eventDispatchImpulseThreshold = 10 ;
protected float eventDiscardImpulseThreshold = 3 ;
protected RagdollPreset preset = new HumanoidRagdollPreset ( ) ;
protected List < String > boneList = new LinkedList < String > ( ) ;
public RagdollControl ( ) {
}
@ -78,6 +80,8 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
if ( control ) {
Quaternion q2 = vars . quat1 ;
Quaternion q3 = vars . quat2 ;
Vector3f p2 = vars . vect2 ;
// skeleton.reset();
for ( PhysicsBoneLink link : boneLinks . values ( ) ) {
@ -101,9 +105,12 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
link . bone . setUserControl ( true ) ;
link . bone . setUserTransformsWorld ( position , q2 ) ;
if ( boneList . isEmpty ( ) ) {
link . bone . setUserControl ( true ) ;
link . bone . setUserTransformsWorld ( position , q2 ) ;
} else {
setTransform ( link . bone , position , q2 ) ;
}
}
@ -112,6 +119,9 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
for ( PhysicsBoneLink link : boneLinks . values ( ) ) {
//the ragdoll does not control the skeleton
link . bone . setUserControl ( false ) ;
if ( ! link . rigidBody . isKinematic ( ) ) {
link . rigidBody . setKinematic ( true ) ;
}
Vector3f position = vars . vect1 ;
Quaternion rotation = vars . quat1 ;
@ -134,6 +144,21 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private void setTransform ( Bone bone , Vector3f pos , Quaternion rot ) {
bone . setUserControl ( true ) ;
bone . setUserTransformsWorld ( pos , rot ) ;
for ( Bone childBone : bone . getChildren ( ) ) {
if ( ! boneList . contains ( childBone . getName ( ) ) ) {
Vector3f tmpVec = childBone . getTmpVec ( ) ;
Quaternion tmpQuat = childBone . getTmpQuat ( ) ;
rot . mult ( childBone . getLocalPosition ( ) , tmpVec ) . addLocal ( pos ) ;
tmpQuat . set ( rot ) . multLocal ( childBone . getLocalRotation ( ) ) ;
setTransform ( childBone , tmpVec , tmpQuat ) ;
}
}
}
public Control cloneForSpatial ( Spatial spatial ) {
throw new UnsupportedOperationException ( "Not supported yet." ) ;
}
@ -165,7 +190,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
// maybe dont reset to ragdoll out of animations?
scanSpatial ( model ) ;
if ( parent ! = null ) {
parent . attachChild ( model ) ;
@ -178,7 +203,7 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
public void addBoneName ( String name ) {
throw new UnsupportedOperationException ( "Not supported yet." ) ;
boneList . add ( name ) ;
}
private void scanSpatial ( Spatial model ) {
@ -204,53 +229,60 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private void boneRecursion ( Spatial model , Bone bone , PhysicsRigidBody parent , int reccount ) {
//get world space position of the bone
Vector3f pos = bone . getModelSpacePosition ( ) . add ( model . getLocalTranslation ( ) ) ;
PhysicsRigidBody parentShape = parent ;
if ( boneList . isEmpty ( ) | | boneList . contains ( bone . getName ( ) ) ) {
//get world space position of the bone
Vector3f pos = bone . getModelSpacePosition ( ) . add ( model . getLocalTranslation ( ) ) ;
// Quaternion rot = bone.getModelSpaceRotation().mult(initRotation);
//creating the collision shape from the bone's associated vertices
PhysicsRigidBody shapeNode = new PhysicsRigidBody ( makeShape ( bone , model ) , 10 . 0f / ( float ) reccount ) ;
//creating the collision shape from the bone's associated vertices
PhysicsRigidBody shapeNode = new PhysicsRigidBody ( makeShape ( bone , model ) , 10 . 0f / ( float ) reccount ) ;
// shapeNode.setPhysicsRotation(rot);
// shapeNode.setPhysicsRotation(rot);
PhysicsBoneLink link = new PhysicsBoneLink ( ) ;
link . bone = bone ;
link . rigidBody = shapeNode ;
link . initalWorldRotation = bone . getModelSpaceRotation ( ) . clone ( ) ;
// link.mass = 10.0f / (float) reccount;
PhysicsBoneLink link = new PhysicsBoneLink ( ) ;
link . bone = bone ;
link . rigidBody = shapeNode ;
//TODO: ragdoll mass 1
if ( parent ! = null ) {
//get joint position for parent
Vector3f posToParent = new Vector3f ( ) ;
if ( bone . getParent ( ) ! = null ) {
bone . getModelSpacePosition ( ) . subtract ( bone . getParent ( ) . getModelSpacePosition ( ) , posToParent ) ;
}
link . initalWorldRotation = bone . getModelSpaceRotation ( ) . clone ( ) ;
// link.mass = 10.0f / (float) reccount;
//Joint local position from parent
link . pivotA = posToParent ;
//joint local position from current bone
link . pivotB = new Vector3f ( 0 , 0 , 0f ) ;
//TODO: ragdoll mass 1
if ( parent ! = null ) {
//get joint position for parent
Vector3f posToParent = new Vector3f ( ) ;
if ( bone . getParent ( ) ! = null ) {
bone . getModelSpacePosition ( ) . subtract ( bone . getParent ( ) . getModelSpacePosition ( ) , posToParent ) ;
}
//Joint local position from parent
link . pivotA = posToParent ;
//joint local position from current bone
link . pivotB = new Vector3f ( 0 , 0 , 0f ) ;
SixDofJoint joint = new SixDofJoint ( parent , shapeNode , link . pivotA , link . pivotB , true ) ;
//TODO find a way to correctly compute/import joints (maybe based on their names)
preset . setupJointForBone ( bone . getName ( ) , joint ) ;
//setJointLimit(joint, 0, 0, 0, 0, 0, 0);
SixDofJoint joint = new SixDofJoint ( parent , shapeNode , link . pivotA , link . pivotB , true ) ;
joint . getTranslationalLimitMotor ( ) . setUpperLimit ( new Vector3f ( 0 , 0 , 0 ) ) ;
joint . getTranslationalLimitMotor ( ) . setLowerLimit ( new Vector3f ( 0 , 0 , 0 ) ) ;
//TODO find a way to correctly compute/import joints (maybe based on their names)
preset . setupJointForBone ( bone . getName ( ) , joint ) ;
//setJointLimit(joint, 0, 0, 0, 0, 0, 0);
link . joint = joint ;
joint . setCollisionBetweenLinkedBodys ( false ) ;
link . joint = joint ;
joint . setCollisionBetweenLinkedBodys ( false ) ;
}
boneLinks . put ( bone . getName ( ) , link ) ;
shapeNode . setUserObject ( link ) ;
parentShape = shapeNode ;
}
boneLinks . put ( bone . getName ( ) , link ) ;
shapeNode . setUserObject ( link ) ;
for ( Iterator < Bone > it = bone . getChildren ( ) . iterator ( ) ; it . hasNext ( ) ; ) {
Bone childBone = it . next ( ) ;
boneRecursion ( model , childBone , shapeNod e, reccount + + ) ;
boneRecursion ( model , childBone , parentShap e, reccount + + ) ;
}
}
/ * *
@ -323,17 +355,31 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
}
private HullCollisionShape makeShape ( Bone bone , Spatial model ) {
int boneIndex = skeleton . getBoneIndex ( bone ) ;
List < Integer > boneIndices = null ;
if ( boneList . isEmpty ( ) ) {
boneIndices = new LinkedList < Integer > ( ) ;
boneIndices . add ( skeleton . getBoneIndex ( bone ) ) ;
} else {
boneIndices = getBoneIndices ( bone , skeleton ) ;
}
ArrayList < Float > points = new ArrayList < Float > ( ) ;
if ( model instanceof Geometry ) {
Geometry g = ( Geometry ) model ;
points . addAll ( getPoints ( g . getMesh ( ) , boneIndex , bone . getModelSpacePosition ( ) ) ) ;
for ( Integer index : boneIndices ) {
points . addAll ( getPoints ( g . getMesh ( ) , index , bone . getModelSpacePosition ( ) ) ) ;
}
} else if ( model instanceof Node ) {
Node node = ( Node ) model ;
for ( Spatial s : node . getChildren ( ) ) {
if ( s instanceof Geometry ) {
Geometry g = ( Geometry ) s ;
points . addAll ( getPoints ( g . getMesh ( ) , boneIndex , bone . getModelSpacePosition ( ) ) ) ;
for ( Integer index : boneIndices ) {
points . addAll ( getPoints ( g . getMesh ( ) , index , bone . getModelSpacePosition ( ) ) ) ;
}
}
}
}
@ -345,6 +391,17 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
return new HullCollisionShape ( p ) ;
}
private List < Integer > getBoneIndices ( Bone bone , Skeleton skeleton ) {
List < Integer > list = new LinkedList < Integer > ( ) ;
list . add ( skeleton . getBoneIndex ( bone ) ) ;
for ( Bone chilBone : bone . getChildren ( ) ) {
if ( ! boneList . contains ( chilBone . getName ( ) ) ) {
list . addAll ( getBoneIndices ( chilBone , skeleton ) ) ;
}
}
return list ;
}
protected List < Float > getPoints ( Mesh mesh , int boneIndex , Vector3f offset ) {
FloatBuffer vertices = mesh . getFloatBuffer ( Type . Position ) ;
@ -529,10 +586,22 @@ public class RagdollControl implements PhysicsControl, PhysicsCollisionListener
this . control = control ;
for ( PhysicsBoneLink link : boneLinks . values ( ) ) {
link . bone . setUserControl ( control ) ;
// link.bone.setUserControl(control);
link . rigidBody . setKinematic ( ! control ) ;
}
for ( Bone bone : skeleton . getRoots ( ) ) {
setUserControl ( bone , control ) ;
}
}
private void setUserControl ( Bone bone , boolean bool ) {
bone . setUserControl ( bool ) ;
for ( Bone child : bone . getChildren ( ) ) {
setUserControl ( child , bool ) ;
}
}
public boolean hasControl ( ) {