@vctrl/hooks 0.9.5 → 0.11.1

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.
Files changed (71) hide show
  1. package/CHANGELOG.md +210 -0
  2. package/README.md +202 -383
  3. package/package.json +66 -55
  4. package/project.json +55 -0
  5. package/src/index.ts +38 -0
  6. package/src/use-export-model/use-export-model.ts +113 -0
  7. package/src/use-load-model/event-system.ts +46 -0
  8. package/src/use-load-model/index.ts +15 -0
  9. package/src/use-load-model/model-context.tsx +174 -0
  10. package/src/use-load-model/state.ts +75 -0
  11. package/src/use-load-model/types.ts +284 -0
  12. package/src/use-load-model/use-load-model.ts +682 -0
  13. package/src/use-load-model/utils/calculate-referenced-bytes.ts +123 -0
  14. package/src/use-load-model/utils/index.ts +7 -0
  15. package/src/use-load-model/utils/read-directory.ts +35 -0
  16. package/src/use-load-model/utils/reconstruct-files.ts +85 -0
  17. package/src/use-load-model/utils/resolve-scene-payload.ts +151 -0
  18. package/{use-optimize-model/index.d.ts → src/use-optimize-model/index.ts} +2 -1
  19. package/src/use-optimize-model/state.ts +40 -0
  20. package/src/use-optimize-model/types.ts +37 -0
  21. package/src/use-optimize-model/use-calc-optimization-info.ts +97 -0
  22. package/src/use-optimize-model/use-optimize-model.ts +467 -0
  23. package/src/use-optimize-model/utils/index.ts +29 -0
  24. package/src/use-optimize-model/utils/texture-optimization.ts +292 -0
  25. package/src/use-optimize-model/utils/validation.ts +62 -0
  26. package/src/utils/server-communication.ts +351 -0
  27. package/tsconfig.json +21 -0
  28. package/tsconfig.lib.json +16 -0
  29. package/vite.config.ts +77 -0
  30. package/GLTFExporter-BmLF430n.cjs +0 -18
  31. package/GLTFExporter-C4hCeb4H.js +0 -1263
  32. package/index.cjs.js +0 -1
  33. package/index.d.ts +0 -3
  34. package/index.es.js +0 -12
  35. package/model-context-CQJta_vi.cjs +0 -9
  36. package/model-context-D1Q8WdpT.js +0 -3431
  37. package/use-export-model/types.d.ts +0 -19
  38. package/use-export-model/use-export-model.d.ts +0 -14
  39. package/use-export-model/utils/data-uri-to-blob.d.ts +0 -9
  40. package/use-export-model/utils/export-handlers.d.ts +0 -23
  41. package/use-export-model/utils/file-helpers.d.ts +0 -17
  42. package/use-export-model/utils/index.d.ts +0 -3
  43. package/use-export-model-AFharGg5.js +0 -77
  44. package/use-export-model-CWcKp4A3.cjs +0 -1
  45. package/use-export-model.cjs.js +0 -1
  46. package/use-export-model.es.js +0 -4
  47. package/use-load-model/event-system.d.ts +0 -7
  48. package/use-load-model/file-type-hooks/index.d.ts +0 -2
  49. package/use-load-model/file-type-hooks/use-load-binary.d.ts +0 -11
  50. package/use-load-model/file-type-hooks/use-load-gltf.d.ts +0 -5
  51. package/use-load-model/index.d.ts +0 -3
  52. package/use-load-model/loaders/create-gltf-loader.d.ts +0 -3
  53. package/use-load-model/loaders/create-usdz-loader.d.ts +0 -3
  54. package/use-load-model/loaders/index.d.ts +0 -2
  55. package/use-load-model/model-context.d.ts +0 -78
  56. package/use-load-model/state.d.ts +0 -19
  57. package/use-load-model/types.d.ts +0 -51
  58. package/use-load-model/use-load-model.d.ts +0 -74
  59. package/use-load-model/utils/array-buffer-to-base64.d.ts +0 -2
  60. package/use-load-model/utils/index.d.ts +0 -2
  61. package/use-load-model/utils/read-directory.d.ts +0 -8
  62. package/use-load-model.cjs.js +0 -1
  63. package/use-load-model.es.js +0 -8
  64. package/use-optimize-model/state.d.ts +0 -13
  65. package/use-optimize-model/types.d.ts +0 -37
  66. package/use-optimize-model/use-optimize-model.d.ts +0 -29
  67. package/use-optimize-model-Cqkp__Vi.cjs +0 -1
  68. package/use-optimize-model-DZWIb_40.js +0 -127
  69. package/use-optimize-model.cjs.js +0 -1
  70. package/use-optimize-model.es.js +0 -4
  71. /package/{use-export-model/index.d.ts → src/use-export-model/index.ts} +0 -0
package/README.md CHANGED
@@ -1,444 +1,263 @@
1
- # vctrl/hooks
2
-
3
- [![Version and release packages to NPM](https://img.shields.io/github/actions/workflow/status/vectreal/vectreal-core/version-release.yaml?logo=github&logoColor=%23fc6c18&label=Version%20and%20release%20packages%20to%20NPM&color=%23fc6c18)
4
- ](https://github.com/Vectreal/vectreal-core/actions/workflows/version-release.yaml)
5
- [![@vctrl/hooks | NPM Downloads](https://img.shields.io/npm/dm/%40vctrl%2Fhooks?logo=npm&logoColor=%23fc6c18&label=%40vctrl%2Fhooks%20%7C%20NPM%20Downloads&color=%23fc6c18)](https://www.npmjs.com/package/@vctrl/hooks)
6
-
7
- > **Note**: This library is still undergoing heavy development until the first major version is released. This may lead to breaking changes in upcoming updates.
8
-
9
- ## Overview
10
-
11
- `@vctrl/hooks` is a React hooks package designed to simplify 3D model loading, optimization, and exporting within React applications. It's part of the [vectreal-core](https://github.com/vectreal/vectreal-core) ecosystem and is fully integrated into the [official website application](https://core.vectreal.com).
12
-
13
- The package provides powerful hooks for:
14
-
15
- - **Loading various 3D model file formats** (`useLoadModel`)
16
- - **Optimizing 3D models** (`useOptimizeModel`)
17
- - **Exporting 3D models from Three.js scenes** (`useExportModel`)
18
-
19
- It also includes a React context (`ModelContext`) for easy state management and an event system for handling different stages of the model loading process.
20
-
21
- ### Table of Contents
22
-
23
- - [vctrl/hooks](#vctrlhooks)
24
- - [Overview](#overview)
25
- - [Table of Contents](#table-of-contents)
26
- - [Installation](#installation)
27
- - [Hooks](#hooks)
28
- - [useLoadModel](#useloadmodel)
29
- - [Overview](#overview-1)
30
- - [Features](#features)
31
- - [Usage](#usage)
32
- - [API Reference](#api-reference)
33
- - [Optimization Integration](#optimization-integration)
34
- - [useOptimizeModel](#useoptimizemodel)
35
- - [Overview](#overview-2)
36
- - [Features](#features-1)
37
- - [Usage](#usage-1)
38
- - [API Reference](#api-reference-1)
39
- - [useExportModel](#useexportmodel)
40
- - [Overview](#overview-3)
41
- - [Features](#features-2)
42
- - [Usage](#usage-2)
43
- - [API Reference](#api-reference-2)
44
- - [ModelContext](#modelcontext)
45
- - [Common Concepts](#common-concepts)
46
- - [Supported File Types](#supported-file-types)
47
- - [File Loading Process](#file-loading-process)
48
- - [State Management](#state-management)
49
- - [Integration with Three.js](#integration-with-threejs)
50
- - [Development](#development)
51
- - [License](#license)
52
- - [Contributing](#contributing)
53
- - [Support](#support)
1
+ # @vctrl/hooks
54
2
 
55
- ## Installation
3
+ [![NPM Downloads](https://img.shields.io/npm/dm/%40vctrl%2Fhooks?logo=npm&logoColor=%23fc6c18&label=%40vctrl%2Fhooks%20%7C%20NPM%20Downloads&color=%23fc6c18)](https://www.npmjs.com/package/@vctrl/hooks)
4
+
5
+ Browser-side React hooks for loading, optimizing, and exporting 3D models. The runtime counterpart to [`@vctrl/core`](https://vectreal.com/docs/packages/core), built for React apps that need to handle 3D files directly in the browser.
56
6
 
57
- To install the package, use npm or yarn:
7
+ ---
8
+
9
+ ## Installation
58
10
 
59
11
  ```bash
60
12
  npm install @vctrl/hooks
61
13
  # or
62
- yarn add @vctrl/hooks
14
+ pnpm add @vctrl/hooks
63
15
  ```
64
16
 
65
- ## Hooks
66
-
67
- ### useLoadModel
17
+ ---
68
18
 
69
- #### Overview
19
+ ## Hooks overview
70
20
 
71
- `useLoadModel` is a React hook for loading and managing 3D model files in your application. It supports various file formats and integrates with Three.js for rendering.
21
+ | Hook | Import path | Description |
22
+ | ------------------ | --------------------------------- | ------------------------------------------------------------------------------- |
23
+ | `useLoadModel` | `@vctrl/hooks/use-load-model` | Load and parse GLTF, GLB, and USDZ files from file lists or dropped directories |
24
+ | `useOptimizeModel` | `@vctrl/hooks/use-optimize-model` | Run glTF-Transform optimizations on loaded models |
25
+ | `useExportModel` | `@vctrl/hooks/use-export-model` | Export the current scene to GLB or glTF |
72
26
 
73
- #### Features
27
+ ---
74
28
 
75
- - Supports direct 3D model file loading (GLTF, GLB, USDZ)
76
- - Provides loading progress updates
77
- - Emits events during the loading process
78
- - Integrates with Three.js
79
- - Supports multiple file uploads (e.g., `.gltf` with associated `.bin` and texture files)
80
- - Integrates with `useOptimizeModel` for model optimization
81
- - TypeScript support
29
+ ## `useLoadModel`
82
30
 
83
- #### Usage
31
+ Loads 3D files and exposes the parsed Three.js `Object3D` scene.
84
32
 
85
- Here's a basic example of how to use `useLoadModel`:
33
+ ```tsx
34
+ import { ModelProvider, useLoadModel } from '@vctrl/hooks/use-load-model'
86
35
 
87
- ```jsx
88
- import React from 'react';
89
- import { useLoadModel } from '@vctrl/hooks/use-load-model';
36
+ function Uploader() {
37
+ const { load, file, isFileLoading } = useLoadModel()
90
38
 
91
- function ModelLoader() {
92
- const { load, file, progress, isLoading } = useLoadModel();
39
+ const handleDrop = (e: React.DragEvent) => {
40
+ e.preventDefault()
41
+ void load(Array.from(e.dataTransfer.files))
42
+ }
93
43
 
94
- const onFileChange = (event) => {
95
- const files = Array.from(event.target.files);
96
- load(files);
97
- };
44
+ if (isFileLoading) return <p>Loading...</p>
45
+ if (file?.model) return <p>Model loaded: {file.name}</p>
98
46
 
99
- return (
100
- <div>
101
- <input type="file" onChange={onFileChange} multiple />
102
- {isLoading && <p>Loading: {progress}%</p>}
103
- {file && <p>Model loaded: {file.name}</p>}
104
- </div>
105
- );
47
+ return (
48
+ <div onDrop={handleDrop} onDragOver={(e) => e.preventDefault()}>
49
+ Drop a file
50
+ </div>
51
+ )
106
52
  }
107
- ```
108
-
109
- > **Note**: Multiple files can be handled, e.g., when uploading a `.gltf` model along with its `.bin` file and relevant texture files (e.g., `.jpeg`, `.png`).
110
-
111
- You can also use the `ModelProvider` and `useModelContext` to access the model state across your application:
112
53
 
113
- ```jsx
114
- // App.jsx
115
- import React from 'react';
116
- import { ModelProvider } from '@vctrl/hooks/use-load-model';
117
- import ModelConsumer from './ModelConsumer';
118
-
119
- function App() {
120
- return (
121
- <ModelProvider>
122
- <ModelConsumer />
123
- </ModelProvider>
124
- );
125
- }
126
-
127
- // ModelConsumer.jsx
128
- import React from 'react';
129
- import { useModelContext } from '@vctrl/hooks/use-load-model';
130
-
131
- function ModelConsumer() {
132
- const { file, isLoading, progress, load } = useModelContext();
133
-
134
- // Use the context values
135
- return (
136
- // ... your component logic
137
- );
54
+ export default function App() {
55
+ return (
56
+ <ModelProvider>
57
+ <Uploader />
58
+ </ModelProvider>
59
+ )
138
60
  }
139
61
  ```
140
62
 
141
- > **Note**: When using the React context, load models using the `useModelContext` hook.
142
-
143
- #### API Reference
144
-
145
- The `useLoadModel` hook returns the following:
146
-
147
- - `file`: The loaded file object (`ModelFile | null`).
148
- - `isLoading`: A boolean indicating whether a file is currently being loaded.
149
- - `progress`: A number between 0 and 100 representing the loading progress.
150
- - `load(files)`: A function to handle file uploads. It accepts an array of `File` objects or a mixed array of `File` objects and directory entries.
151
- - `reset()`: A function to reset the internal state back to its initial values.
152
- - `on(event, handler)`: A function to subscribe to events.
153
- - `off(event, handler)`: A function to unsubscribe from events.
154
- - `optimize`: An object populated by the `useOptimizeModel` hook integration, providing optimization functions (see below).
155
-
156
- #### Optimization Integration
157
-
158
- If you pass an instance of `useOptimizeModel` to `useLoadModel`, it will integrate optimization functions into the `optimize` object:
159
-
160
- ```jsx
161
- import React from 'react';
162
- import { useLoadModel } from '@vctrl/hooks/use-load-model';
163
- import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model';
164
-
165
- function ModelLoader() {
166
- const optimizer = useOptimizeModel();
167
- const { load, file, optimize } = useLoadModel(optimizer);
168
-
169
- const handleSimplify = async () => {
170
- await optimize.simplifyOptimization();
171
- // The optimized model is now in file.model
172
- };
173
-
174
- return (
175
- // ... your component logic
176
- );
63
+ ### Context and direct usage
64
+
65
+ `useLoadModel` can be used in two ways:
66
+
67
+ 1. Context mode: wrap your app with `ModelProvider`, then consume with `useModelContext()` anywhere in that tree.
68
+ 2. Direct mode: call `useLoadModel()` outside a provider to manage a local model state.
69
+
70
+ ### Return values
71
+
72
+ | Value | Type | Description |
73
+ | -------------------------- | ------------------------------------ | ----------------------------------------------------------- |
74
+ | `file` | `ModelFile \| null` | Loaded file metadata and Three.js model |
75
+ | `isFileLoading` | `boolean` | True while loading and parsing |
76
+ | `progress` | `number` | Progress value from 0 to 100 |
77
+ | `load(filesOrDirectories)` | `Promise<void>` | Load files or dropped `FileSystemDirectoryHandle` entries |
78
+ | `loadFromData(options)` | `Promise<SceneLoadResult>` | Load already-resolved server scene payload |
79
+ | `loadFromServer(options)` | `Promise<SceneLoadResult>` | Fetch and load scene from an API endpoint |
80
+ | `reset` | `() => void` | Clear the current model |
81
+ | `on` / `off` | Event helpers | Subscribe and unsubscribe to loader lifecycle events |
82
+ | `optimizer` | `OptimizerIntegrationReturn \| null` | Populated when the hook is called with `useOptimizeModel()` |
83
+
84
+ ### `useLoadModel` events
85
+
86
+ `on` and `off` support these typed events:
87
+
88
+ | Event | Payload |
89
+ | ---------------------- | ------------------- |
90
+ | `multiple-models` | `File[]` |
91
+ | `not-loaded-files` | `File[]` |
92
+ | `load-start` | `null` |
93
+ | `load-progress` | `number` |
94
+ | `load-complete` | `ModelFile \| null` |
95
+ | `load-reset` | `null` |
96
+ | `load-error` | `Error \| unknown` |
97
+ | `server-load-start` | `string` |
98
+ | `server-load-complete` | `SceneLoadResult` |
99
+ | `server-load-error` | `Error \| unknown` |
100
+
101
+ ### Scene loading option types
102
+
103
+ `loadFromServer(options)` uses:
104
+
105
+ | Field | Type | Description |
106
+ | --------------- | --------------- | --------------------------------------------- |
107
+ | `sceneId` | `string` | Scene identifier to fetch |
108
+ | `serverOptions` | `ServerOptions` | Endpoint, auth, and header configuration |
109
+ | `applySettings` | `boolean` | Whether scene settings are applied after load |
110
+
111
+ `loadFromData(options)` uses:
112
+
113
+ | Field | Type | Description |
114
+ | --------------- | --------------------- | -------------------------------------------------------------- |
115
+ | `sceneId` | `string \| undefined` | Optional scene identifier |
116
+ | `sceneData` | `ServerSceneData` | Already-resolved payload containing glTF, settings, and assets |
117
+ | `applySettings` | `boolean` | Whether scene settings are applied after load |
118
+
119
+ ---
120
+
121
+ ## `useOptimizeModel`
122
+
123
+ Runs mesh simplification and texture compression using [glTF-Transform](https://gltf-transform.dev) in a Web Worker.
124
+
125
+ ```tsx
126
+ import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model'
127
+ import { useLoadModel } from '@vctrl/hooks/use-load-model'
128
+
129
+ function Optimizer() {
130
+ const optimizer = useOptimizeModel()
131
+ const { file, optimizer: integrated } = useLoadModel(optimizer)
132
+
133
+ const handleOptimize = async () => {
134
+ if (!file?.model || !integrated) return
135
+ await integrated.applyOptimization(integrated.simplifyOptimization, {
136
+ ratio: 0.6,
137
+ error: 0.001
138
+ })
139
+ }
140
+
141
+ return (
142
+ <button onClick={handleOptimize} disabled={optimizer.loading}>
143
+ {optimizer.loading ? 'Optimizing...' : 'Optimize model'}
144
+ </button>
145
+ )
177
146
  }
178
147
  ```
179
148
 
180
- The `optimize` object includes quick access optimization:
181
-
182
- - `simplifyOptimization(options)`: Simplifies the model using mesh simplification.
183
- - `dedupOptimization(options)`: Removes duplicate vertices and meshes.
184
- - `quantizeOptimization(options)`: Reduces the precision of vertex attributes.
185
- - `normalsOptimization(options)`: Overrides the normals of each object in the scene.
186
- - `texturesCompressionOptimization(options)`: Compresses the relevant textures in the model file using texture compression.
187
-
188
- ### useOptimizeModel
189
-
190
- #### Overview
191
-
192
- `useOptimizeModel` is a React hook used to optimize 3D models, particularly GLTF-based scenes. It can be used in conjunction with `useLoadModel` or independently.
193
-
194
- #### Features
195
-
196
- - Simplifies 3D models using mesh optimization algorithms
197
- - Provides deduplication and quantization optimizations
198
- - Integrates with `useLoadModel` and `ModelContext`
199
- - TypeScript support
200
-
201
- #### Usage
202
-
203
- There are two ways to use the `useOptimizeModel` hook:
204
-
205
- 1. **Directly with `useLoadModel`**
206
-
207
- ```jsx
208
- import React from 'react';
209
- import { useLoadModel } from '@vctrl/hooks/use-load-model';
210
- import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model';
211
-
212
- function ModelLoader() {
213
- const optimizer = useOptimizeModel();
214
- const { load, file, optimize } = useLoadModel(optimizer);
215
-
216
- const handleSimplify = async () => {
217
- await optimize.simplifyOptimization();
218
- // The optimized model is now in file.model
219
- };
149
+ ### Key API surface
220
150
 
221
- const handleDedup = async () => {
222
- await optimize.dedupOptimization();
223
- };
151
+ | Method / State | Type | Description |
152
+ | ------------------------------------ | ------------------------------------------------------------------ | ---------------------------------------------------------------------- |
153
+ | `load(model)` | `(model: Object3D) => Promise<void>` | Load a Three.js scene into the optimizer |
154
+ | `loadFromServerSceneData(sceneData)` | `Promise<void>` | Initialize optimizer from a server scene payload |
155
+ | `applyOptimization(fn, opts?)` | `<T>(fn?: (opts?: T) => Promise<void>, opts?: T) => Promise<void>` | Apply optimization and sync the optimized model back into loader state |
156
+ | `simplifyOptimization(options?)` | `Promise<void>` | Simplify mesh geometry |
157
+ | `dedupOptimization(options?)` | `Promise<void>` | Deduplicate model data |
158
+ | `quantizeOptimization(options?)` | `Promise<void>` | Quantize vertex attributes |
159
+ | `normalsOptimization(options?)` | `Promise<void>` | Recompute or normalize normals |
160
+ | `texturesOptimization(options?)` | `Promise<void>` | Run texture compression flow |
161
+ | `getModel()` | `Promise<Uint8Array \| null>` | Export the current optimized model as GLB binary |
162
+ | `report` / `info` | Objects | Optimization metrics and derived stats |
163
+ | `loading` / `error` | State | Optimization status |
224
164
 
225
- const handleQuantize = async () => {
226
- await optimize.quantizeOptimization();
227
- };
165
+ ### Optimization option types
228
166
 
229
- return (
230
- <div>
231
- <input
232
- type="file"
233
- onChange={(e) => load(Array.from(e.target.files))}
234
- multiple
235
- />
236
- <button onClick={handleSimplify}>Simplify Model</button>
237
- <button onClick={handleDedup}>Deduplicate Model</button>
238
- <button onClick={handleQuantize}>Quantize Model</button>
239
- </div>
240
- );
241
- }
242
- ```
167
+ `useOptimizeModel` methods map directly to `@vctrl/core/model-optimizer` option types:
243
168
 
244
- > **Note**: Changes are applied to the `file.model` field from `useLoadModel` automatically when using optimizations.
169
+ | Method | Option fields |
170
+ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
171
+ | `simplifyOptimization` | `ratio?: number`, `error?: number` |
172
+ | `dedupOptimization` | `textures?: boolean`, `materials?: boolean`, `meshes?: boolean`, `accessors?: boolean` |
173
+ | `quantizeOptimization` | `quantizePosition?: number`, `quantizeNormal?: number`, `quantizeColor?: number`, `quantizeTexcoord?: number` |
174
+ | `normalsOptimization` | `overwrite?: boolean` |
175
+ | `texturesOptimization` | `resize?: [number, number]`, `targetFormat?: 'webp' \| 'jpeg' \| 'png'`, `quality?: number`, `requestTimeoutMs?: number`, `maxTextureUploadBytes?: number`, `maxRetries?: number`, `maxConcurrentRequests?: number`, `serverOptions?: ServerOptions` |
245
176
 
246
- 2. **With `ModelProvider` and `useModelContext`**
247
-
248
- ```jsx
249
- // App.jsx
250
- import React from 'react';
251
- import { ModelProvider } from '@vctrl/hooks/use-load-model';
252
- import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model';
253
- import Scene from './Scene';
254
-
255
- function App() {
256
- const optimizer = useOptimizeModel();
257
-
258
- return (
259
- <ModelProvider optimizer={optimizer}>
260
- <Scene />
261
- </ModelProvider>
262
- );
263
- }
264
-
265
- // Scene.jsx
266
- import React from 'react';
267
- import { useModelContext } from '@vctrl/hooks/use-load-model';
268
-
269
- function Scene() {
270
- const { optimize } = useModelContext();
271
-
272
- const handleSimplify = async () => {
273
- await optimize.simplifyOptimization();
274
- };
275
-
276
- const handleDedup = async () => {
277
- await optimize.dedupOptimization();
278
- };
279
-
280
- const handleQuantize = async () => {
281
- await optimize.quantizeOptimization();
282
- };
283
-
284
- return (
285
- <div>
286
- <button onClick={handleSimplify}>Simplify Model</button>
287
- <button onClick={handleDedup}>Deduplicate Model</button>
288
- <button onClick={handleQuantize}>Quantize Model</button>
289
- </div>
290
- );
291
- }
292
- ```
293
-
294
- #### API Reference
295
-
296
- The `useOptimizeModel` hook returns the following:
297
-
298
- - `load(model)`: Loads a Three.js `Object3D` model into the optimizer.
299
- - `getModel()`: Retrieves the optimized model as a binary array buffer.
300
- - `simplifyOptimization(options)`: Simplifies the current model using the `MeshoptSimplifier`.
301
- - `dedupOptimization(options)`: Removes duplicate vertices and meshes.
302
- - `quantizeOptimization(options)`: Reduces the precision of vertex attributes.
303
- - `normalsOptimization`: Overrides normals
304
- - `texturesOptimization(options)`: Compresses related textures.
305
- - `getSize()`: Object with byte size of gltf scene and a formatted megabyte string
306
- - `reset()`: Resets the current optimizer model and report state.
307
- - `report`: @gltf-transform gltf report object with relevant details about a gltf scene
308
- - `error`: Stores any possible optimization errors
309
- - `loading`: Boolean for when the model is being loaded
310
-
311
- ### useExportModel
312
-
313
- #### Overview
314
-
315
- `useExportModel` is a React hook for exporting 3D models from a Three.js scene.
316
-
317
- #### Features
318
-
319
- - Exports models in GLTF or GLB format
320
- - Handles embedded resources and textures
321
- - Integrates with Three.js scenes
322
- - TypeScript support
323
-
324
- #### Usage
325
-
326
- ```jsx
327
- import React from 'react';
328
- import { useExportModel } from '@vctrl/hooks/use-export-model';
329
-
330
- function ExportButton({ file }) {
331
- const { handleGltfExport } = useExportModel(
332
- () => console.log('Export complete'),
333
- (error) => console.error('Export error:', error),
334
- );
335
-
336
- const exportAsGlb = () => {
337
- handleGltfExport(file, true); // Export as GLB (binary)
338
- };
339
-
340
- const exportAsGltf = () => {
341
- handleGltfExport(file, false); // Export as GLTF
342
- };
343
-
344
- return (
345
- <div>
346
- <button onClick={exportAsGlb}>Export as GLB</button>
347
- <button onClick={exportAsGltf}>Export as GLTF</button>
348
- </div>
349
- );
350
- }
351
- ```
352
-
353
- #### API Reference
177
+ `serverOptions` is provided by `@vctrl/core` and supports endpoint, API key, and headers.
354
178
 
355
- The `useExportModel` hook returns the following:
179
+ ---
356
180
 
357
- - `handleGltfExport(file, binary)`: Function to handle exporting the model.
358
- - `file`: The `ModelFile` object to export.
359
- - `binary`: A boolean indicating whether to export in binary format (`true` for GLB, `false` for GLTF).
360
- - The function exports the model and triggers file download.
181
+ ## `useExportModel`
361
182
 
362
- ### ModelContext
183
+ Exports the current scene from `ModelProvider` context to a downloadable file.
363
184
 
364
- `ModelContext` is a React context that provides the state and functions from `useLoadModel` (and optionally `useOptimizeModel`) to child components.
185
+ ```tsx
186
+ import { useExportModel } from '@vctrl/hooks/use-export-model'
187
+ import type { ModelFile } from '@vctrl/hooks/use-load-model'
365
188
 
366
- ```jsx
367
- import { ModelProvider, useModelContext } from '@vctrl/hooks/use-load-model';
368
-
369
- function App() {
370
- return (
371
- <ModelProvider>
372
- <ModelConsumer />
373
- </ModelProvider>
374
- );
375
- }
189
+ function ExportButton({ file }: { file: ModelFile | null }) {
190
+ const { handleThreeGltfExport } = useExportModel()
376
191
 
377
- function ModelConsumer() {
378
- const { file, isLoading, progress, load, optimize } = useModelContext();
379
- // Use the context values
192
+ return (
193
+ <button onClick={() => void handleThreeGltfExport(file, true)}>
194
+ Download GLB
195
+ </button>
196
+ )
380
197
  }
381
198
  ```
382
199
 
383
- > **Note**: When using the React context, load models using the `useModelContext` hook.
200
+ ### Methods
384
201
 
385
- ## Common Concepts
202
+ | Method | Description |
203
+ | -------------------------------------------------------------- | ------------------------------------------------------------------- |
204
+ | `handleThreeGltfExport(file, binary)` | Export a loaded Three.js model to `.glb` or a zipped `.gltf` bundle |
205
+ | `handleDocumentGltfExport(document, file, binary?, download?)` | Export from a glTF-Transform `Document` |
386
206
 
387
- ### Supported File Types
207
+ `binary = true` writes `.glb`; `binary = false` writes a zipped `.gltf` package.
388
208
 
389
- The package currently supports the following 3D model file formats:
209
+ ---
390
210
 
391
- - GLTF (`.gltf`)
392
- - GLB (`.glb`)
393
- - USDZ (`.usdz`)
211
+ ## Additional exports
394
212
 
395
- These are defined in the `ModelFileTypes` enum in `types.ts`.
213
+ - `ServerCommunicationService` from `@vctrl/hooks`
214
+ - `reconstructGltfFiles` from `@vctrl/hooks`
215
+ - `ModelProvider` and `useModelContext` from `@vctrl/hooks/use-load-model`
216
+ - Shared types such as `ModelFile`, `SceneLoadResult`, and `ServerSceneData`
396
217
 
397
- ### File Loading Process
218
+ `ServerCommunicationService` methods:
398
219
 
399
- The file loading process, particularly for GLTF files, is handled internally by the hooks. The process includes:
220
+ | Method | Description |
221
+ | -------------------------------------------------- | ------------------------- |
222
+ | `request(config)` | Generic request helper |
223
+ | `get(endpoint, serverOptions?)` | Convenience GET |
224
+ | `post(endpoint, body, serverOptions?)` | Convenience JSON POST |
225
+ | `postFormData(endpoint, formData, serverOptions?)` | Convenience FormData POST |
400
226
 
401
- 1. Parsing the GLTF file content.
402
- 2. Embedding external resources (buffers and images) into the GLTF content.
403
- 3. Using Three.js `GLTFLoader` to parse the modified GLTF content.
404
- 4. Updating the state with the loaded model.
405
- 5. Integrating with the optimizer if provided.
227
+ `ServerRequestConfig` fields:
406
228
 
407
- The loading process includes progress updates, which are communicated through the event system.
229
+ | Field | Type |
230
+ | --------------- | ------------------------------------------------- |
231
+ | `endpoint` | `string` |
232
+ | `method` | `'GET' \| 'POST' \| 'PUT' \| 'DELETE' \| 'PATCH'` |
233
+ | `body` | `FormData \| Record<string, unknown> \| string` |
234
+ | `serverOptions` | `ServerOptions` |
235
+ | `contentType` | `string` |
408
236
 
409
- ### State Management
237
+ ---
410
238
 
411
- The package uses a reducer pattern for state management. The state includes:
239
+ ## Peer dependencies
412
240
 
413
- - `file`: The currently loaded model file.
414
- - `isLoading`: A boolean indicating if a file is being loaded.
415
- - `progress`: The current loading progress.
416
- - `supportedFileTypes`: An array of supported file types.
241
+ | Package | Version |
242
+ | -------------------- | -------------- |
243
+ | `react` | `^18 \|\| ^19` |
244
+ | `three` | `^0.170` |
245
+ | `@react-three/fiber` | `^9` |
417
246
 
418
- Actions for updating the state are defined in the `Action` type in `types.ts`.
247
+ ---
419
248
 
420
- ### Integration with Three.js
249
+ ## Related docs
421
250
 
422
- The package integrates with Three.js for handling 3D model rendering and manipulation. The loaded models are compatible with Three.js scenes, with the model stored as a Three.js `Object3D` in the `ModelFile` interface.
251
+ - [Uploading Models](https://vectreal.com/docs/guides/upload)
252
+ - [Optimizing & Configuring](https://vectreal.com/docs/guides/optimize)
253
+ - [@vctrl/viewer](https://vectreal.com/docs/packages/viewer)
423
254
 
424
- ## Development
255
+ ---
425
256
 
426
- This package is part of a monorepo workspace managed with Nx. To contribute or modify the package:
257
+ ## Source
427
258
 
428
- 1. Clone the monorepo from [vectreal-core](https://github.com/vectreal/vectreal-core).
429
- 2. Install dependencies: `npm install` or `yarn install`.
430
- 3. Make your changes.
431
- 4. Build the package: `nx build vctrl/hooks`.
432
- 5. Test your changes: `nx test vctrl/hooks`.
259
+ The full source and README live in [packages/hooks](https://github.com/Vectreal/vectreal-platform/tree/main/packages/hooks).
433
260
 
434
261
  ## License
435
262
 
436
- This project is licensed under the **GNU Affero General Public License v3.0**. Please refer to the [LICENSE](https://github.com/vectreal/vectreal-core/blob/main/LICENSE) file in the package root for licensing information.
437
-
438
- ## Contributing
439
-
440
- Contributions are welcome! Please read the contributing guidelines in the [vectreal-core](https://github.com/vectreal/vectreal-core) monorepo before submitting pull requests.
441
-
442
- ## Support
443
-
444
- For issues, feature requests, or questions, please file an issue in the [GitHub repository](https://github.com/vectreal/vectreal-core/issues).
263
+ AGPL-3.0-only. See [LICENSE.md](https://github.com/Vectreal/vectreal-platform/blob/main/packages/hooks/LICENSE.md).