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