UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

113 lines (83 loc) 3.6 kB
import { v3_distance_above_plane } from "../../vec3/v3_distance_above_plane.js"; import Vector3 from "../../Vector3.js"; import { plane3_compute_plane_intersection } from "../plane/plane3_compute_plane_intersection.js"; import { plane3_project_point } from "../plane/plane3_project_point.js"; import { plane3_three_compute_convex_3_plane_intersection } from "../plane/plane3_three_compute_convex_3_plane_intersection.js"; import { ray3_compute_nearest_point_to_point } from "../ray/ray3_compute_nearest_point_to_point.js"; /** * * @type {Plane[]} */ const scratch_outer_planes = []; const scratch_v3_0 = new Vector3(); const scratch_v3_1 = new Vector3(); /** * * @type {number[]} */ const scratch_v3_array = []; /** * * @param {Vector3} result * @param {Plane[]} planes * @param {number} target_x * @param {number} target_y * @param {number} target_z * @returns {boolean} if point is inside the frustum - true, false otherwise */ export function frustum3_computeNearestPointToPoint(result, planes, target_x, target_y, target_z) { let j; let outside_plane_count = 0; const plane_count = planes.length; for (j = 0; j < plane_count; j++) { const plane = planes[j]; const plane_normal = plane.normal; const distance = v3_distance_above_plane( target_x, target_y, target_z, plane_normal.x, plane_normal.y, plane_normal.z, plane.constant ); if (distance < 0) { scratch_outer_planes[outside_plane_count] = j; outside_plane_count++; } } if (outside_plane_count === 0) { result.set(target_x, target_y, target_z); return true; } // point is outside the frustum if (outside_plane_count === 1) { const plane_0_index = scratch_outer_planes[0]; const plane_0 = planes[plane_0_index]; // point lies outside exactly one plane plane3_project_point(result, target_x, target_y, target_z, plane_0.normal.z, plane_0.normal.y, plane_0.normal.z, plane_0.constant); } else if (outside_plane_count === 2) { // outside two planes, nearest point lies on the intersection line of two planes const plane_0_index = scratch_outer_planes[0]; const plane_1_index = scratch_outer_planes[1]; const plane_0 = planes[plane_0_index]; const plane_1 = planes[plane_1_index]; const intersection_exists = plane3_compute_plane_intersection(plane_0, plane_1, scratch_v3_0, scratch_v3_1); if (!intersection_exists) { throw new Error('Planes are parallel and do not intersect, likely an invalid frustum'); } ray3_compute_nearest_point_to_point(result, scratch_v3_0.x, scratch_v3_0.y, scratch_v3_0.z, scratch_v3_1.x, scratch_v3_1.y, scratch_v3_1.z, target_x, target_y, target_z ); } else if (outside_plane_count === 3) { // outside 3 planes, nearest point is intersect of 3 planes const plane_0_index = scratch_outer_planes[0]; const plane_1_index = scratch_outer_planes[1]; const plane_2_index = scratch_outer_planes[2]; const plane_0 = planes[plane_0_index]; const plane_1 = planes[plane_1_index]; const plane_2 = planes[plane_2_index]; plane3_three_compute_convex_3_plane_intersection(scratch_v3_array, 0, plane_0, plane_1, plane_2); result.fromArray(scratch_v3_array, 0) } return false; }