浏览代码

Never return the cached spatial directly: prevent the manipulation of the first instance of a spatial from poisoning the cache. (#2104)

Riccardo Balbo 1 年之前
父节点
当前提交
88813e27a0
共有 1 个文件被更改,包括 115 次插入116 次删除
  1. 115 116
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

+ 115 - 116
jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java

@@ -364,136 +364,135 @@ public class GltfLoader implements AssetLoader {
 
     public Geometry[] readMeshPrimitives(int meshIndex) throws IOException {
         Geometry[] geomArray = (Geometry[]) fetchFromCache("meshes", meshIndex, Object.class);
-        if (geomArray != null) {
-            // cloning the geoms.
-            Geometry[] geoms = new Geometry[geomArray.length];
-            for (int i = 0; i < geoms.length; i++) {
-                geoms[i] = geomArray[i].clone(false);
-            }
-            return geoms;
-        }
-        JsonObject meshData = meshes.get(meshIndex).getAsJsonObject();
-        JsonArray primitives = meshData.getAsJsonArray("primitives");
-        assertNotNull(primitives, "Can't find any primitives in mesh " + meshIndex);
-        String name = getAsString(meshData, "name");
-
-        geomArray = new Geometry[primitives.size()];
-        int index = 0;
-        for (JsonElement primitive : primitives) {
-            JsonObject meshObject = primitive.getAsJsonObject();
-            Mesh mesh = new Mesh();
-            addToCache("mesh", 0, mesh, 1);
-            Integer mode = getAsInteger(meshObject, "mode");
-            mesh.setMode(getMeshMode(mode));
-            Integer indices = getAsInteger(meshObject, "indices");
-            if (indices != null) {
-                mesh.setBuffer(readAccessorData(indices, new VertexBufferPopulator(VertexBuffer.Type.Index)));
-            }
-            JsonObject attributes = meshObject.getAsJsonObject("attributes");
-            assertNotNull(attributes, "No attributes defined for mesh " + mesh);
-
-            skinBuffers.clear();
-
-            for (Map.Entry<String, JsonElement> entry : attributes.entrySet()) {
-                // special case for joints and weights buffer.
-                // If there are more than 4 bones per vertex, there might be several of them
-                // we need to read them all and to keep only the 4 that have the most weight on the vertex.
-                String bufferType = entry.getKey();
-                if (bufferType.startsWith("JOINTS")) {
-                    SkinBuffers buffs = getSkinBuffers(bufferType);
-                    SkinBuffers buffer
-                            = readAccessorData(entry.getValue().getAsInt(), new JointArrayPopulator());
-                    buffs.joints = buffer.joints;
-                    buffs.componentSize = buffer.componentSize;
-                } else if (bufferType.startsWith("WEIGHTS")) {
-                    SkinBuffers buffs = getSkinBuffers(bufferType);
-                    buffs.weights = readAccessorData(entry.getValue().getAsInt(), new FloatArrayPopulator());
-                } else {
-                    VertexBuffer vb = readAccessorData(entry.getValue().getAsInt(),
-                            new VertexBufferPopulator(getVertexBufferType(bufferType)));
-                    if (vb != null) {
-                        mesh.setBuffer(vb);
+        if (geomArray == null) {                
+            JsonObject meshData = meshes.get(meshIndex).getAsJsonObject();
+            JsonArray primitives = meshData.getAsJsonArray("primitives");
+            assertNotNull(primitives, "Can't find any primitives in mesh " + meshIndex);
+            String name = getAsString(meshData, "name");
+
+            geomArray = new Geometry[primitives.size()];
+            int index = 0;
+            for (JsonElement primitive : primitives) {
+                JsonObject meshObject = primitive.getAsJsonObject();
+                Mesh mesh = new Mesh();
+                addToCache("mesh", 0, mesh, 1);
+                Integer mode = getAsInteger(meshObject, "mode");
+                mesh.setMode(getMeshMode(mode));
+                Integer indices = getAsInteger(meshObject, "indices");
+                if (indices != null) {
+                    mesh.setBuffer(readAccessorData(indices, new VertexBufferPopulator(VertexBuffer.Type.Index)));
+                }
+                JsonObject attributes = meshObject.getAsJsonObject("attributes");
+                assertNotNull(attributes, "No attributes defined for mesh " + mesh);
+
+                skinBuffers.clear();
+
+                for (Map.Entry<String, JsonElement> entry : attributes.entrySet()) {
+                    // special case for joints and weights buffer.
+                    // If there are more than 4 bones per vertex, there might be several of them
+                    // we need to read them all and to keep only the 4 that have the most weight on the vertex.
+                    String bufferType = entry.getKey();
+                    if (bufferType.startsWith("JOINTS")) {
+                        SkinBuffers buffs = getSkinBuffers(bufferType);
+                        SkinBuffers buffer
+                                = readAccessorData(entry.getValue().getAsInt(), new JointArrayPopulator());
+                        buffs.joints = buffer.joints;
+                        buffs.componentSize = buffer.componentSize;
+                    } else if (bufferType.startsWith("WEIGHTS")) {
+                        SkinBuffers buffs = getSkinBuffers(bufferType);
+                        buffs.weights = readAccessorData(entry.getValue().getAsInt(), new FloatArrayPopulator());
+                    } else {
+                        VertexBuffer vb = readAccessorData(entry.getValue().getAsInt(),
+                                new VertexBufferPopulator(getVertexBufferType(bufferType)));
+                        if (vb != null) {
+                            mesh.setBuffer(vb);
+                        }
                     }
                 }
-            }
-            handleSkinningBuffers(mesh, skinBuffers);
-
-            if (mesh.getBuffer(VertexBuffer.Type.BoneIndex) != null) {
-                // the mesh has some skinning, let's create needed buffers for HW skinning
-                // creating empty buffers for HW skinning
-                // the buffers will be set up if ever used.
-                VertexBuffer weightsHW = new VertexBuffer(VertexBuffer.Type.HWBoneWeight);
-                VertexBuffer indicesHW = new VertexBuffer(VertexBuffer.Type.HWBoneIndex);
-                // setting usage to cpuOnly so that the buffer is not sent empty to the GPU
-                indicesHW.setUsage(VertexBuffer.Usage.CpuOnly);
-                weightsHW.setUsage(VertexBuffer.Usage.CpuOnly);
-                mesh.setBuffer(weightsHW);
-                mesh.setBuffer(indicesHW);
-                mesh.generateBindPose();
-            }
-
-            // Read morph target names
-            LinkedList<String> targetNames = new LinkedList<>();
-            if (meshData.has("extras") && meshData.getAsJsonObject("extras").has("targetNames")) {
-                JsonArray targetNamesJson = meshData.getAsJsonObject("extras").getAsJsonArray("targetNames");
-                for (JsonElement target : targetNamesJson) {
-                    targetNames.add(target.getAsString());
+                handleSkinningBuffers(mesh, skinBuffers);
+
+                if (mesh.getBuffer(VertexBuffer.Type.BoneIndex) != null) {
+                    // the mesh has some skinning, let's create needed buffers for HW skinning
+                    // creating empty buffers for HW skinning
+                    // the buffers will be set up if ever used.
+                    VertexBuffer weightsHW = new VertexBuffer(VertexBuffer.Type.HWBoneWeight);
+                    VertexBuffer indicesHW = new VertexBuffer(VertexBuffer.Type.HWBoneIndex);
+                    // setting usage to cpuOnly so that the buffer is not sent empty to the GPU
+                    indicesHW.setUsage(VertexBuffer.Usage.CpuOnly);
+                    weightsHW.setUsage(VertexBuffer.Usage.CpuOnly);
+                    mesh.setBuffer(weightsHW);
+                    mesh.setBuffer(indicesHW);
+                    mesh.generateBindPose();
                 }
-            }
 
-            // Read morph targets
-            JsonArray targets = meshObject.getAsJsonArray("targets");
-            if (targets != null) {
-                for (JsonElement target : targets) {
-                    MorphTarget morphTarget = new MorphTarget();
-                    if (targetNames.size() > 0) {
-                        morphTarget.setName(targetNames.pop());
+                // Read morph target names
+                LinkedList<String> targetNames = new LinkedList<>();
+                if (meshData.has("extras") && meshData.getAsJsonObject("extras").has("targetNames")) {
+                    JsonArray targetNamesJson = meshData.getAsJsonObject("extras").getAsJsonArray("targetNames");
+                    for (JsonElement target : targetNamesJson) {
+                        targetNames.add(target.getAsString());
                     }
-                    for (Map.Entry<String, JsonElement> entry : target.getAsJsonObject().entrySet()) {
-                        String bufferType = entry.getKey();
-                        VertexBuffer.Type type = getVertexBufferType(bufferType);
-                        VertexBuffer vb = readAccessorData(entry.getValue().getAsInt(),
-                                new VertexBufferPopulator(type));
-                        if (vb != null) {
-                            morphTarget.setBuffer(type, (FloatBuffer) vb.getData());
+                }
+
+                // Read morph targets
+                JsonArray targets = meshObject.getAsJsonArray("targets");
+                if (targets != null) {
+                    for (JsonElement target : targets) {
+                        MorphTarget morphTarget = new MorphTarget();
+                        if (targetNames.size() > 0) {
+                            morphTarget.setName(targetNames.pop());
+                        }
+                        for (Map.Entry<String, JsonElement> entry : target.getAsJsonObject().entrySet()) {
+                            String bufferType = entry.getKey();
+                            VertexBuffer.Type type = getVertexBufferType(bufferType);
+                            VertexBuffer vb = readAccessorData(entry.getValue().getAsInt(),
+                                    new VertexBufferPopulator(type));
+                            if (vb != null) {
+                                morphTarget.setBuffer(type, (FloatBuffer) vb.getData());
+                            }
                         }
+                        mesh.addMorphTarget(morphTarget);
                     }
-                    mesh.addMorphTarget(morphTarget);
                 }
-            }
 
-            // Read mesh extras
-            mesh = customContentManager.readExtensionAndExtras("primitive", meshObject, mesh);
-            Geometry geom = new Geometry(null, mesh);
+                // Read mesh extras
+                mesh = customContentManager.readExtensionAndExtras("primitive", meshObject, mesh);
+                Geometry geom = new Geometry(null, mesh);
 
-            Integer materialIndex = getAsInteger(meshObject, "material");
-            if (materialIndex == null) {
-                geom.setMaterial(defaultMat);
-            } else {
-                useNormalsFlag = false;
-                geom.setMaterial(readMaterial(materialIndex));
-                if (geom.getMaterial().getAdditionalRenderState().getBlendMode()
-                        == RenderState.BlendMode.Alpha) {
-                    // Alpha blending is enabled for this material. Let's place the geom in the transparent bucket.
-                    geom.setQueueBucket(RenderQueue.Bucket.Transparent);
-                }
-                if (useNormalsFlag && mesh.getBuffer(VertexBuffer.Type.Tangent) == null) {
-                    // No tangent buffer, but there is a normal map, we have to generate them using MikktSpace
-                    MikktspaceTangentGenerator.generate(geom);
+                Integer materialIndex = getAsInteger(meshObject, "material");
+                if (materialIndex == null) {
+                    geom.setMaterial(defaultMat);
+                } else {
+                    useNormalsFlag = false;
+                    geom.setMaterial(readMaterial(materialIndex));
+                    if (geom.getMaterial().getAdditionalRenderState().getBlendMode()
+                            == RenderState.BlendMode.Alpha) {
+                        // Alpha blending is enabled for this material. Let's place the geom in the transparent bucket.
+                        geom.setQueueBucket(RenderQueue.Bucket.Transparent);
+                    }
+                    if (useNormalsFlag && mesh.getBuffer(VertexBuffer.Type.Tangent) == null) {
+                        // No tangent buffer, but there is a normal map, we have to generate them using MikktSpace
+                        MikktspaceTangentGenerator.generate(geom);
+                    }
                 }
-            }
 
-            geom.setName(name + "_" + index);
-            
-            geom.updateModelBound();
-            geomArray[index] = geom;
-            index++;
-        }
+                geom.setName(name + "_" + index);
+                
+                geom.updateModelBound();
+                geomArray[index] = geom;
+                index++;
+            }
 
-        geomArray = customContentManager.readExtensionAndExtras("mesh", meshData, geomArray);
+            geomArray = customContentManager.readExtensionAndExtras("mesh", meshData, geomArray);
 
-        addToCache("meshes", meshIndex, geomArray, meshes.size());
-        return geomArray;
+            addToCache("meshes", meshIndex, geomArray, meshes.size());
+        }
+        // cloning the geoms.
+        Geometry[] geoms = new Geometry[geomArray.length];
+        for (int i = 0; i < geoms.length; i++) {
+            geoms[i] = geomArray[i].clone(false);
+        }
+        return geoms;
     }
 
     private SkinBuffers getSkinBuffers(String bufferType) {