Added support for attachment nodes.

JME now supports byte buffers for index buffer
fix-456
Nehon 7 years ago committed by Rémy Bouquet
parent d6c74dbf37
commit 1bdebd5505
  1. 1
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  2. 27
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  3. 40
      jme3-core/src/main/java/com/jme3/util/BufferUtils.java
  4. 37
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

@ -2592,6 +2592,7 @@ public final class GLRenderer implements Renderer {
}
switch (indexBuf.getFormat()) {
case UnsignedByte:
case UnsignedShort:
// OK: Works on all platforms.
break;

@ -53,6 +53,8 @@ import com.jme3.util.IntMap.Entry;
import com.jme3.util.SafeArrayList;
import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable;
import com.sun.javaws.exceptions.InvalidArgumentException;
import java.io.IOException;
import java.nio.*;
import java.util.ArrayList;
@ -402,11 +404,20 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
// convert indices to ubytes on the heap
VertexBuffer indices = getBuffer(Type.BoneIndex);
if (!indices.getData().hasArray()) {
ByteBuffer originalIndex = (ByteBuffer) indices.getData();
ByteBuffer arrayIndex = ByteBuffer.allocate(originalIndex.capacity());
originalIndex.clear();
arrayIndex.put(originalIndex);
indices.updateData(arrayIndex);
if (indices.getFormat() == Format.UnsignedByte) {
ByteBuffer originalIndex = (ByteBuffer) indices.getData();
ByteBuffer arrayIndex = ByteBuffer.allocate(originalIndex.capacity());
originalIndex.clear();
arrayIndex.put(originalIndex);
indices.updateData(arrayIndex);
} else {
//bone indices can be stored in an UnsignedShort buffer
ShortBuffer originalIndex = (ShortBuffer) indices.getData();
ShortBuffer arrayIndex = ShortBuffer.allocate(originalIndex.capacity());
originalIndex.clear();
arrayIndex.put(originalIndex);
indices.updateData(arrayIndex);
}
}
indices.setUsage(Usage.CpuOnly);
@ -1437,7 +1448,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
return false; // no bone animation data
}
ByteBuffer boneIndexBuffer = (ByteBuffer) biBuf.getData();
BufferUtils.ByteShortIntBufferReader boneIndexBuffer = new BufferUtils.ByteShortIntBufferReader(biBuf.getData());
boneIndexBuffer.rewind();
int numBoneIndices = boneIndexBuffer.remaining();
assert numBoneIndices % 4 == 0 : numBoneIndices;
@ -1450,10 +1461,10 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
/*
* Test each vertex to determine whether the bone affects it.
*/
byte biByte = (byte) boneIndex; // bone indices wrap after 127
int biByte = boneIndex;
for (int vIndex = 0; vIndex < numVertices; vIndex++) {
for (int wIndex = 0; wIndex < 4; wIndex++) {
byte bIndex = boneIndexBuffer.get();
int bIndex = boneIndexBuffer.get();
float weight = weightBuffer.get();
if (wIndex < maxNumWeights && bIndex == biByte && weight != 0f) {
return true;

@ -1340,4 +1340,44 @@ public final class BufferUtils {
}
}
}
public static class ByteShortIntBufferReader {
Buffer buffer;
public ByteShortIntBufferReader(Buffer buffer) {
this.buffer = buffer;
}
public int get() {
if (buffer instanceof ByteBuffer) {
return ((ByteBuffer) buffer).get();
} else if (buffer instanceof ShortBuffer) {
return ((ShortBuffer) buffer).get();
} else if (buffer instanceof IntBuffer) {
return ((IntBuffer) buffer).get();
} else {
throw new UnsupportedOperationException("Buffer must be a ByteBuffer, a ShortBuffer or an IntBuffer");
}
}
public int get(int index) {
if (buffer instanceof ByteBuffer) {
return ((ByteBuffer) buffer).get(index);
} else if (buffer instanceof ShortBuffer) {
return ((ShortBuffer) buffer).get(index);
} else if (buffer instanceof IntBuffer) {
return ((IntBuffer) buffer).get(index);
} else {
throw new UnsupportedOperationException("Buffer must be a ByteBuffer, a ShortBuffer or an IntBuffer");
}
}
public void rewind() {
buffer.rewind();
}
public int remaining() {
return buffer.remaining();
}
}
}

@ -894,7 +894,6 @@ public class GltfLoader implements AssetLoader {
int boneIndex = joints.get(i).getAsInt();
//we don't need the inverse bind matrix, we need the bind matrix so let's invert it.
Matrix4f modelBindMatrix = inverseBindMatrices[i].invertLocal();
//TODO actually a regular node or a geometry can be attached to a bone, we have to handle this and attach it to the AttachementNode.
bones[i] = readNodeAsBone(boneIndex, i, index, modelBindMatrix);
}
@ -990,10 +989,11 @@ public class GltfLoader implements AssetLoader {
return bone;
}
private void findChildren(int nodeIndex) {
private void findChildren(int nodeIndex) throws IOException {
BoneWrapper bw = fetchFromCache("nodes", nodeIndex, BoneWrapper.class);
JsonObject nodeData = nodes.get(nodeIndex).getAsJsonObject();
JsonArray children = nodeData.getAsJsonArray("children");
if (children != null) {
for (JsonElement child : children) {
int childIndex = child.getAsInt();
@ -1001,8 +1001,18 @@ public class GltfLoader implements AssetLoader {
if (cbw != null) {
bw.bone.addChild(cbw.bone);
bw.children.add(childIndex);
} else {
JsonObject childNode = nodes.get(childIndex).getAsJsonObject();
//The child might be a Geom
if (getAsInteger(childNode, "mesh") != null) {
//this is a geometry, let's load it as a spatial
Spatial s = (Spatial) readNode(childIndex);
bw.attachedSpatial = s;
// addToCache("nodes", nodeIndex, s, nodes.size());
}
}
}
}
}
@ -1010,6 +1020,10 @@ public class GltfLoader implements AssetLoader {
for (SkinData skinData : skinnedSpatials.keySet()) {
List<Spatial> spatials = skinnedSpatials.get(skinData);
Spatial spatial;
if (spatials.isEmpty()) {
//can happen when a file contains a skin that is not used by any mesh...
continue;
}
if (spatials.size() >= 1) {
spatial = findCommonAncestor(spatials);
} else {
@ -1028,9 +1042,17 @@ public class GltfLoader implements AssetLoader {
if (skinData.animControl != null) {
spatial.addControl(skinData.animControl);
spatial.addControl(skinData.skeletonControl);
}
spatial.addControl(skinData.skeletonControl);
}
for (int i = 0; i < nodes.size(); i++) {
BoneWrapper bw = fetchFromCache("nodes", i, BoneWrapper.class);
if (bw == null || bw.attachedSpatial == null) {
continue;
}
SkinData skinData = fetchFromCache("skins", bw.skinIndex, SkinData.class);
skinData.skeletonControl.getAttachmentsNode(bw.bone.getName()).attachChild(bw.attachedSpatial);
}
}
@ -1044,7 +1066,13 @@ public class GltfLoader implements AssetLoader {
if (data == null) {
return null;
}
return type.cast(data[index]);
try {
T ret = type.cast(data[index]);
return ret;
} catch (ClassCastException e) {
return null;
}
}
public void addToCache(String name, int index, Object object, int maxLength) {
@ -1128,6 +1156,7 @@ public class GltfLoader implements AssetLoader {
Transform localTransform;
Matrix4f modelBindMatrix;
boolean isRoot = false;
Spatial attachedSpatial;
List<Integer> children = new ArrayList<>();
public BoneWrapper(Bone bone, int boneIndex, int skinIndex, Matrix4f modelBindMatrix, Transform localTransform) {

Loading…
Cancel
Save