@flighthq/camera 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/basis.d.ts +6 -0
- package/dist/basis.d.ts.map +1 -0
- package/dist/basis.js +63 -0
- package/dist/basis.js.map +1 -0
- package/dist/camera.d.ts +14 -0
- package/dist/camera.d.ts.map +1 -0
- package/dist/camera.js +79 -0
- package/dist/camera.js.map +1 -0
- package/dist/culling.d.ts +6 -0
- package/dist/culling.d.ts.map +1 -0
- package/dist/culling.js +39 -0
- package/dist/culling.js.map +1 -0
- package/dist/depth.d.ts +4 -0
- package/dist/depth.d.ts.map +1 -0
- package/dist/depth.js +39 -0
- package/dist/depth.js.map +1 -0
- package/dist/frustumCorners.d.ts +3 -0
- package/dist/frustumCorners.d.ts.map +1 -0
- package/dist/frustumCorners.js +64 -0
- package/dist/frustumCorners.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/intersection.d.ts +4 -0
- package/dist/intersection.d.ts.map +1 -0
- package/dist/intersection.js +69 -0
- package/dist/intersection.js.map +1 -0
- package/dist/picking.d.ts +4 -0
- package/dist/picking.d.ts.map +1 -0
- package/dist/picking.js +90 -0
- package/dist/picking.js.map +1 -0
- package/dist/projection.d.ts +16 -0
- package/dist/projection.d.ts.map +1 -0
- package/dist/projection.js +48 -0
- package/dist/projection.js.map +1 -0
- package/dist/shadowCamera.d.ts +3 -0
- package/dist/shadowCamera.d.ts.map +1 -0
- package/dist/shadowCamera.js +43 -0
- package/dist/shadowCamera.js.map +1 -0
- package/package.json +39 -0
- package/src/basis.test.ts +83 -0
- package/src/camera.test.ts +189 -0
- package/src/culling.test.ts +90 -0
- package/src/depth.test.ts +65 -0
- package/src/frustumCorners.test.ts +75 -0
- package/src/intersection.test.ts +118 -0
- package/src/picking.test.ts +94 -0
- package/src/projection.test.ts +97 -0
- package/src/shadowCamera.test.ts +45 -0
package/dist/basis.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Camera, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraForward(out: Vector3Like, camera: Readonly<Camera>): void;
|
|
3
|
+
export declare function getCameraPosition(out: Vector3Like, camera: Readonly<Camera>): void;
|
|
4
|
+
export declare function getCameraRight(out: Vector3Like, camera: Readonly<Camera>): void;
|
|
5
|
+
export declare function getCameraUp(out: Vector3Like, camera: Readonly<Camera>): void;
|
|
6
|
+
//# sourceMappingURL=basis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis.d.ts","sourceRoot":"","sources":["../src/basis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAO3D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAOjF;AAWD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CA2BlF;AAMD,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAK/E;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAK5E"}
|
package/dist/basis.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Extracts the camera's world-space forward direction (-Z of the camera frame) from the view
|
|
2
|
+
// matrix and writes it into `out`. In a right-handed camera frame the forward vector points
|
|
3
|
+
// from the eye toward the target; it is the negated third row of the view matrix.
|
|
4
|
+
//
|
|
5
|
+
// Safe when `out` aliases any field of the camera.
|
|
6
|
+
export function getCameraForward(out, camera) {
|
|
7
|
+
const m = camera.view.m;
|
|
8
|
+
// Row 2 of the view matrix is the negated forward direction in world space.
|
|
9
|
+
// Negate to get the true forward (eye→target).
|
|
10
|
+
out.x = -m[2];
|
|
11
|
+
out.y = -m[6];
|
|
12
|
+
out.z = -m[10];
|
|
13
|
+
}
|
|
14
|
+
// Extracts the camera's world-space eye position from the view matrix and writes it into
|
|
15
|
+
// `out`. For an orthonormal view matrix (rotation + translation), the eye position is
|
|
16
|
+
// computed as the inverse translation without a full matrix inversion:
|
|
17
|
+
// eye = -(R^T · t) where R is the upper-3x3 and t is m[12..14] of the view.
|
|
18
|
+
//
|
|
19
|
+
// This is the canonical source for the camera eye position; the scene-gl mesh renderer
|
|
20
|
+
// (setGlMeshCameraPosition) should delegate here rather than recomputing it inline.
|
|
21
|
+
//
|
|
22
|
+
// Safe when `out` aliases any field of the camera.
|
|
23
|
+
export function getCameraPosition(out, camera) {
|
|
24
|
+
const m = camera.view.m;
|
|
25
|
+
// Column-major storage: element(row, col) = m[row + 4*col].
|
|
26
|
+
// The 3×3 rotation block R^T (transposed) has rows:
|
|
27
|
+
// row 0: m[0], m[1], m[2] (column 0 of R = right x-components)
|
|
28
|
+
// row 1: m[4], m[5], m[6] (column 1 of R = up y-components ... wait, this is col 1 of R)
|
|
29
|
+
// Actually R^T column 0 = R row 0 = [m[0], m[4], m[8]], but the inverse translation is:
|
|
30
|
+
// eye = -(R^T · t)
|
|
31
|
+
// (R^T · t).x = m[0]*m[12] + m[1]*m[13] + m[2]*m[14]
|
|
32
|
+
// (R^T · t).y = m[4]*m[12] + m[5]*m[13] + m[6]*m[14]
|
|
33
|
+
// (R^T · t).z = m[8]*m[12] + m[9]*m[13] + m[10]*m[14]
|
|
34
|
+
const m00 = m[0], m01 = m[1], m02 = m[2];
|
|
35
|
+
const m10 = m[4], m11 = m[5], m12 = m[6];
|
|
36
|
+
const m20 = m[8], m21 = m[9], m22 = m[10];
|
|
37
|
+
const tx = m[12], ty = m[13], tz = m[14];
|
|
38
|
+
// Read all inputs before writing (alias-safe).
|
|
39
|
+
out.x = -(m00 * tx + m01 * ty + m02 * tz);
|
|
40
|
+
out.y = -(m10 * tx + m11 * ty + m12 * tz);
|
|
41
|
+
out.z = -(m20 * tx + m21 * ty + m22 * tz);
|
|
42
|
+
}
|
|
43
|
+
// Extracts the camera's world-space right direction (+X of the camera frame) from the view
|
|
44
|
+
// matrix and writes it into `out`. It is the first row of the view matrix.
|
|
45
|
+
//
|
|
46
|
+
// Safe when `out` aliases any field of the camera.
|
|
47
|
+
export function getCameraRight(out, camera) {
|
|
48
|
+
const m = camera.view.m;
|
|
49
|
+
out.x = m[0];
|
|
50
|
+
out.y = m[4];
|
|
51
|
+
out.z = m[8];
|
|
52
|
+
}
|
|
53
|
+
// Extracts the camera's world-space up direction (+Y of the camera frame) from the view
|
|
54
|
+
// matrix and writes it into `out`. It is the second row of the view matrix.
|
|
55
|
+
//
|
|
56
|
+
// Safe when `out` aliases any field of the camera.
|
|
57
|
+
export function getCameraUp(out, camera) {
|
|
58
|
+
const m = camera.view.m;
|
|
59
|
+
out.x = m[1];
|
|
60
|
+
out.y = m[5];
|
|
61
|
+
out.z = m[9];
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=basis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basis.js","sourceRoot":"","sources":["../src/basis.ts"],"names":[],"mappings":"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"}
|
package/dist/camera.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Camera, Matrix4Like, Projection, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function createCamera(opts: Readonly<CameraOptions>): Camera;
|
|
3
|
+
export declare function getCameraInverseViewProjectionMatrix4(out: Matrix4Like, camera: Readonly<Camera>, aspect: number): boolean;
|
|
4
|
+
export declare function getCameraViewProjectionMatrix4(out: Matrix4Like, camera: Readonly<Camera>, aspect: number): void;
|
|
5
|
+
export declare function setCameraJitter(camera: Camera, x: number, y: number): void;
|
|
6
|
+
export declare function setCameraViewMatrix4FromLookAt(camera: Camera, eye: Readonly<Vector3Like>, target: Readonly<Vector3Like>, up: Readonly<Vector3Like>): void;
|
|
7
|
+
export declare function setCameraViewMatrix4FromMatrix4(camera: Camera, view: Readonly<Matrix4Like>): void;
|
|
8
|
+
export declare function updateCameraInverseViewProjection(camera: Camera, aspect: number): boolean;
|
|
9
|
+
export interface CameraOptions {
|
|
10
|
+
far: number;
|
|
11
|
+
near: number;
|
|
12
|
+
projection: Projection;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAUpF,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,MAAM,CASlE;AAUD,wBAAgB,qCAAqC,CACnD,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAGT;AAQD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/G;AAID,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAG1E;AAOD,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC1B,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC7B,EAAE,EAAE,QAAQ,CAAC,WAAW,CAAC,GACxB,IAAI,CAEN;AAID,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAEjG;AAQD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOzF;AAGD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;CACxB"}
|
package/dist/camera.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createEntity } from '@flighthq/entity';
|
|
2
|
+
import { createMatrix4, createVector2, inverseMatrix4, multiplyMatrix4, setMatrix4LookAt } from '@flighthq/geometry';
|
|
3
|
+
import { setProjectionMatrix4 } from './projection';
|
|
4
|
+
// Allocates a 3D camera. The camera stores its projection descriptor, a world->view Matrix4
|
|
5
|
+
// (`view`, initialized to identity), the clip-plane distances `near`/`far`, the per-frame
|
|
6
|
+
// sub-pixel NDC `jitter` (consumed by TAA, initialized to zero), and a cached
|
|
7
|
+
// `inverseViewProjection` (consumed by TAA / velocity / fog / depth-of-field, initialized to
|
|
8
|
+
// identity). The view matrix is canonical: the camera has no separate Transform3D — a Matrix4 is
|
|
9
|
+
// the only world->view representation.
|
|
10
|
+
export function createCamera(opts) {
|
|
11
|
+
return createEntity({
|
|
12
|
+
far: opts.far,
|
|
13
|
+
inverseViewProjection: createMatrix4(),
|
|
14
|
+
jitter: createVector2(0, 0),
|
|
15
|
+
near: opts.near,
|
|
16
|
+
projection: opts.projection,
|
|
17
|
+
view: createMatrix4(),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Writes the inverse of the camera's view-projection matrix into `out` and returns true, or
|
|
21
|
+
// returns false (writing NaN into `out`) when the view-projection is non-invertible. `aspect`
|
|
22
|
+
// is the viewport width / height. This is the matrix the existing TAA / velocity / fog /
|
|
23
|
+
// depth-of-field effects consume to reconstruct world position from NDC.
|
|
24
|
+
//
|
|
25
|
+
// Reads camera fields into a scratch matrix before writing `out`, so it is safe even if `out`
|
|
26
|
+
// aliases the camera's own `inverseViewProjection` or `view`. Use
|
|
27
|
+
// `updateCameraInverseViewProjection` instead to safely update the cached field.
|
|
28
|
+
export function getCameraInverseViewProjectionMatrix4(out, camera, aspect) {
|
|
29
|
+
getCameraViewProjectionMatrix4(__scratchViewProjection, camera, aspect);
|
|
30
|
+
return inverseMatrix4(out, __scratchViewProjection);
|
|
31
|
+
}
|
|
32
|
+
// Writes the camera's view-projection matrix (projection × view) into `out`. `aspect` is the
|
|
33
|
+
// viewport width / height, applied to a perspective projection. `near`/`far` are taken from the
|
|
34
|
+
// camera.
|
|
35
|
+
//
|
|
36
|
+
// Reads camera fields into a scratch matrix before writing `out`, so it is safe even if `out`
|
|
37
|
+
// aliases the camera's own `view`.
|
|
38
|
+
export function getCameraViewProjectionMatrix4(out, camera, aspect) {
|
|
39
|
+
setProjectionMatrix4(__scratchProjection, camera.projection, aspect, camera.near, camera.far);
|
|
40
|
+
multiplyMatrix4(out, __scratchProjection, camera.view);
|
|
41
|
+
}
|
|
42
|
+
// Sets the camera's per-frame sub-pixel jitter offset (in NDC), in place. TAA reads this when
|
|
43
|
+
// building the jittered projection matrix.
|
|
44
|
+
export function setCameraJitter(camera, x, y) {
|
|
45
|
+
camera.jitter.x = x;
|
|
46
|
+
camera.jitter.y = y;
|
|
47
|
+
}
|
|
48
|
+
// Builds the camera's world->view matrix in place from an eye position, a look-at target, and an
|
|
49
|
+
// up vector (right-handed look-at). This is the common path for positioning a camera without an
|
|
50
|
+
// explicit world transform.
|
|
51
|
+
//
|
|
52
|
+
// Reads all vector inputs before writing, so it is safe when the vectors alias one another.
|
|
53
|
+
export function setCameraViewMatrix4FromLookAt(camera, eye, target, up) {
|
|
54
|
+
setMatrix4LookAt(camera.view, eye, target, up);
|
|
55
|
+
}
|
|
56
|
+
// Copies a precomputed world->view matrix into the camera in place. Use this when the view matrix
|
|
57
|
+
// is derived elsewhere (for example, the inverse of a scene node's world transform).
|
|
58
|
+
export function setCameraViewMatrix4FromMatrix4(camera, view) {
|
|
59
|
+
camera.view.m.set(view.m);
|
|
60
|
+
}
|
|
61
|
+
// Recomputes and stores the inverse view-projection into camera.inverseViewProjection for the
|
|
62
|
+
// given aspect. Returns true on success or false when the matrix is non-invertible (leaving the
|
|
63
|
+
// cached field untouched). `aspect` is viewport width / height.
|
|
64
|
+
//
|
|
65
|
+
// Call this once per frame after setting the view matrix and before any effects that read
|
|
66
|
+
// camera.inverseViewProjection (TAA, velocity, fog, depth-of-field).
|
|
67
|
+
export function updateCameraInverseViewProjection(camera, aspect) {
|
|
68
|
+
// Write into a scratch first so the cache is never clobbered with NaN on failure.
|
|
69
|
+
const ok = getCameraInverseViewProjectionMatrix4(__scratchInverse, camera, aspect);
|
|
70
|
+
if (ok) {
|
|
71
|
+
camera.inverseViewProjection.m.set(__scratchInverse.m);
|
|
72
|
+
}
|
|
73
|
+
return ok;
|
|
74
|
+
}
|
|
75
|
+
// Scratch matrices reused by the view-projection helpers. Single-threaded; not re-entrant.
|
|
76
|
+
const __scratchInverse = createMatrix4();
|
|
77
|
+
const __scratchProjection = createMatrix4();
|
|
78
|
+
const __scratchViewProjection = createMatrix4();
|
|
79
|
+
//# sourceMappingURL=camera.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AabbLike, BoundingSphereLike, Camera, FrustumLike, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraFrustum(out: FrustumLike, camera: Readonly<Camera>, aspect: number): void;
|
|
3
|
+
export declare function isBoxInCameraFrustum(camera: Readonly<Camera>, aabb: Readonly<AabbLike>, aspect: number): boolean;
|
|
4
|
+
export declare function isPointInCameraFrustum(camera: Readonly<Camera>, point: Readonly<Vector3Like>, aspect: number): boolean;
|
|
5
|
+
export declare function isSphereInCameraFrustum(camera: Readonly<Camera>, sphere: Readonly<BoundingSphereLike>, aspect: number): boolean;
|
|
6
|
+
//# sourceMappingURL=culling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"culling.d.ts","sourceRoot":"","sources":["../src/culling.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAYtG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAGjG;AAOD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGhH;AAID,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAGT;AAID,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAGT"}
|
package/dist/culling.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createFrustum, createMatrix4, isFrustumContainingPoint, isFrustumIntersectingAabb, isFrustumIntersectingSphere, setFrustumFromMatrix4, } from '@flighthq/geometry';
|
|
2
|
+
import { getCameraViewProjectionMatrix4 } from './camera';
|
|
3
|
+
// Extracts the six clip planes of the camera's view frustum into `out` and returns true.
|
|
4
|
+
// The planes are normalized with inward-pointing normals (the convention used by geometry's
|
|
5
|
+
// isFrustumContainingPoint / isFrustumIntersectingAabb / isFrustumIntersectingSphere).
|
|
6
|
+
// `aspect` is viewport width / height.
|
|
7
|
+
//
|
|
8
|
+
// Use this when you need the raw planes (e.g. to cache the frustum for a frame). For one-shot
|
|
9
|
+
// culling queries prefer the isBoxInCameraFrustum / isSphereInCameraFrustum / isPointInCameraFrustum
|
|
10
|
+
// helpers which reuse a single scratch frustum.
|
|
11
|
+
export function getCameraFrustum(out, camera, aspect) {
|
|
12
|
+
getCameraViewProjectionMatrix4(__scratchViewProjection, camera, aspect);
|
|
13
|
+
setFrustumFromMatrix4(out, __scratchViewProjection);
|
|
14
|
+
}
|
|
15
|
+
// Returns true when an axis-aligned bounding box intersects or is contained by the camera
|
|
16
|
+
// frustum. A box outside any frustum plane is rejected. `aspect` is viewport width / height.
|
|
17
|
+
//
|
|
18
|
+
// Uses the same conservative positive-vertex test as geometry's isFrustumIntersectingAabb:
|
|
19
|
+
// may report false positives for boxes straddling a frustum corner, never false negatives.
|
|
20
|
+
export function isBoxInCameraFrustum(camera, aabb, aspect) {
|
|
21
|
+
getCameraFrustum(__scratchFrustum, camera, aspect);
|
|
22
|
+
return isFrustumIntersectingAabb(__scratchFrustum, aabb);
|
|
23
|
+
}
|
|
24
|
+
// Returns true when a world-space point lies inside the camera frustum.
|
|
25
|
+
// `aspect` is viewport width / height.
|
|
26
|
+
export function isPointInCameraFrustum(camera, point, aspect) {
|
|
27
|
+
getCameraFrustum(__scratchFrustum, camera, aspect);
|
|
28
|
+
return isFrustumContainingPoint(__scratchFrustum, point);
|
|
29
|
+
}
|
|
30
|
+
// Returns true when a bounding sphere intersects or is contained by the camera frustum.
|
|
31
|
+
// An empty sphere (negative radius) always returns false. `aspect` is viewport width / height.
|
|
32
|
+
export function isSphereInCameraFrustum(camera, sphere, aspect) {
|
|
33
|
+
getCameraFrustum(__scratchFrustum, camera, aspect);
|
|
34
|
+
return isFrustumIntersectingSphere(__scratchFrustum, sphere);
|
|
35
|
+
}
|
|
36
|
+
// Scratch objects reused across calls. Single-threaded; not re-entrant.
|
|
37
|
+
const __scratchViewProjection = createMatrix4();
|
|
38
|
+
const __scratchFrustum = createFrustum();
|
|
39
|
+
//# sourceMappingURL=culling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"culling.js","sourceRoot":"","sources":["../src/culling.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAE1D,yFAAyF;AACzF,4FAA4F;AAC5F,uFAAuF;AACvF,uCAAuC;AACvC,EAAE;AACF,8FAA8F;AAC9F,qGAAqG;AACrG,gDAAgD;AAChD,MAAM,UAAU,gBAAgB,CAAC,GAAgB,EAAE,MAAwB,EAAE,MAAc;IACzF,8BAA8B,CAAC,uBAAuB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxE,qBAAqB,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;AACtD,CAAC;AAED,0FAA0F;AAC1F,6FAA6F;AAC7F,EAAE;AACF,2FAA2F;AAC3F,2FAA2F;AAC3F,MAAM,UAAU,oBAAoB,CAAC,MAAwB,EAAE,IAAwB,EAAE,MAAc;IACrG,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,yBAAyB,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,wEAAwE;AACxE,uCAAuC;AACvC,MAAM,UAAU,sBAAsB,CACpC,MAAwB,EACxB,KAA4B,EAC5B,MAAc;IAEd,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,wBAAwB,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,wFAAwF;AACxF,+FAA+F;AAC/F,MAAM,UAAU,uBAAuB,CACrC,MAAwB,EACxB,MAAoC,EACpC,MAAc;IAEd,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,OAAO,2BAA2B,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,wEAAwE;AACxE,MAAM,uBAAuB,GAAG,aAAa,EAAE,CAAC;AAChD,MAAM,gBAAgB,GAAG,aAAa,EAAE,CAAC"}
|
package/dist/depth.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Camera } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraLinearDepth(camera: Readonly<Camera>, ndcZ: number): number;
|
|
3
|
+
export declare function getCameraViewSpaceZ(camera: Readonly<Camera>, ndcZ: number): number;
|
|
4
|
+
//# sourceMappingURL=depth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"depth.d.ts","sourceRoot":"","sources":["../src/depth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAc9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBnF;AAOD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAElF"}
|
package/dist/depth.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Converts a raw NDC depth value (ndcZ ∈ [-1, 1]) from the camera's projection back to a linear
|
|
2
|
+
// view-space Z value (distance from the camera along its -Z axis). Returns a negative value for a
|
|
3
|
+
// point in front of the camera (standard right-handed convention where the camera looks toward -Z).
|
|
4
|
+
//
|
|
5
|
+
// For perspective projection the NDC depth is non-linear; this undoes that non-linearity using the
|
|
6
|
+
// camera's near/far clip planes. For orthographic projection the depth is already linear, so the
|
|
7
|
+
// same formula still applies but the result is a simple remap.
|
|
8
|
+
//
|
|
9
|
+
// `ndcZ` should be in [-1, 1] (OpenGL depth convention). Values outside that range are clamped
|
|
10
|
+
// mathematically — no explicit clamp is applied; callers should supply valid NDC depths.
|
|
11
|
+
//
|
|
12
|
+
// Returns 0 when `near` equals `far` (degenerate clip range).
|
|
13
|
+
export function getCameraLinearDepth(camera, ndcZ) {
|
|
14
|
+
const near = camera.near;
|
|
15
|
+
const far = camera.far;
|
|
16
|
+
const range = far - near;
|
|
17
|
+
if (range === 0) {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
// Map ndcZ from [-1, 1] back to the view-space Z for a perspective projection.
|
|
21
|
+
// Derived from the perspective depth mapping:
|
|
22
|
+
// ndcZ = (far + near) / (near - far) + (2 * far * near) / ((near - far) * viewZ)
|
|
23
|
+
// Solving for viewZ:
|
|
24
|
+
// viewZ = (2 * far * near) / ((ndcZ * (far - near)) - (far + near))
|
|
25
|
+
const denominator = ndcZ * range - (far + near);
|
|
26
|
+
if (denominator === 0) {
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
return (2 * far * near) / denominator;
|
|
30
|
+
}
|
|
31
|
+
// Converts a raw NDC depth value (ndcZ ∈ [-1, 1]) to a positive linear depth in [near, far] —
|
|
32
|
+
// the distance along the camera's view axis. This is the unsigned version of getCameraLinearDepth,
|
|
33
|
+
// useful for fog and SSAO where a positive scalar distance is needed rather than a signed Z.
|
|
34
|
+
//
|
|
35
|
+
// Returns 0 when `near` equals `far` (degenerate clip range).
|
|
36
|
+
export function getCameraViewSpaceZ(camera, ndcZ) {
|
|
37
|
+
return -getCameraLinearDepth(camera, ndcZ);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=depth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"depth.js","sourceRoot":"","sources":["../src/depth.ts"],"names":[],"mappings":"AAEA,gGAAgG;AAChG,kGAAkG;AAClG,oGAAoG;AACpG,EAAE;AACF,mGAAmG;AACnG,iGAAiG;AACjG,+DAA+D;AAC/D,EAAE;AACF,+FAA+F;AAC/F,yFAAyF;AACzF,EAAE;AACF,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,MAAwB,EAAE,IAAY;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACvB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC;IACzB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,+EAA+E;IAC/E,8CAA8C;IAC9C,mFAAmF;IACnF,qBAAqB;IACrB,sEAAsE;IACtE,MAAM,WAAW,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAChD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;AACxC,CAAC;AAED,8FAA8F;AAC9F,mGAAmG;AACnG,6FAA6F;AAC7F,EAAE;AACF,8DAA8D;AAC9D,MAAM,UAAU,mBAAmB,CAAC,MAAwB,EAAE,IAAY;IACxE,OAAO,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Camera, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraFrustumCorners(out: [Vector3Like, Vector3Like, Vector3Like, Vector3Like, Vector3Like, Vector3Like, Vector3Like, Vector3Like], camera: Readonly<Camera>, aspect: number): boolean;
|
|
3
|
+
//# sourceMappingURL=frustumCorners.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frustumCorners.d.ts","sourceRoot":"","sources":["../src/frustumCorners.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAoB3D,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,EAC7G,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAyCT"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createMatrix4, inverseMatrix4 } from '@flighthq/geometry';
|
|
2
|
+
import { getCameraViewProjectionMatrix4 } from './camera';
|
|
3
|
+
// Writes the 8 world-space corners of the camera frustum into `out` (a length-8 array of
|
|
4
|
+
// Vector3Like) and returns true. Returns false (leaving `out` untouched) when the
|
|
5
|
+
// view-projection is non-invertible. `aspect` is viewport width / height.
|
|
6
|
+
//
|
|
7
|
+
// Corner ordering (NDC cube vertices, rows = near then far):
|
|
8
|
+
// 0: (-1, -1, -1) near bottom-left
|
|
9
|
+
// 1: ( 1, -1, -1) near bottom-right
|
|
10
|
+
// 2: (-1, 1, -1) near top-left
|
|
11
|
+
// 3: ( 1, 1, -1) near top-right
|
|
12
|
+
// 4: (-1, -1, 1) far bottom-left
|
|
13
|
+
// 5: ( 1, -1, 1) far bottom-right
|
|
14
|
+
// 6: (-1, 1, 1) far top-left
|
|
15
|
+
// 7: ( 1, 1, 1) far top-right
|
|
16
|
+
//
|
|
17
|
+
// Needed for cascaded shadow maps, debug draw, and tight bounds fitting.
|
|
18
|
+
// Reads all inputs before writing any `out` element, so it is alias-safe.
|
|
19
|
+
export function getCameraFrustumCorners(out, camera, aspect) {
|
|
20
|
+
getCameraViewProjectionMatrix4(__scratchViewProjection, camera, aspect);
|
|
21
|
+
if (!inverseMatrix4(__scratchInverseVP, __scratchViewProjection)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const m = __scratchInverseVP.m;
|
|
25
|
+
// Unproject each NDC corner through the inverse view-projection, applying
|
|
26
|
+
// the perspective divide. All results are computed before writing to out.
|
|
27
|
+
const ndcCorners = [
|
|
28
|
+
[-1, -1, -1],
|
|
29
|
+
[1, -1, -1],
|
|
30
|
+
[-1, 1, -1],
|
|
31
|
+
[1, 1, -1],
|
|
32
|
+
[-1, -1, 1],
|
|
33
|
+
[1, -1, 1],
|
|
34
|
+
[-1, 1, 1],
|
|
35
|
+
[1, 1, 1],
|
|
36
|
+
];
|
|
37
|
+
// Compute all 8 corners into temporaries before writing.
|
|
38
|
+
const results = [];
|
|
39
|
+
for (let i = 0; i < 8; i++) {
|
|
40
|
+
const [nx, ny, nz] = ndcCorners[i];
|
|
41
|
+
let wx = m[0] * nx + m[4] * ny + m[8] * nz + m[12];
|
|
42
|
+
let wy = m[1] * nx + m[5] * ny + m[9] * nz + m[13];
|
|
43
|
+
let wz = m[2] * nx + m[6] * ny + m[10] * nz + m[14];
|
|
44
|
+
const ww = m[3] * nx + m[7] * ny + m[11] * nz + m[15];
|
|
45
|
+
if (ww !== 0) {
|
|
46
|
+
const invW = 1 / ww;
|
|
47
|
+
wx *= invW;
|
|
48
|
+
wy *= invW;
|
|
49
|
+
wz *= invW;
|
|
50
|
+
}
|
|
51
|
+
results.push([wx, wy, wz]);
|
|
52
|
+
}
|
|
53
|
+
// Write all results to output.
|
|
54
|
+
for (let i = 0; i < 8; i++) {
|
|
55
|
+
out[i].x = results[i][0];
|
|
56
|
+
out[i].y = results[i][1];
|
|
57
|
+
out[i].z = results[i][2];
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
// Scratch objects reused across calls. Single-threaded; not re-entrant.
|
|
62
|
+
const __scratchViewProjection = createMatrix4();
|
|
63
|
+
const __scratchInverseVP = createMatrix4();
|
|
64
|
+
//# sourceMappingURL=frustumCorners.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frustumCorners.js","sourceRoot":"","sources":["../src/frustumCorners.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './basis';
|
|
2
|
+
export * from './camera';
|
|
3
|
+
export * from './culling';
|
|
4
|
+
export * from './depth';
|
|
5
|
+
export * from './frustumCorners';
|
|
6
|
+
export * from './intersection';
|
|
7
|
+
export * from './picking';
|
|
8
|
+
export * from './projection';
|
|
9
|
+
export * from './shadowCamera';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './basis';
|
|
2
|
+
export * from './camera';
|
|
3
|
+
export * from './culling';
|
|
4
|
+
export * from './depth';
|
|
5
|
+
export * from './frustumCorners';
|
|
6
|
+
export * from './intersection';
|
|
7
|
+
export * from './picking';
|
|
8
|
+
export * from './projection';
|
|
9
|
+
export * from './shadowCamera';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BoundingSphereLike, Camera, PlaneLike, Ray3DLike, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraRayThroughBoundingSphere(out: Ray3DLike, camera: Readonly<Camera>, sphere: Readonly<BoundingSphereLike>, aspect: number): boolean;
|
|
3
|
+
export declare function intersectCameraRayWithPlane(out: Vector3Like, ray: Readonly<Ray3DLike>, plane: Readonly<PlaneLike>): boolean;
|
|
4
|
+
//# sourceMappingURL=intersection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intersection.d.ts","sourceRoot":"","sources":["../src/intersection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAiBrG,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAUT;AAgBD,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,EACxB,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,GACzB,OAAO,CA0BT"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { getCameraScreenToWorldRay, getCameraWorldToScreen } from './picking';
|
|
2
|
+
// Returns the world-space ray from the camera through the center of a bounding sphere, writing
|
|
3
|
+
// the result into `out` and returning true. The ray is suitable for picking and hover-highlight
|
|
4
|
+
// queries: it passes through the screen-space projection of the sphere center, and represents
|
|
5
|
+
// "the ray a user would cast toward this sphere's center from the camera."
|
|
6
|
+
//
|
|
7
|
+
// Returns false when:
|
|
8
|
+
// - The sphere is empty (negative radius).
|
|
9
|
+
// - The sphere center is at or behind the camera (w <= 0 in clip space).
|
|
10
|
+
// - The view-projection is non-invertible.
|
|
11
|
+
//
|
|
12
|
+
// The ray direction is normalized. `aspect` is viewport width / height.
|
|
13
|
+
//
|
|
14
|
+
// Reads all inputs before writing `out`, so it is alias-safe.
|
|
15
|
+
export function getCameraRayThroughBoundingSphere(out, camera, sphere, aspect) {
|
|
16
|
+
if (sphere.radius < 0) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
// Project sphere center to NDC.
|
|
20
|
+
if (!getCameraWorldToScreen(__scratchNdc, camera, sphere.center, aspect)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
// Unproject those NDC coords back to a world-space ray.
|
|
24
|
+
return getCameraScreenToWorldRay(out, camera, __scratchNdc.x, __scratchNdc.y, aspect);
|
|
25
|
+
}
|
|
26
|
+
// Computes the intersection of a ray with an infinite plane, writing the hit point into `out`
|
|
27
|
+
// and returning true. Returns false when:
|
|
28
|
+
// - The ray direction is parallel to the plane (dot(normal, direction) = 0).
|
|
29
|
+
// - The intersection is behind the ray origin (t < 0).
|
|
30
|
+
// - The plane normal is zero.
|
|
31
|
+
//
|
|
32
|
+
// The plane is given in the standard Flight form: a·x + b·y + c·z + d = 0. The normal (a, b, c)
|
|
33
|
+
// does not need to be unit length. The ray direction does not need to be unit length either.
|
|
34
|
+
//
|
|
35
|
+
// This is not specific to a camera but lives here as an ergonomic companion to
|
|
36
|
+
// `getCameraScreenToWorldRay`: cast a ray from mouse position, intersect with a ground plane,
|
|
37
|
+
// and you have world-space mouse drag.
|
|
38
|
+
//
|
|
39
|
+
// Reads all inputs before writing `out`, so it is alias-safe.
|
|
40
|
+
export function intersectCameraRayWithPlane(out, ray, plane) {
|
|
41
|
+
const dx = ray.direction.x;
|
|
42
|
+
const dy = ray.direction.y;
|
|
43
|
+
const dz = ray.direction.z;
|
|
44
|
+
const ox = ray.origin.x;
|
|
45
|
+
const oy = ray.origin.y;
|
|
46
|
+
const oz = ray.origin.z;
|
|
47
|
+
const a = plane.a;
|
|
48
|
+
const b = plane.b;
|
|
49
|
+
const c = plane.c;
|
|
50
|
+
const d = plane.d;
|
|
51
|
+
// denom = dot(normal, direction)
|
|
52
|
+
const denom = a * dx + b * dy + c * dz;
|
|
53
|
+
if (denom === 0) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// t = -(dot(normal, origin) + d) / denom
|
|
57
|
+
const t = -(a * ox + b * oy + c * oz + d) / denom;
|
|
58
|
+
if (t < 0) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
// Hit point: origin + t * direction. Read all inputs first (already done into locals above).
|
|
62
|
+
out.x = ox + t * dx;
|
|
63
|
+
out.y = oy + t * dy;
|
|
64
|
+
out.z = oz + t * dz;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
// Scratch for NDC projection result. Single-threaded; not re-entrant.
|
|
68
|
+
const __scratchNdc = { x: 0, y: 0, z: 0 };
|
|
69
|
+
//# sourceMappingURL=intersection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intersection.js","sourceRoot":"","sources":["../src/intersection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAE9E,+FAA+F;AAC/F,gGAAgG;AAChG,8FAA8F;AAC9F,2EAA2E;AAC3E,EAAE;AACF,sBAAsB;AACtB,6CAA6C;AAC7C,2EAA2E;AAC3E,6CAA6C;AAC7C,EAAE;AACF,wEAAwE;AACxE,EAAE;AACF,8DAA8D;AAC9D,MAAM,UAAU,iCAAiC,CAC/C,GAAc,EACd,MAAwB,EACxB,MAAoC,EACpC,MAAc;IAEd,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,gCAAgC;IAChC,IAAI,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,wDAAwD;IACxD,OAAO,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACxF,CAAC;AAED,8FAA8F;AAC9F,0CAA0C;AAC1C,+EAA+E;AAC/E,yDAAyD;AACzD,gCAAgC;AAChC,EAAE;AACF,gGAAgG;AAChG,6FAA6F;AAC7F,EAAE;AACF,+EAA+E;AAC/E,8FAA8F;AAC9F,uCAAuC;AACvC,EAAE;AACF,8DAA8D;AAC9D,MAAM,UAAU,2BAA2B,CACzC,GAAgB,EAChB,GAAwB,EACxB,KAA0B;IAE1B,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAClB,iCAAiC;IACjC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACvC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,yCAAyC;IACzC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAClD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;IACD,6FAA6F;IAC7F,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACpB,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACpB,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;IACpB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sEAAsE;AACtE,MAAM,YAAY,GAAgB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Camera, Ray3DLike, Vector3Like } from '@flighthq/types';
|
|
2
|
+
export declare function getCameraScreenToWorldRay(out: Ray3DLike, camera: Readonly<Camera>, ndcX: number, ndcY: number, aspect: number): boolean;
|
|
3
|
+
export declare function getCameraWorldToScreen(out: Vector3Like, camera: Readonly<Camera>, worldPoint: Readonly<Vector3Like>, aspect: number): boolean;
|
|
4
|
+
//# sourceMappingURL=picking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picking.d.ts","sourceRoot":"","sources":["../src/picking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AActE,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CA8CT;AAUD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,UAAU,EAAE,QAAQ,CAAC,WAAW,CAAC,EACjC,MAAM,EAAE,MAAM,GACb,OAAO,CAkBT"}
|
package/dist/picking.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { createMatrix4, createVector3, inverseMatrix4, normalizeVector3, subtractVector3 } from '@flighthq/geometry';
|
|
2
|
+
import { getCameraViewProjectionMatrix4 } from './camera';
|
|
3
|
+
// Writes the world-space ray from the camera through an NDC screen point (ndcX, ndcY) into
|
|
4
|
+
// `out` and returns true, or returns false (leaving `out` untouched) when the view-projection
|
|
5
|
+
// is non-invertible. NDC coordinates range from -1 to +1 on both axes (center = 0, top-right =
|
|
6
|
+
// (1, 1)). `aspect` is viewport width / height.
|
|
7
|
+
//
|
|
8
|
+
// The returned ray origin is the near-plane world position and the direction is the normalized
|
|
9
|
+
// world-space direction from near through far. Use this for mouse picking, drag raycasts, and
|
|
10
|
+
// any screen-to-world query.
|
|
11
|
+
//
|
|
12
|
+
// Reads all inputs into locals before writing `out`, so it is alias-safe.
|
|
13
|
+
export function getCameraScreenToWorldRay(out, camera, ndcX, ndcY, aspect) {
|
|
14
|
+
getCameraViewProjectionMatrix4(__scratchViewProjection, camera, aspect);
|
|
15
|
+
if (!inverseMatrix4(__scratchInverseVP, __scratchViewProjection)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const m = __scratchInverseVP.m;
|
|
19
|
+
const nx = ndcX, ny = ndcY;
|
|
20
|
+
// Unproject near-plane point (ndcX, ndcY, -1, 1) through the inverse view-projection.
|
|
21
|
+
let nearX = m[0] * nx + m[4] * ny + m[8] * -1 + m[12];
|
|
22
|
+
let nearY = m[1] * nx + m[5] * ny + m[9] * -1 + m[13];
|
|
23
|
+
let nearZ = m[2] * nx + m[6] * ny + m[10] * -1 + m[14];
|
|
24
|
+
const nearW = m[3] * nx + m[7] * ny + m[11] * -1 + m[15];
|
|
25
|
+
if (nearW !== 0) {
|
|
26
|
+
const invW = 1 / nearW;
|
|
27
|
+
nearX *= invW;
|
|
28
|
+
nearY *= invW;
|
|
29
|
+
nearZ *= invW;
|
|
30
|
+
}
|
|
31
|
+
// Unproject far-plane point (ndcX, ndcY, 1, 1).
|
|
32
|
+
let farX = m[0] * nx + m[4] * ny + m[8] + m[12];
|
|
33
|
+
let farY = m[1] * nx + m[5] * ny + m[9] + m[13];
|
|
34
|
+
let farZ = m[2] * nx + m[6] * ny + m[10] + m[14];
|
|
35
|
+
const farW = m[3] * nx + m[7] * ny + m[11] + m[15];
|
|
36
|
+
if (farW !== 0) {
|
|
37
|
+
const invW = 1 / farW;
|
|
38
|
+
farX *= invW;
|
|
39
|
+
farY *= invW;
|
|
40
|
+
farZ *= invW;
|
|
41
|
+
}
|
|
42
|
+
// Direction: from near to far, normalized.
|
|
43
|
+
__scratchNear.x = nearX;
|
|
44
|
+
__scratchNear.y = nearY;
|
|
45
|
+
__scratchNear.z = nearZ;
|
|
46
|
+
__scratchFar.x = farX;
|
|
47
|
+
__scratchFar.y = farY;
|
|
48
|
+
__scratchFar.z = farZ;
|
|
49
|
+
subtractVector3(__scratchDir, __scratchFar, __scratchNear);
|
|
50
|
+
normalizeVector3(__scratchDir, __scratchDir);
|
|
51
|
+
out.origin.x = nearX;
|
|
52
|
+
out.origin.y = nearY;
|
|
53
|
+
out.origin.z = nearZ;
|
|
54
|
+
out.direction.x = __scratchDir.x;
|
|
55
|
+
out.direction.y = __scratchDir.y;
|
|
56
|
+
out.direction.z = __scratchDir.z;
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
// Writes the NDC coordinates (x, y ∈ [-1, 1], z = clip-space depth) of a world-space point
|
|
60
|
+
// into `out` and returns true, or returns false (leaving `out` untouched) when the point is
|
|
61
|
+
// behind the camera (w <= 0) or when the perspective divide yields a degenerate result.
|
|
62
|
+
// `aspect` is viewport width / height.
|
|
63
|
+
//
|
|
64
|
+
// Use this to anchor HUD elements, labels, and gizmos to world positions.
|
|
65
|
+
//
|
|
66
|
+
// Reads all inputs into locals before writing `out`, so it is alias-safe.
|
|
67
|
+
export function getCameraWorldToScreen(out, camera, worldPoint, aspect) {
|
|
68
|
+
getCameraViewProjectionMatrix4(__scratchViewProjection, camera, aspect);
|
|
69
|
+
const m = __scratchViewProjection.m;
|
|
70
|
+
const wx = worldPoint.x, wy = worldPoint.y, wz = worldPoint.z;
|
|
71
|
+
const clipX = m[0] * wx + m[4] * wy + m[8] * wz + m[12];
|
|
72
|
+
const clipY = m[1] * wx + m[5] * wy + m[9] * wz + m[13];
|
|
73
|
+
const clipZ = m[2] * wx + m[6] * wy + m[10] * wz + m[14];
|
|
74
|
+
const clipW = m[3] * wx + m[7] * wy + m[11] * wz + m[15];
|
|
75
|
+
if (clipW <= 0) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const invW = 1 / clipW;
|
|
79
|
+
out.x = clipX * invW;
|
|
80
|
+
out.y = clipY * invW;
|
|
81
|
+
out.z = clipZ * invW;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
// Scratch objects reused across calls. Single-threaded; not re-entrant.
|
|
85
|
+
const __scratchViewProjection = createMatrix4();
|
|
86
|
+
const __scratchInverseVP = createMatrix4();
|
|
87
|
+
const __scratchNear = createVector3();
|
|
88
|
+
const __scratchFar = createVector3();
|
|
89
|
+
const __scratchDir = createVector3();
|
|
90
|
+
//# sourceMappingURL=picking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picking.js","sourceRoot":"","sources":["../src/picking.ts"],"names":[],"mappings":"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"}
|