Huggingface.js documentation
@huggingface/usd-web-viewer
@huggingface/usd-web-viewer
OpenUSD no navegador: composição de USD em WebAssembly, construído sobre openusd (Rust puro), renderizado com three.js. Lê .usd, .usda, .usdc e .usdz; os carregamentos são executados em um Web Worker.
npm install @huggingface/usd-web-viewer three
Uso
Um visualizador pronto (renderizador, iluminação, controles de órbita):
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 em sua própria cena 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 geometryFísica e articulações
info também relata o que os autores do estágio para simulação (UsdPhysics) e seus rótulos UsdSemantics, conforme autorizados: nada é estimado. As massas estão em quilogramas, as densidades em kg/m³, a inércia em kg·m², os limites e as posições das juntas em graus ou metros; as posições e as matrizes estão no espaço do estágio, assim como as malhas sob 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 posePosing é apenas cinemático (sem colisões ou gravidade) e barato o suficiente para cada quadro de um arraste de slider ou de uma gravação.
Opções
loadUsd(url, options) e viewer.load(url, options) aceitam:
| Opção | Padrão | |
|---|---|---|
textures | 'preview' | 'none', 'preview' (cor base, pequenos mapas de dados, sem mapas normais) ou 'full' |
maxTextureSize | 1024 | Lado longo das texturas decodificadas, em pixels |
signal | Um AbortSignal; o carregamento é rejeitado com um UsdLoadError de código aborted | |
onProgress | Chamado com o estágio e uma fraction geral de 0 a 1 | |
files | Carregar arquivos descartados ou selecionados em vez da rede (veja abaixo) | |
wasmUrl, workerUrl | ao lado do pacote | De onde o binário WASM e o script do worker são servidos |
maxConcurrentFetches | 16 | Requisitos em andamento simultaneamente |
maxLayerBytes, maxLayers | 768 MiB, 1024 | Limites de download de camadas |
maxTextureBytes | 512 MiB | Limite de download de texturas |
maxTriangles, maxInstances | 20M, 100,000 | O que é desenhado no máximo |
createViewer(container, options) aceita background (padrão transparente), onContextLost e onContextRestored (chamadas com um recarregamento do último modelo exibido).
Falhas são UsdLoadErrors com um code (aborted, fetch, compose, worker, webgl); tudo que não pôde ser exibido fielmente é listado em info.warnings. Cada opção, erro e aviso é tipado.
Carregando arquivos não confiáveis
- As solicitações são enviadas como as de
<model-viewer>: cookies apenas para a origem própria da página (credentials: 'same-origin'), sem cabeçalhos personalizados e sem referrer. - Camadas e texturas são obtidas apenas via http(s).
- A análise é executada em Rust compilado para WebAssembly, em um Web Worker.
- Cada carga tem limites:
maxLayerBytes(768 MiB),maxLayers(1024),maxTextureBytes(512 MiB),maxTriangles(20M) emaxInstances(100.000); imagens de até 16384 px por lado e 8192 x 8192 px em área; prims aninhados em até 256 níveis de profundidade; entradas.usdzde até 512 MiB cada e 1 GiB no total, armazenadas sem compressão. - Arquivos malformados falham no carregamento com um
UsdLoadError.
Arquivos locais
Para exibir arquivos soltos na página ou selecionados com <input type="file" webkitdirectory>, passe-os como files, indexados pelo caminho deles no pacote, e carregue a chave da camada raiz. Caminhos relativos nos arquivos são resolvidos entre si; nada é buscado para eles.
const files = new Map([...input.files].map((file) => [file.webkitRelativePath || file.name, file]));
await viewer.load('chair/simready_usd/sm_chair.usd', { files });Bundlers
O worker e o binário WASM são encontrados com new URL(..., import.meta.url), que o Vite, o webpack e outros bundlers resolvem e emitem. Com o servidor de desenvolvimento do Vite, exclua o pacote do pré-empacotamento de dependências:
// vite.config.js
export default { optimizeDeps: { exclude: ['@huggingface/usd-web-viewer'] } };Licenciado sob a licença MIT. As licenças dos crates Rust compilados no binário WASM estão em THIRD_PARTY_LICENSES.