@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
103 lines (82 loc) • 2.92 kB
JavaScript
import { lerp } from "../../../math/lerp.js";
import Vector3 from "../../Vector3.js";
import { v3_dot } from "../../vec3/v3_dot.js";
import { v3_length_sqr } from "../../vec3/v3_length_sqr.js";
import { v3_slerp } from "../../vec3/v3_slerp.js";
import { EPSILON } from "../../../math/EPSILON.js";
const e = new Vector3();
const point = new Vector3();
const v0 = new Vector3();
const v1 = new Vector3();
/**
* @see https://stackoverflow.com/a/57824137
* @param {number[]} destination
* @param {number} destination_offset
* @param {number} a_normal_x
* @param {number} a_normal_y
* @param {number} a_normal_z
* @param {number} a_constant
* @param {number} b_normal_x
* @param {number} b_normal_y
* @param {number} b_normal_z
* @param {number} b_constant
* @param {number} t
*/
export function plane3_slerp(
destination, destination_offset,
a_normal_x, a_normal_y, a_normal_z, a_constant,
b_normal_x, b_normal_y, b_normal_z, b_constant,
t
) {
// The common line of the two planes is along the (non-unit) direction
e._crossVectors(
a_normal_x, a_normal_y, a_normal_z,
b_normal_x, b_normal_y, b_normal_z
);
const determinant = v3_length_sqr(e.x, e.y, e.z);
if (determinant < EPSILON) {
// no intersection, planes are parallel
// determine if planes are facing the same direction or not
const d = v3_dot(
a_normal_x, a_normal_y, a_normal_z,
b_normal_x, b_normal_y, b_normal_z
);
// if planes are parallel, we assume normal of one of the planes
destination[destination_offset] = a_normal_x;
destination[destination_offset + 1] = a_normal_y;
destination[destination_offset + 2] = a_normal_z;
destination[destination_offset + 3] = lerp(a_constant, b_constant * d, t);
return;
}
v0._crossVectors(
a_normal_x, a_normal_y, a_normal_z,
e.x, e.y, e.z
);
v0.multiplyScalar(b_constant);
v1._crossVectors(
b_normal_x, b_normal_y, b_normal_z,
e.x, e.y, e.z
);
v1.multiplyScalar(a_constant);
// The point on this line closest to the origin
// point = (d_1*cross(n_2,e)-d_2*cross(n_1,e))/dot(e.e)
point.subVectors(v0, v1);
const inv_determinant = 1 / determinant;
point.multiplyScalar(inv_determinant);
// compute normal
v3_slerp(
v0,
a_normal_x, a_normal_y, a_normal_z,
b_normal_x, b_normal_y, b_normal_z,
t
);
// compute distance (constant)
const d = v3_dot(
v0.x, v0.y, v0.z,
point.x, point.y, point.z
);
destination[destination_offset] = v0.x;
destination[destination_offset + 1] = v0.y;
destination[destination_offset + 2] = v0.z;
destination[destination_offset + 3] = -d;
}