@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
96 lines (77 loc) • 3.17 kB
JavaScript
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;
}