Просмотр исходного кода

BatchNode now uses absolute world transforsm to update the underlying batch mesh, instead of computing the offset from next frame.
The real geometry mesh data is now used as a bind pose.
This avoids errors accumulations over time in some case and is less expensive.
See this post for the original issue http://hub.jmonkeyengine.org/forum/topic/batchnode-bug/

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10647 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om 12 лет назад
Родитель
Сommit
4c4e235e61

+ 30 - 18
engine/src/core/com/jme3/scene/BatchNode.java

@@ -139,28 +139,37 @@ public class BatchNode extends Node implements Savable {
         assert refreshFlags == 0;
     }
 
-    protected Transform getTransforms(Geometry geom) {
-        return geom.getWorldTransform();
+    protected Matrix4f getTransformMatrix(Geometry g){
+        return g.cachedWorldMat;
     }
-
+    
     protected void updateSubBatch(Geometry bg) {
         Batch batch = batchesByGeom.get(bg);
         if (batch != null) {
             Mesh mesh = batch.geometry.getMesh();
+            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 opvb = origMesh.getBuffer(VertexBuffer.Type.Position);
+            FloatBuffer oposBuf = (FloatBuffer) opvb.getData();
+            VertexBuffer onvb = origMesh.getBuffer(VertexBuffer.Type.Normal);
+            FloatBuffer onormBuf = (FloatBuffer) onvb.getData();
+            Matrix4f transformMat = getTransformMatrix(bg);
+            
             if (mesh.getBuffer(VertexBuffer.Type.Tangent) != null) {
 
                 VertexBuffer tvb = mesh.getBuffer(VertexBuffer.Type.Tangent);
                 FloatBuffer tanBuf = (FloatBuffer) tvb.getData();
-                doTransformsTangents(posBuf, normBuf, tanBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), bg.cachedOffsetMat);
+                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);
                 tvb.updateData(tanBuf);
             } else {
-                doTransforms(posBuf, normBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), bg.cachedOffsetMat);
+                doTransforms(oposBuf, onormBuf, posBuf, normBuf, bg.startIndex, bg.startIndex + bg.getVertexCount(), transformMat);
             }
             pvb.updateData(posBuf);
             nvb.updateData(normBuf);
@@ -585,7 +594,7 @@ public class BatchNode extends Node implements Savable {
         }
     }
 
-    private void doTransforms(FloatBuffer bufPos, FloatBuffer bufNorm, int start, int end, Matrix4f transform) {
+    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;
@@ -595,10 +604,12 @@ public class BatchNode extends Node implements Savable {
         // offset is given in element units
         // convert to be in component units
         int offset = start * 3;
-        bufPos.position(offset);
-        bufNorm.position(offset);
-        bufPos.get(tmpFloat, 0, length);
-        bufNorm.get(tmpFloatN, 0, length);
+        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];
@@ -629,7 +640,7 @@ public class BatchNode extends Node implements Savable {
         bufNorm.put(tmpFloatN, 0, length);
     }
 
-    private void doTransformsTangents(FloatBuffer bufPos, FloatBuffer bufNorm, FloatBuffer bufTangents, int start, int end, Matrix4f transform) {
+    private void doTransformsTangents(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;
@@ -643,12 +654,13 @@ public class BatchNode extends Node implements Savable {
         int offset = start * 3;
         int tanOffset = start * 4;
 
-        bufPos.position(offset);
-        bufNorm.position(offset);
-        bufTangents.position(tanOffset);
-        bufPos.get(tmpFloat, 0, length);
-        bufNorm.get(tmpFloatN, 0, length);
-        bufTangents.get(tmpFloatT, 0, tanLength);
+        
+        bindBufPos.rewind();
+        bindBufNorm.rewind();
+        bindBufTangents.rewind();
+        bindBufPos.get(tmpFloat, 0, length);
+        bindBufNorm.get(tmpFloatN, 0, length);
+        bindBufTangents.get(tmpFloatT, 0, tanLength);
 
         int index = 0;
         int tanIndex = 0;

+ 4 - 50
engine/src/core/com/jme3/scene/Geometry.java

@@ -78,16 +78,7 @@ public class Geometry extends Spatial {
     /**
      * the start index of this geom's mesh in the batchNode mesh
      */
-    protected int startIndex;
-    /**
-     * the previous transforms of the geometry used to compute world transforms
-     */
-    protected Transform prevBatchTransforms = null;
-    /**
-     * the cached offset matrix used when the geometry is batched
-     */
-    protected Matrix4f cachedOffsetMat = null;
-
+    protected int startIndex;    
     /**
      * Serialization only. Do not use.
      */
@@ -291,11 +282,8 @@ public class Geometry extends Spatial {
         super.updateWorldTransforms();
         computeWorldMatrix();
 
-        if (isBatched()) {
-            computeOffsetTransform();
-            batchNode.updateSubBatch(this);
-            prevBatchTransforms.set(batchNode.getTransforms(this));
-
+        if (isBatched()) {        
+            batchNode.updateSubBatch(this);     
         }
         // geometry requires lights to be sorted
         worldLights.sort(true);
@@ -308,9 +296,7 @@ public class Geometry extends Spatial {
      */
     protected void batch(BatchNode node, int startIndex) {
         this.batchNode = node;
-        this.startIndex = startIndex;
-        prevBatchTransforms = new Transform();
-        cachedOffsetMat = new Matrix4f();
+        this.startIndex = startIndex;       
         setCullHint(CullHint.Always);
     }
 
@@ -319,8 +305,6 @@ public class Geometry extends Spatial {
      */
     protected void unBatch() {
         this.startIndex = 0;
-        prevBatchTransforms = null;
-        cachedOffsetMat = null;
         //once the geometry is removed from the screnegraph the batchNode needs to be rebatched.
         if (batchNode != null) {
             this.batchNode.setNeedsFullRebatch(true);
@@ -343,36 +327,6 @@ public class Geometry extends Spatial {
         }
     }
 
-    /**
-     * Recomputes the cached offset matrix used when the geometry is batched     * 
-     */
-    public void computeOffsetTransform() {
-        TempVars vars = TempVars.get();
-        Matrix4f tmpMat = vars.tempMat42;
-
-        // Compute the cached world matrix
-        cachedOffsetMat.loadIdentity();
-        cachedOffsetMat.setRotationQuaternion(prevBatchTransforms.getRotation());
-        cachedOffsetMat.setTranslation(prevBatchTransforms.getTranslation());
-
-
-        Matrix4f scaleMat = vars.tempMat4;
-        scaleMat.loadIdentity();
-        scaleMat.scale(prevBatchTransforms.getScale());
-        cachedOffsetMat.multLocal(scaleMat);
-        cachedOffsetMat.invertLocal();
-
-        tmpMat.loadIdentity();
-        tmpMat.setRotationQuaternion(batchNode.getTransforms(this).getRotation());
-        tmpMat.setTranslation(batchNode.getTransforms(this).getTranslation());
-        scaleMat.loadIdentity();
-        scaleMat.scale(batchNode.getTransforms(this).getScale());
-        tmpMat.multLocal(scaleMat);
-
-        tmpMat.mult(cachedOffsetMat, cachedOffsetMat);
-
-        vars.release();
-    }
 
     /**
      * Indicate that the transform of this spatial has changed and that

+ 19 - 3
engine/src/core/com/jme3/scene/SimpleBatchNode.java

@@ -31,7 +31,9 @@
  */
 package com.jme3.scene;
 
+import com.jme3.math.Matrix4f;
 import com.jme3.math.Transform;
+import com.jme3.util.TempVars;
 
 /**
  * 
@@ -70,10 +72,24 @@ public class SimpleBatchNode extends BatchNode {
             batch.geometry.setTransformRefresh();
         }
     }
-    
-     protected Transform getTransforms(Geometry geom){
-        return geom.getLocalTransform();
+    private Matrix4f cachedLocalMat = new Matrix4f();
+
+    @Override
+    protected Matrix4f getTransformMatrix(Geometry g){
+        // Compute the Local matrix for the geometry
+        cachedLocalMat.loadIdentity();
+        cachedLocalMat.setRotationQuaternion(g.localTransform.getRotation());
+        cachedLocalMat.setTranslation(g.localTransform.getTranslation());
+
+        TempVars vars = TempVars.get();
+        Matrix4f scaleMat = vars.tempMat4;
+        scaleMat.loadIdentity();
+        scaleMat.scale(g.localTransform.getScale());
+        cachedLocalMat.multLocal(scaleMat);
+        vars.release();
+        return cachedLocalMat;
     }
+    
 
     @Override
     public void batch() {