parent
7e17cdc498
commit
5bbc6bcf1e
@ -57,6 +57,7 @@ import com.jme3.math.Quaternion;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.RenderManager;
|
import com.jme3.renderer.RenderManager;
|
||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.scene.control.Control;
|
import com.jme3.scene.control.Control;
|
||||||
@ -212,6 +213,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
* @param ex exporter (not null)
|
* @param ex exporter (not null)
|
||||||
* @throws IOException from exporter
|
* @throws IOException from exporter
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
oc.write(rigidBody, "rigidBody", null);
|
oc.write(rigidBody, "rigidBody", null);
|
||||||
@ -229,6 +231,7 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
* @param im importer (not null)
|
* @param im importer (not null)
|
||||||
* @throws IOException from importer
|
* @throws IOException from importer
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void read(JmeImporter im) throws IOException {
|
public void read(JmeImporter im) throws IOException {
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
rigidBody = (PhysicsRigidBody) ic.readSavable("rigidBody", null);
|
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)
|
* @param tpf the time interval between frames (in seconds, ≥0)
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void update(float tpf) {
|
public void update(float tpf) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
@ -348,15 +352,9 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
link.bone.setUserTransformsInModelSpace(position, tmpRot1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//If boneList is empty, every bone has a collision shape,
|
//some bones of the skeleton might not be associated with a collision shape.
|
||||||
//so we simply update the bone position.
|
//So we update them recusively
|
||||||
if (boneList.isEmpty()) {
|
RagdollUtils.setTransform(link.bone, position, tmpRot1, false, boneList);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vars.release();
|
vars.release();
|
||||||
@ -391,17 +389,8 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
tmpRot1.set(tmpRot2);
|
tmpRot1.set(tmpRot2);
|
||||||
position.set(position2);
|
position.set(position2);
|
||||||
|
|
||||||
//updating bones transforms
|
//update bone transforms
|
||||||
if (boneList.isEmpty()) {
|
RagdollUtils.setTransform(link.bone, position, tmpRot1, true, boneList);
|
||||||
//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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//setting skeleton transforms to the ragdoll
|
//setting skeleton transforms to the ragdoll
|
||||||
matchPhysicObjectToBone(link, position, tmpRot1);
|
matchPhysicObjectToBone(link, position, tmpRot1);
|
||||||
@ -589,6 +578,22 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
model.removeControl(sc);
|
model.removeControl(sc);
|
||||||
model.addControl(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
|
// put into bind pose and compute bone transforms in model space
|
||||||
// maybe don't reset to ragdoll out of animations?
|
// maybe don't reset to ragdoll out of animations?
|
||||||
scanSpatial(model);
|
scanSpatial(model);
|
||||||
@ -608,6 +613,25 @@ public class KinematicRagdollControl extends AbstractPhysicsControl implements P
|
|||||||
logger.log(Level.FINE, "Created physics ragdoll for skeleton {0}", skeleton);
|
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
|
* Destroy spatial-dependent data. Invoked when this control is removed from
|
||||||
* a spatial.
|
* 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) {
|
protected void boneRecursion(Spatial model, Bone bone, PhysicsRigidBody parent, int reccount, Map<Integer, List<Float>> pointsMap) {
|
||||||
PhysicsRigidBody parentShape = parent;
|
PhysicsRigidBody parentShape = parent;
|
||||||
if (boneList.isEmpty() || boneList.contains(bone.getName())) {
|
if (boneList.contains(bone.getName())) {
|
||||||
|
|
||||||
PhysicsBoneLink link = new PhysicsBoneLink();
|
PhysicsBoneLink link = new PhysicsBoneLink();
|
||||||
link.bone = bone;
|
link.bone = bone;
|
||||||
|
@ -56,6 +56,12 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class RagdollUtils {
|
public class RagdollUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private constructor to inhibit instantiation of this class.
|
||||||
|
*/
|
||||||
|
private RagdollUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alter the limits of the specified 6-DOF joint.
|
* 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()];
|
float[] p = new float[points.size()];
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
p[i] = points.get(i);
|
p[i] = points.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new HullCollisionShape(p);
|
return new HullCollisionShape(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,12 +241,13 @@ public class RagdollUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert !points.isEmpty();
|
||||||
float[] p = new float[points.size()];
|
float[] p = new float[points.size()];
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
p[i] = points.get(i);
|
p[i] = points.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new HullCollisionShape(p);
|
return new HullCollisionShape(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,4 +350,39 @@ public class RagdollUtils {
|
|||||||
setUserControl(child, bool);
|
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