Huggingface.js documentation
@huggingface/usd-web-viewer
@huggingface/usd-web-viewer
OpenUSD dans le navigateur : composition USD en WebAssembly, basée sur openusd (Rust pur), rendue avec three.js. Lit les fichiers .usd, .usda, .usdc et .usdz ; les chargements s’exécutent dans un Web Worker.
npm install @huggingface/usd-web-viewer three
Utilisation
Un visualiseur prêt à l'emploi (rendu, éclairage, contrôles d'orbite) :
import { createViewer } from '@huggingface/usd-web-viewer';
const viewer = createViewer(document.getElementById('viewer')); // a container element
const { info } = await viewer.load(
'https://huggingface.co/datasets/Robotiq-Official/simready-assets/resolve/main/Robotiq_2F_85/simready_usd/Robotiq_2F_85.usda',
);Ou dans votre propre scène three.js :
import { loadUsd } from '@huggingface/usd-web-viewer';
const { root, complete, dispose } = await loadUsd(url);
scene.add(root); // a THREE.Group, Y-up, in meters
await complete; // textures stream in after the geometryPhysique et articulations
info signale également ce que les auteurs de la scène ont défini pour la simulation (UsdPhysics) et ses étiquettes UsdSemantics, telles qu’elles ont été créées : rien n’est estimé. Les masses sont en kilogrammes, les densités en kg/m³, les moments d’inertie en kg·m², les limites et positions des articulations en degrés ou en mètres ; les positions et les matrices sont dans l’espace de la scène, tout comme les maillages sous root.
const { info, joints, setJointPositions, resetJointPositions, getJointPositions, getWorldMatrix } = await viewer.load(url);
info.physics.bodies; // rigid bodies: mass, center of mass, inertia, colliders, bodies fixed to them
info.physics.colliders; // shape, approximation (convexHull, sdf, ...), physics material
info.physics.materials; // density, friction, restitution
info.physics.joints; // revolute, prismatic, spherical, distance, fixed and generic joints with their limits and drives
info.physics.articulationRoots; // where articulations (bodies solved together, like a robot) start
info.physics.frames; // Xforms under a body, often points with no mesh, like a gripper's tip
info.labels; // e.g. { path: '/RootNode', taxonomy: 'wikidata_class', values: ['cabinet'] }
info.variantSelections; // e.g. { prim: '/Robotiq_2F_85', set: 'Physics', selection: 'Physx_parallel_grip' }
info.dependencies; // every layer and texture the stage read, with its size
joints; // the joints setJointPositions can move, e.g. to build sliders
setJointPositions({ '/Robotiq_2F_85/Robotiq_2F_85/Joints/finger_joint': 40 }); // revolute and prismatic joints, any number at once; what hangs from them and mimic joints follow
getJointPositions(); // where every revolute and prismatic joint is now
getWorldMatrix('/SO101/gripper/gripper_frame_link'); // where a body, frame or mesh under a body is now and which way it faces, as a THREE.Matrix4 in the scene; null if it is none of those
resetJointPositions(); // back to the authored poseLe positionnement est purement cinématique (sans collisions ni gravité) et suffisamment léger pour être appliqué à chaque image d'un glissement de curseur ou d'un enregistrement.
Options
loadUsd(url, options) et viewer.load(url, options) prennent :
| Option | Par défaut | |
|---|---|---|
textures | 'preview' | 'none', 'preview' (couleur de base, petites cartes de données, pas de cartes normales) ou 'full' |
maxTextureSize | 1024 | Côté long des textures décodées, en pixels |
signal | Un AbortSignal ; le chargement est rejeté avec une UsdLoadError de code aborted | |
onProgress | Appelé avec le stage et une fraction globale allant de 0 à 1 | |
files | Charger les fichiers déposés ou sélectionnés au lieu du réseau (voir ci-dessous) | |
wasmUrl, workerUrl | à côté du package | L'endroit où le binaire WASM et le script worker sont servis |
maxConcurrentFetches | 16 | Demandes en cours simultanément |
maxLayerBytes, maxLayers | 768 Mio, 1024 | Limites de téléchargement des couches |
maxTextureBytes | 512 Mio | Limite de téléchargement de texture |
maxTriangles, maxInstances | 20M, 100,000 | Ce qui est dessiné au maximum |
createViewer(container, options) prend background (transparent par défaut), onContextLost et onContextRestored (appelés avec un rechargement du dernier modèle affiché).
Les échecs sont des UsdLoadError avec un code (aborted, fetch, compose, worker, webgl) ; tout ce qui n’a pas pu être affiché fidèlement est répertorié dans info.warnings. Chaque option, erreur et avertissement est typé.
Chargement de fichiers non fiables
- Les requêtes sont envoyées comme celles de
<model-viewer>: les cookies sont limités à l’origine de la page (credentials: 'same-origin'), sans en-têtes personnalisés ni référenceur. - Les calques et les textures sont récupérés uniquement via http(s).
- L'analyse est exécutée en Rust compilé en WebAssembly, dans un Web Worker.
- Chaque chargement est plafonné :
maxLayerBytes(768 Mio),maxLayers(1024),maxTextureBytes(512 Mio),maxTriangles(20 M) etmaxInstances(100 000) ; images d'une largeur maximale de 16384 px et d'une surface de 8192 x 8192 px ; primitives imbriquées jusqu'à 256 niveaux de profondeur ; entrées.usdzde 512 Mio chacune et 1 Gio au total, stockées sans compression. - Les fichiers malformés échouent au chargement avec une
UsdLoadError.
Fichiers locaux
Pour afficher les fichiers déposés sur la page ou sélectionnés avec <input type="file" webkitdirectory>, passez-les en tant que files, indexés par leur chemin dans le package, et chargez la clé de la couche racine. Les chemins relatifs dans les fichiers sont résolus les uns par rapport aux autres ; rien n’est récupéré pour eux.
const files = new Map([...input.files].map((file) => [file.webkitRelativePath || file.name, file]));
await viewer.load('chair/simready_usd/sm_chair.usd', { files });Bundlers
Le worker et le binaire WASM sont localisés à l’aide de new URL(..., import.meta.url), que Vite, webpack et d’autres bundlers résolvent et émettent. Avec le serveur de développement Vite, excluez le package du pré-bundling des dépendances :
// vite.config.js
export default { optimizeDeps: { exclude: ['@huggingface/usd-web-viewer'] } };Sous licence MIT. Les licences des crates Rust compilés dans le binaire WASM se trouvent dans THIRD_PARTY_LICENSES.