Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/RayTriangle.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56JPH_NAMESPACE_BEGIN78/// Intersect ray with triangle, returns closest point or FLT_MAX if no hit (branch less version)9/// Adapted from: http://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm10JPH_INLINE float RayTriangle(Vec3Arg inOrigin, Vec3Arg inDirection, Vec3Arg inV0, Vec3Arg inV1, Vec3Arg inV2)11{12// Epsilon13Vec3 epsilon = Vec3::sReplicate(1.0e-12f);1415// Zero & one16Vec3 zero = Vec3::sZero();17Vec3 one = Vec3::sOne();1819// Find vectors for two edges sharing inV020Vec3 e1 = inV1 - inV0;21Vec3 e2 = inV2 - inV0;2223// Begin calculating determinant - also used to calculate u parameter24Vec3 p = inDirection.Cross(e2);2526// if determinant is near zero, ray lies in plane of triangle27Vec3 det = Vec3::sReplicate(e1.Dot(p));2829// Check if determinant is near zero30UVec4 det_near_zero = Vec3::sLess(det.Abs(), epsilon);3132// When the determinant is near zero, set it to one to avoid dividing by zero33det = Vec3::sSelect(det, Vec3::sOne(), det_near_zero);3435// Calculate distance from inV0 to ray origin36Vec3 s = inOrigin - inV0;3738// Calculate u parameter39Vec3 u = Vec3::sReplicate(s.Dot(p)) / det;4041// Prepare to test v parameter42Vec3 q = s.Cross(e1);4344// Calculate v parameter45Vec3 v = Vec3::sReplicate(inDirection.Dot(q)) / det;4647// Get intersection point48Vec3 t = Vec3::sReplicate(e2.Dot(q)) / det;4950// Check if there is an intersection51UVec4 no_intersection =52UVec4::sOr53(54UVec4::sOr55(56UVec4::sOr57(58det_near_zero,59Vec3::sLess(u, zero)60),61UVec4::sOr62(63Vec3::sLess(v, zero),64Vec3::sGreater(u + v, one)65)66),67Vec3::sLess(t, zero)68);6970// Select intersection point or FLT_MAX based on if there is an intersection or not71return Vec3::sSelect(t, Vec3::sReplicate(FLT_MAX), no_intersection).GetX();72}7374/// Intersect ray with 4 triangles in SOA format, returns 4 vector of closest points or FLT_MAX if no hit (uses bit tricks to do less divisions)75JPH_INLINE Vec4 RayTriangle4(Vec3Arg inOrigin, Vec3Arg inDirection, Vec4Arg inV0X, Vec4Arg inV0Y, Vec4Arg inV0Z, Vec4Arg inV1X, Vec4Arg inV1Y, Vec4Arg inV1Z, Vec4Arg inV2X, Vec4Arg inV2Y, Vec4Arg inV2Z)76{77// Epsilon78Vec4 epsilon = Vec4::sReplicate(1.0e-12f);7980// Zero81Vec4 zero = Vec4::sZero();8283// Find vectors for two edges sharing inV084Vec4 e1x = inV1X - inV0X;85Vec4 e1y = inV1Y - inV0Y;86Vec4 e1z = inV1Z - inV0Z;87Vec4 e2x = inV2X - inV0X;88Vec4 e2y = inV2Y - inV0Y;89Vec4 e2z = inV2Z - inV0Z;9091// Get direction vector components92Vec4 dx = inDirection.SplatX();93Vec4 dy = inDirection.SplatY();94Vec4 dz = inDirection.SplatZ();9596// Begin calculating determinant - also used to calculate u parameter97Vec4 px = dy * e2z - dz * e2y;98Vec4 py = dz * e2x - dx * e2z;99Vec4 pz = dx * e2y - dy * e2x;100101// if determinant is near zero, ray lies in plane of triangle102Vec4 det = e1x * px + e1y * py + e1z * pz;103104// Get sign bit for determinant and make positive105Vec4 det_sign = Vec4::sAnd(det, UVec4::sReplicate(0x80000000).ReinterpretAsFloat());106det = Vec4::sXor(det, det_sign);107108// Check which determinants are near zero109UVec4 det_near_zero = Vec4::sLess(det, epsilon);110111// Set components of the determinant to 1 that are near zero to avoid dividing by zero112det = Vec4::sSelect(det, Vec4::sOne(), det_near_zero);113114// Calculate distance from inV0 to ray origin115Vec4 sx = inOrigin.SplatX() - inV0X;116Vec4 sy = inOrigin.SplatY() - inV0Y;117Vec4 sz = inOrigin.SplatZ() - inV0Z;118119// Calculate u parameter and flip sign if determinant was negative120Vec4 u = Vec4::sXor(sx * px + sy * py + sz * pz, det_sign);121122// Prepare to test v parameter123Vec4 qx = sy * e1z - sz * e1y;124Vec4 qy = sz * e1x - sx * e1z;125Vec4 qz = sx * e1y - sy * e1x;126127// Calculate v parameter and flip sign if determinant was negative128Vec4 v = Vec4::sXor(dx * qx + dy * qy + dz * qz, det_sign);129130// Get intersection point and flip sign if determinant was negative131Vec4 t = Vec4::sXor(e2x * qx + e2y * qy + e2z * qz, det_sign);132133// Check if there is an intersection134UVec4 no_intersection =135UVec4::sOr136(137UVec4::sOr138(139UVec4::sOr140(141det_near_zero,142Vec4::sLess(u, zero)143),144UVec4::sOr145(146Vec4::sLess(v, zero),147Vec4::sGreater(u + v, det)148)149),150Vec4::sLess(t, zero)151);152153// Select intersection point or FLT_MAX based on if there is an intersection or not154return Vec4::sSelect(t / det, Vec4::sReplicate(FLT_MAX), no_intersection);155}156157JPH_NAMESPACE_END158159160