UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

96 lines (77 loc) 3.17 kB
import { v3_dot } from "../../vec3/v3_dot.js"; /** * Compute barycentric coordinates for triangle intersection * Operates on edges, this is optimized for raytracing, as same edges are required to reconstruct various attributes later on * NOTE: most of the code is inlined for speed to avoid allocation and function calls * @see https://github.com/erich666/jgt-code/blob/master/Volume_02/Number_1/Moller1997a/raytri.c * @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28) * @param {number[]} result * @param {number} origin_x * @param {number} origin_y * @param {number} origin_z * @param {number} direction_x * @param {number} direction_y * @param {number} direction_z * @param {number} ax * @param {number} ay * @param {number} az * @param {number} edge1_x * @param {number} edge1_y * @param {number} edge1_z * @param {number} edge2_x * @param {number} edge2_y * @param {number} edge2_z * @return {boolean} */ export function computeTriangleRayIntersectionBarycentricEdge( result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, edge1_x, edge1_y, edge1_z, edge2_x, edge2_y, edge2_z ) { // begin calculating determinant - also used to calculate U parameter // CROSS(pvec, dir, edge2) const pvec_x = direction_y * edge2_z - direction_z * edge2_y; const pvec_y = direction_z * edge2_x - direction_x * edge2_z; const pvec_z = direction_x * edge2_y - direction_y * edge2_x; //if determinant is near zero, ray lies in plane of triangle const det = v3_dot(edge1_x, edge1_y, edge1_z, pvec_x, pvec_y, pvec_z); if(det === 0){ // ray is parallel to the plane of the triange, no intersection possible return false; } if (det <= 0) { // back-face culling // return false; } const inv_det = 1 / det; // calculate distance from vert0 to ray origin (not really, but okay) const tvec_x = origin_x - ax; const tvec_y = origin_y - ay; const tvec_z = origin_z - az; // calculate u const u = v3_dot(tvec_x, tvec_y, tvec_z, pvec_x, pvec_y, pvec_z)*inv_det; if (u < 0 || u > 1) { // outside of bounds of the triangle return false; } // prepare to test V parameter // CROSS(qvec, tvec, edge1) const qvec_x = tvec_y * edge1_z - tvec_z * edge1_y; const qvec_y = tvec_z * edge1_x - tvec_x * edge1_z; const qvec_z = tvec_x * edge1_y - tvec_y * edge1_x; // calculate V parameter const v = v3_dot(direction_x, direction_y, direction_z, qvec_x, qvec_y, qvec_z)*inv_det; if (v < 0 || u + v > 1) { // out of bounds return false; } // calculate t, scale parameter, ray intersects triangle const t = v3_dot(edge2_x, edge2_y, edge2_z, qvec_x, qvec_y, qvec_z) * inv_det; result[0] = t; result[1] = u ; result[2] = v ; return true; }