public override float AddSingleResult(LocalRayResult rayResult, bool normalInWorldSpace) { var collisionObject = rayResult.CollisionObject; if (collisionObject == null) { return(base.AddSingleResult(rayResult, normalInWorldSpace)); } var meshShape = collisionObject.CollisionShape as BvhTriangleMeshShape; if (meshShape == null) { return(base.AddSingleResult(rayResult, normalInWorldSpace)); } var meshObject = rayResult.CollisionObject.CollisionShape as BvhTriangleMeshShape; if (meshObject == null) { return(base.AddSingleResult(rayResult, normalInWorldSpace)); } var rayFromWorld = RayFromWorld; var rayDirection = RayToWorld - rayFromWorld; var triangleBuffer = new TriangleBuffer( ); meshShape.PerformRaycast(triangleBuffer, RayFromWorld, RayToWorld); float closestFrontFace = 1000f; for (int i = 0; i < triangleBuffer.NumTriangles; i++) { var triangle = triangleBuffer.GetTriangle(i); var triangleIndex = triangle.triangleIndex * 3; var info = meshShape.MeshInterface as InfoTriangleIndexVertexArray; var part = info?.IndexedMeshArray[triangle.partId]; if (part == null) { continue; } var edge1 = triangle.vertex1 - triangle.vertex0; var edge2 = triangle.vertex2 - triangle.vertex0; var normal = Vector3.Cross(edge1, edge2); var dot = Vector3.Dot(normal, rayDirection); if (dot > 0) { continue; } float t; if (TriangleRayIntersection.Test(triangle.vertex0, triangle.vertex1, triangle.vertex2, rayFromWorld, rayDirection, out t)) { if (!(closestFrontFace < t)) { GLDebug.QueueTriangleDraw(ref triangle.vertex0, ref triangle.vertex1, ref triangle.vertex2); closestFrontFace = t; } } else { continue; } var bitangent = info.SurfaceInfo[triangle.partId].Bitangents[ part.TriangleIndices[triangleIndex]]; var tangent = Vector3.Cross(bitangent, normal); HitSurfaceTangent = tangent.Normalized(); HitSurfaceNormal = normal.Normalized(); HitSurfaceBitangent = bitangent.Normalized(); } rayResult.HitFraction = closestFrontFace; if (closestFrontFace < ClosestHitFraction) { base.AddSingleResult(rayResult, normalInWorldSpace); } return(closestFrontFace); }