From d694f7a072578b05b49f092a6613ad01618ba4cd Mon Sep 17 00:00:00 2001 From: Stephen Gold Date: Sat, 14 Jan 2023 21:51:08 -0800 Subject: [PATCH] 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) --- .../jme3/util/mikktspace/MikkTSpaceImpl.java | 8 +- .../java/com/jme3/util/TestIssue1909.java | 97 +++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 jme3-core/src/test/java/com/jme3/util/TestIssue1909.java diff --git a/jme3-core/src/main/java/com/jme3/util/mikktspace/MikkTSpaceImpl.java b/jme3-core/src/main/java/com/jme3/util/mikktspace/MikkTSpaceImpl.java index cb5912907c..18417b6b4c 100644 --- a/jme3-core/src/main/java/com/jme3/util/mikktspace/MikkTSpaceImpl.java +++ b/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 @@ 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 void setTSpace(float[] tangent, float[] biTangent, float magS, float magT } private int getIndex(int face, int vert) { - IndexBuffer index = mesh.getIndexBuffer(); int vertIndex = index.get(face * 3 + vert); return vertIndex; } diff --git a/jme3-core/src/test/java/com/jme3/util/TestIssue1909.java b/jme3-core/src/test/java/com/jme3/util/TestIssue1909.java new file mode 100644 index 0000000000..3cc91ef6f6 --- /dev/null +++ b/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); + } +}