From 93b3b744f3640209c2b283ef484fbee6ba7920f9 Mon Sep 17 00:00:00 2001 From: abies Date: Sun, 15 Jun 2014 19:20:32 +0200 Subject: [PATCH 1/5] Added parallel processing mode to tangent generator --- .../jme3/util/TangentBinormalGenerator.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java index e982e9665..521c1bcff 100644 --- a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java +++ b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java @@ -40,7 +40,9 @@ import com.jme3.scene.VertexBuffer.Format; import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Usage; import com.jme3.scene.mesh.IndexBuffer; + import static com.jme3.util.BufferUtils.*; + import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.DoubleBuffer; @@ -49,8 +51,12 @@ import java.nio.IntBuffer; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; @@ -147,6 +153,44 @@ public class TangentBinormalGenerator { generate(scene, false); } + public static void generateParallel(Spatial scene, ExecutorService executor) { + final Set meshes = new HashSet(); + scene.breadthFirstTraversal(new SceneGraphVisitor(){ + @Override + public void visit(Spatial spatial) { + if ( spatial instanceof Geometry ) { + Geometry geom = (Geometry) spatial; + 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){ + meshes.add(mesh); + } + } + } + }); + List> futures = new ArrayList>(); + for ( final Mesh m : meshes ) { + futures.add(executor.submit(new Runnable() { + @Override + public void run() { + generate(m,true,false); + } + })); + } + for ( Future f : futures ) { + try { + f.get(); + } catch (Exception exc) { + log.log(Level.WARNING,"Error while computing tangents",exc); + } + } + + } + + + public static void generate(Mesh mesh, boolean approxTangents, boolean splitMirrored) { int[] index = new int[3]; Vector3f[] v = new Vector3f[3]; From ae9f2819765cb9ab4a5760cdb3bb0fb490c8c279 Mon Sep 17 00:00:00 2001 From: abies Date: Sun, 22 Jun 2014 12:20:46 +0200 Subject: [PATCH 2/5] Use TempVars for triangle processing instead of explicit allocations, speeds up processing by around 30% --- .../jme3/util/TangentBinormalGenerator.java | 127 +++++++++--------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java index 521c1bcff..8b9008d76 100644 --- a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java +++ b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java @@ -556,67 +556,72 @@ public class TangentBinormalGenerator { public static TriangleData processTriangle(int[] index, Vector3f[] v, Vector2f[] t) { - Vector3f edge1 = new Vector3f(); - Vector3f edge2 = new Vector3f(); - Vector2f edge1uv = new Vector2f(); - Vector2f edge2uv = new Vector2f(); - - Vector3f tangent = new Vector3f(); - Vector3f binormal = new Vector3f(); - Vector3f normal = new Vector3f(); - - 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, "Colinear uv coordinates for triangle " - + "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " - + "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", - new Object[]{index[0], index[1], index[2], - t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y}); - 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}].", - 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; - tangent.z = (edge2uv.y * edge1.z - edge1uv.y * edge2.z) * factor; - 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, - binormal, - normal); + 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, "Colinear uv coordinates for triangle " + + "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " + + "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", + new Object[]{index[0], index[1], index[2], + t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y}); + 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}].", + 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; + tangent.z = (edge2uv.y * edge1.z - edge1uv.y * edge2.z) * factor; + 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, + binormal, + normal); + } finally { + tmp.release(); + } } public static void setToleranceAngle(float angle) { From 2f7dbe54dc3f5ce9dab5eb57fc724758b4597528 Mon Sep 17 00:00:00 2001 From: abies Date: Sun, 22 Jun 2014 23:05:00 +0200 Subject: [PATCH 3/5] Fixed indentation --- .../jme3/util/TangentBinormalGenerator.java | 196 +++++++++--------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java index 8b9008d76..ae82b3422 100644 --- a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java +++ b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java @@ -154,40 +154,40 @@ public class TangentBinormalGenerator { } public static void generateParallel(Spatial scene, ExecutorService executor) { - final Set meshes = new HashSet(); - scene.breadthFirstTraversal(new SceneGraphVisitor(){ - @Override - public void visit(Spatial spatial) { - if ( spatial instanceof Geometry ) { - Geometry geom = (Geometry) spatial; - 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){ - meshes.add(mesh); - } - } - } - }); - List> futures = new ArrayList>(); - for ( final Mesh m : meshes ) { - futures.add(executor.submit(new Runnable() { - @Override - public void run() { - generate(m,true,false); - } - })); + final Set meshes = new HashSet(); + scene.breadthFirstTraversal(new SceneGraphVisitor() { + @Override + public void visit(Spatial spatial) { + if (spatial instanceof Geometry) { + Geometry geom = (Geometry) spatial; + 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) { + meshes.add(mesh); + } + } + } + }); + List> futures = new ArrayList>(); + for (final Mesh m : meshes) { + futures.add(executor.submit(new Runnable() { + @Override + public void run() { + generate(m, true, false); + } + })); } - for ( Future f : futures ) { - try { - f.get(); - } catch (Exception exc) { - log.log(Level.WARNING,"Error while computing tangents",exc); - } + for (Future f : futures) { + try { + f.get(); + } catch (Exception exc) { + log.log(Level.WARNING, "Error while computing tangents", exc); + } } - - } + + } @@ -556,72 +556,72 @@ public class TangentBinormalGenerator { 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, "Colinear uv coordinates for triangle " - + "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " - + "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", - new Object[]{index[0], index[1], index[2], - t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y}); - 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}].", - 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; - tangent.z = (edge2uv.y * edge1.z - edge1uv.y * edge2.z) * factor; - 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, - binormal, - normal); - } finally { - tmp.release(); - } + 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, "Colinear uv coordinates for triangle " + + "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " + + "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", + new Object[]{index[0], index[1], index[2], + t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y}); + 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}].", + 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; + tangent.z = (edge2uv.y * edge1.z - edge1uv.y * edge2.z) * factor; + 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, + binormal, + normal); + } finally { + tmp.release(); + } } public static void setToleranceAngle(float angle) { From f80d6474a4c9e69725a1de1fe13acdb07a56c2b4 Mon Sep 17 00:00:00 2001 From: abies Date: Mon, 28 Jul 2014 12:14:14 +0200 Subject: [PATCH 4/5] Utility methods for getting arbitrary properties for triangles from mesh buffers --- .../src/main/java/com/jme3/scene/Mesh.java | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index 8b3ffc80e..5717350fa 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -824,12 +824,28 @@ public class Mesh implements Savable, Cloneable { * @param v3 Vector to contain third vertex position */ public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3){ - VertexBuffer pb = getBuffer(Type.Position); + getTriangle(Type.Position,index,v1,v2,v3); + } + + /** + * Gets the triangle vertex data at the given triangle index + * and stores them into the v1, v2, v3 arguments. Works for 3-value components like position or normals + * + * @param type buffer type to retrieve data from + * @param index The index of the triangle. + * Should be between 0 and {@link #getTriangleCount()}. + * + * @param v1 Vector to contain first vertex data + * @param v2 Vector to contain second vertex data + * @param v3 Vector to contain third vertex data + */ + public void getTriangle(Type type, int index, Vector3f v1, Vector3f v2, Vector3f v3){ + VertexBuffer pb = getBuffer(type); IndexBuffer ib = getIndicesAsList(); if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 3){ FloatBuffer fpb = (FloatBuffer) pb.getData(); - // aquire triangle's vertex indices + // acquire triangle's vertex indices int vertIndex = index * 3; int vert1 = ib.get(vertIndex); int vert2 = ib.get(vertIndex+1); @@ -839,11 +855,46 @@ public class Mesh implements Savable, Cloneable { BufferUtils.populateFromBuffer(v2, fpb, vert2); BufferUtils.populateFromBuffer(v3, fpb, vert3); }else{ - throw new UnsupportedOperationException("Position buffer not set or " + throw new UnsupportedOperationException(type + " buffer not set or " + " has incompatible format"); } } + /** + * Gets the triangle vertex data at the given triangle index + * and stores them into the v1, v2, v3 arguments. Works for 2-value components like texture coordinates + * + * @param type buffer type to retrieve data from + * @param index The index of the triangle. + * Should be between 0 and {@link #getTriangleCount()}. + * + * @param v1 Vector to contain first vertex data + * @param v2 Vector to contain second vertex data + * @param v3 Vector to contain third vertex data + */ + + public void getTriangle(Type type, int index, Vector2f v1, Vector2f v2, Vector2f v3){ + VertexBuffer pb = getBuffer(type); + IndexBuffer ib = getIndicesAsList(); + if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 2){ + FloatBuffer fpb = (FloatBuffer) pb.getData(); + + // acquire triangle's vertex indices + int vertIndex = index * 3; + int vert1 = ib.get(vertIndex); + int vert2 = ib.get(vertIndex+1); + int vert3 = ib.get(vertIndex+2); + + BufferUtils.populateFromBuffer(v1, fpb, vert1); + BufferUtils.populateFromBuffer(v2, fpb, vert2); + BufferUtils.populateFromBuffer(v3, fpb, vert3); + }else{ + throw new UnsupportedOperationException(type + " buffer not set or " + + " has incompatible format"); + } + } + + /** * Gets the triangle vertex positions at the given triangle index * and stores them into the {@link Triangle} argument. From a6827ead5a22e0811bfbff846a574854aa3d032c Mon Sep 17 00:00:00 2001 From: abies Date: Mon, 28 Jul 2014 12:19:16 +0200 Subject: [PATCH 5/5] Revert "Utility methods for getting arbitrary properties for triangles from mesh buffers" This reverts commit f80d6474a4c9e69725a1de1fe13acdb07a56c2b4. --- .../src/main/java/com/jme3/scene/Mesh.java | 57 +------------------ 1 file changed, 3 insertions(+), 54 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index 5717350fa..8b3ffc80e 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -824,28 +824,12 @@ public class Mesh implements Savable, Cloneable { * @param v3 Vector to contain third vertex position */ public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3){ - getTriangle(Type.Position,index,v1,v2,v3); - } - - /** - * Gets the triangle vertex data at the given triangle index - * and stores them into the v1, v2, v3 arguments. Works for 3-value components like position or normals - * - * @param type buffer type to retrieve data from - * @param index The index of the triangle. - * Should be between 0 and {@link #getTriangleCount()}. - * - * @param v1 Vector to contain first vertex data - * @param v2 Vector to contain second vertex data - * @param v3 Vector to contain third vertex data - */ - public void getTriangle(Type type, int index, Vector3f v1, Vector3f v2, Vector3f v3){ - VertexBuffer pb = getBuffer(type); + VertexBuffer pb = getBuffer(Type.Position); IndexBuffer ib = getIndicesAsList(); if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 3){ FloatBuffer fpb = (FloatBuffer) pb.getData(); - // acquire triangle's vertex indices + // aquire triangle's vertex indices int vertIndex = index * 3; int vert1 = ib.get(vertIndex); int vert2 = ib.get(vertIndex+1); @@ -855,46 +839,11 @@ public class Mesh implements Savable, Cloneable { BufferUtils.populateFromBuffer(v2, fpb, vert2); BufferUtils.populateFromBuffer(v3, fpb, vert3); }else{ - throw new UnsupportedOperationException(type + " buffer not set or " + throw new UnsupportedOperationException("Position buffer not set or " + " has incompatible format"); } } - /** - * Gets the triangle vertex data at the given triangle index - * and stores them into the v1, v2, v3 arguments. Works for 2-value components like texture coordinates - * - * @param type buffer type to retrieve data from - * @param index The index of the triangle. - * Should be between 0 and {@link #getTriangleCount()}. - * - * @param v1 Vector to contain first vertex data - * @param v2 Vector to contain second vertex data - * @param v3 Vector to contain third vertex data - */ - - public void getTriangle(Type type, int index, Vector2f v1, Vector2f v2, Vector2f v3){ - VertexBuffer pb = getBuffer(type); - IndexBuffer ib = getIndicesAsList(); - if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 2){ - FloatBuffer fpb = (FloatBuffer) pb.getData(); - - // acquire triangle's vertex indices - int vertIndex = index * 3; - int vert1 = ib.get(vertIndex); - int vert2 = ib.get(vertIndex+1); - int vert3 = ib.get(vertIndex+2); - - BufferUtils.populateFromBuffer(v1, fpb, vert1); - BufferUtils.populateFromBuffer(v2, fpb, vert2); - BufferUtils.populateFromBuffer(v3, fpb, vert3); - }else{ - throw new UnsupportedOperationException(type + " buffer not set or " - + " has incompatible format"); - } - } - - /** * Gets the triangle vertex positions at the given triangle index * and stores them into the {@link Triangle} argument.