Fixed an issue where loaded glTF models couldn't use software skinning

fix-456
Nehon 7 years ago
parent 510562a62d
commit 32b947a0ac
  1. 20
      jme3-core/src/main/java/com/jme3/animation/SkeletonControl.java
  2. 19
      jme3-core/src/main/java/com/jme3/util/BufferUtils.java
  3. 21
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfUtils.java

@ -44,8 +44,7 @@ import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.control.AbstractControl; import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control; import com.jme3.scene.control.Control;
import com.jme3.shader.VarType; import com.jme3.shader.VarType;
import com.jme3.util.SafeArrayList; import com.jme3.util.*;
import com.jme3.util.TempVars;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
@ -113,6 +112,8 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
*/ */
private Set<Material> materials = new HashSet<Material>(); private Set<Material> materials = new HashSet<Material>();
//temp reader
private BufferUtils.ByteShortIntBufferReader indexReader = new BufferUtils.ByteShortIntBufferReader();
/** /**
* Serialization only. Do not use. * Serialization only. Do not use.
*/ */
@ -533,7 +534,6 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
if (maxWeightsPerVert <= 0) { if (maxWeightsPerVert <= 0) {
throw new IllegalStateException("Max weights per vert is incorrectly set!"); throw new IllegalStateException("Max weights per vert is incorrectly set!");
} }
int fourMinusMaxWeights = 4 - maxWeightsPerVert; int fourMinusMaxWeights = 4 - maxWeightsPerVert;
// NOTE: This code assumes the vertex buffer is in bind pose // NOTE: This code assumes the vertex buffer is in bind pose
@ -547,14 +547,13 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
fnb.rewind(); fnb.rewind();
// get boneIndexes and weights for mesh // get boneIndexes and weights for mesh
ByteBuffer ib = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData(); indexReader.setBuffer(mesh.getBuffer(Type.BoneIndex).getData());
FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData(); FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
ib.rewind(); indexReader.rewind();
wb.rewind(); wb.rewind();
float[] weights = wb.array(); float[] weights = wb.array();
byte[] indices = ib.array();
int idxWeights = 0; int idxWeights = 0;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
@ -592,7 +591,7 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
for (int w = maxWeightsPerVert - 1; w >= 0; w--) { for (int w = maxWeightsPerVert - 1; w >= 0; w--) {
float weight = weights[idxWeights]; float weight = weights[idxWeights];
Matrix4f mat = offsetMatrices[indices[idxWeights++] & 0xff]; Matrix4f mat = offsetMatrices[indexReader.getUnsigned(idxWeights++)];
rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight; rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight; ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
@ -665,14 +664,13 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
// get boneIndexes and weights for mesh // get boneIndexes and weights for mesh
ByteBuffer ib = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData(); indexReader.setBuffer(mesh.getBuffer(Type.BoneIndex).getData());
FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData(); FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
ib.rewind(); indexReader.rewind();
wb.rewind(); wb.rewind();
float[] weights = wb.array(); float[] weights = wb.array();
byte[] indices = ib.array();
int idxWeights = 0; int idxWeights = 0;
TempVars vars = TempVars.get(); TempVars vars = TempVars.get();
@ -725,7 +723,7 @@ public class SkeletonControl extends AbstractControl implements Cloneable, JmeCl
for (int w = maxWeightsPerVert - 1; w >= 0; w--) { for (int w = maxWeightsPerVert - 1; w >= 0; w--) {
float weight = weights[idxWeights]; float weight = weights[idxWeights];
Matrix4f mat = offsetMatrices[indices[idxWeights++] & 0xff]; Matrix4f mat = offsetMatrices[indexReader.getUnsigned(idxWeights++)];
rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight; rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight; ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;

@ -1344,6 +1344,9 @@ public final class BufferUtils {
public static class ByteShortIntBufferReader { public static class ByteShortIntBufferReader {
Buffer buffer; Buffer buffer;
public ByteShortIntBufferReader() {
}
public ByteShortIntBufferReader(Buffer buffer) { public ByteShortIntBufferReader(Buffer buffer) {
this.buffer = buffer; this.buffer = buffer;
} }
@ -1372,6 +1375,22 @@ public final class BufferUtils {
} }
} }
public int getUnsigned(int index) {
if (buffer instanceof ByteBuffer) {
return ((ByteBuffer) buffer).get(index) & 0xff;
} else if (buffer instanceof ShortBuffer) {
return ((ShortBuffer) buffer).get(index) & 0xffff;
} else if (buffer instanceof IntBuffer) {
return ((IntBuffer) buffer).get(index) & 0xffffff;
} else {
throw new UnsupportedOperationException("Buffer must be a ByteBuffer, a ShortBuffer or an IntBuffer");
}
}
public void setBuffer(Buffer buffer) {
this.buffer = buffer;
}
public void rewind() { public void rewind() {
buffer.rewind(); buffer.rewind();
} }

@ -382,11 +382,6 @@ public class GltfUtils {
public static void handleSkinningBuffers(Mesh mesh, IntMap<GltfLoader.SkinBuffers> skinBuffers) { public static void handleSkinningBuffers(Mesh mesh, IntMap<GltfLoader.SkinBuffers> skinBuffers) {
if (skinBuffers.size() > 0) { if (skinBuffers.size() > 0) {
if (skinBuffers.size() == 1) {
GltfLoader.SkinBuffers buffs = skinBuffers.get(0);
setSkinBuffers(mesh, buffs.joints, skinBuffers.get(0).weights, buffs.componentSize);
} else {
int length = skinBuffers.get(0).joints.length; int length = skinBuffers.get(0).joints.length;
short[] jointsArray = new short[length]; short[] jointsArray = new short[length];
float[] weightsArray = new float[length]; float[] weightsArray = new float[length];
@ -414,17 +409,31 @@ public class GltfUtils {
} }
} }
}); });
float sum = 0;
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
GltfLoader.WeightData data = weightData.get(j); GltfLoader.WeightData data = weightData.get(j);
jointsArray[i + j] = data.index; jointsArray[i + j] = data.index;
weightsArray[i + j] = data.value; weightsArray[i + j] = data.value;
sum += data.value;
if (data.value > 0 && (j + 1) > mesh.getMaxNumWeights()) {
mesh.setMaxNumWeights(j + 1);
}
if (data.componentSize > componentSize) { if (data.componentSize > componentSize) {
componentSize = data.componentSize; componentSize = data.componentSize;
} }
} }
if (sum != 1f) {
// compute new vals based on sum
float sumToB = sum == 0 ? 0 : 1f / sum;
weightsArray[i] *= sumToB;
weightsArray[i + 1] *= sumToB;
weightsArray[i + 2] *= sumToB;
weightsArray[i + 3] *= sumToB;
} }
setSkinBuffers(mesh, jointsArray, weightsArray, componentSize);
} }
setSkinBuffers(mesh, jointsArray, weightsArray, componentSize);
} }
} }

Loading…
Cancel
Save