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 +110 -0
- package/dist/BiFovCamera.d.ts +49 -0
- package/dist/Bounds.d.ts +15 -1
- package/dist/GeometryHasher.d.ts +17 -0
- package/dist/InstanceAssembler.d.ts +23 -7
- package/dist/SceneProcessor.d.ts +25 -10
- package/dist/SceneTraversal.d.ts +20 -0
- package/dist/SkinnedMeshBaker.d.ts +13 -14
- package/dist/Sun.d.ts +22 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +285 -240
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -0
- package/dist/index.min.js.map +1 -0
- package/package.json +12 -4
- package/dist/DoubleFOVCamera.d.ts +0 -7
- package/dist/Enumerator.d.ts +0 -12
- package/dist/GeometryComparator.d.ts +0 -27
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
|
-
|
|
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 {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
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 {};
|
package/dist/SceneProcessor.d.ts
CHANGED
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
import { Object3D } from "three";
|
|
2
|
-
|
|
3
|
-
interface
|
|
4
|
-
asset
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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,
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
*
|
|
8
|
-
*
|
|
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 -
|
|
11
|
-
* @returns
|
|
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
|
-
*
|
|
14
|
+
* Bake a single frame from an animation into a static mesh.
|
|
16
15
|
*
|
|
17
|
-
* @param armature -
|
|
18
|
-
* @param skinnedMesh -
|
|
19
|
-
* @param timeOffset -
|
|
20
|
-
* @param clip -
|
|
21
|
-
* @returns
|
|
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 {
|
|
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
|
-
|
|
4
|
-
private
|
|
5
|
-
private
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private
|
|
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";
|