@vctrl/hooks
v0.2.2
Published
vctrl/hooks is a React hooks package designed to simplify 3D model loading and management within React applications. It's part of the vectreal-core ecosystem and is primarily used in the vctrl/viewer React component and the official website application.
Downloads
412
Readme
vctrl/hooks
This library is still undergoing heavy development until the first major version is released. This may lead to breaking changes in upcoming updates.
Overview
vctrl/hooks is a React hooks package designed to simplify 3D model loading and management within React applications. It's part of the vectreal-core ecosystem and is primarily used in the vctrl/viewer React component and the official website application.
The package provides a powerful hook for loading various 3D model file formats, along with a React context for easy state management and an event system for handling different stages of the model loading process.
Table of contents
Features
- Direct 3D model file loading (supports GLTF, GLB, and USDZ formats)
- React context for state management (ModelContext)
- Event system for handling loading progress and completion
- Three.js integration
- TypeScript support
Installation
To install the package, use npm or yarn:
npm install @vctrl/hooks
# or
yarn add @vctrl/hooks
Usage
The main hook exported by this package is useLoadModel
. Here's a basic example of how to use it:
import React from 'react';
import { useLoadModel } from '@vctrl/hooks/use-load-model';
function ModelLoader() {
const { load, file, progress, isLoading } = useLoadModel();
const onFileChange = (event) => {
const files = Array.from(event.target.files);
load(files);
};
return (
<div>
<input type="file" onChange={onFileChange} />
{isLoading && <p>Loading: {progress}%</p>}
{file && <p>Model loaded: {file.name}</p>}
</div>
);
}
Multiple files can be handled, e.g. when uploading a
.gltf
model, its.bin
file and the relavant image texture files as.jpeg
/.png
(Other texture file formats have not been tested).
The useLoadModel
and useOptimizeModel
hooks may be used together or standalone to optimize gltf based scenes.
Either use the optimizer directly with the
useLoadModel
hookimport React from 'react'; import { useLoadModel } from '@vctrl/hooks/use-load-model'; import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model'; function ModelLoader() { const optimizer = useOptimizeModel(); const { load: loadFile, file, optimize } = useLoadModel(optimizer); const { load: loadModel, getModel, simplifyOptimization } = optimize; async function handleClick() { await simplifyOptimization(); } }
Changes are applied to the
file.model
field fromuseLoadModel
automatically when using optimizations
Or use the optimizer together with the
ModelProvider
// App.tsx import { ModelProvider } from '@vctrl/hooks/use-load-model'; import { useOptimizeModel } from '@vctrl/hooks/use-optimize-model'; function App() { const optimizer = useOptimizeModel(); return ( <ModelProvider optimizer={optimizer}> <Scene> </ModelProvider> ) }
// Scene.tsx import { useModelContext } from '@vctrl/hooks/use-load-model'; function Scene() { const { optimize } = useModelContext(); const { load, getModel, simplifyOptimization } = optimize; //... }
API Reference
useLoadModel
The main hook for loading and managing 3D model files.
Returns
file
: The loaded file object of typeModelFile | null
.isLoading
: A boolean indicating whether a file is currently being loaded.progress
: A number between 0 and 100 representing the loading progress.load
: A function to handle file upload. It accepts an array ofFile
objects or a mixed array ofFile
objects and directory entries.reset
: A function to reset the internal state back to it's initial values.on
: A function to subscribe to events.off
: A function to unsubscribe from events.optimize
: An object optionally populated by theuseOptimizeModel
hook
useOptimizeModel
An addon that may be used in conjunction with the useLoadModel
hook. It populates the optimize
property returned by the useLoadModel
and useModelContext
hooks.
Returns
load
: Loads a Three.js Object3D model into the optimizer.getModel
: Simplifies the current model document using the MeshoptSimplifier.simplifyOptimization
: Returns the current model document as a binary array buffer.
ModelContext
A React context that provides the state and functions from useLoadModel
to child components. It's implemented in model-context.tsx
.
import { ModelProvider, useModelContext } from '@vctrl/hooks/use-load-model';
function App() {
return (
<ModelProvider>
<ModelConsumer />
</ModelProvider>
);
}
function ModelConsumer() {
const { file, isLoading, progress, load } = useModelContext();
// Use the context values
}
When using the React Context, only load models with the
useModelContext
hook.
Event System
The package includes a custom event system for handling various stages of the model loading process. The event system is implemented in event-system.ts
and provides three main methods:
emit<T extends EventTypes>(event: T, data: EventData[T]): void
on<T extends EventTypes>(event: T, handler: EventHandler<T>): void
off<T extends EventTypes>(event: T, handler: EventHandler<T>): void
Events
You can subscribe to these events using the on
method:
'UPLOAD_PROGRESS'
: Emitted with the current progress (0-100) during file upload.'UPLOAD_COMPLETE'
: Emitted with the loaded file object when the upload is complete.'MULTIPLE_3D_MODELS'
: Emitted if multiple supported 3D model files are detected in the upload.'UNSUPPORTED_FILE_TYPE'
: Emitted if an unsupported file type is uploaded.
Example usage:
const { on, off } = useLoadModel();
useEffect(() => {
const handleProgress = (progress) => {
console.log(`Upload progress: ${progress}%`);
};
on('UPLOAD_PROGRESS', handleProgress);
return () => off('UPLOAD_PROGRESS', handleProgress);
}, [on, off]);
Supported File Types
The package currently supports the following 3D model file formats:
- GLTF (.gltf)
- GLB (.glb)
- USDZ (.usdz)
These are defined in the ModelFileTypes
enum in types.ts
.
File Loading Process
The file loading process, particularly for GLTF files, is handled by the useLoadGltf
hook in use-load-gltf.ts
. This hook performs the following steps:
- Parses the GLTF file content.
- Embeds external resources (buffers and images) into the GLTF content.
- Uses Three.js GLTFLoader to parse the modified GLTF content.
- Dispatches actions to update the state with the loaded model.
The loading process includes progress updates, which are communicated through the event system.
State Management
The package uses a reducer pattern for state management, implemented in state.ts
. The state includes:
file
: The currently loaded model file.isFileLoading
: A boolean indicating if a file is being loaded.progress
: The current loading progress.supportedFileTypes
: An array of supported file types.
Actions for updating the state are defined in the Action
type in types.ts
.
Integration with Three.js
The package integrates with Three.js for handling 3D model rendering. The loaded models are compatible with Three.js scene rendering, with the model stored as a Three.js Object3D
in the ModelFile
interface.
Development
This package is part of a monorepo workspace managed with Nx. To contribute or modify the package:
- Clone the monorepo
- Install dependencies:
npm install
oryarn install
- Make your changes
- Build the package:
nx build vctrl/hooks
- Test your changes:
nx test vctrl/hooks
License
Please refer to the LICENSE file in the package root for licensing information.
Contributing
Contributions are welcome! Please read the contributing guidelines in the vectreal-core monorepo before submitting pull requests.
Support
For issues, feature requests, or questions, please file an issue in the GitHub repository.