浏览代码

code formatting (#1667)

-TangentBinormalGenerator: no changes, just remove extra empty lines and
code formatting.

-TestLodGeneration: code formatting; removal of commented or deprecated code.
Wyatt Gillette 3 年之前
父节点
当前提交
d35a068e7a

+ 203 - 228
jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java

@@ -59,64 +59,66 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 /**
- * 
+ *
  * @author Lex (Aleksey Nikiforov)
-  */
+ */
 public class TangentBinormalGenerator {
-    
+
+    private static final Logger log = Logger.getLogger(TangentBinormalGenerator.class.getName());
     private static final float ZERO_TOLERANCE = 0.0000001f;
-    private static final Logger log = Logger.getLogger(
-            TangentBinormalGenerator.class.getName());
     private static float toleranceDot;
     public static boolean debug = false;
-    
+
     static {
         setToleranceAngle(45);
     }
 
-    
     private static class VertexInfo {
+
         public final Vector3f position;
         public final Vector3f normal;
         public final Vector2f texCoord;
         public final ArrayList<Integer> indices = new ArrayList<>();
-        
+
         public VertexInfo(Vector3f position, Vector3f normal, Vector2f texCoord) {
             this.position = position;
             this.normal = normal;
             this.texCoord = texCoord;
         }
     }
-    
-    /** Collects all the triangle data for one vertex.
+
+    /**
+     * Collects all the triangle data for one vertex.
      */
     private static class VertexData {
+
         public final ArrayList<TriangleData> triangles = new ArrayList<>();
-        
-        public VertexData() { }
     }
-    
-    /** Keeps track of tangent, binormal, and normal for one triangle.
+
+    /**
+     * Keeps track of tangent, binormal, and normal for one triangle.
      */
     public static class TriangleData {
+
         public final Vector3f tangent;
         public final Vector3f binormal;
-        public final Vector3f normal;        
+        public final Vector3f normal;
         public int[] index = new int[3];
         public int triangleOffset;
-        
+
         public TriangleData(Vector3f tangent, Vector3f binormal, Vector3f normal) {
             this.tangent = tangent;
             this.binormal = binormal;
             this.normal = normal;
         }
+
         public void setIndex(int[] index) {
             for (int i = 0; i < index.length; i++) {
                 this.index[i] = index[i];
             }
         }
     }
-    
+
     /**
      * A private constructor to inhibit instantiation of this class.
      */
@@ -124,17 +126,17 @@ public class TangentBinormalGenerator {
     }
 
     private static List<VertexData> initVertexData(int size) {
-        List<VertexData> vertices = new ArrayList<>(size);        
+        List<VertexData> vertices = new ArrayList<>(size);
         for (int i = 0; i < size; i++) {
             vertices.add(new VertexData());
         }
         return vertices;
     }
-    
+
     public static void generate(Mesh mesh) {
         generate(mesh, true, false);
     }
-    
+
     public static void generate(Spatial scene, boolean splitMirrored) {
         if (scene instanceof Node) {
             Node node = (Node) scene;
@@ -144,19 +146,19 @@ public class TangentBinormalGenerator {
         } else {
             Geometry geom = (Geometry) scene;
             Mesh mesh = geom.getMesh();
-            
+
             // Check to ensure mesh has texcoords and normals before generating
-            if (mesh.getBuffer(Type.TexCoord) != null 
-             && mesh.getBuffer(Type.Normal) != null){
-                generate(geom.getMesh(),true, splitMirrored);
+            if (mesh.getBuffer(Type.TexCoord) != null
+                    && mesh.getBuffer(Type.Normal) != null) {
+                generate(geom.getMesh(), true, splitMirrored);
             }
         }
     }
-    
+
     public static void generate(Spatial scene) {
         generate(scene, false);
     }
-    
+
     public static void generateParallel(Spatial scene, ExecutorService executor) {
         final Set<Mesh> meshes = new HashSet<>();
         scene.breadthFirstTraversal(new SceneGraphVisitor() {
@@ -190,12 +192,9 @@ public class TangentBinormalGenerator {
                 log.log(Level.WARNING, "Error while computing tangents", exc);
             }
         }
+    }
 
-    }    
-    
-    
-    
-    public static void generate(Mesh mesh, boolean approxTangents, boolean splitMirrored) {        
+    public static void generate(Mesh mesh, boolean approxTangents, boolean splitMirrored) {
         int[] index = new int[3];
         Vector3f[] v = new Vector3f[3];
         Vector2f[] t = new Vector2f[3];
@@ -203,16 +202,16 @@ public class TangentBinormalGenerator {
             v[i] = new Vector3f();
             t[i] = new Vector2f();
         }
-        
+
         if (mesh.getBuffer(Type.Normal) == null) {
             throw new IllegalArgumentException("The given mesh has no normal data!");
         }
-        
-         List<VertexData> vertices;
+
+        List<VertexData> vertices;
         switch (mesh.getMode()) {
             case Triangles:
                 vertices = processTriangles(mesh, index, v, t, splitMirrored);
-                if(splitMirrored){
+                if (splitMirrored) {
                     splitVertices(mesh, vertices, splitMirrored);
                 }
                 break;
@@ -223,21 +222,20 @@ public class TangentBinormalGenerator {
                 vertices = processTriangleFan(mesh, index, v, t);
                 break;
             default:
-                throw new UnsupportedOperationException(
-                        mesh.getMode() + " is not supported.");
+                throw new UnsupportedOperationException(mesh.getMode() + " is not supported.");
         }
-        
-        processTriangleData(mesh, vertices, approxTangents,splitMirrored);
+
+        processTriangleData(mesh, vertices, approxTangents, splitMirrored);
 
         //if the mesh has a bind pose, we need to generate the bind pose for the tangent buffer
         TangentUtils.generateBindPoseTangentsIfNecessary(mesh);
     }
-    
+
     public static void generate(Mesh mesh, boolean approxTangents) {
         generate(mesh, approxTangents, false);
     }
 
-    private static  List<VertexData> processTriangles(Mesh mesh,
+    private static List<VertexData> processTriangles(Mesh mesh,
             int[] index, Vector3f[] v, Vector2f[] t, boolean splitMirrored) {
         IndexBuffer indexBuffer = mesh.getIndexBuffer();
         FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
@@ -245,36 +243,37 @@ public class TangentBinormalGenerator {
             throw new IllegalArgumentException("Can only generate tangents for "
                     + "meshes with texture coordinates");
         }
-        
+
         FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
-        
+
         List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3);
-        
+
         for (int i = 0; i < indexBuffer.size() / 3; i++) {
             for (int j = 0; j < 3; j++) {
                 index[j] = indexBuffer.get(i * 3 + j);
                 populateFromBuffer(v[j], vertexBuffer, index[j]);
                 populateFromBuffer(t[j], textureBuffer, index[j]);
             }
-            
+
             TriangleData triData = processTriangle(index, v, t);
-            if(splitMirrored){
+            if (splitMirrored) {
                 triData.setIndex(index);
-                triData.triangleOffset = i * 3 ;
+                triData.triangleOffset = i * 3;
             }
             vertices.get(index[0]).triangles.add(triData);
             vertices.get(index[1]).triangles.add(triData);
             vertices.get(index[2]).triangles.add(triData);
         }
-        
+
         return vertices;
     }
-    
+
     //Don't remove split mirrored boolean. It's not used right now, but I intend to
     //make this method also split vertices with rotated tangent space and I'll
     //add another splitRotated boolean 
     private static List<VertexData> splitVertices(Mesh mesh, List<VertexData> vertexData, boolean splitMirorred) {
-        int nbVertices = mesh.getBuffer(Type.Position).getNumElements();
+        
+    	int nbVertices = mesh.getBuffer(Type.Position).getNumElements();
         List<VertexData> newVertices = new ArrayList<>();
         Map<Integer, Integer> indexMap = new HashMap<>();
         FloatBuffer normalBuffer = mesh.getFloatBuffer(Type.Normal);
@@ -283,63 +282,64 @@ public class TangentBinormalGenerator {
             ArrayList<TriangleData> triangles = vertexData.get(i).triangles;
             Vector3f givenNormal = new Vector3f();
             populateFromBuffer(givenNormal, normalBuffer, i);
-          
+
             ArrayList<TriangleData> trianglesUp = new ArrayList<>();
-            ArrayList<TriangleData> trianglesDown = new ArrayList<>();  
+            ArrayList<TriangleData> trianglesDown = new ArrayList<>();
             for (int j = 0; j < triangles.size(); j++) {
                 TriangleData triangleData = triangles.get(j);
-                if(parity(givenNormal, triangleData.normal) > 0){
+                if (parity(givenNormal, triangleData.normal) > 0) {
                     trianglesUp.add(triangleData);
-                }else{
+                } else {
                     trianglesDown.add(triangleData);
                 }
             }
-            
+
             //if the vertex has triangles with opposite parity it has to be split
-            if(!trianglesUp.isEmpty() && !trianglesDown.isEmpty()){
+            if (!trianglesUp.isEmpty() && !trianglesDown.isEmpty()) {
                 log.log(Level.FINE, "Splitting vertex {0}", i);
                 //assigning triangle with the same parity to the original vertex
                 vertexData.get(i).triangles.clear();
                 vertexData.get(i).triangles.addAll(trianglesUp);
-                
+
                 //creating a new vertex
                 VertexData newVert = new VertexData();
                 //assigning triangles with opposite parity to it
                 newVert.triangles.addAll(trianglesDown);
-                
+
                 newVertices.add(newVert);
                 //keep vertex index to fix the index buffers later
                 indexMap.put(nbVertices, i);
                 for (TriangleData tri : newVert.triangles) {
                     for (int j = 0; j < tri.index.length; j++) {
-                        if(tri.index[j] == i){
-                            tri.index[j] = nbVertices;                            
+                        if (tri.index[j] == i) {
+                            tri.index[j] = nbVertices;
                         }
                     }
                 }
                 nbVertices++;
-                
-            }            
-
-
+            }
         }
 
-        if(!newVertices.isEmpty()){
-            
+        if (!newVertices.isEmpty()) {
+
             //we have new vertices, we need to update the mesh's buffers.
             for (Type type : VertexBuffer.Type.values()) {
                 //skip tangent buffer as we're gonna overwrite it later
-                if(type == Type.Tangent || type == Type.BindPoseTangent) continue;
+                if (type == Type.Tangent || type == Type.BindPoseTangent) {
+                    continue;
+                }
                 VertexBuffer vb = mesh.getBuffer(type);
                 //Some buffer (hardware skinning ones) can be there but not 
                 //initialized, they must be skipped. 
                 //They'll be initialized when Hardware Skinning is engaged
-                if(vb==null || vb.getNumComponents() == 0) continue;
-                
-                Buffer buffer = vb.getData();   
+                if (vb == null || vb.getNumComponents() == 0) {
+                    continue;
+                }
+
+                Buffer buffer = vb.getData();
                 //IndexBuffer has special treatment, only swapping the vertex indices is needed
-                if(type == Type.Index){
-                    boolean isShortBuffer = vb.getFormat() == VertexBuffer.Format.UnsignedShort;                     
+                if (type == Type.Index) {
+                    boolean isShortBuffer = vb.getFormat() == VertexBuffer.Format.UnsignedShort;
                     for (VertexData vertex : newVertices) {
                         for (TriangleData tri : vertex.triangles) {
                             for (int i = 0; i < tri.index.length; i++) {
@@ -352,36 +352,36 @@ public class TangentBinormalGenerator {
                         }
                     }
                     vb.setUpdateNeeded();
-                }else{
+                } else {
                     //copy the buffer in a bigger one and append nex vertices to the end
-                    Buffer newVerts = VertexBuffer.createBuffer(vb.getFormat(), vb.getNumComponents(), nbVertices);                   
+                    Buffer newVerts = VertexBuffer.createBuffer(vb.getFormat(), vb.getNumComponents(), nbVertices);
                     if (buffer != null) {
                         buffer.rewind();
-                        bulkPut(vb.getFormat(), newVerts,buffer);  
-                        
-                        int index = vertexData.size();                      
+                        bulkPut(vb.getFormat(), newVerts, buffer);
+
+                        int index = vertexData.size();
                         newVerts.position(vertexData.size() * vb.getNumComponents());
                         for (int j = 0; j < newVertices.size(); j++) {
-                            int oldInd = indexMap.get(index) ;
-                            for (int i = 0; i < vb.getNumComponents(); i++) {                                
-                                    putValue(vb.getFormat(), newVerts, buffer, oldInd* vb.getNumComponents() + i);
-                            }                            
+                            int oldInd = indexMap.get(index);
+                            for (int i = 0; i < vb.getNumComponents(); i++) {
+                                putValue(vb.getFormat(), newVerts, buffer, oldInd * vb.getNumComponents() + i);
+                            }
                             index++;
-                        }                        
-                        vb.updateData(newVerts);    
+                        }
+                        vb.updateData(newVerts);
                         //destroy previous buffer as it's no longer needed
                         destroyDirectBuffer(buffer);
-                    }             
-                }                
+                    }
+                }
             }
             vertexData.addAll(newVertices);
-            
+
             mesh.updateCounts();
         }
 
         return vertexData;
     }
-    
+
     private static void bulkPut(VertexBuffer.Format format, Buffer buf1, Buffer buf2) {
         switch (format) {
             case Byte:
@@ -411,8 +411,8 @@ public class TangentBinormalGenerator {
                 throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
         }
     }
-    
-     private static void putValue(VertexBuffer.Format format, Buffer buf1, Buffer buf2,int index) {
+
+    private static void putValue(VertexBuffer.Format format, Buffer buf1, Buffer buf2, int index) {
         switch (format) {
             case Byte:
             case Half:
@@ -423,113 +423,115 @@ public class TangentBinormalGenerator {
             case Short:
             case UnsignedShort:
                 short s = ((ShortBuffer) buf2).get(index);
-                ((ShortBuffer) buf1).put(s);              
+                ((ShortBuffer) buf1).put(s);
                 break;
 
             case Int:
             case UnsignedInt:
                 int i = ((IntBuffer) buf2).get(index);
-                ((IntBuffer) buf1).put(i);              
-                break;                
+                ((IntBuffer) buf1).put(i);
+                break;
             case Float:
                 float f = ((FloatBuffer) buf2).get(index);
-                ((FloatBuffer) buf1).put(f);              
-                break;                   
+                ((FloatBuffer) buf1).put(f);
+                break;
             case Double:
                 double d = ((DoubleBuffer) buf2).get(index);
-                ((DoubleBuffer) buf1).put(d);              
-                break;                 
+                ((DoubleBuffer) buf1).put(d);
+                break;
             default:
                 throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
         }
     }
-    
+
     private static List<VertexData> processTriangleStrip(Mesh mesh,
             int[] index, Vector3f[] v, Vector2f[] t) {
+        
         IndexBuffer indexBuffer = mesh.getIndexBuffer();
         FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
         FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
-        
+
         List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3);
-        
+
         index[0] = indexBuffer.get(0);
         index[1] = indexBuffer.get(1);
-        
+
         populateFromBuffer(v[0], vertexBuffer, index[0]);
         populateFromBuffer(v[1], vertexBuffer, index[1]);
-        
+
         populateFromBuffer(t[0], textureBuffer, index[0]);
         populateFromBuffer(t[1], textureBuffer, index[1]);
-        
+
         for (int i = 2; i < indexBuffer.size(); i++) {
             index[2] = indexBuffer.get(i);
             BufferUtils.populateFromBuffer(v[2], vertexBuffer, index[2]);
             BufferUtils.populateFromBuffer(t[2], textureBuffer, index[2]);
-            
+
             boolean isDegenerate = isDegenerateTriangle(v[0], v[1], v[2]);
             TriangleData triData = processTriangle(index, v, t);
-            
+
             if (!isDegenerate) {
                 vertices.get(index[0]).triangles.add(triData);
                 vertices.get(index[1]).triangles.add(triData);
                 vertices.get(index[2]).triangles.add(triData);
             }
-            
+
             Vector3f vTemp = v[0];
             v[0] = v[1];
             v[1] = v[2];
             v[2] = vTemp;
-            
+
             Vector2f tTemp = t[0];
             t[0] = t[1];
             t[1] = t[2];
             t[2] = tTemp;
-            
+
             index[0] = index[1];
             index[1] = index[2];
         }
-        
+
         return vertices;
     }
-    
+
     private static List<VertexData> processTriangleFan(Mesh mesh,
             int[] index, Vector3f[] v, Vector2f[] t) {
+        
         IndexBuffer indexBuffer = mesh.getIndexBuffer();
         FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
         FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
-        
+
         List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3);
-        
+
         index[0] = indexBuffer.get(0);
         index[1] = indexBuffer.get(1);
-        
+
         populateFromBuffer(v[0], vertexBuffer, index[0]);
         populateFromBuffer(v[1], vertexBuffer, index[1]);
-        
+
         populateFromBuffer(t[0], textureBuffer, index[0]);
         populateFromBuffer(t[1], textureBuffer, index[1]);
-        
+
         for (int i = 2; i < vertexBuffer.limit() / 3; i++) {
             index[2] = indexBuffer.get(i);
             populateFromBuffer(v[2], vertexBuffer, index[2]);
             populateFromBuffer(t[2], textureBuffer, index[2]);
-            
+
             TriangleData triData = processTriangle(index, v, t);
             vertices.get(index[0]).triangles.add(triData);
             vertices.get(index[1]).triangles.add(triData);
             vertices.get(index[2]).triangles.add(triData);
-            
+
             Vector3f vTemp = v[1];
             v[1] = v[2];
             v[2] = vTemp;
-            
+
             Vector2f tTemp = t[1];
             t[1] = t[2];
             t[2] = tTemp;
-            
+
             index[1] = index[2];
         }
-        
+
         return vertices;
     }
 
@@ -537,24 +539,23 @@ public class TangentBinormalGenerator {
     private static boolean isDegenerateTriangle(Vector3f a, Vector3f b, Vector3f c) {
         return (a.subtract(b).cross(c.subtract(b))).lengthSquared() == 0;
     }
-    
-    public static TriangleData processTriangle(int[] index,
-            Vector3f[] v, Vector2f[] t) {
+
+    public static TriangleData processTriangle(int[] index, Vector3f[] v, Vector2f[] t) {
         TempVars tmp = TempVars.get();
         try {
             Vector3f edge1 = tmp.vect1;
             Vector3f edge2 = tmp.vect2;
             Vector2f edge1uv = tmp.vect2d;
             Vector2f edge2uv = tmp.vect2d2;
-            
+
             Vector3f tangent = tmp.vect3;
             Vector3f binormal = tmp.vect4;
             Vector3f normal = tmp.vect5;
-            
+
             t[1].subtract(t[0], edge1uv);
             t[2].subtract(t[0], edge2uv);
             float det = edge1uv.x * edge2uv.y - edge1uv.y * edge2uv.x;
-            
+
             boolean normalize = false;
             if (Math.abs(det) < ZERO_TOLERANCE) {
                 log.log(Level.WARNING, "Collinear uv coordinates for triangle "
@@ -565,22 +566,20 @@ public class TangentBinormalGenerator {
                 det = 1;
                 normalize = true;
             }
-            
+
             v[1].subtract(v[0], edge1);
             v[2].subtract(v[0], edge2);
-            
+
             tangent.set(edge1);
             tangent.normalizeLocal();
             binormal.set(edge2);
             binormal.normalizeLocal();
-            
-            if (Math.abs(Math.abs(tangent.dot(binormal)) - 1)
-                    < ZERO_TOLERANCE) {
-                log.log(Level.WARNING, "Vertices are on the same line "
-                        + "for triangle [{0}, {1}, {2}].",
+
+            if (Math.abs(Math.abs(tangent.dot(binormal)) - 1) < ZERO_TOLERANCE) {
+                log.log(Level.WARNING, "Vertices are on the same line for triangle [{0}, {1}, {2}].",
                         new Object[]{index[0], index[1], index[2]});
             }
-            
+
             float factor = 1 / det;
             tangent.x = (edge2uv.y * edge1.x - edge1uv.y * edge2.x) * factor;
             tangent.y = (edge2uv.y * edge1.y - edge1uv.y * edge2.y) * factor;
@@ -588,96 +587,92 @@ public class TangentBinormalGenerator {
             if (normalize) {
                 tangent.normalizeLocal();
             }
-            
+
             binormal.x = (edge1uv.x * edge2.x - edge2uv.x * edge1.x) * factor;
             binormal.y = (edge1uv.x * edge2.y - edge2uv.x * edge1.y) * factor;
             binormal.z = (edge1uv.x * edge2.z - edge2uv.x * edge1.z) * factor;
             if (normalize) {
                 binormal.normalizeLocal();
             }
-            
+
             tangent.cross(binormal, normal);
             normal.normalizeLocal();
+
+            return new TriangleData(tangent.clone(), binormal.clone(), normal.clone());
             
-            return new TriangleData(
-                    tangent.clone(),
-                    binormal.clone(),
-                    normal.clone());
         } finally {
             tmp.release();
         }
     }
-    
+
     public static void setToleranceAngle(float angle) {
         if (angle < 0 || angle > 179) {
-            throw new IllegalArgumentException(
-                    "The angle must be between 0 and 179 degrees.");
+            throw new IllegalArgumentException("The angle must be between 0 and 179 degrees.");
         }
         toleranceDot = FastMath.cos(angle * FastMath.DEG_TO_RAD);
     }
-    
-    
+
     private static boolean approxEqual(Vector3f u, Vector3f v) {
         float tolerance = 1E-4f;
-        return (FastMath.abs(u.x - v.x) < tolerance) &&
-               (FastMath.abs(u.y - v.y) < tolerance) &&
-               (FastMath.abs(u.z - v.z) < tolerance);
+        return (FastMath.abs(u.x - v.x) < tolerance)
+                && (FastMath.abs(u.y - v.y) < tolerance)
+                && (FastMath.abs(u.z - v.z) < tolerance);
     }
-    
+
     private static boolean approxEqual(Vector2f u, Vector2f v) {
         float tolerance = 1E-4f;
-        return (FastMath.abs(u.x - v.x) < tolerance) &&
-               (FastMath.abs(u.y - v.y) < tolerance);
+        return (FastMath.abs(u.x - v.x) < tolerance)
+                && (FastMath.abs(u.y - v.y) < tolerance);
     }
-    
+
     private static ArrayList<VertexInfo> linkVertices(Mesh mesh, boolean splitMirrored) {
         ArrayList<VertexInfo> vertexMap = new ArrayList<>();
-        
+
         FloatBuffer vertexBuffer = mesh.getFloatBuffer(Type.Position);
         FloatBuffer normalBuffer = mesh.getFloatBuffer(Type.Normal);
         FloatBuffer texcoordBuffer = mesh.getFloatBuffer(Type.TexCoord);
-        
+
         Vector3f position = new Vector3f();
         Vector3f normal = new Vector3f();
         Vector2f texCoord = new Vector2f();
-        
+
         final int size = vertexBuffer.limit() / 3;
         for (int i = 0; i < size; i++) {
-            
+
             populateFromBuffer(position, vertexBuffer, i);
             populateFromBuffer(normal, normalBuffer, i);
             populateFromBuffer(texCoord, texcoordBuffer, i);
-            
+
             boolean found = false;
             //Nehon 07/07/2013
             //Removed this part, joining split vertices to compute tangent space makes no sense to me
             //separate vertices should have separate tangent space   
-            if(!splitMirrored){
+            if (!splitMirrored) {
                 for (int j = 0; j < vertexMap.size(); j++) {
                     VertexInfo vertexInfo = vertexMap.get(j);
-                    if (approxEqual(vertexInfo.position, position) &&
-                        approxEqual(vertexInfo.normal, normal) &&
-                        approxEqual(vertexInfo.texCoord, texCoord))
-                    {
+                    if (approxEqual(vertexInfo.position, position)
+                            && approxEqual(vertexInfo.normal, normal)
+                            && approxEqual(vertexInfo.texCoord, texCoord)) {
                         vertexInfo.indices.add(i);
                         found = true;
-                        break;  
+                        break;
                     }
                 }
             }
+            
             if (!found) {
                 VertexInfo vertexInfo = new VertexInfo(position.clone(), normal.clone(), texCoord.clone());
                 vertexInfo.indices.add(i);
                 vertexMap.add(vertexInfo);
             }
         }
-        
+
         return vertexMap;
     }
-    
+
     private static void processTriangleData(Mesh mesh, List<VertexData> vertices,
             boolean approxTangent, boolean splitMirrored) {
-        ArrayList<VertexInfo> vertexMap = linkVertices(mesh,splitMirrored);
+        ArrayList<VertexInfo> vertexMap = linkVertices(mesh, splitMirrored);
 
         FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.size() * 4);
 
@@ -719,9 +714,7 @@ public class TangentBinormalGenerator {
                     tangentUnit.set(triangleData.tangent);
                     tangentUnit.normalizeLocal();
                     if (tangent.dot(tangentUnit) < toleranceDot) {
-                        log.log(Level.WARNING,
-                                "Angle between tangents exceeds tolerance "
-                                + "for vertex {0}.", i);
+                        log.log(Level.WARNING, "Angle between tangents exceeds tolerance for vertex {0}.", i);
                         break;
                     }
 
@@ -729,16 +722,13 @@ public class TangentBinormalGenerator {
                         binormalUnit.set(triangleData.binormal);
                         binormalUnit.normalizeLocal();
                         if (binormal.dot(binormalUnit) < toleranceDot) {
-                            log.log(Level.WARNING,
-                                    "Angle between binormals exceeds tolerance "
-                                    + "for vertex {0}.", i);
+                            log.log(Level.WARNING, "Angle between binormals exceeds tolerance for vertex {0}.", i);
                             break;
                         }
                     }
                 }
             }
 
-
             // find average tangent
             tangent.set(0, 0, 0);
             binormal.set(0, 0, 0);
@@ -755,16 +745,13 @@ public class TangentBinormalGenerator {
                     TriangleData triangleData = triangles.get(j);
                     tangent.addLocal(triangleData.tangent);
                     binormal.addLocal(triangleData.binormal);
-
                 }
             }
 
-
             int blameVertex = vertexInfo.indices.get(0);
 
             if (tangent.length() < ZERO_TOLERANCE) {
-                log.log(Level.WARNING,
-                        "Shared tangent is zero for vertex {0}.", blameVertex);
+                log.log(Level.WARNING, "Shared tangent is zero for vertex {0}.", blameVertex);
                 // attempt to fix from binormal
                 if (binormal.length() >= ZERO_TOLERANCE) {
                     binormal.cross(givenNormal, tangent);
@@ -779,17 +766,13 @@ public class TangentBinormalGenerator {
 
             tangentUnit.set(tangent);
             tangentUnit.normalizeLocal();
-            if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1)
-                    < ZERO_TOLERANCE) {
-                log.log(Level.WARNING,
-                        "Normal and tangent are parallel for vertex {0}.", blameVertex);
+            if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
+                log.log(Level.WARNING, "Normal and tangent are parallel for vertex {0}.", blameVertex);
             }
 
-
             if (!approxTangent) {
                 if (binormal.length() < ZERO_TOLERANCE) {
-                    log.log(Level.WARNING,
-                            "Shared binormal is zero for vertex {0}.", blameVertex);
+                    log.log(Level.WARNING, "Shared binormal is zero for vertex {0}.", blameVertex);
                     // attempt to fix from tangent
                     if (tangent.length() >= ZERO_TOLERANCE) {
                         givenNormal.cross(tangent, binormal);
@@ -804,16 +787,12 @@ public class TangentBinormalGenerator {
 
                 binormalUnit.set(binormal);
                 binormalUnit.normalizeLocal();
-                if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1)
-                        < ZERO_TOLERANCE) {
-                    log.log(Level.WARNING,
-                            "Normal and binormal are parallel for vertex {0}.", blameVertex);
+                if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
+                    log.log(Level.WARNING, "Normal and binormal are parallel for vertex {0}.", blameVertex);
                 }
 
-                if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1)
-                        < ZERO_TOLERANCE) {
-                    log.log(Level.WARNING,
-                            "Tangent and binormal are parallel for vertex {0}.", blameVertex);
+                if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1) < ZERO_TOLERANCE) {
+                    log.log(Level.WARNING, "Tangent and binormal are parallel for vertex {0}.", blameVertex);
                 }
             }
 
@@ -845,10 +824,8 @@ public class TangentBinormalGenerator {
         // If the model already had a tangent buffer, replace it with the regenerated one
         mesh.clearBuffer(Type.Tangent);
         mesh.setBuffer(Type.Tangent, 4, tangents);
-        
-        
-        
-        if(mesh.isAnimated()){
+
+        if (mesh.isAnimated()) {
             mesh.clearBuffer(Type.BindPoseNormal);
             mesh.clearBuffer(Type.BindPosePosition);
             mesh.clearBuffer(Type.BindPoseTangent);
@@ -856,12 +833,12 @@ public class TangentBinormalGenerator {
         }
 
         if (debug) {
-            writeColorBuffer( vertices, cols, mesh);
+            writeColorBuffer(vertices, cols, mesh);
         }
         mesh.updateBound();
         mesh.updateCounts();
-    }    
-    
+    }
+
     private static void writeColorBuffer(List<VertexData> vertices, ColorRGBA[] cols, Mesh mesh) {
         FloatBuffer colors = BufferUtils.createFloatBuffer(vertices.size() * 4);
         colors.rewind();
@@ -881,7 +858,6 @@ public class TangentBinormalGenerator {
         } else {
             return 1;
         }
-
     }
 
     public static Mesh genTbnLines(Mesh mesh, float scale) {
@@ -891,80 +867,80 @@ public class TangentBinormalGenerator {
             return genTangentLines(mesh, scale);
         }
     }
-    
+
     public static Mesh genNormalLines(Mesh mesh, float scale) {
         FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
         FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
-        
+
         ColorRGBA originColor = ColorRGBA.White;
         ColorRGBA normalColor = ColorRGBA.Blue;
-        
+
         Mesh lineMesh = new Mesh();
         lineMesh.setMode(Mesh.Mode.Lines);
-        
+
         Vector3f origin = new Vector3f();
         Vector3f point = new Vector3f();
-        
+
         FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 2);
         FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 2);
-        
+
         for (int i = 0; i < vertexBuffer.limit() / 3; i++) {
             populateFromBuffer(origin, vertexBuffer, i);
             populateFromBuffer(point, normalBuffer, i);
-            
+
             int index = i * 2;
-            
+
             setInBuffer(origin, lineVertex, index);
             setInBuffer(originColor, lineColor, index);
-            
+
             point.multLocal(scale);
             point.addLocal(origin);
             setInBuffer(point, lineVertex, index + 1);
             setInBuffer(normalColor, lineColor, index + 1);
         }
-        
+
         lineMesh.setBuffer(Type.Position, 3, lineVertex);
         lineMesh.setBuffer(Type.Color, 4, lineColor);
-        
+
         lineMesh.setStatic();
         //lineMesh.setInterleaved();
         return lineMesh;
     }
-    
+
     private static Mesh genTangentLines(Mesh mesh, float scale) {
         FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
         FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
         FloatBuffer tangentBuffer = (FloatBuffer) mesh.getBuffer(Type.Tangent).getData();
-        
+
         FloatBuffer binormalBuffer = null;
         if (mesh.getBuffer(Type.Binormal) != null) {
             binormalBuffer = (FloatBuffer) mesh.getBuffer(Type.Binormal).getData();
         }
-        
+
         ColorRGBA originColor = ColorRGBA.White;
         ColorRGBA tangentColor = ColorRGBA.Red;
         ColorRGBA binormalColor = ColorRGBA.Green;
         ColorRGBA normalColor = ColorRGBA.Blue;
-        
+
         Mesh lineMesh = new Mesh();
         lineMesh.setMode(Mesh.Mode.Lines);
-        
+
         Vector3f origin = new Vector3f();
         Vector3f point = new Vector3f();
         Vector3f tangent = new Vector3f();
         Vector3f normal = new Vector3f();
-        
+
         IntBuffer lineIndex = BufferUtils.createIntBuffer(vertexBuffer.limit() / 3 * 6);
         FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 4);
         FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 4);
-        
+
         boolean hasParity = mesh.getBuffer(Type.Tangent).getNumComponents() == 4;
         float tangentW = 1;
-        
+
         for (int i = 0; i < vertexBuffer.limit() / 3; i++) {
             populateFromBuffer(origin, vertexBuffer, i);
             populateFromBuffer(normal, normalBuffer, i);
-            
+
             if (hasParity) {
                 tangent.x = tangentBuffer.get(i * 4);
                 tangent.y = tangentBuffer.get(i * 4 + 1);
@@ -973,9 +949,9 @@ public class TangentBinormalGenerator {
             } else {
                 populateFromBuffer(tangent, tangentBuffer, i);
             }
-            
+
             int index = i * 4;
-            
+
             int id = i * 6;
             lineIndex.put(id, index);
             lineIndex.put(id + 1, index + 1);
@@ -983,10 +959,10 @@ public class TangentBinormalGenerator {
             lineIndex.put(id + 3, index + 2);
             lineIndex.put(id + 4, index);
             lineIndex.put(id + 5, index + 3);
-            
+
             setInBuffer(origin, lineVertex, index);
             setInBuffer(originColor, lineColor, index);
-            
+
             point.set(tangent);
             point.multLocal(scale);
             point.addLocal(origin);
@@ -994,7 +970,6 @@ public class TangentBinormalGenerator {
             setInBuffer(tangentColor, lineColor, index + 1);
 
             // wvBinormal = cross(wvNormal, wvTangent) * -inTangent.w
-
             if (binormalBuffer == null) {
                 normal.cross(tangent, point);
                 point.multLocal(-tangentW);
@@ -1002,23 +977,23 @@ public class TangentBinormalGenerator {
             } else {
                 populateFromBuffer(point, binormalBuffer, i);
             }
-            
+
             point.multLocal(scale);
             point.addLocal(origin);
             setInBuffer(point, lineVertex, index + 2);
             setInBuffer(binormalColor, lineColor, index + 2);
-            
+
             point.set(normal);
             point.multLocal(scale);
             point.addLocal(origin);
             setInBuffer(point, lineVertex, index + 3);
             setInBuffer(normalColor, lineColor, index + 3);
         }
-        
+
         lineMesh.setBuffer(Type.Index, 1, lineIndex);
         lineMesh.setBuffer(Type.Position, 3, lineVertex);
         lineMesh.setBuffer(Type.Color, 4, lineColor);
-        
+
         lineMesh.setStatic();
         //lineMesh.setInterleaved();
         return lineMesh;

+ 51 - 80
jme3-examples/src/main/java/jme3test/stress/TestLodGeneration.java

@@ -31,6 +31,11 @@
  */
 package jme3test.stress;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
 import com.jme3.anim.SkinningControl;
 import com.jme3.app.SimpleApplication;
 import com.jme3.bounding.BoundingBox;
@@ -41,14 +46,17 @@ import com.jme3.input.controls.ActionListener;
 import com.jme3.input.controls.KeyTrigger;
 import com.jme3.light.AmbientLight;
 import com.jme3.light.DirectionalLight;
-import com.jme3.math.*;
-import com.jme3.scene.*;
-import jme3tools.optimize.LodGenerator;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.VertexBuffer;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import jme3tools.optimize.LodGenerator;
 
 public class TestLodGeneration extends SimpleApplication {
 
@@ -56,6 +64,7 @@ public class TestLodGeneration extends SimpleApplication {
         TestLodGeneration app = new TestLodGeneration();
         app.start();
     }
+
     private boolean wireFrame = false;
     private float reductionvalue = 0.0f;
     private int lodLevel = 0;
@@ -69,20 +78,22 @@ public class TestLodGeneration extends SimpleApplication {
         DirectionalLight dl = new DirectionalLight();
         dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
         rootNode.addLight(dl);
+
         AmbientLight al = new AmbientLight();
         al.setColor(ColorRGBA.White.mult(0.6f));
         rootNode.addLight(al);
 
-       // model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
+        // model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
         Node model = (Node) assetManager.loadModel("Models/Jaime/Jaime.j3o");
         BoundingBox b = ((BoundingBox) model.getWorldBound());
         model.setLocalScale(1.2f / (b.getYExtent() * 2));
-        //  model.setLocalTranslation(0,-(b.getCenter().y - b.getYExtent())* model.getLocalScale().y, 0);
+        // model.setLocalTranslation(0,-(b.getCenter().y - b.getYExtent())* model.getLocalScale().y, 0);
         for (Spatial spatial : model.getChildren()) {
             if (spatial instanceof Geometry) {
                 listGeoms.add((Geometry) spatial);
             }
         }
+
         ChaseCamera chaseCam = new ChaseCamera(cam, inputManager);
         model.addControl(chaseCam);
         chaseCam.setLookAtOffset(b.getCenter());
@@ -90,30 +101,22 @@ public class TestLodGeneration extends SimpleApplication {
         chaseCam.setMinVerticalRotation(-FastMath.HALF_PI + 0.01f);
         chaseCam.setZoomSensitivity(0.5f);
 
-
-
-//           ch = model.getControl(AnimControl.class).createChannel();
-//          ch.setAnim("Wave");
-        SkinningControl c = model.getControl(SkinningControl.class);
-        if (c != null) {
-            c.setEnabled(false);
+        SkinningControl skControl = model.getControl(SkinningControl.class);
+        if (skControl != null) {
+            skControl.setEnabled(false);
         }
 
-
         reductionvalue = 0.80f;
         lodLevel = 1;
-        for (final Geometry geometry : listGeoms) {
-            LodGenerator lodGenerator = new LodGenerator(geometry);          
+        for (final Geometry geom : listGeoms) {
+            LodGenerator lodGenerator = new LodGenerator(geom);
             lodGenerator.bakeLods(LodGenerator.TriangleReductionMethod.PROPORTIONAL, reductionvalue);
-            geometry.setLodLevel(lodLevel);
-
+            geom.setLodLevel(lodLevel);
         }
 
         rootNode.attachChild(model);
         flyCam.setEnabled(false);
 
-
-
         guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
         hudText = new BitmapText(guiFont, false);
         hudText.setSize(guiFont.getCharSet().getRenderedSize());
@@ -126,105 +129,74 @@ public class TestLodGeneration extends SimpleApplication {
             public void onAction(String name, boolean isPressed, float tpf) {
                 if (isPressed) {
                     if (name.equals("plus")) {
-//                        lodLevel++;
-//                        for (Geometry geometry : listGeoms) {
-//                            if (geometry.getMesh().getNumLodLevels() <= lodLevel) {
-//                                lodLevel = 0;
-//                            }
-//                            geometry.setLodLevel(lodLevel);
-//                        }
-//                        jaimeText.setText(computeNbTri() + " tris");
-
-
-
                         reductionvalue += 0.05f;
                         updateLod();
-
-
-
                     }
                     if (name.equals("minus")) {
-//                        lodLevel--;
-//                        for (Geometry geometry : listGeoms) {
-//                            if (lodLevel < 0) {
-//                                lodLevel = geometry.getMesh().getNumLodLevels() - 1;
-//                            }
-//                            geometry.setLodLevel(lodLevel);
-//                        }
-//                        jaimeText.setText(computeNbTri() + " tris");
-
-
-
                         reductionvalue -= 0.05f;
                         updateLod();
-
-
                     }
                     if (name.equals("wireFrame")) {
                         wireFrame = !wireFrame;
-                        for (Geometry geometry : listGeoms) {
-                            geometry.getMaterial().getAdditionalRenderState().setWireframe(wireFrame);
+                        for (Geometry geom : listGeoms) {
+                            Material mat = geom.getMaterial();
+                            mat.getAdditionalRenderState().setWireframe(wireFrame);
                         }
                     }
-
                 }
-
-            }
-
-            private void updateLod() {
-                reductionvalue = FastMath.clamp(reductionvalue, 0.0f, 1.0f);
-                makeLod(LodGenerator.TriangleReductionMethod.PROPORTIONAL, reductionvalue, 1);
             }
         }, "plus", "minus", "wireFrame");
 
         inputManager.addMapping("plus", new KeyTrigger(KeyInput.KEY_ADD));
         inputManager.addMapping("minus", new KeyTrigger(KeyInput.KEY_SUBTRACT));
         inputManager.addMapping("wireFrame", new KeyTrigger(KeyInput.KEY_SPACE));
-
-
-
     }
 
     @Override
     public void simpleUpdate(float tpf) {
-        //    model.rotate(0, tpf, 0);        
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        exec.shutdown();
+    }
+
+    private void updateLod() {
+        reductionvalue = FastMath.clamp(reductionvalue, 0.0f, 1.0f);
+        makeLod(LodGenerator.TriangleReductionMethod.PROPORTIONAL, reductionvalue, 1);
     }
 
     private int computeNbTri() {
         int nbTri = 0;
-        for (Geometry geometry : listGeoms) {
-            if (geometry.getMesh().getNumLodLevels() > 0) {
-                nbTri += geometry.getMesh().getLodLevel(lodLevel).getNumElements();
+        for (Geometry geom : listGeoms) {
+            Mesh mesh = geom.getMesh();
+            if (mesh.getNumLodLevels() > 0) {
+                nbTri += mesh.getLodLevel(lodLevel).getNumElements();
             } else {
-                nbTri += geometry.getMesh().getTriangleCount();
+                nbTri += mesh.getTriangleCount();
             }
         }
         return nbTri;
     }
 
-    @Override
-    public void destroy() {
-        super.destroy();
-        exec.shutdown();
-    }
-
     private void makeLod(final LodGenerator.TriangleReductionMethod method, final float value, final int ll) {
         exec.execute(new Runnable() {
             @Override
             public void run() {
-                for (final Geometry geometry : listGeoms) {
-                    LodGenerator lODGenerator = new LodGenerator(geometry);
-                    final VertexBuffer[] lods = lODGenerator.computeLods(method, value);
+                for (final Geometry geom : listGeoms) {
+                    LodGenerator lodGenerator = new LodGenerator(geom);
+                    final VertexBuffer[] lods = lodGenerator.computeLods(method, value);
 
                     enqueue(new Callable<Void>() {
                         @Override
                         public Void call() throws Exception {
-                            geometry.getMesh().setLodLevels(lods);
+                            geom.getMesh().setLodLevels(lods);
                             lodLevel = 0;
-                            if (geometry.getMesh().getNumLodLevels() > ll) {
+                            if (geom.getMesh().getNumLodLevels() > ll) {
                                 lodLevel = ll;
                             }
-                            geometry.setLodLevel(lodLevel);
+                            geom.setLodLevel(lodLevel);
                             hudText.setText(computeNbTri() + " tris");
                             return null;
                         }
@@ -232,6 +204,5 @@ public class TestLodGeneration extends SimpleApplication {
                 }
             }
         });
-
     }
 }