2
0
Эх сурвалжийг харах

test and fix for #1909 (NPE while generating tangents) (#1910)

* add a JUnit test for issue 1909 (NPE while generating tangents)

* solve issue #1909 (NPE while generating tangents)
Stephen Gold 2 жил өмнө
parent
commit
d694f7a072

+ 6 - 2
jme3-core/src/main/java/com/jme3/util/mikktspace/MikkTSpaceImpl.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2021 jMonkeyEngine
+ * Copyright (c) 2009-2023 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,14 @@ import java.nio.FloatBuffer;
 public class MikkTSpaceImpl implements MikkTSpaceContext {
 
     Mesh mesh;
+    final private IndexBuffer index;
 
     public MikkTSpaceImpl(Mesh mesh) {
         this.mesh = mesh;
+
+        // If the mesh lacks indices, generate a virtual index buffer.
+        this.index = mesh.getIndicesAsList();
+
         //replacing any existing tangent buffer, if you came here you want them new.
         mesh.clearBuffer(VertexBuffer.Type.Tangent);
         FloatBuffer fb = BufferUtils.createFloatBuffer(mesh.getVertexCount() * 4);
@@ -115,7 +120,6 @@ public class MikkTSpaceImpl implements MikkTSpaceContext {
     }
 
     private int getIndex(int face, int vert) {
-        IndexBuffer index = mesh.getIndexBuffer();
         int vertIndex = index.get(face * 3 + vert);
         return vertIndex;
     }

+ 97 - 0
jme3-core/src/test/java/com/jme3/util/TestIssue1909.java

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2023 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.util;
+
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer;
+import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
+import java.nio.FloatBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Verifies that tangents can be generated without an index buffer. This was
+ * issue #1909 at GitHub.
+ *
+ * @author Stephen Gold
+ */
+public class TestIssue1909 {
+    /**
+     * Tests MikktspaceTangentGenerator.generate() without index buffers.
+     */
+    @Test
+    public void testIssue1909() {
+        /*
+         * Generate normals, texture coordinates, and vertex positions
+         * for a large square in the X-Z plane.
+         */
+        FloatBuffer normals = BufferUtils.createFloatBuffer(
+                0f, 1f, 0f,
+                0f, 1f, 0f,
+                0f, 1f, 0f,
+                0f, 1f, 0f,
+                0f, 1f, 0f,
+                0f, 1f, 0f
+        );
+        float uvDiameter = 5f;
+        FloatBuffer uvs = BufferUtils.createFloatBuffer(
+                uvDiameter, uvDiameter,
+                0f, 0f,
+                uvDiameter, 0f,
+                uvDiameter, uvDiameter,
+                0f, uvDiameter,
+                0f, 0f
+        );
+        float posRadius = 500f;
+        FloatBuffer positions = BufferUtils.createFloatBuffer(
+                +posRadius, 0f, +posRadius,
+                -posRadius, 0f, -posRadius,
+                -posRadius, 0f, +posRadius,
+                +posRadius, 0f, +posRadius,
+                +posRadius, 0f, -posRadius,
+                -posRadius, 0f, -posRadius
+        );
+        Mesh mesh = new Mesh();
+        int numAxes = 3;
+        mesh.setBuffer(VertexBuffer.Type.Normal, numAxes, normals);
+        mesh.setBuffer(VertexBuffer.Type.Position, numAxes, positions);
+        mesh.setBuffer(VertexBuffer.Type.TexCoord, 2, uvs);
+        mesh.updateBound();
+
+        Geometry testGeometry = new Geometry("testGeometry", mesh);
+        MikktspaceTangentGenerator.generate(testGeometry);
+
+        VertexBuffer tangents = mesh.getBuffer(VertexBuffer.Type.Tangent);
+        Assert.assertNotNull(tangents);
+    }
+}