|
|
@ -40,7 +40,9 @@ import com.jme3.scene.VertexBuffer.Format; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
|
import com.jme3.scene.mesh.IndexBuffer; |
|
|
|
import com.jme3.scene.mesh.IndexBuffer; |
|
|
|
|
|
|
|
|
|
|
|
import static com.jme3.util.BufferUtils.*; |
|
|
|
import static com.jme3.util.BufferUtils.*; |
|
|
|
|
|
|
|
|
|
|
|
import java.nio.Buffer; |
|
|
|
import java.nio.Buffer; |
|
|
|
import java.nio.ByteBuffer; |
|
|
|
import java.nio.ByteBuffer; |
|
|
|
import java.nio.DoubleBuffer; |
|
|
|
import java.nio.DoubleBuffer; |
|
|
@ -49,8 +51,12 @@ import java.nio.IntBuffer; |
|
|
|
import java.nio.ShortBuffer; |
|
|
|
import java.nio.ShortBuffer; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
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.Level; |
|
|
|
import java.util.logging.Logger; |
|
|
|
import java.util.logging.Logger; |
|
|
|
|
|
|
|
|
|
|
@ -147,6 +153,44 @@ public class TangentBinormalGenerator { |
|
|
|
generate(scene, false); |
|
|
|
generate(scene, false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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]; |
|
|
|
int[] index = new int[3]; |
|
|
|
Vector3f[] v = new Vector3f[3]; |
|
|
|
Vector3f[] v = new Vector3f[3]; |
|
|
@ -512,67 +556,72 @@ public class TangentBinormalGenerator { |
|
|
|
|
|
|
|
|
|
|
|
public static TriangleData processTriangle(int[] index, |
|
|
|
public static TriangleData processTriangle(int[] index, |
|
|
|
Vector3f[] v, Vector2f[] t) { |
|
|
|
Vector3f[] v, Vector2f[] t) { |
|
|
|
Vector3f edge1 = new Vector3f(); |
|
|
|
TempVars tmp = TempVars.get(); |
|
|
|
Vector3f edge2 = new Vector3f(); |
|
|
|
try { |
|
|
|
Vector2f edge1uv = new Vector2f(); |
|
|
|
Vector3f edge1 = tmp.vect1; |
|
|
|
Vector2f edge2uv = new Vector2f(); |
|
|
|
Vector3f edge2 = tmp.vect2; |
|
|
|
|
|
|
|
Vector2f edge1uv = tmp.vect2d; |
|
|
|
Vector3f tangent = new Vector3f(); |
|
|
|
Vector2f edge2uv = tmp.vect2d2; |
|
|
|
Vector3f binormal = new Vector3f(); |
|
|
|
|
|
|
|
Vector3f normal = new Vector3f(); |
|
|
|
Vector3f tangent = tmp.vect3; |
|
|
|
|
|
|
|
Vector3f binormal = tmp.vect4; |
|
|
|
t[1].subtract(t[0], edge1uv); |
|
|
|
Vector3f normal = tmp.vect5; |
|
|
|
t[2].subtract(t[0], edge2uv); |
|
|
|
|
|
|
|
float det = edge1uv.x * edge2uv.y - edge1uv.y * edge2uv.x; |
|
|
|
t[1].subtract(t[0], edge1uv); |
|
|
|
|
|
|
|
t[2].subtract(t[0], edge2uv); |
|
|
|
boolean normalize = false; |
|
|
|
float det = edge1uv.x * edge2uv.y - edge1uv.y * edge2uv.x; |
|
|
|
if (Math.abs(det) < ZERO_TOLERANCE) { |
|
|
|
|
|
|
|
log.log(Level.WARNING, "Colinear uv coordinates for triangle " |
|
|
|
boolean normalize = false; |
|
|
|
+ "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " |
|
|
|
if (Math.abs(det) < ZERO_TOLERANCE) { |
|
|
|
+ "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", |
|
|
|
log.log(Level.WARNING, "Colinear uv coordinates for triangle " |
|
|
|
new Object[]{index[0], index[1], index[2], |
|
|
|
+ "[{0}, {1}, {2}]; tex0 = [{3}, {4}], " |
|
|
|
t[0].x, t[0].y, t[1].x, t[1].y, t[2].x, t[2].y}); |
|
|
|
+ "tex1 = [{5}, {6}], tex2 = [{7}, {8}]", |
|
|
|
det = 1; |
|
|
|
new Object[]{index[0], index[1], index[2], |
|
|
|
normalize = true; |
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
v[1].subtract(v[0], edge1); |
|
|
|
tangent.set(edge1); |
|
|
|
v[2].subtract(v[0], edge2); |
|
|
|
tangent.normalizeLocal(); |
|
|
|
|
|
|
|
binormal.set(edge2); |
|
|
|
tangent.set(edge1); |
|
|
|
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(); |
|
|
|
tangent.normalizeLocal(); |
|
|
|
} |
|
|
|
binormal.set(edge2); |
|
|
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
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(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tangent.cross(binormal, normal); |
|
|
|
|
|
|
|
normal.normalizeLocal(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new TriangleData( |
|
|
|
|
|
|
|
tangent, |
|
|
|
|
|
|
|
binormal, |
|
|
|
|
|
|
|
normal); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void setToleranceAngle(float angle) { |
|
|
|
public static void setToleranceAngle(float angle) { |
|
|
|