@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
49 lines (37 loc) • 1.46 kB
JavaScript
import { assert } from "../../../assert.js";
import { v3_dot } from "../../vec3/v3_dot.js";
import { v4_multiply_mat4 } from "../../vec4/v4_multiply_mat4.js";
const v4 = [];
/**
* Computations of screen-space pixel area covered by a sphere
* NOTE: Port of GLSL code by Ingo Quilez. Source: http://www.iquilezles.org/www/articles/sphereproj/sphereproj.htm
* @param {number[]|{0:number,1:number,2:number,3:number}} sph Sphere in world space
* @param {number[]|Float32Array} cam camera transform matrix (world to camera)(inverse world matrix of camera)
* @param {number} fl focal length (fov in Radians)
* @returns {number} area on the screen as a fraction, 1=entire screen, 0=zero area
*/
export function sphere_project(sph, cam, fl) {
assert.notNull(cam, 'cam');
assert.isNumber(fl, 'fl');
assert.greaterThan(fl, 0, 'fl');
v4[0] = sph[0];
v4[1] = sph[1];
v4[2] = sph[2];
v4[3] = 1;
//transform to camera space
v4_multiply_mat4(v4, v4, cam);
const r = sph[3];
const r2 = r * r;
const v4_x = v4[0];
const v4_y = v4[1];
const v4_z = v4[2];
const z2 = v4_z * v4_z;
const l2 = v3_dot(v4_x, v4_y, v4_z, v4_x, v4_y, v4_z);
const rz2 = r2 - z2;
if (rz2 === 0) {
// avoid division by 0
return 0;
}
const area = -Math.PI * fl * fl * r2 * Math.sqrt(Math.abs((l2 - r2) / rz2)) / rz2;
return Math.abs(area);
}