google/xb-modelviewer
>- Load and display 3D models in an XR Blocks app with `xb.ModelViewer` — GLTF/GLB models (static or animated), Gaussian-splat (.spz) models, or your own `THREE.Object3D` — wrapped with an optional draggable platform, bounding box, and raycast cylinder so users can grab and reposition them in XR. Use when spawning, scaling, or placing 3D objects/assets in the scene, putting a model inside a UI panel, or auto-placing a model on a real-world horizontal surface. Covers `loadGLTFModel`, `loadSplatModel`, `setupPlatform`, and `world.placeOnHorizontalSurface`.
npx skills add https://github.com/google/xrblocks --skill xb-modelviewer
xb.ModelViewer is a THREE.Object3D that holds a model plus optional affordances (platform,
bounding box, raycast cylinder) for grab-and-move interaction. See samples/modelviewer.
class Scene extends xb.Script {
async init() {
this.add(new THREE.HemisphereLight(0xbbbbbb, 0x888888, 3));
const model = new xb.ModelViewer({});
this.add(model);
await model.loadGLTFModel({
data: {
path: 'https://cdn.jsdelivr.net/gh/xrblocks/assets@main/',
model: 'models/Cat/cat.gltf',
scale: {x: 1, y: 1, z: 1},
rotation: {x: 0, y: 180, z: 0}, // degrees, optional
},
renderer: xb.core.renderer,
});
model.position.set(0, 0.7, -1.2);
}
}
const model = new xb.ModelViewer({castShadow: false, receiveShadow: false});
this.add(model);
await model.loadSplatModel({
data: {
model: BASE_URL + 'lego/lego.spz',
scale: {x: 0.6, y: 0.6, z: 0.6},
rotation: {x: 0, y: 180, z: 0},
},
});
const model = new xb.ModelViewer({});
model.add(new THREE.Mesh(geometry, material));
model.setupBoundingBox();
model.setupRaycastCylinder();
model.setupPlatform(); // draggable base so users can move it in XR
model.position.set(-0.6, 0.5, -1.5);
this.add(model);
Defer placement until the session starts, then drop the model onto a detected horizontal
surface:
onXRSessionStarted() { this.place(model); }
onSimulatorStarted() { this.onXRSessionStarted(); }
place(model) {
return xb.world.placeOnHorizontalSurface(model, /*timeout*/ {seconds: 30});
}
{setupPlatform: false} to loadGLTFModel to embed a model inside a UI panel(panel.add(model)); use model.bbox.getSize(v) to normalize scale.
renderer: xb.core.renderer. Splats require the Spark dependency in yourimportmap.
THREE lights — ModelViewer does not add lighting for you.Take google/xb-modelviewer from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.