three-zoo 0.4.1 → 0.4.3

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/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # three-zoo
2
+
3
+ A few Three.js utilities to handle common 3D tasks.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install three-zoo
9
+ ```
10
+
11
+ ## Tools
12
+
13
+ ### BiFovCamera
14
+
15
+ Camera with separate horizontal and vertical FOV control:
16
+
17
+ ```typescript
18
+ const camera = new BiFovCamera(90, 60); // hFov, vFov
19
+ camera.horizontalFov = 100; // Change horizontal FOV
20
+ camera.verticalFov = 70; // Change vertical FOV
21
+ ```
22
+
23
+ ### Bounds
24
+
25
+ Extra bounding box calculations:
26
+
27
+ ```typescript
28
+ const bounds = new Bounds(mesh);
29
+ console.log(bounds.width); // x-axis length
30
+ console.log(bounds.depth); // z-axis length
31
+ console.log(bounds.getVolume()); // volume
32
+ ```
33
+
34
+ ### InstanceAssembler
35
+
36
+ Combines identical meshes into instances:
37
+
38
+ ```typescript
39
+ // Basic - combine all identical meshes
40
+ InstanceAssembler.assemble(scene);
41
+
42
+ // Custom - only specific meshes
43
+ InstanceAssembler.assemble(scene, {
44
+ filter: mesh => mesh.name.startsWith('Tree_'),
45
+ geometryTolerance: 0.001
46
+ });
47
+ ```
48
+
49
+ ### SceneProcessor
50
+
51
+ Sets up materials and shadows based on naming patterns:
52
+
53
+ ```typescript
54
+ SceneProcessor.process(scene, {
55
+ castShadowExpressions: [/^Tree_.*/],
56
+ receiveShadwoExpressions: [/Ground/],
57
+ transparentMaterialExpressions: [/Glass/],
58
+ });
59
+ ```
60
+
61
+ ### SceneTraversal
62
+
63
+ Scene graph utilities:
64
+
65
+ ```typescript
66
+ // Find objects
67
+ const obj = SceneTraversal.getObjectByName(scene, 'player');
68
+ const objects = SceneTraversal.filterObjects(scene, /^enemy_/);
69
+
70
+ // Configure shadows
71
+ SceneTraversal.setShadowRecursive(scene, true, true);
72
+ ```
73
+
74
+ ### SkinnedMeshBaker
75
+
76
+ Converts skinned meshes to static geometry:
77
+
78
+ ```typescript
79
+ // Bake current pose
80
+ const staticMesh = SkinnedMeshBaker.bakePose(skinnedMesh);
81
+
82
+ // Bake animation frame
83
+ const frameMesh = SkinnedMeshBaker.bakeAnimationFrame(
84
+ armature,
85
+ skinnedMesh,
86
+ 1.5, // time
87
+ clip // animation
88
+ );
89
+ ```
90
+
91
+ ### Sun
92
+
93
+ Directional light with spherical positioning:
94
+
95
+ ```typescript
96
+ const sun = new Sun();
97
+ sun.elevation = Math.PI / 4; // 45°
98
+ sun.azimuth = Math.PI / 2; // 90°
99
+
100
+ // Set up shadows
101
+ sun.setShadowMapFromBox3(new Bounds().setFromObject(scene));
102
+ ```
103
+
104
+ ## Requirements
105
+
106
+ - three >= 0.150.0
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,49 @@
1
+ import { PerspectiveCamera } from "three";
2
+ /**
3
+ * A camera that supports independent horizontal and vertical FOV settings.
4
+ * Extends Three.js PerspectiveCamera to allow separate control over horizontal
5
+ * and vertical fields of view.
6
+ */
7
+ export declare class BiFovCamera extends PerspectiveCamera {
8
+ private horizontalFovInternal;
9
+ private verticalFovInternal;
10
+ /**
11
+ * @param horizontalFov - Horizontal FOV in degrees (90° default)
12
+ * @param verticalFov - Vertical FOV in degrees (90° default)
13
+ * @param aspect - Width/height ratio (1 default)
14
+ * @param near - Near clipping plane (1 default)
15
+ * @param far - Far clipping plane (1000 default)
16
+ */
17
+ constructor(horizontalFov?: number, verticalFov?: number, aspect?: number, near?: number, far?: number);
18
+ /** Current horizontal FOV in degrees */
19
+ get horizontalFov(): number;
20
+ /** Current vertical FOV in degrees */
21
+ get verticalFov(): number;
22
+ /** Set horizontal FOV in degrees (clamped between 1° and 179°) */
23
+ set horizontalFov(value: number);
24
+ /** Set vertical FOV in degrees (clamped between 1° and 179°) */
25
+ set verticalFov(value: number);
26
+ /**
27
+ * Update both horizontal and vertical FOV
28
+ * @param horizontal - Horizontal FOV in degrees
29
+ * @param vertical - Vertical FOV in degrees
30
+ */
31
+ setFov(horizontal: number, vertical: number): void;
32
+ /**
33
+ * Copy FOV settings from another BiFovCamera
34
+ * @param source - Camera to copy from
35
+ */
36
+ copyFovSettings(source: BiFovCamera): void;
37
+ /**
38
+ * Updates the projection matrix based on FOV settings and aspect ratio.
39
+ * In landscape: preserves horizontal FOV
40
+ * In portrait: preserves vertical FOV
41
+ */
42
+ updateProjectionMatrix(): void;
43
+ /** Get actual horizontal FOV after aspect ratio adjustments */
44
+ getEffectiveHorizontalFov(): number;
45
+ /** Get actual vertical FOV after aspect ratio adjustments */
46
+ getEffectiveVerticalFov(): number;
47
+ /** Create a clone of this camera */
48
+ clone(): this;
49
+ }
package/dist/Bounds.d.ts CHANGED
@@ -1,8 +1,22 @@
1
+ import type { Object3D } from "three";
1
2
  import { Box3 } from "three";
3
+ /**
4
+ * Box3 with additional convenience methods for width, height, depth, etc.
5
+ */
2
6
  export declare class Bounds extends Box3 {
3
- private readonly tempVector3;
7
+ /** Temporary vector for calculations */
8
+ private readonly tempVector3A;
9
+ constructor(object?: Object3D);
10
+ /** Width (x-axis length) */
4
11
  get width(): number;
12
+ /** Height (y-axis length) */
5
13
  get height(): number;
14
+ /** Depth (z-axis length) */
6
15
  get depth(): number;
16
+ /** Length of the box's diagonal */
7
17
  get diagonal(): number;
18
+ /** Volume (width * height * depth) */
19
+ getVolume(): number;
20
+ /** Surface area (sum of all six faces) */
21
+ getSurfaceArea(): number;
8
22
  }
@@ -0,0 +1,17 @@
1
+ import type { BufferGeometry } from "three";
2
+ /**
3
+ * Internal utility to identify identical geometries.
4
+ * @internal
5
+ */
6
+ export declare class GeometryHasher {
7
+ /**
8
+ * Creates a hash for a geometry based on its vertex data.
9
+ * Vertices that differ by less than tolerance are considered the same.
10
+ *
11
+ * @param geometry - Geometry to hash
12
+ * @param tolerance - How close vertices need to be to count as identical
13
+ * @returns Hash string that's the same for matching geometries
14
+ * @internal
15
+ */
16
+ static getGeometryHash(geometry: BufferGeometry, tolerance: number): string;
17
+ }
@@ -1,10 +1,26 @@
1
- import { Mesh, Object3D } from "three";
2
- interface IOptions {
3
- container: Object3D;
4
- filter?: (child: Mesh) => boolean;
5
- geometryTolerance?: number;
1
+ import type { Object3D } from "three";
2
+ import { Mesh } from "three";
3
+ /** Configuration for instance assembly */
4
+ export interface InstanceAssemblerOptions {
5
+ /** Filter which meshes to include */
6
+ filter: (child: Mesh) => boolean;
7
+ /** How close vertices need to be to count as identical */
8
+ geometryTolerance: number;
6
9
  }
10
+ /**
11
+ * Combines identical meshes into instanced versions for better performance.
12
+ * Meshes are considered identical if they share the same geometry and materials.
13
+ */
7
14
  export declare class InstanceAssembler {
8
- static assemble(options: IOptions): void;
15
+ /**
16
+ * Find meshes that can be instanced and combine them.
17
+ * Only processes meshes that:
18
+ * - Have no children
19
+ * - Pass the filter function (if any)
20
+ * - Share geometry with at least one other mesh
21
+ *
22
+ * @param container - Object containing meshes to process
23
+ * @param options - Optional settings
24
+ */
25
+ static assemble(container: Object3D, options?: Partial<InstanceAssemblerOptions>): void;
9
26
  }
10
- export {};
@@ -1,14 +1,29 @@
1
- import { Object3D } from "three";
2
- type IPattern = string | RegExp;
3
- interface IOptions {
4
- asset: Object3D;
5
- castShadowMeshNames?: IPattern[];
6
- receiveShadowMeshNames?: IPattern[];
7
- transparentMaterialNames?: IPattern[];
8
- noDepthWriteMaterialNames?: IPattern[];
1
+ import type { Object3D } from "three";
2
+ /** Options for scene post-processing */
3
+ export interface SceneProcessorOptions {
4
+ /** Clone the input asset before processing? */
5
+ cloneAsset: boolean;
6
+ /** Combine identical meshes into instances? */
7
+ assembleInstances: boolean;
8
+ /** Names matching these patterns will cast shadows */
9
+ castShadowExpressions: RegExp[];
10
+ /** Names matching these patterns will receive shadows */
11
+ receiveShadwoExpressions: RegExp[];
12
+ /** Names matching these patterns will be transparent */
13
+ transparentMaterialExpressions: RegExp[];
14
+ /** Names matching these patterns won't write to depth buffer */
15
+ noDepthWriteMaterialExpressions: RegExp[];
9
16
  }
17
+ /** Post-processes a scene based on name patterns */
10
18
  export declare class SceneProcessor {
11
- static process(options: IOptions): Object3D[];
19
+ /**
20
+ * Process a scene to set up materials and shadows.
21
+ *
22
+ * @param asset - Scene to process
23
+ * @param options - How to process the scene
24
+ * @returns Processed scene root objects
25
+ */
26
+ static process(asset: Object3D, options: Partial<SceneProcessorOptions>): Object3D[];
27
+ /** Does the string match any of the patterns? */
12
28
  private static matchesAny;
13
29
  }
14
- export {};
@@ -0,0 +1,20 @@
1
+ import type { Material, Object3D } from "three";
2
+ /** Constructor type for type-safe scene traversal */
3
+ export type Constructor<T> = abstract new (...args: never[]) => T;
4
+ /** Find and modify objects in a Three.js scene */
5
+ export declare class SceneTraversal {
6
+ /** Find first object with exact name match */
7
+ static getObjectByName(object: Object3D, name: string): Object3D | null;
8
+ /** Find first material with exact name match */
9
+ static getMaterialByName(object: Object3D, name: string): Material | null;
10
+ /** Process all objects of a specific type */
11
+ static enumerateObjectsByType<T>(object: Object3D, type: Constructor<T>, callback: (instance: T) => void): void;
12
+ /** Process all materials in meshes */
13
+ static enumerateMaterials(object: Object3D, callback: (material: Material) => void): void;
14
+ /** Find all objects whose names match a pattern */
15
+ static filterObjects(object: Object3D, name: RegExp): Object3D[];
16
+ /** Find all materials whose names match a pattern */
17
+ static filterMaterials(object: Object3D, name: RegExp): Material[];
18
+ /** Set shadow properties on meshes */
19
+ static setShadowRecursive(object: Object3D, castShadow?: boolean, receiveShadow?: boolean, filter?: (object: Object3D) => boolean): void;
20
+ }
@@ -1,24 +1,23 @@
1
- import { AnimationClip, Mesh, Object3D, SkinnedMesh } from "three";
2
- /**
3
- * Utilities for baking poses and animations from SkinnedMesh into a regular static Mesh.
4
- */
1
+ import type { AnimationClip, Object3D, SkinnedMesh } from "three";
2
+ import { Mesh } from "three";
3
+ /** Convert skinned meshes to regular static meshes */
5
4
  export declare class SkinnedMeshBaker {
6
5
  /**
7
- * Bakes the current pose of a SkinnedMesh into a regular geometry.
8
- * Transforms all vertices according to the current skeleton state.
6
+ * Convert a skinned mesh to a regular mesh in its current pose.
7
+ * The resulting mesh will have no bones but look identical.
9
8
  *
10
- * @param skinnedMesh - SkinnedMesh from which to bake the geometry
11
- * @returns A new Mesh with positions corresponding to the current bone positions
9
+ * @param skinnedMesh - Mesh to convert
10
+ * @returns Static mesh with baked vertex positions
12
11
  */
13
12
  static bakePose(skinnedMesh: SkinnedMesh): Mesh;
14
13
  /**
15
- * Bakes a SkinnedMesh in a specific pose derived from an AnimationClip at the given timestamp.
14
+ * Bake a single frame from an animation into a static mesh.
16
15
  *
17
- * @param armature - The parent object (typically an armature from GLTF) containing the bones
18
- * @param skinnedMesh - The SkinnedMesh to be baked
19
- * @param timeOffset - The animation time in seconds to set
20
- * @param clip - The animation clip
21
- * @returns A new Mesh with geometry matching the specified animation frame
16
+ * @param armature - Root object with bones (usually from GLTF)
17
+ * @param skinnedMesh - Mesh to convert
18
+ * @param timeOffset - Time in seconds within the animation
19
+ * @param clip - Animation to get the pose from
20
+ * @returns Static mesh with baked vertex positions
22
21
  */
23
22
  static bakeAnimationFrame(armature: Object3D, skinnedMesh: SkinnedMesh, timeOffset: number, clip: AnimationClip): Mesh;
24
23
  }
package/dist/Sun.d.ts CHANGED
@@ -1,21 +1,32 @@
1
- import { Box3, DirectionalLight, Texture } from "three";
1
+ import type { Texture } from "three";
2
+ import { Box3, DirectionalLight } from "three";
3
+ /** A directional light with spherical positioning controls */
2
4
  export declare class Sun extends DirectionalLight {
3
- private tempVector3D0;
4
- private tempVector3D1;
5
- private tempVector3D2;
6
- private tempVector3D3;
7
- private tempVector3D4;
8
- private tempVector3D5;
9
- private tempVector3D6;
10
- private tempVector3D7;
11
- private tempBox3;
12
- private tempSpherical;
5
+ /** Internal vectors to avoid garbage collection */
6
+ private readonly tempVector3D0;
7
+ private readonly tempVector3D1;
8
+ private readonly tempVector3D2;
9
+ private readonly tempVector3D3;
10
+ private readonly tempVector3D4;
11
+ private readonly tempVector3D5;
12
+ private readonly tempVector3D6;
13
+ private readonly tempVector3D7;
14
+ private readonly tempBox3;
15
+ private readonly tempSpherical;
16
+ /** Distance from the light to its target */
13
17
  get distance(): number;
18
+ /** Vertical angle from the ground in radians */
14
19
  get elevation(): number;
20
+ /** Horizontal angle around the target in radians */
15
21
  get azimuth(): number;
22
+ /** Set distance while keeping current angles */
16
23
  set distance(value: number);
24
+ /** Set elevation while keeping current distance and azimuth */
17
25
  set elevation(value: number);
26
+ /** Set azimuth while keeping current distance and elevation */
18
27
  set azimuth(value: number);
28
+ /** Configure shadows to cover all corners of a bounding box */
19
29
  setShadowMapFromBox3(box3: Box3): void;
30
+ /** Set light direction based on brightest point in an HDR texture */
20
31
  setDirectionFromHDR(texture: Texture, distance?: number): void;
21
32
  }
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
+ export * from "./BiFovCamera";
1
2
  export * from "./Bounds";
2
- export * from "./DoubleFOVCamera";
3
- export * from "./Enumerator";
4
3
  export * from "./InstanceAssembler";
5
4
  export * from "./SceneProcessor";
5
+ export * from "./SceneTraversal";
6
6
  export * from "./SkinnedMeshBaker";
7
7
  export * from "./Sun";