Pārlūkot izejas kodu

Refactored how BatchNode transforms vertex buffers, and fixed issue #731 (NPE when no normal buffer)

Nehon 8 gadi atpakaļ
vecāks
revīzija
ef5952bcad
1 mainītis faili ar 82 papildinājumiem un 104 dzēšanām
  1. 82 104
      jme3-core/src/main/java/com/jme3/scene/BatchNode.java

+ 82 - 104
jme3-core/src/main/java/com/jme3/scene/BatchNode.java

@@ -63,7 +63,6 @@ import com.jme3.util.clone.JmeCloneable;
  * Sub geoms can be added after the batch() method has been called but won't be batched and will just be rendered as normal geometries.
  * To integrate them in the batch you have to call the batch() method again on the batchNode.
  * <p>
- * TODO normal or tangents or both looks a bit weird
  * TODO more automagic (batch when needed in the updateLogicalState)
  *
  * @author Nehon
@@ -134,35 +133,44 @@ public class BatchNode extends GeometryGroupNode {
             Mesh origMesh = bg.getMesh();
 
             VertexBuffer pvb = mesh.getBuffer(VertexBuffer.Type.Position);
-            FloatBuffer posBuf = (FloatBuffer) pvb.getData();
             VertexBuffer nvb = mesh.getBuffer(VertexBuffer.Type.Normal);
-            FloatBuffer normBuf = (FloatBuffer) nvb.getData();
+            VertexBuffer tvb = mesh.getBuffer(VertexBuffer.Type.Tangent);
 
             VertexBuffer opvb = origMesh.getBuffer(VertexBuffer.Type.Position);
-            FloatBuffer oposBuf = (FloatBuffer) opvb.getData();
             VertexBuffer onvb = origMesh.getBuffer(VertexBuffer.Type.Normal);
-            FloatBuffer onormBuf = (FloatBuffer) onvb.getData();
+            VertexBuffer otvb = origMesh.getBuffer(VertexBuffer.Type.Tangent);
+
+            FloatBuffer posBuf = getFloatBuffer(pvb);
+            FloatBuffer normBuf = getFloatBuffer(nvb);
+            FloatBuffer tanBuf = getFloatBuffer(tvb);
+
+            FloatBuffer oposBuf = getFloatBuffer(opvb);
+            FloatBuffer onormBuf = getFloatBuffer(onvb);
+            FloatBuffer otanBuf = getFloatBuffer(otvb);
+
             Matrix4f transformMat = getTransformMatrix(bg);
+            doTransforms(oposBuf, onormBuf, otanBuf, posBuf, normBuf, tanBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat);
 
-            if (mesh.getBuffer(VertexBuffer.Type.Tangent) != null) {
+            pvb.updateData(posBuf);
 
-                VertexBuffer tvb = mesh.getBuffer(VertexBuffer.Type.Tangent);
-                FloatBuffer tanBuf = (FloatBuffer) tvb.getData();
-                VertexBuffer otvb = origMesh.getBuffer(VertexBuffer.Type.Tangent);
-                FloatBuffer otanBuf = (FloatBuffer) otvb.getData();
-                doTransformsTangents(oposBuf, onormBuf, otanBuf, posBuf, normBuf, tanBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat);
+            if (nvb != null) {
+                nvb.updateData(normBuf);
+            }
+            if (tvb != null) {
                 tvb.updateData(tanBuf);
-            } else {
-                doTransforms(oposBuf, onormBuf, posBuf, normBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat);
             }
-            pvb.updateData(posBuf);
-            nvb.updateData(normBuf);
-
 
             batch.geometry.updateModelBound();
         }
     }
 
+    private FloatBuffer getFloatBuffer(VertexBuffer vb) {
+        if (vb == null) {
+            return null;
+        }
+        return (FloatBuffer) vb.getData();
+    }
+
     /**
      * Batch this batchNode
      * every geometry of the sub scene graph of this node will be batched into a single mesh that will be rendered in one call
@@ -521,53 +529,7 @@ public class BatchNode extends GeometryGroupNode {
         }
     }
 
-    private void doTransforms(FloatBuffer bindBufPos, FloatBuffer bindBufNorm, FloatBuffer bufPos, FloatBuffer bufNorm, int start, int end, Matrix4f transform) {
-        TempVars vars = TempVars.get();
-        Vector3f pos = vars.vect1;
-        Vector3f norm = vars.vect2;
-
-        int length = (end - start) * 3;
-
-        // offset is given in element units
-        // convert to be in component units
-        int offset = start * 3;
-        bindBufPos.rewind();
-        bindBufNorm.rewind();
-        //bufPos.position(offset);
-        //bufNorm.position(offset);
-        bindBufPos.get(tmpFloat, 0, length);
-        bindBufNorm.get(tmpFloatN, 0, length);
-        int index = 0;
-        while (index < length) {
-            pos.x = tmpFloat[index];
-            norm.x = tmpFloatN[index++];
-            pos.y = tmpFloat[index];
-            norm.y = tmpFloatN[index++];
-            pos.z = tmpFloat[index];
-            norm.z = tmpFloatN[index];
-
-            transform.mult(pos, pos);
-            transform.multNormal(norm, norm);
-
-            index -= 2;
-            tmpFloat[index] = pos.x;
-            tmpFloatN[index++] = norm.x;
-            tmpFloat[index] = pos.y;
-            tmpFloatN[index++] = norm.y;
-            tmpFloat[index] = pos.z;
-            tmpFloatN[index++] = norm.z;
-
-        }
-        vars.release();
-        bufPos.position(offset);
-        //using bulk put as it's faster
-        bufPos.put(tmpFloat, 0, length);
-        bufNorm.position(offset);
-        //using bulk put as it's faster
-        bufNorm.put(tmpFloatN, 0, length);
-    }
-
-    private void doTransformsTangents(FloatBuffer bindBufPos, FloatBuffer bindBufNorm, FloatBuffer bindBufTangents, FloatBuffer bufPos, FloatBuffer bufNorm, FloatBuffer bufTangents, int start, int end, Matrix4f transform) {
+    private void doTransforms(FloatBuffer bindBufPos, FloatBuffer bindBufNorm, FloatBuffer bindBufTangents, FloatBuffer bufPos, FloatBuffer bufNorm, FloatBuffer bufTangents, int start, int end, Matrix4f transform) {
         TempVars vars = TempVars.get();
         Vector3f pos = vars.vect1;
         Vector3f norm = vars.vect2;
@@ -581,60 +543,76 @@ public class BatchNode extends GeometryGroupNode {
         int offset = start * 3;
         int tanOffset = start * 4;
 
-
         bindBufPos.rewind();
-        bindBufNorm.rewind();
-        bindBufTangents.rewind();
         bindBufPos.get(tmpFloat, 0, length);
-        bindBufNorm.get(tmpFloatN, 0, length);
-        bindBufTangents.get(tmpFloatT, 0, tanLength);
+
+        if (bindBufNorm != null) {
+            bindBufNorm.rewind();
+            bindBufNorm.get(tmpFloatN, 0, length);
+        }
+
+        if (bindBufTangents != null) {
+            bindBufTangents.rewind();
+            bindBufTangents.get(tmpFloatT, 0, tanLength);
+        }
 
         int index = 0;
         int tanIndex = 0;
-        while (index < length) {
-            pos.x = tmpFloat[index];
-            norm.x = tmpFloatN[index++];
-            pos.y = tmpFloat[index];
-            norm.y = tmpFloatN[index++];
-            pos.z = tmpFloat[index];
-            norm.z = tmpFloatN[index];
+        int index1, index2, tanIndex1, tanIndex2;
 
-            tan.x = tmpFloatT[tanIndex++];
-            tan.y = tmpFloatT[tanIndex++];
-            tan.z = tmpFloatT[tanIndex++];
+        while (index < length) {
+            index1 = index + 1;
+            index2 = index + 2;
 
+            pos.x = tmpFloat[index];
+            pos.y = tmpFloat[index1];
+            pos.z = tmpFloat[index2];
             transform.mult(pos, pos);
-            transform.multNormal(norm, norm);
-            transform.multNormal(tan, tan);
-
-            index -= 2;
-            tanIndex -= 3;
-
             tmpFloat[index] = pos.x;
-            tmpFloatN[index++] = norm.x;
-            tmpFloat[index] = pos.y;
-            tmpFloatN[index++] = norm.y;
-            tmpFloat[index] = pos.z;
-            tmpFloatN[index++] = norm.z;
-
-            tmpFloatT[tanIndex++] = tan.x;
-            tmpFloatT[tanIndex++] = tan.y;
-            tmpFloatT[tanIndex++] = tan.z;
+            tmpFloat[index1] = pos.y;
+            tmpFloat[index2] = pos.z;
+
+            if (bindBufNorm != null) {
+                norm.x = tmpFloatN[index];
+                norm.y = tmpFloatN[index1];
+                norm.z = tmpFloatN[index2];
+                transform.multNormal(norm, norm);
+                tmpFloatN[index] = norm.x;
+                tmpFloatN[index1] = norm.y;
+                tmpFloatN[index2] = norm.z;
+            }
 
-            //Skipping 4th element of tangent buffer (handedness)
-            tanIndex++;
+            index += 3;
+
+            if (bindBufTangents != null) {
+                tanIndex1 = tanIndex + 1;
+                tanIndex2 = tanIndex + 2;
+                tan.x = tmpFloatT[tanIndex];
+                tan.y = tmpFloatT[tanIndex1];
+                tan.z = tmpFloatT[tanIndex2];
+                transform.multNormal(tan, tan);
+                tmpFloatT[tanIndex] = tan.x;
+                tmpFloatT[tanIndex1] = tan.y;
+                tmpFloatT[tanIndex2] = tan.z;
+                tanIndex += 4;
+            }
 
         }
         vars.release();
-        bufPos.position(offset);
+
         //using bulk put as it's faster
+        bufPos.position(offset);
         bufPos.put(tmpFloat, 0, length);
-        bufNorm.position(offset);
-        //using bulk put as it's faster
-        bufNorm.put(tmpFloatN, 0, length);
-        bufTangents.position(tanOffset);
-        //using bulk put as it's faster
-        bufTangents.put(tmpFloatT, 0, tanLength);
+
+        if (bindBufNorm != null) {
+            bufNorm.position(offset);
+            bufNorm.put(tmpFloatN, 0, length);
+        }
+
+        if (bindBufTangents != null) {
+            bufTangents.position(tanOffset);
+            bufTangents.put(tmpFloatT, 0, tanLength);
+        }
     }
 
     private void doCopyBuffer(FloatBuffer inBuf, int offset, FloatBuffer outBuf, int componentSize) {
@@ -646,11 +624,11 @@ public class BatchNode extends GeometryGroupNode {
         offset *= componentSize;
 
         for (int i = 0; i < inBuf.limit() / componentSize; i++) {
-            pos.x = inBuf.get(i * componentSize + 0);
+            pos.x = inBuf.get(i * componentSize);
             pos.y = inBuf.get(i * componentSize + 1);
             pos.z = inBuf.get(i * componentSize + 2);
 
-            outBuf.put(offset + i * componentSize + 0, pos.x);
+            outBuf.put(offset + i * componentSize, pos.x);
             outBuf.put(offset + i * componentSize + 1, pos.y);
             outBuf.put(offset + i * componentSize + 2, pos.z);
         }