@@ -336,6 +336,90 @@ public float intersects(Vector3f v0, Vector3f v1, Vector3f v2) {
336336 return Float .POSITIVE_INFINITY ;
337337 }
338338
339+ /**
340+ * Test for an intersection between the ray and the given triangle and,
341+ * if an intersection exists, store the barycentric coordinates of the
342+ * contact point in <code>baryCoords</code>.
343+ *
344+ * <p>The stored (u, v) barycentric coordinates mean: u is the weight
345+ * of <code>v1</code>, v is the weight of <code>v2</code>, and
346+ * (1 - u - v) is the weight of <code>v0</code>.
347+ *
348+ * @param v0 first vertex of the triangle (not null, unaffected)
349+ * @param v1 second vertex of the triangle (not null, unaffected)
350+ * @param v2 third vertex of the triangle (not null, unaffected)
351+ * @param baryCoords storage for the barycentric (u, v) coordinates of the
352+ * contact point (modified on hit, may be null)
353+ * @return the distance along the ray to the intersection, or
354+ * {@link Float#POSITIVE_INFINITY} if there is no intersection
355+ */
356+ public float intersects (Vector3f v0 , Vector3f v1 , Vector3f v2 , Vector2f baryCoords ) {
357+ float edge1X = v1 .x - v0 .x ;
358+ float edge1Y = v1 .y - v0 .y ;
359+ float edge1Z = v1 .z - v0 .z ;
360+
361+ float edge2X = v2 .x - v0 .x ;
362+ float edge2Y = v2 .y - v0 .y ;
363+ float edge2Z = v2 .z - v0 .z ;
364+
365+ float normX = ((edge1Y * edge2Z ) - (edge1Z * edge2Y ));
366+ float normY = ((edge1Z * edge2X ) - (edge1X * edge2Z ));
367+ float normZ = ((edge1X * edge2Y ) - (edge1Y * edge2X ));
368+
369+ float dirDotNorm = direction .x * normX + direction .y * normY + direction .z * normZ ;
370+
371+ float diffX = origin .x - v0 .x ;
372+ float diffY = origin .y - v0 .y ;
373+ float diffZ = origin .z - v0 .z ;
374+
375+ float sign ;
376+ if (dirDotNorm > FastMath .FLT_EPSILON ) {
377+ sign = 1 ;
378+ } else if (dirDotNorm < -FastMath .FLT_EPSILON ) {
379+ sign = -1f ;
380+ dirDotNorm = -dirDotNorm ;
381+ } else {
382+ // ray and triangle/quad are parallel
383+ return Float .POSITIVE_INFINITY ;
384+ }
385+
386+ float diffEdge2X = ((diffY * edge2Z ) - (diffZ * edge2Y ));
387+ float diffEdge2Y = ((diffZ * edge2X ) - (diffX * edge2Z ));
388+ float diffEdge2Z = ((diffX * edge2Y ) - (diffY * edge2X ));
389+
390+ float dirDotDiffxEdge2 = sign * (direction .x * diffEdge2X
391+ + direction .y * diffEdge2Y
392+ + direction .z * diffEdge2Z );
393+
394+ if (dirDotDiffxEdge2 >= 0.0f ) {
395+ diffEdge2X = ((edge1Y * diffZ ) - (edge1Z * diffY ));
396+ diffEdge2Y = ((edge1Z * diffX ) - (edge1X * diffZ ));
397+ diffEdge2Z = ((edge1X * diffY ) - (edge1Y * diffX ));
398+
399+ float dirDotEdge1xDiff = sign * (direction .x * diffEdge2X
400+ + direction .y * diffEdge2Y
401+ + direction .z * diffEdge2Z );
402+
403+ if (dirDotEdge1xDiff >= 0.0f ) {
404+ if (dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm ) {
405+ float diffDotNorm = -sign * (diffX * normX + diffY * normY + diffZ * normZ );
406+ if (diffDotNorm >= 0.0f ) {
407+ // ray intersects triangle
408+ float inv = 1f / dirDotNorm ;
409+ float t = diffDotNorm * inv ;
410+ if (baryCoords != null ) {
411+ baryCoords .set (dirDotDiffxEdge2 * inv ,
412+ dirDotEdge1xDiff * inv );
413+ }
414+ return t ;
415+ }
416+ }
417+ }
418+ }
419+
420+ return Float .POSITIVE_INFINITY ;
421+ }
422+
339423 /**
340424 * <code>intersectWherePlanar</code> determines if the Ray intersects a
341425 * quad defined by the specified points and if so it stores the point of
@@ -393,13 +477,16 @@ public int collideWith(Collidable other, CollisionResults results) {
393477 return bv .collideWith (this , results );
394478 } else if (other instanceof AbstractTriangle ) {
395479 AbstractTriangle tri = (AbstractTriangle ) other ;
396- float d = intersects (tri .get1 (), tri .get2 (), tri .get3 ());
480+ Vector2f baryCoords = new Vector2f ();
481+ float d = intersects (tri .get1 (), tri .get2 (), tri .get3 (), baryCoords );
397482 if (Float .isInfinite (d ) || Float .isNaN (d )) {
398483 return 0 ;
399484 }
400485
401486 Vector3f point = new Vector3f (direction ).multLocal (d ).addLocal (origin );
402- results .addCollision (new CollisionResult (point , d ));
487+ CollisionResult cr = new CollisionResult (point , d );
488+ cr .setContactBaryCoords (baryCoords );
489+ results .addCollision (cr );
403490 return 1 ;
404491 } else {
405492 throw new UnsupportedCollisionException ();
0 commit comments