parent
7e17cdc498
commit
5bbc6bcf1e
@ -57,6 +57,7 @@ import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.control.Control;
|
||||
@ -212,6 +213,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
* @param ex exporter (not null)
|
||||
* @throws IOException from exporter
|
||||
*/
|
||||
@Override
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
OutputCapsule oc = ex.getCapsule(this);
|
||||
oc.write(rigidBody, "rigidBody", null);
|
||||
@ -229,6 +231,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
* @param im importer (not null)
|
||||
* @throws IOException from importer
|
||||
*/
|
||||
@Override
|
||||
public void read(JmeImporter im) throws IOException {
|
||||
InputCapsule ic = im.getCapsule(this);
|
||||
rigidBody = (PhysicsRigidBody) ic.readSavable("rigidBody", null);
|
||||
@ -288,6 +291,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
*
|
||||
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||
*/
|
||||
@Override
|
||||
public void update(float tpf) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
@ -348,15 +352,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||
|
||||
} else {
|
||||
//If boneList is empty, every bone has a collision shape,
|
||||
//so we simply update the bone position.
|
||||
if (boneList.isEmpty()) {
|
||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||
} else {
|
||||
//boneList is not empty, this means some bones of the skeleton might not be associated with a collision shape.
|
||||
//So we update them recusively
|
||||
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
|
||||
}
|
||||
//some bones of the skeleton might not be associated with a collision shape.
|
||||
//So we update them recusively
|
||||
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
|
||||
}
|
||||
}
|
||||
vars.release();
|
||||
@ -391,17 +389,8 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
tmpRot1.set(tmpRot2);
|
||||
position.set(position2);
|
||||
|
||||
//updating bones transforms
|
||||
if (boneList.isEmpty()) {
|
||||
//we ensure we have the control to update the bone
|
||||
link.bone.setUserControl(true);
|
||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||
//we give control back to the key framed animation.
|
||||
link.bone.setUserControl(false);
|
||||
} else {
|
||||
RagdollUtils.setTransform(link.bone, position, tmpRot1, true, boneList);
|
||||
}
|
||||
|
||||
//update bone transforms
|
||||
RagdollUtils.setTransform(link.bone, position, tmpRot1, true, boneList);
|
||||
}
|
||||
//setting skeleton transforms to the ragdoll
|
||||
matchPhysicObjectToBone(link, position, tmpRot1);
|
||||
@ -589,6 +578,22 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
model.removeControl(sc);
|
||||
model.addControl(sc);
|
||||
|
||||
if (boneList.isEmpty()) {
|
||||
// add all bones to the list
|
||||
skeleton = sc.getSkeleton();
|
||||
for (int boneI = 0; boneI < skeleton.getBoneCount(); boneI++) {
|
||||
String boneName = skeleton.getBone(boneI).getName();
|
||||
boneList.add(boneName);
|
||||
}
|
||||
}
|
||||
// filter out bones without vertices
|
||||
filterBoneList(sc);
|
||||
|
||||
if (boneList.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"No suitable bones were found in the model's skeleton.");
|
||||
}
|
||||
|
||||
// put into bind pose and compute bone transforms in model space
|
||||
// maybe don't reset to ragdoll out of animations?
|
||||
scanSpatial(model);
|
||||
@ -608,6 +613,25 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any bones without vertices from the boneList, so that every hull
|
||||
* shape will contain at least 1 vertex.
|
||||
*/
|
||||
private void filterBoneList(SkeletonControl skeletonControl) {
|
||||
Mesh[] targets = skeletonControl.getTargets();
|
||||
Skeleton skel = skeletonControl.getSkeleton();
|
||||
for (int boneI = 0; boneI < skel.getBoneCount(); boneI++) {
|
||||
String boneName = skel.getBone(boneI).getName();
|
||||
if (boneList.contains(boneName)) {
|
||||
boolean hasVertices = RagdollUtils.hasVertices(boneI, targets,
|
||||
weightThreshold);
|
||||
if (!hasVertices) {
|
||||
boneList.remove(boneName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy spatial-dependent data. Invoked when this control is removed from
|
||||
* a spatial.
|
||||
@ -669,7 +693,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
||||
*/
|
||||
protected void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) {
|
||||
PhysicsRigidBody parentShape = parent;
|
||||
if (boneList.isEmpty() || boneList.contains(bone.getName())) {
|
||||
if (boneList.contains(bone.getName())) {
|
||||
|
||||
PhysicsBoneLink link = new PhysicsBoneLink();
|
||||
link.bone = bone;
|
||||
|
@ -56,6 +56,12 @@ import java.util.*;
|
||||
*/
|
||||
public class RagdollUtils {
|
||||
|
||||
/**
|
||||
* A private constructor to inhibit instantiation of this class.
|
||||
*/
|
||||
private RagdollUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter the limits of the specified 6-DOF joint.
|
||||
*
|
||||
@ -172,12 +178,12 @@ public class RagdollUtils {
|
||||
}
|
||||
}
|
||||
|
||||
assert !points.isEmpty();
|
||||
float[] p = new float[points.size()];
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
p[i] = points.get(i);
|
||||
}
|
||||
|
||||
|
||||
return new HullCollisionShape(p);
|
||||
}
|
||||
|
||||
@ -235,12 +241,13 @@ public class RagdollUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert !points.isEmpty();
|
||||
float[] p = new float[points.size()];
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
p[i] = points.get(i);
|
||||
}
|
||||
|
||||
|
||||
return new HullCollisionShape(p);
|
||||
}
|
||||
|
||||
@ -343,4 +350,39 @@ public class RagdollUtils {
|
||||
setUserControl(child, bool);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the indexed bone has at least one vertex in the specified
|
||||
* meshes with a weight greater than the specified threshold.
|
||||
*
|
||||
* @param boneIndex the index of the bone (≥0)
|
||||
* @param targets the meshes to search (not null, no null elements)
|
||||
* @param weightThreshold the threshold (≥0, ≤1)
|
||||
* @return true if at least 1 vertex found, otherwise false
|
||||
*/
|
||||
public static boolean hasVertices(int boneIndex, Mesh[] targets,
|
||||
float weightThreshold) {
|
||||
for (Mesh mesh : targets) {
|
||||
ByteBuffer boneIndices
|
||||
= (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
|
||||
FloatBuffer boneWeight
|
||||
= (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
|
||||
|
||||
boneIndices.rewind();
|
||||
boneWeight.rewind();
|
||||
|
||||
int vertexComponents = mesh.getVertexCount() * 3;
|
||||
for (int i = 0; i < vertexComponents; i += 3) {
|
||||
int start = i / 3 * 4;
|
||||
for (int k = start; k < start + 4; k++) {
|
||||
if (boneIndices.get(k) == boneIndex
|
||||
&& boneWeight.get(k) >= weightThreshold) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user