@womp/vlm-mesh-compose
v0.0.3
Published
Compose a 3D scene from a reference image and a set of part GLBs. Outputs a single composed GLB on disk.
Keywords
Readme
@womp/vlm-mesh-compose
Compose a 3D scene from a reference image and a set of part GLBs. Outputs a single composed GLB on disk.
Usage
import { compose, InputError, ApiCallError } from "@womp/vlm-mesh-compose";
try {
const result = await compose({
imagePath: "/path/to/scene.png",
parts: [
{ id: "scientist", description: "the person", glbPath: "/path/to/scientist.glb" },
{ id: "controller", description: "the controller", glbPath: "/path/to/controller.glb" },
],
outputPath: "/path/to/composed.glb",
config: {
googleApiKey: process.env.GEMINI_API_KEY!,
tencentApiKey: process.env.TENCENT_API_KEY!, // secretId:secretKey:region (or JSON)
// Optional:
// hunyuanModel: "hunyuan3d-3",
},
onProgress: (e) => console.log(`${(e.progress * 100).toFixed(0)}% ${e.stage}`),
});
console.log(result.outputPath, result.durationMs);
} catch (e) {
if (e instanceof InputError) {
// bad input: missing files, missing config, duplicate part ids, etc.
} else if (e instanceof ApiCallError) {
// upstream API failed; e.cause has the underlying detail
} else {
throw e;
}
}The output GLB is a tree of parts, each preserving the original materials and textures from its source GLB:
composed (Scene)
├── scientist (Node — placement TRS)
│ └── ...original sub-tree
└── controller
└── ...API
compose(input): Promise<ComposeResult>
interface ComposeInput {
imagePath: string;
parts: Array<{
id: string;
description: string; // used by the VLM to locate the part in ortho views
glbPath: string;
}>;
outputPath: string; // caller must create the parent directory
config: Config;
onProgress?: (event: ProgressEvent) => void;
}
interface Config {
googleApiKey: string;
tencentApiKey: string; // secretId:secretKey:region or JSON {secretId,secretKey,region}
hunyuanModel?: "hunyuan3d-3" | "hunyuan3d-3-turbo"; // default: hunyuan3d-3
}
interface ComposeResult {
outputPath: string;
durationMs: number;
}
interface ProgressEvent {
stage: "generate" | "render" | "detect" | "place" | "merge";
progress: number; // 0.2, 0.4, 0.6, 0.8, 1.0
}