@vctrl/hooks 0.11.1 → 0.17.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +184 -0
  2. package/GLTFLoader-CygFefRr.cjs +1 -0
  3. package/GLTFLoader-NiJ7qzh1.js +1381 -0
  4. package/README.md +0 -20
  5. package/__vite-browser-external-Bn_csQuM.js +7 -0
  6. package/__vite-browser-external-CVmj8TrW.cjs +1 -0
  7. package/chunk-foFoljWS.js +23 -0
  8. package/chunk-gGpyby2o.cjs +1 -0
  9. package/index.cjs.js +1 -0
  10. package/index.d.ts +5 -0
  11. package/index.es.js +4 -0
  12. package/lib-DKn2MJ9X.js +4111 -0
  13. package/lib-DZ-MihdJ.cjs +2 -0
  14. package/model-exporter-SMSAY90N.cjs +1 -0
  15. package/model-exporter-cvguDGnn.js +6512 -0
  16. package/package.json +4 -4
  17. package/server-communication-Bj6ZxFw2.js +4659 -0
  18. package/server-communication-yXZR8eso.cjs +18 -0
  19. package/use-export-model/use-export-model.d.ts +14 -0
  20. package/use-export-model-CaijtW1c.cjs +1 -0
  21. package/use-export-model-DzVKdqnY.js +49 -0
  22. package/use-export-model.cjs.js +1 -0
  23. package/use-export-model.es.js +2 -0
  24. package/use-load-model/event-system.d.ts +7 -0
  25. package/use-load-model/index.d.ts +4 -0
  26. package/use-load-model/state.d.ts +19 -0
  27. package/use-load-model/types.d.ts +231 -0
  28. package/use-load-model/use-load-model.d.ts +30 -0
  29. package/use-load-model/utils/calculate-referenced-bytes.d.ts +8 -0
  30. package/use-load-model/utils/index.d.ts +4 -0
  31. package/use-load-model/utils/read-directory.d.ts +8 -0
  32. package/use-load-model/utils/reconstruct-files.d.ts +29 -0
  33. package/use-load-model/utils/resolve-scene-payload.d.ts +6 -0
  34. package/use-load-model-B6UXiFWh.js +517 -0
  35. package/use-load-model-CH-WPQ_s.cjs +1 -0
  36. package/use-load-model.cjs.js +1 -0
  37. package/use-load-model.es.js +18 -0
  38. package/{src/use-optimize-model/index.ts → use-optimize-model/index.d.ts} +2 -2
  39. package/use-optimize-model/state.d.ts +13 -0
  40. package/use-optimize-model/types.d.ts +39 -0
  41. package/use-optimize-model/use-calc-optimization-info.d.ts +6 -0
  42. package/use-optimize-model/use-optimize-model.d.ts +119 -0
  43. package/use-optimize-model/utils/index.d.ts +2 -0
  44. package/use-optimize-model/utils/texture-optimization.d.ts +17 -0
  45. package/use-optimize-model/utils/validation.d.ts +8 -0
  46. package/use-optimize-model-C-fzzKh6.cjs +1 -0
  47. package/use-optimize-model-Cb3WMvDZ.js +299 -0
  48. package/use-optimize-model.cjs.js +1 -0
  49. package/use-optimize-model.es.js +2 -0
  50. package/utils/server-communication.d.ts +122 -0
  51. package/project.json +0 -55
  52. package/src/index.ts +0 -38
  53. package/src/use-export-model/use-export-model.ts +0 -113
  54. package/src/use-load-model/event-system.ts +0 -46
  55. package/src/use-load-model/index.ts +0 -15
  56. package/src/use-load-model/model-context.tsx +0 -174
  57. package/src/use-load-model/state.ts +0 -75
  58. package/src/use-load-model/types.ts +0 -284
  59. package/src/use-load-model/use-load-model.ts +0 -682
  60. package/src/use-load-model/utils/calculate-referenced-bytes.ts +0 -123
  61. package/src/use-load-model/utils/index.ts +0 -7
  62. package/src/use-load-model/utils/read-directory.ts +0 -35
  63. package/src/use-load-model/utils/reconstruct-files.ts +0 -85
  64. package/src/use-load-model/utils/resolve-scene-payload.ts +0 -151
  65. package/src/use-optimize-model/state.ts +0 -40
  66. package/src/use-optimize-model/types.ts +0 -37
  67. package/src/use-optimize-model/use-calc-optimization-info.ts +0 -97
  68. package/src/use-optimize-model/use-optimize-model.ts +0 -467
  69. package/src/use-optimize-model/utils/index.ts +0 -29
  70. package/src/use-optimize-model/utils/texture-optimization.ts +0 -292
  71. package/src/use-optimize-model/utils/validation.ts +0 -62
  72. package/src/utils/server-communication.ts +0 -351
  73. package/tsconfig.json +0 -21
  74. package/tsconfig.lib.json +0 -16
  75. package/vite.config.ts +0 -77
  76. /package/{src/use-export-model/index.ts → use-export-model/index.d.ts} +0 -0
@@ -1,467 +0,0 @@
1
- /* vectreal-core | vctrl/hooks
2
- Copyright (C) 2024 Moritz Becker
3
-
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU Affero General Public License as published by
6
- the Free Software Foundation, either version 3 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU Affero General Public License for more details.
13
-
14
- You should have received a copy of the GNU Affero General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
-
17
- import { toSerializedAssetBytes } from '@vctrl/core'
18
- import {
19
- type DedupOptions,
20
- ModelOptimizer,
21
- type NormalsOptions,
22
- type QuantizeOptions,
23
- type SimplifyOptions,
24
- type TextureCompressOptions
25
- } from '@vctrl/core/model-optimizer'
26
- import { useCallback, useEffect, useReducer, useRef } from 'react'
27
- import { Object3D } from 'three'
28
-
29
- import { initialState, reducer } from './state'
30
- import { useCalcOptimizationInfo } from './use-calc-optimization-info'
31
- import { optimizeTextures } from './utils'
32
-
33
- import type { JSONDocument } from '@gltf-transform/core'
34
- import type { ServerSceneData } from '@vctrl/core'
35
-
36
- /**
37
- * Custom React hook for optimizing 3D models using the ModelOptimizer from @vctrl/core.
38
- *
39
- * This hook provides a React-friendly interface to advanced model optimization capabilities,
40
- * including mesh simplification, deduplication, quantization, normal optimization, and texture compression.
41
- * It manages the optimization state and provides callbacks for each optimization operation.
42
- *
43
- * **Features:**
44
- * - Mesh simplification using MeshoptSimplifier
45
- * - Geometry deduplication to remove redundant data
46
- * - Vertex attribute quantization to reduce file size
47
- * - Normal vector optimization
48
- * - Texture compression (server-side only)
49
- * - Progress tracking and error handling
50
- * - Optimization reports with before/after metrics
51
- *
52
- * @example
53
- * const optimizer = useOptimizeModel()
54
- *
55
- * // Load a model
56
- * await optimizer.load(threeJsScene)
57
- *
58
- * // Apply optimizations
59
- * await optimizer.simplifyOptimization({ ratio: 0.5 })
60
- * await optimizer.quantizeOptimization({ bits: 12 })
61
- *
62
- * // Get optimized model
63
- * const optimizedBinary = await optimizer.getModel()
64
- *
65
- * @returns Object containing optimization methods, state, and report data
66
- */
67
- const useOptimizeModel = () => {
68
- // Manage state with useReducer for complex state transitions
69
- const [state, dispatch] = useReducer(reducer, initialState)
70
- const { report, error, loading } = state
71
-
72
- // Calculate optimization statistics (file size reduction, etc.)
73
- const { info, reset: resetInfo } = useCalcOptimizationInfo(state)
74
-
75
- // Store the ModelOptimizer instance in a ref to persist across renders
76
- const optimizerRef = useRef<ModelOptimizer>(new ModelOptimizer())
77
-
78
- /**
79
- * Initialize the optimizer and set up progress tracking.
80
- * Cleanup function resets the optimizer when component unmounts.
81
- */
82
- useEffect(() => {
83
- const optimizer = optimizerRef.current
84
-
85
- // Set up progress callback for optimization operations
86
- // Can be extended to dispatch progress updates to state if needed
87
- // TODO: dispatch({ type: 'UPDATE_PROGRESS', payload: progress })
88
- // optimizer.onProgress((progress: OperationProgress) => {
89
- // })
90
-
91
- // Cleanup: reset optimizer when component unmounts
92
- return () => {
93
- optimizer.reset()
94
- }
95
- }, [])
96
-
97
- /**
98
- * Loads a Three.js Object3D model into the optimizer for processing.
99
- * Converts the Three.js scene to glTF format and generates an initial optimization report.
100
- *
101
- * @param model - The Three.js Object3D scene to optimize
102
- * @returns Promise that resolves when the model is loaded and ready for optimization
103
- */
104
- const load = useCallback(async (model: Object3D): Promise<void> => {
105
- dispatch({ type: 'LOAD_START' })
106
-
107
- try {
108
- const optimizer = optimizerRef.current
109
-
110
- // Convert Three.js scene to glTF document for optimization
111
- await optimizer.loadFromThreeJS(model)
112
-
113
- const report = await optimizer.getReport()
114
- dispatch({
115
- type: 'LOAD_SUCCESS',
116
- payload: { report }
117
- })
118
- } catch (err) {
119
- dispatch({ type: 'LOAD_ERROR', payload: err as Error })
120
- console.error('Error loading model:', err)
121
- }
122
- }, [])
123
-
124
- const loadFromServerSceneData = useCallback(
125
- async (sceneData: ServerSceneData): Promise<void> => {
126
- dispatch({ type: 'LOAD_START' })
127
-
128
- try {
129
- const optimizer = optimizerRef.current
130
- const resources: Record<string, Uint8Array> = {}
131
-
132
- for (const asset of Object.values(sceneData.assetData ?? {})) {
133
- resources[asset.fileName] = toSerializedAssetBytes(asset)
134
- }
135
-
136
- const jsonDocument = {
137
- json: sceneData.gltfJson as unknown as JSONDocument['json'],
138
- resources
139
- }
140
-
141
- await optimizer.loadFromJSON(jsonDocument)
142
-
143
- const report = await optimizer.getReport()
144
- dispatch({
145
- type: 'LOAD_SUCCESS',
146
- payload: { report }
147
- })
148
- } catch (err) {
149
- dispatch({ type: 'LOAD_ERROR', payload: err as Error })
150
- console.error('Error loading server scene into optimizer:', err)
151
- throw err
152
- }
153
- },
154
- []
155
- )
156
-
157
- /**
158
- * Simplifies the loaded model by reducing polygon count using MeshoptSimplifier.
159
- * This reduces file size and improves rendering performance while maintaining visual quality.
160
- *
161
- * @param options - Configuration options for simplification
162
- * @param options.ratio - Target ratio of triangles to keep (0.0-1.0). Default: 0.5
163
- * @param options.error - Maximum allowed error threshold. Default: 0.01
164
- * @returns Promise that resolves when simplification is complete
165
- */
166
- const simplifyOptimization = useCallback(
167
- async (options?: SimplifyOptions): Promise<void> => {
168
- // Guard: ensure a model is loaded before attempting optimization
169
- if (!optimizerRef.current.hasModel()) return
170
-
171
- try {
172
- // Apply mesh simplification
173
- await optimizerRef.current.simplify(options)
174
-
175
- // Generate updated report with new metrics
176
- const report = await optimizerRef.current.getReport()
177
-
178
- // Update state with optimized model
179
- dispatch({
180
- type: 'LOAD_SUCCESS',
181
- payload: {
182
- report
183
- }
184
- })
185
- } catch (err) {
186
- console.error('Simplification failed:', err)
187
- }
188
- },
189
- []
190
- )
191
-
192
- /**
193
- * De-duplicates geometry and material data in the model.
194
- * Removes redundant vertices, primitives, and other duplicate data to reduce file size.
195
- *
196
- * @param options - Configuration options for deduplication
197
- * @returns Promise that resolves when deduplication is complete
198
- */
199
- const dedupOptimization = useCallback(
200
- async (options?: DedupOptions): Promise<void> => {
201
- // Guard: ensure a model is loaded before attempting optimization
202
- if (!optimizerRef.current.hasModel()) return
203
-
204
- try {
205
- // Remove duplicate geometry and material data
206
- await optimizerRef.current.deduplicate(options)
207
-
208
- // Generate updated report
209
- const report = await optimizerRef.current.getReport()
210
-
211
- // Update state with optimized model
212
- dispatch({
213
- type: 'LOAD_SUCCESS',
214
- payload: { report }
215
- })
216
- } catch (err) {
217
- console.error('Deduplication failed:', err)
218
- }
219
- },
220
- []
221
- )
222
-
223
- /**
224
- * Quantizes vertex attributes (positions, normals, UVs) to use fewer bits.
225
- * Reduces file size with minimal visual quality loss by storing data with lower precision.
226
- *
227
- * @param options - Configuration options for quantization
228
- * @param options.bits - Number of bits to use for quantization. Default: 14
229
- * @returns Promise that resolves when quantization is complete
230
- */
231
- const quantizeOptimization = useCallback(
232
- async (options?: QuantizeOptions): Promise<void> => {
233
- // Guard: ensure a model is loaded before attempting optimization
234
- if (!optimizerRef.current.hasModel()) return
235
-
236
- try {
237
- // Apply vertex attribute quantization
238
- await optimizerRef.current.quantize(options)
239
-
240
- // Generate updated report
241
- const report = await optimizerRef.current.getReport()
242
-
243
- // Update state with optimized model
244
- dispatch({
245
- type: 'LOAD_SUCCESS',
246
- payload: { report }
247
- })
248
- } catch (err) {
249
- console.error('Quantization failed:', err)
250
- }
251
- },
252
- []
253
- )
254
-
255
- /**
256
- * Optimizes normal vectors in the model.
257
- * Can remove, generate, or clean up normal data to improve rendering quality or reduce file size.
258
- *
259
- * @param options - Configuration options for normal optimization
260
- * @returns Promise that resolves when normal optimization is complete
261
- */
262
- const normalsOptimization = useCallback(
263
- async (options?: NormalsOptions): Promise<void> => {
264
- // Guard: ensure a model is loaded before attempting optimization
265
- if (!optimizerRef.current.hasModel()) return
266
-
267
- try {
268
- // Apply normal vector optimizations
269
- await optimizerRef.current.optimizeNormals(options)
270
-
271
- // Generate updated report
272
- const report = await optimizerRef.current.getReport()
273
-
274
- // Update state with optimized model
275
- dispatch({
276
- type: 'LOAD_SUCCESS',
277
- payload: { report }
278
- })
279
- } catch (err) {
280
- console.error('Normals optimization failed:', err)
281
- }
282
- },
283
- []
284
- )
285
-
286
- /**
287
- * Compresses textures in the model using advanced compression formats.
288
- * Significantly reduces file size while maintaining visual quality.
289
- *
290
- * **Note:** This optimization requires server-side processing (Sharp library)
291
- * and may not work in browser-only environments.
292
- *
293
- * @param options - Configuration options for texture compression
294
- * @param options.format - Target compression format (e.g., from '@shared/ui', 'ktx2')
295
- * @param options.quality - Compression quality (0-100)
296
- * @returns Promise that resolves when texture compression is complete
297
- * @throws Error if Sharp is not available or compression fails
298
- */
299
- const texturesOptimization = useCallback(
300
- async (options?: TextureCompressOptions): Promise<void> => {
301
- try {
302
- // Apply texture compression using utility function
303
- // This handles Sharp availability checks and fallbacks
304
- await optimizeTextures(optimizerRef.current, options)
305
-
306
- // Generate updated report
307
- const report = await optimizerRef.current.getReport()
308
-
309
- // Update state with optimized model
310
- dispatch({
311
- type: 'LOAD_SUCCESS',
312
- payload: { report }
313
- })
314
- } catch (err) {
315
- console.error('Texture optimization failed:', err)
316
- // Re-throw to allow caller to handle compression failures
317
- throw err
318
- }
319
- },
320
- []
321
- )
322
-
323
- /**
324
- * Exports the current optimized model as a binary Uint8Array.
325
- * The model is exported in glTF binary (.glb) format.
326
- *
327
- * @returns Promise that resolves with the model binary, or null if no model is loaded
328
- */
329
- const getModel = useCallback(async (): Promise<Uint8Array | null> => {
330
- // Guard: return null if no model is currently loaded
331
- if (!optimizerRef.current.hasModel()) return null
332
-
333
- try {
334
- // Export model as Uint8Array binary data
335
- return await optimizerRef.current.export()
336
- } catch (err) {
337
- console.error('Error getting model binary:', err)
338
- return null
339
- }
340
- }, [])
341
-
342
- const getDocument = useCallback(() => {
343
- if (!optimizerRef.current.hasModel()) {
344
- return null
345
- }
346
-
347
- return optimizerRef.current.document
348
- }, [])
349
-
350
- const isReady = Boolean(getDocument()) && !loading
351
-
352
- /**
353
- * Resets the optimizer to its initial state.
354
- * Clears the loaded model, all optimization data, reports, and calculated info.
355
- */
356
- const reset = useCallback((): void => {
357
- // Reset the core optimizer instance
358
- optimizerRef.current.reset()
359
-
360
- // Reset React state to initial values
361
- dispatch({ type: 'RESET' })
362
-
363
- // Reset calculated optimization info
364
- resetInfo()
365
- }, [resetInfo])
366
-
367
- return {
368
- /**
369
- * Loads a Three.js Object3D model into the optimizer.
370
- * Converts the scene to glTF format and generates an initial optimization report.
371
- *
372
- * @param model - The Three.js Object3D model to load
373
- * @returns Promise that resolves when the model is loaded
374
- */
375
- load,
376
-
377
- loadFromServerSceneData,
378
-
379
- /**
380
- * Retrieves the current model as a binary Uint8Array in glTF (.glb) format.
381
- *
382
- * @returns Promise that resolves with the model binary or null if no model is loaded
383
- */
384
- getModel,
385
-
386
- isReady,
387
-
388
- /**
389
- * Exposes the underlying ModelOptimizer document instance for advanced use cases.
390
- */
391
- _getDocument: getDocument, // Expose document for advanced use cases --- IGNORE ---
392
-
393
- /**
394
- * Resets the optimizer, clearing all model data, reports, and state.
395
- */
396
- reset,
397
-
398
- /**
399
- * Error object if any optimization operation failed, otherwise null.
400
- */
401
- error,
402
-
403
- /**
404
- * Boolean indicating if an optimization operation is currently in progress.
405
- */
406
- loading,
407
-
408
- /**
409
- * Detailed optimization report containing metrics about the model
410
- * (vertex count, triangle count, file size, etc.) before and after optimizations.
411
- */
412
- report, // Keep report in state for direct access --- IGNORE ---
413
-
414
- /**
415
- * Calculated optimization information including file size reduction percentages
416
- * and comparative metrics.
417
- */
418
- info,
419
-
420
- /**
421
- * Simplifies the model by reducing polygon count using MeshoptSimplifier.
422
- * Maintains visual quality while improving performance.
423
- *
424
- * @param options - Simplification options (ratio, error threshold)
425
- * @returns Promise that resolves when simplification is complete
426
- */
427
- simplifyOptimization,
428
-
429
- /**
430
- * Removes duplicate vertices, primitives, and other redundant data.
431
- * Reduces file size without affecting visual appearance.
432
- *
433
- * @param options - Deduplication options
434
- * @returns Promise that resolves when deduplication is complete
435
- */
436
- dedupOptimization,
437
-
438
- /**
439
- * Quantizes vertex attributes to use fewer bits per value.
440
- * Reduces file size with minimal visual quality loss.
441
- *
442
- * @param options - Quantization options (bit depth)
443
- * @returns Promise that resolves when quantization is complete
444
- */
445
- quantizeOptimization,
446
-
447
- /**
448
- * Optimizes normal vectors by removing, generating, or cleaning up normal data.
449
- *
450
- * @param options - Normal optimization options
451
- * @returns Promise that resolves when optimization is complete
452
- */
453
- normalsOptimization,
454
-
455
- /**
456
- * Compresses textures using advanced formats (requires server-side processing).
457
- * Note: Only works in Node.js environments with Sharp library available.
458
- *
459
- * @param options - Texture compression options (format, quality)
460
- * @returns Promise that resolves when compression is complete
461
- * @throws Error if Sharp is not available
462
- */
463
- texturesOptimization
464
- }
465
- }
466
-
467
- export default useOptimizeModel
@@ -1,29 +0,0 @@
1
- /* vectreal-core | vctrl/hooks
2
- Copyright (C) 2024 Moritz Becker
3
-
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU Affero General Public License as published by
6
- the Free Software Foundation, either version 3 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU Affero General Public License for more details.
13
-
14
- You should have received a copy of the GNU Affero General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
-
17
- // Texture optimization utilities
18
- export {
19
- optimizeTextures,
20
- performClientSideTextureOptimization,
21
- performServerSideTextureOptimization,
22
- shouldUseServerOptimization
23
- } from './texture-optimization'
24
-
25
- // Validation utilities
26
- export {
27
- validateResponseContentType,
28
- validateServerResponse
29
- } from './validation'