Sfoglia il codice sorgente

Added support for attachment nodes.
JME now supports byte buffers for index buffer

Nehon 8 anni fa
parent
commit
1bdebd5505

+ 1 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

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

+ 19 - 8
jme3-core/src/main/java/com/jme3/scene/Mesh.java

@@ -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;

+ 40 - 0
jme3-core/src/main/java/com/jme3/util/BufferUtils.java

@@ -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();
+        }
+    }
 }

+ 33 - 4
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

@@ -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) {