@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
87 lines (72 loc) • 2.63 kB
JavaScript
import { v4_dot } from "../../vec4/v4_dot.js";
import Vector3 from "../../Vector3.js";
const V1 = new Vector3();
const V2 = new Vector3();
/**
* 2,0,or -2; 2: above, -2 : below, 0 : intersects plane
* NOTE: used an article by Bart Wronski https://bartwronski.com/2017/04/13/cull-that-cone/
* @param {number} plane_normal_x
* @param {number} plane_normal_y
* @param {number} plane_normal_z
* @param {number} plane_constant
* @param {number} originX
* @param {number} originY
* @param {number} originZ
* @param {number} directionX
* @param {number} directionY
* @param {number} directionZ
* @param {number} angle
* @param {number} length
* @returns {number}
*/
export function computeConePlaneSide(
plane_normal_x, plane_normal_y, plane_normal_z,
plane_constant,
originX, originY, originZ,
directionX, directionY, directionZ,
angle,
length
) {
/*
ORIGINAL HLSL:
bool TestConeVsPlane(in float3 origin, in float3 forward, in float size, in float angle, in float4 testPlane)
{
const float3 V1 = cross(testPlane.xyz, forward);
const float3 V2 = cross(V1, forward);
const float3 capRimPoint = origin +
size * cos(angle) * forward +
size * sin(angle) * V2;
return dot(float4(capRimPoint, 1.0f), testPlane) >= 0.0f || dot(float4(origin, 1.0f), testPlane) >= 0.0f;
}
*/
V1._crossVectors(plane_normal_x, plane_normal_y, plane_normal_z, directionX, directionY, directionZ);
V2._crossVectors(V1.x, V1.y, V1.z, directionX, directionY, directionZ);
const scaled_cos = length * Math.cos(angle);
const scaled_sin = length * Math.sin(angle);
// compute cap rim point (closest point to the plane on the wide side of the cone)
V1.set(
originX + scaled_cos * directionX + scaled_sin * V2.x,
originY + scaled_cos * directionY + scaled_sin * V2.y,
originZ + scaled_cos * directionZ + scaled_sin * V2.z
);
const rim_point_side = v4_dot(
V1.x, V1.y, V1.z, 1,
plane_normal_x, plane_normal_y, plane_normal_z, plane_constant
);
const origin_point_side = v4_dot(
originX, originY, originZ, 1,
plane_normal_x, plane_normal_y, plane_normal_z, plane_constant
);
let result = 0;
if (rim_point_side >= 0) {
result += 1;
} else {
result -= 1;
}
if (origin_point_side >= 0) {
result += 1;
} else {
result -= 1;
}
return result;
}