Parallel Tangents

No, not this kind of parallel :wink:

To add TangentBinormalGenerator:

    public static void generateParallel(Spatial scene, ExecutorService executor) {
    	final Set<Mesh> meshes = new HashSet<Mesh>();
    	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<Future<?>> futures = new ArrayList<Future<?>>();
        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);
        	}
        }
        
    }

Pass Executors.newFixedThreadPool(Runtime.runtime.availableProcessors) (of course stored in some variable for reuse) and enjoy faster generation.

In theory, we could have all the fancy combinations of flags here, but this is left as exercise for the reader :wink:

2 Likes

With following patch, I’m getting considerable speedup for Sponza scene (from 24s to 14s on single threaded generation).

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 521c1bc..712a948 100644
--- a/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java
+++ b/jme3-core/src/main/java/com/jme3/util/TangentBinormalGenerator.java
@@ -556,14 +556,16 @@
     
     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();
+    	TempVars tmp = TempVars.get();
+    	try {
+        Vector3f edge1 = tmp.vect1;
+        Vector3f edge2 = tmp.vect2;
+        Vector2f edge1uv = tmp.vect2d;
+        Vector2f edge2uv = tmp.vect2d2;
         
-        Vector3f tangent = new Vector3f();
-        Vector3f binormal = new Vector3f();
-        Vector3f normal = new Vector3f();
+        Vector3f tangent = tmp.vect3;
+        Vector3f binormal = tmp.vect4;
+        Vector3f normal = tmp.vect5;
         
         t[1].subtract(t[0], edge1uv);
         t[2].subtract(t[0], edge2uv);
@@ -617,6 +619,9 @@
                 tangent,
                 binormal,
                 normal);
+    	} finally {
+    		tmp.release();
+    	}
     }
     
     public static void setToleranceAngle(float angle) {
1 Like

That’s pretty cool, could you make a pull request on git hub?

Done:

1 Like

thanks