UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

106 lines (79 loc) 2.87 kB
import { array_copy } from "../../../collection/array/array_copy.js"; import { solve_linear_system } from "../../../math/linalg/solve_linear_system.js"; import { v3_dot } from "../../vec3/v3_dot.js"; const MAX_FLOAT32 = 3.4028234663852886e+38; const n12 = new Float64Array(3); const n13 = new Float64Array(3); const n14 = new Float64Array(3); const x12 = new Float64Array(3); const x13 = new Float64Array(3); const x14 = new Float64Array(3); const A = new Float64Array(9); const rhs = new Float64Array(3); /** * Compute the circumcenter (center[3]) and radius squared (method return value) of a tetrahedron defined by the four points x1, x2, x3, and x4. * * @see https://github.com/Kitware/VTK/blob/ac3fd8005bce7b3da4423c305f61ffd9df9695ef/Common/DataModel/vtkTetra.cxx * @param {number[]} result [center_x, center_y, center_z, radius_squared] * @param {number[]} points * @param {number} a * @param {number} b * @param {number} c * @param {number} d */ export function tetrahedron_compute_circumsphere( result, points, a, b, c, d ) { // calculate normals and intersection points of bisecting planes. for (let i = 0; i < 3; i++) { const v_a = points[a * 3 + i]; const v_b = points[b * 3 + i]; const v_c = points[c * 3 + i]; const v_d = points[d * 3 + i]; n12[i] = v_b - v_a; n13[i] = v_c - v_a; n14[i] = v_d - v_a; x12[i] = (v_b + v_a) * 0.5; x13[i] = (v_c + v_a) * 0.5; x14[i] = (v_d + v_a) * 0.5; } array_copy(n12, 0, A, 0, 3); array_copy(n13, 0, A, 3, 3); array_copy(n14, 0, A, 6, 3); rhs[0] = v3_dot(n12[0], n12[1], n12[2], x12[0], x12[1], x12[2]); rhs[1] = v3_dot(n13[0], n13[1], n13[2], x13[0], x13[1], x13[2]); rhs[2] = v3_dot(n14[0], n14[1], n14[2], x14[0], x14[1], x14[2]); // Solve system of equations if (solve_linear_system(A, rhs, 3) === false) { // failed to solve, fall-back to infinitely-sized sphere centered around origin result[0] = result[1] = result[2] = 0; result[3] = MAX_FLOAT32; return; } else { result[0] = rhs[0]; result[1] = rhs[1]; result[2] = rhs[2]; } let sum = 0; let diff; for (let i = 0; i < 3; i++) { const rhs_offset = rhs[i]; diff = points[a * 3 + i] - rhs_offset; sum += diff * diff; diff = points[b * 3 + i] - rhs_offset; sum += diff * diff; diff = points[c * 3 + i] - rhs_offset; sum += diff * diff; diff = points[d * 3 + i] - rhs_offset; sum += diff * diff; } // divide sum *= 0.25; if (sum >= MAX_FLOAT32) { result[3] = MAX_FLOAT32; } else { result[3] = sum; } }