Commit MetaInfo
Log Message
Change Summary
Incremental Difference
| | @@ -35,16 +35,22 @@ import com.jme3.math.ColorRGBA; | 35 | 35 | import com.jme3.math.FastMath; | 36 | 36 | import com.jme3.math.Vector2f; | 37 | 37 | import com.jme3.math.Vector3f; | 38 | | -import com.jme3.math.Vector4f; | 39 | 38 | import com.jme3.scene.*; | 40 | 39 | import com.jme3.scene.VertexBuffer.Format; | 41 | 40 | import com.jme3.scene.VertexBuffer.Type; | 42 | 41 | import com.jme3.scene.VertexBuffer.Usage; | 43 | 42 | import com.jme3.scene.mesh.IndexBuffer; | 44 | 43 | import static com.jme3.util.BufferUtils.*; | | 44 | +import java.nio.Buffer; | | 45 | +import java.nio.ByteBuffer; | | 46 | +import java.nio.DoubleBuffer; | 45 | 47 | import java.nio.FloatBuffer; | 46 | 48 | import java.nio.IntBuffer; | | 49 | +import java.nio.ShortBuffer; | 47 | 50 | import java.util.ArrayList; | | 51 | +import java.util.HashMap; | | 52 | +import java.util.List; | | 53 | +import java.util.Map; | 48 | 54 | import java.util.logging.Level; | 49 | 55 | import java.util.logging.Logger; | 50 | 56 | |
| | @@ -57,13 +63,13 @@ public class TangentBinormalGenerator { | 57 | 63 | private static final float ZERO_TOLERANCE = 0.0000001f; | 58 | 64 | private static final Logger log = Logger.getLogger( | 59 | 65 | TangentBinormalGenerator.class.getName()); | 60 | | - private static float toleranceAngle; | 61 | 66 | private static float toleranceDot; | | 67 | + public static boolean debug = false; | 62 | 68 | | 63 | 69 | static { | 64 | 70 | setToleranceAngle(45); | 65 | 71 | } | 66 | | - | | 72 | + | 67 | 73 | | 68 | 74 | private static class VertexInfo { | 69 | 75 | public final Vector3f position; |
| | @@ -91,32 +97,39 @@ public class TangentBinormalGenerator { | 91 | 97 | public static class TriangleData { | 92 | 98 | public final Vector3f tangent; | 93 | 99 | public final Vector3f binormal; | 94 | | - public final Vector3f normal; | | 100 | + public final Vector3f normal; | | 101 | + public int[] index = new int[3]; | | 102 | + public int triangleOffset; | 95 | 103 | | 96 | 104 | public TriangleData(Vector3f tangent, Vector3f binormal, Vector3f normal) { | 97 | 105 | this.tangent = tangent; | 98 | 106 | this.binormal = binormal; | 99 | 107 | this.normal = normal; | 100 | 108 | } | | 109 | + public void setIndex(int[] index) { | | 110 | + for (int i = 0; i < index.length; i++) { | | 111 | + this.index[i] = index[i]; | | 112 | + } | | 113 | + } | 101 | 114 | } | 102 | 115 | | 103 | | - private static VertexData[] initVertexData(int size) { | 104 | | - VertexData[] vertices = new VertexData[size]; | | 116 | + private static List<VertexData> initVertexData(int size) { | | 117 | + List<VertexData> vertices = new ArrayList<VertexData>(size); | 105 | 118 | for (int i = 0; i < size; i++) { | 106 | | - vertices[i] = new VertexData(); | | 119 | + vertices.add(new VertexData()); | 107 | 120 | } | 108 | 121 | return vertices; | 109 | 122 | } | 110 | 123 | | 111 | 124 | public static void generate(Mesh mesh) { | 112 | | - generate(mesh, true); | | 125 | + generate(mesh, true, false); | 113 | 126 | } | 114 | 127 | | 115 | | - public static void generate(Spatial scene) { | | 128 | + public static void generate(Spatial scene, boolean splitMirrored) { | 116 | 129 | if (scene instanceof Node) { | 117 | 130 | Node node = (Node) scene; | 118 | 131 | for (Spatial child : node.getChildren()) { | 119 | | - generate(child); | | 132 | + generate(child, splitMirrored); | 120 | 133 | } | 121 | 134 | } else { | 122 | 135 | Geometry geom = (Geometry) scene; |
| | @@ -125,12 +138,16 @@ public class TangentBinormalGenerator { | 125 | 138 | // Check to ensure mesh has texcoords and normals before generating | 126 | 139 | if (mesh.getBuffer(Type.TexCoord) != null | 127 | 140 | && mesh.getBuffer(Type.Normal) != null){ | 128 | | - generate(geom.getMesh()); | | 141 | + generate(geom.getMesh(),true, splitMirrored); | 129 | 142 | } | 130 | 143 | } | 131 | 144 | } | 132 | 145 | | 133 | | - public static void generate(Mesh mesh, boolean approxTangents) { | | 146 | + public static void generate(Spatial scene) { | | 147 | + generate(scene, false); | | 148 | + } | | 149 | + | | 150 | + public static void generate(Mesh mesh, boolean approxTangents, boolean splitMirrored) { | 134 | 151 | int[] index = new int[3]; | 135 | 152 | Vector3f[] v = new Vector3f[3]; | 136 | 153 | Vector2f[] t = new Vector2f[3]; |
| | @@ -143,10 +160,13 @@ public class TangentBinormalGenerator { | 143 | 160 | throw new IllegalArgumentException("The given mesh has no normal data!"); | 144 | 161 | } | 145 | 162 | | 146 | | - VertexData[] vertices; | | 163 | + List<VertexData> vertices; | 147 | 164 | switch (mesh.getMode()) { | 148 | 165 | case Triangles: | 149 | | - vertices = processTriangles(mesh, index, v, t); | | 166 | + vertices = processTriangles(mesh, index, v, t, splitMirrored); | | 167 | + if(splitMirrored){ | | 168 | + splitVertices(mesh, vertices, splitMirrored); | | 169 | + } | 150 | 170 | break; | 151 | 171 | case TriangleStrip: | 152 | 172 | vertices = processTriangleStrip(mesh, index, v, t); |
| | @@ -181,8 +201,8 @@ public class TangentBinormalGenerator { | 181 | 201 | } | 182 | 202 | } | 183 | 203 | | 184 | | - private static VertexData[] processTriangles(Mesh mesh, | 185 | | - int[] index, Vector3f[] v, Vector2f[] t) { | | 204 | + private static List<VertexData> processTriangles(Mesh mesh, | | 205 | + int[] index, Vector3f[] v, Vector2f[] t, boolean splitMirrored) { | 186 | 206 | IndexBuffer indexBuffer = mesh.getIndexBuffer(); | 187 | 207 | FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); | 188 | 208 | if (mesh.getBuffer(Type.TexCoord) == null) { |
| | @@ -192,7 +212,7 @@ public class TangentBinormalGenerator { | 192 | 212 | | 193 | 213 | FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData(); | 194 | 214 | | 195 | | - VertexData[] vertices = initVertexData(vertexBuffer.limit() / 3); | | 215 | + List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3); | 196 | 216 | | 197 | 217 | for (int i = 0; i < indexBuffer.size() / 3; i++) { | 198 | 218 | for (int j = 0; j < 3; j++) { |
| | @@ -202,23 +222,201 @@ public class TangentBinormalGenerator { | 202 | 222 | } | 203 | 223 | | 204 | 224 | TriangleData triData = processTriangle(index, v, t); | | 225 | + if(splitMirrored){ | | 226 | + triData.setIndex(index); | | 227 | + triData.triangleOffset = i * 3 ; | | 228 | + } | 205 | 229 | if (triData != null) { | 206 | | - vertices[index[0]].triangles.add(triData); | 207 | | - vertices[index[1]].triangles.add(triData); | 208 | | - vertices[index[2]].triangles.add(triData); | | 230 | + vertices.get(index[0]).triangles.add(triData); | | 231 | + vertices.get(index[1]).triangles.add(triData); | | 232 | + vertices.get(index[2]).triangles.add(triData); | 209 | 233 | } | 210 | 234 | } | 211 | 235 | | 212 | 236 | return vertices; | 213 | 237 | } | 214 | 238 | | 215 | | - private static VertexData[] processTriangleStrip(Mesh mesh, | | 239 | + //Don't remove splitmirorred boolean,It's not used right now, but i intend to | | 240 | + //make this method also split vertice with rotated tangent space and I'll | | 241 | + //add another splitRotated boolean | | 242 | + private static List<VertexData> splitVertices(Mesh mesh, List<VertexData> vertexData, boolean splitMirorred) { | | 243 | + int nbVertices = mesh.getBuffer(Type.Position).getNumElements(); | | 244 | + List<VertexData> newVertices = new ArrayList<VertexData>(); | | 245 | + Map<Integer, Integer> indiceMap = new HashMap<Integer, Integer>(); | | 246 | + FloatBuffer normalBuffer = mesh.getFloatBuffer(Type.Normal); | | 247 | + | | 248 | + for (int i = 0; i < vertexData.size(); i++) { | | 249 | + ArrayList<TriangleData> triangles = vertexData.get(i).triangles; | | 250 | + Vector3f givenNormal = new Vector3f(); | | 251 | + populateFromBuffer(givenNormal, normalBuffer, i); | | 252 | + | | 253 | + ArrayList<TriangleData> trianglesUp = new ArrayList<TriangleData>(); | | 254 | + ArrayList<TriangleData> trianglesDown = new ArrayList<TriangleData>(); | | 255 | + for (int j = 0; j < triangles.size(); j++) { | | 256 | + TriangleData triangleData = triangles.get(j); | | 257 | + if(parity(givenNormal, triangleData.normal) > 0){ | | 258 | + trianglesUp.add(triangleData); | | 259 | + }else{ | | 260 | + trianglesDown.add(triangleData); | | 261 | + } | | 262 | + } | | 263 | + | | 264 | + //if the vertex has triangles with opposite parity it has to be split | | 265 | + if(!trianglesUp.isEmpty() && !trianglesDown.isEmpty()){ | | 266 | + log.log(Level.FINE, "Splitting vertex {0}", i); | | 267 | + //assigning triangle with the same parity to the original vertex | | 268 | + vertexData.get(i).triangles.clear(); | | 269 | + vertexData.get(i).triangles.addAll(trianglesUp); | | 270 | + | | 271 | + //creating a new vertex | | 272 | + VertexData newVert = new VertexData(); | | 273 | + //assigning triangles with opposite parity to it | | 274 | + newVert.triangles.addAll(trianglesDown); | | 275 | + | | 276 | + newVertices.add(newVert); | | 277 | + //keep vertex index to fix the index buffers later | | 278 | + indiceMap.put(nbVertices, i); | | 279 | + for (TriangleData tri : newVert.triangles) { | | 280 | + for (int j = 0; j < tri.index.length; j++) { | | 281 | + if(tri.index[j] == i){ | | 282 | + tri.index[j] = nbVertices; | | 283 | + } | | 284 | + } | | 285 | + } | | 286 | + nbVertices++; | | 287 | + | | 288 | + } | | 289 | + | | 290 | + | | 291 | + } | | 292 | + | | 293 | + if(!newVertices.isEmpty()){ | | 294 | + | | 295 | + //we have new vertices, we need to update the mesh's buffers. | | 296 | + for (Type type : VertexBuffer.Type.values()) { | | 297 | + //skip tangent buffer as we're gonna overwrite it later | | 298 | + if(type == Type.Tangent || type == Type.BindPoseTangent) continue; | | 299 | + VertexBuffer vb = mesh.getBuffer(type); | | 300 | + //Some buffer (hardware skinning ones) can be there but not | | 301 | + //initialized, they must be skipped. | | 302 | + //They'll be initialized when Hardware Skinning is engaged | | 303 | + if(vb==null || vb.getNumComponents() == 0) continue; | | 304 | + | | 305 | + Buffer buffer = vb.getData(); | | 306 | + //IndexBuffer has special treatement, only swapping the vertex indices is needed | | 307 | + if(type == Type.Index){ | | 308 | + boolean isShortBuffer = vb.getFormat() == VertexBuffer.Format.UnsignedShort; | | 309 | + for (VertexData vertex : newVertices) { | | 310 | + for (TriangleData tri : vertex.triangles) { | | 311 | + for (int i = 0; i < tri.index.length; i++) { | | 312 | + if (isShortBuffer) { | | 313 | + ((ShortBuffer) buffer).put(tri.triangleOffset + i, (short) tri.index[i]); | | 314 | + } else { | | 315 | + ((IntBuffer) buffer).put(tri.triangleOffset + i, tri.index[i]); | | 316 | + } | | 317 | + } | | 318 | + } | | 319 | + } | | 320 | + vb.setUpdateNeeded(); | | 321 | + }else{ | | 322 | + //copy the buffer in a bigger one and append nex vertices to the end | | 323 | + Buffer newVerts = VertexBuffer.createBuffer(vb.getFormat(), vb.getNumComponents(), nbVertices); | | 324 | + if (buffer != null) { | | 325 | + buffer.rewind(); | | 326 | + bulkPut(vb.getFormat(), newVerts,buffer); | | 327 | + | | 328 | + int index = vertexData.size(); | | 329 | + newVerts.position(vertexData.size() * vb.getNumComponents()); | | 330 | + for (int j = 0; j < newVertices.size(); j++) { | | 331 | + int oldInd = indiceMap.get(index) ; | | 332 | + for (int i = 0; i < vb.getNumComponents(); i++) { | | 333 | + putValue(vb.getFormat(), newVerts, buffer, oldInd* vb.getNumComponents() + i); | | 334 | + } | | 335 | + index++; | | 336 | + } | | 337 | + vb.updateData(newVerts); | | 338 | + //destroy previous buffer as it's no longer needed | | 339 | + destroyDirectBuffer(buffer); | | 340 | + } | | 341 | + } | | 342 | + } | | 343 | + vertexData.addAll(newVertices); | | 344 | + | | 345 | + mesh.updateCounts(); | | 346 | + } | | 347 | + | | 348 | + return vertexData; | | 349 | + } | | 350 | + | | 351 | + private static void bulkPut(VertexBuffer.Format format, Buffer buf1, Buffer buf2) { | | 352 | + switch (format) { | | 353 | + case Byte: | | 354 | + case Half: | | 355 | + case UnsignedByte: | | 356 | + ((ByteBuffer) buf1).put((ByteBuffer) buf2); | | 357 | + break; | | 358 | + case Short: | | 359 | + case UnsignedShort: | | 360 | + | | 361 | + ((ShortBuffer) buf1).put((ShortBuffer) buf2); | | 362 | + break; | | 363 | + | | 364 | + case Int: | | 365 | + case UnsignedInt: | | 366 | + ((IntBuffer) buf1).put((IntBuffer) buf2); | | 367 | + break; | | 368 | + case Float: | | 369 | + | | 370 | + ((FloatBuffer) buf1).put((FloatBuffer) buf2); | | 371 | + break; | | 372 | + case Double: | | 373 | + ((DoubleBuffer) buf1).put((DoubleBuffer) buf2); | | 374 | + break; | | 375 | + | | 376 | + default: | | 377 | + throw new UnsupportedOperationException("Unrecoginized buffer format: " + format); | | 378 | + } | | 379 | + } | | 380 | + | | 381 | + private static void putValue(VertexBuffer.Format format, Buffer buf1, Buffer buf2,int index) { | | 382 | + switch (format) { | | 383 | + case Byte: | | 384 | + case Half: | | 385 | + case UnsignedByte: | | 386 | + byte b = ((ByteBuffer) buf2).get(index); | | 387 | + ((ByteBuffer) buf1).put(b); | | 388 | + break; | | 389 | + case Short: | | 390 | + case UnsignedShort: | | 391 | + short s = ((ShortBuffer) buf2).get(index); | | 392 | + ((ShortBuffer) buf1).put(s); | | 393 | + break; | | 394 | + | | 395 | + case Int: | | 396 | + case UnsignedInt: | | 397 | + int i = ((IntBuffer) buf2).get(index); | | 398 | + ((IntBuffer) buf1).put(i); | | 399 | + break; | | 400 | + case Float: | | 401 | + float f = ((FloatBuffer) buf2).get(index); | | 402 | + ((FloatBuffer) buf1).put(f); | | 403 | + break; | | 404 | + case Double: | | 405 | + double d = ((DoubleBuffer) buf2).get(index); | | 406 | + ((DoubleBuffer) buf1).put(d); | | 407 | + break; | | 408 | + default: | | 409 | + throw new UnsupportedOperationException("Unrecoginized buffer format: " + format); | | 410 | + } | | 411 | + } | | 412 | + | | 413 | + private static List<VertexData> processTriangleStrip(Mesh mesh, | 216 | 414 | int[] index, Vector3f[] v, Vector2f[] t) { | 217 | 415 | IndexBuffer indexBuffer = mesh.getIndexBuffer(); | 218 | 416 | FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); | 219 | 417 | FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData(); | 220 | 418 | | 221 | | - VertexData[] vertices = initVertexData(vertexBuffer.limit() / 3); | | 419 | + List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3); | 222 | 420 | | 223 | 421 | index[0] = indexBuffer.get(0); | 224 | 422 | index[1] = indexBuffer.get(1); |
| | @@ -238,9 +436,9 @@ public class TangentBinormalGenerator { | 238 | 436 | TriangleData triData = processTriangle(index, v, t); | 239 | 437 | | 240 | 438 | if (triData != null && !isDegenerate) { | 241 | | - vertices[index[0]].triangles.add(triData); | 242 | | - vertices[index[1]].triangles.add(triData); | 243 | | - vertices[index[2]].triangles.add(triData); | | 439 | + vertices.get(index[0]).triangles.add(triData); | | 440 | + vertices.get(index[1]).triangles.add(triData); | | 441 | + vertices.get(index[2]).triangles.add(triData); | 244 | 442 | } | 245 | 443 | | 246 | 444 | Vector3f vTemp = v[0]; |
| | @@ -260,13 +458,13 @@ public class TangentBinormalGenerator { | 260 | 458 | return vertices; | 261 | 459 | } | 262 | 460 | | 263 | | - private static VertexData[] processTriangleFan(Mesh mesh, | | 461 | + private static List<VertexData> processTriangleFan(Mesh mesh, | 264 | 462 | int[] index, Vector3f[] v, Vector2f[] t) { | 265 | 463 | IndexBuffer indexBuffer = mesh.getIndexBuffer(); | 266 | 464 | FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData(); | 267 | 465 | FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData(); | 268 | 466 | | 269 | | - VertexData[] vertices = initVertexData(vertexBuffer.limit() / 3); | | 467 | + List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3); | 270 | 468 | | 271 | 469 | index[0] = indexBuffer.get(0); | 272 | 470 | index[1] = indexBuffer.get(1); |
| | @@ -284,9 +482,9 @@ public class TangentBinormalGenerator { | 284 | 482 | | 285 | 483 | TriangleData triData = processTriangle(index, v, t); | 286 | 484 | if (triData != null) { | 287 | | - vertices[index[0]].triangles.add(triData); | 288 | | - vertices[index[1]].triangles.add(triData); | 289 | | - vertices[index[2]].triangles.add(triData); | | 485 | + vertices.get(index[0]).triangles.add(triData); | | 486 | + vertices.get(index[1]).triangles.add(triData); | | 487 | + vertices.get(index[2]).triangles.add(triData); | 290 | 488 | } | 291 | 489 | | 292 | 490 | Vector3f vTemp = v[1]; |
| | @@ -379,7 +577,6 @@ public class TangentBinormalGenerator { | 379 | 577 | "The angle must be between 0 and 179 degrees."); | 380 | 578 | } | 381 | 579 | toleranceDot = FastMath.cos(angle * FastMath.DEG_TO_RAD); | 382 | | - toleranceAngle = angle; | 383 | 580 | } | 384 | 581 | | 385 | 582 | |
| | @@ -415,18 +612,20 @@ public class TangentBinormalGenerator { | 415 | 612 | populateFromBuffer(texCoord, texcoordBuffer, i); | 416 | 613 | | 417 | 614 | boolean found = false; | 418 | | - | 419 | | - for (int j = 0; j < vertexMap.size(); j++) { | 420 | | - VertexInfo vertexInfo = vertexMap.get(j); | 421 | | - if (approxEqual(vertexInfo.position, position) && | 422 | | - approxEqual(vertexInfo.normal, normal) && | 423 | | - approxEqual(vertexInfo.texCoord, texCoord)) | 424 | | - { | 425 | | - vertexInfo.indices.add(i); | 426 | | - found = true; | 427 | | - break; | 428 | | - } | 429 | | - } | | 615 | + //Nehon 07/07/2013 | | 616 | + //Removed this part, joining splitted vertice to compute tangent space makes no sense to me | | 617 | + //separate vertice should have separate tangent space | | 618 | +// for (int j = 0; j < vertexMap.size(); j++) { | | 619 | +// VertexInfo vertexInfo = vertexMap.get(j); | | 620 | +// if (approxEqual(vertexInfo.position, position) && | | 621 | +// approxEqual(vertexInfo.normal, normal) && | | 622 | +// approxEqual(vertexInfo.texCoord, texCoord)) | | 623 | +// { | | 624 | +// vertexInfo.indices.add(i); | | 625 | +// found = true; | | 626 | +// break; | | 627 | +// } | | 628 | +// } | 430 | 629 | | 431 | 630 | if (!found) { | 432 | 631 | VertexInfo vertexInfo = new VertexInfo(position.clone(), normal.clone(), texCoord.clone()); |
| | @@ -438,43 +637,44 @@ public class TangentBinormalGenerator { | 438 | 637 | return vertexMap; | 439 | 638 | } | 440 | 639 | | 441 | | - private static void processTriangleData(Mesh mesh, VertexData[] vertices, | 442 | | - boolean approxTangent) | 443 | | - { | | 640 | + private static void processTriangleData(Mesh mesh, List<VertexData> vertices, | | 641 | + boolean approxTangent) { | 444 | 642 | ArrayList<VertexInfo> vertexMap = linkVertices(mesh); | 445 | | - | 446 | | - // FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData(); | 447 | | - | 448 | | - FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.length * 4); | 449 | | -// FloatBuffer binormals = BufferUtils.createFloatBuffer(vertices.length * 3); | | 643 | + | | 644 | + FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.size() * 4); | | 645 | + | | 646 | + ColorRGBA[] cols = null; | | 647 | + if (debug) { | | 648 | + cols = new ColorRGBA[vertices.size()]; | | 649 | + } | 450 | 650 | | 451 | 651 | Vector3f tangent = new Vector3f(); | 452 | 652 | Vector3f binormal = new Vector3f(); | 453 | 653 | //Vector3f normal = new Vector3f(); | 454 | 654 | Vector3f givenNormal = new Vector3f(); | 455 | | - | | 655 | + | 456 | 656 | Vector3f tangentUnit = new Vector3f(); | 457 | 657 | Vector3f binormalUnit = new Vector3f(); | 458 | | - | | 658 | + | 459 | 659 | for (int k = 0; k < vertexMap.size(); k++) { | 460 | 660 | float wCoord = -1; | 461 | | - | | 661 | + | 462 | 662 | VertexInfo vertexInfo = vertexMap.get(k); | 463 | | - | | 663 | + | 464 | 664 | givenNormal.set(vertexInfo.normal); | 465 | 665 | givenNormal.normalizeLocal(); | 466 | | - | 467 | | - TriangleData firstTriangle = vertices[vertexInfo.indices.get(0)].triangles.get(0); | | 666 | + | | 667 | + TriangleData firstTriangle = vertices.get(vertexInfo.indices.get(0)).triangles.get(0); | 468 | 668 | | 469 | 669 | // check tangent and binormal consistency | 470 | 670 | tangent.set(firstTriangle.tangent); | 471 | 671 | tangent.normalizeLocal(); | 472 | 672 | binormal.set(firstTriangle.binormal); | 473 | 673 | binormal.normalizeLocal(); | 474 | | - | | 674 | + | 475 | 675 | for (int i : vertexInfo.indices) { | 476 | | - ArrayList<TriangleData> triangles = vertices[i].triangles; | 477 | | - | | 676 | + ArrayList<TriangleData> triangles = vertices.get(i).triangles; | | 677 | + | 478 | 678 | for (int j = 0; j < triangles.size(); j++) { | 479 | 679 | TriangleData triangleData = triangles.get(j); | 480 | 680 | |
| | @@ -499,40 +699,31 @@ public class TangentBinormalGenerator { | 499 | 699 | } | 500 | 700 | } | 501 | 701 | } | 502 | | - | 503 | | - | | 702 | + | | 703 | + | 504 | 704 | // find average tangent | 505 | 705 | tangent.set(0, 0, 0); | 506 | 706 | binormal.set(0, 0, 0); | 507 | | - | | 707 | + | 508 | 708 | int triangleCount = 0; | 509 | 709 | for (int i : vertexInfo.indices) { | 510 | | - ArrayList<TriangleData> triangles = vertices[i].triangles; | | 710 | + ArrayList<TriangleData> triangles = vertices.get(i).triangles; | 511 | 711 | triangleCount += triangles.size(); | 512 | | - | 513 | | - // boolean flippedNormal = false; | | 712 | + if (debug) { | | 713 | + cols[i] = ColorRGBA.White; | | 714 | + } | | 715 | + | 514 | 716 | for (int j = 0; j < triangles.size(); j++) { | 515 | 717 | TriangleData triangleData = triangles.get(j); | 516 | 718 | tangent.addLocal(triangleData.tangent); | 517 | 719 | binormal.addLocal(triangleData.binormal); | 518 | 720 | | 519 | | -// if (givenNormal.dot(triangleData.normal) < 0) { | 520 | | -// flippedNormal = true; | 521 | | -// } | 522 | 721 | } | 523 | | -// if (flippedNormal /*&& approxTangent*/) { | 524 | | -// // Generated normal is flipped for this vertex, | 525 | | -// // so binormal = normal.cross(tangent) will be flipped in the shader | 526 | | -// // log.log(Level.WARNING, | 527 | | -// // "Binormal is flipped for vertex {0}.", i); | 528 | | -// | 529 | | -// wCoord = 1; | 530 | | -// } | 531 | 722 | } | 532 | 723 | | 533 | | - | | 724 | + | 534 | 725 | int blameVertex = vertexInfo.indices.get(0); | 535 | | - | | 726 | + | 536 | 727 | if (tangent.length() < ZERO_TOLERANCE) { | 537 | 728 | log.log(Level.WARNING, | 538 | 729 | "Shared tangent is zero for vertex {0}.", blameVertex); |
| | @@ -587,21 +778,21 @@ public class TangentBinormalGenerator { | 587 | 778 | "Tangent and binormal are parallel for vertex {0}.", blameVertex); | 588 | 779 | } | 589 | 780 | } | 590 | | - | | 781 | + | 591 | 782 | Vector3f finalTangent = new Vector3f(); | 592 | 783 | Vector3f tmp = new Vector3f(); | 593 | 784 | for (int i : vertexInfo.indices) { | 594 | 785 | if (approxTangent) { | 595 | 786 | // Gram-Schmidt orthogonalize | 596 | | - finalTangent.set(tangent).subtractLocal(tmp.set(givenNormal).multLocal(givenNormal.dot(tangent))); | | 787 | + finalTangent.set(tangent).subtractLocal(tmp.set(givenNormal).multLocal(givenNormal.dot(tangent))); | 597 | 788 | finalTangent.normalizeLocal(); | 598 | | - | 599 | | - wCoord = tmp.set(givenNormal).crossLocal(tangent).dot(binormal) <0f? -1f:1f; | | 789 | + | | 790 | + wCoord = tmp.set(givenNormal).crossLocal(tangent).dot(binormal) < 0f ? -1f : 1f; | 600 | 791 | | 601 | 792 | tangents.put((i * 4), finalTangent.x); | 602 | 793 | tangents.put((i * 4) + 1, finalTangent.y); | 603 | 794 | tangents.put((i * 4) + 2, finalTangent.z); | 604 | | - tangents.put((i * 4) + 3, wCoord); | | 795 | + tangents.put((i * 4) + 3, wCoord); | 605 | 796 | } else { | 606 | 797 | tangents.put((i * 4), tangent.x); | 607 | 798 | tangents.put((i * 4) + 1, tangent.y); |
| | @@ -612,13 +803,49 @@ public class TangentBinormalGenerator { | 612 | 803 | } | 613 | 804 | } | 614 | 805 | } | 615 | | - | | 806 | + tangents.limit(tangents.capacity()); | 616 | 807 | // If the model already had a tangent buffer, replace it with the regenerated one | 617 | | - mesh.clearBuffer(Type.Tangent); | | 808 | + mesh.clearBuffer(Type.Tangent); | 618 | 809 | mesh.setBuffer(Type.Tangent, 4, tangents); | 619 | | -// if (!approxTangent) mesh.setBuffer(Type.Binormal, 3, binormals); | 620 | | - } | | 810 | + | | 811 | + | | 812 | + | | 813 | + if(mesh.isAnimated()){ | | 814 | + mesh.clearBuffer(Type.BindPoseNormal); | | 815 | + mesh.clearBuffer(Type.BindPosePosition); | | 816 | + mesh.clearBuffer(Type.BindPoseTangent); | | 817 | + mesh.generateBindPose(true); | | 818 | + } | | 819 | + | | 820 | + if (debug) { | | 821 | + writeColorBuffer( vertices, cols, mesh); | | 822 | + } | | 823 | + mesh.updateBound(); | | 824 | + mesh.updateCounts(); | | 825 | + } | 621 | 826 | | | 827 | + private static void writeColorBuffer(List<VertexData> vertices, ColorRGBA[] cols, Mesh mesh) { | | 828 | + FloatBuffer colors = BufferUtils.createFloatBuffer(vertices.size() * 4); | | 829 | + colors.rewind(); | | 830 | + for (ColorRGBA color : cols) { | | 831 | + colors.put(color.r); | | 832 | + colors.put(color.g); | | 833 | + colors.put(color.b); | | 834 | + colors.put(color.a); | | 835 | + } | | 836 | + mesh.clearBuffer(Type.Color); | | 837 | + mesh.setBuffer(Type.Color, 4, colors); | | 838 | + } | | 839 | + | | 840 | + private static int parity(Vector3f n1, Vector3f n) { | | 841 | + if (n1.dot(n) < 0) { | | 842 | + return -1; | | 843 | + } else { | | 844 | + return 1; | | 845 | + } | | 846 | + | | 847 | + } | | 848 | + | 622 | 849 | public static Mesh genTbnLines(Mesh mesh, float scale) { | 623 | 850 | if (mesh.getBuffer(Type.Tangent) == null) { | 624 | 851 | return genNormalLines(mesh, scale); |
Show on old repository browser
|