UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

49 lines (37 loc) 1.46 kB
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); }