Skip to content

LoaderService

Loads 3D model files into the scene. Handles GLTF/GLB, FBX, PLY, LAS (modern ILoader-based), STL, OBJ (legacy), and chunked manifest-based models.

Access

Registered under the name "loader". No service dependencies.

ts
import { LoaderService } from "@optellix/xviewr-sdk";

await viewer.ready();
const loader = viewer.getService<LoaderService>("loader");
const model = await loader?.loadFile({
  url: "/models/part.glb",
  type: "glb",
  filename: "part.glb",
});

Public API

Lifecycle

  • init(context: ServiceContext): Promise<void>
  • destroy(): Promise<void>
  • getStatus(): ServiceStatus

Loading

  • loadFile(fileSpec: FileSpec, options?: LoadOptions): Promise<THREE.Object3D> — generic entry point. Dispatches by fileSpec.type. For type: "chunked", delegates to loadChunkedModel.
  • loadChunkedModel(manifestUrl: string, options?: ChunkedLoadOptions & { fileSpec?: FileSpec }): Promise<THREE.Group> — fetches a chunk manifest, loads baseline LOD chunks concurrently, returns a root Group. Detail LODs are loaded on demand by LODService.

Registration / queries

  • registerLoader(loader: ILoader): Promise<void> — register a custom loader by extension.
  • getSupportedFormats(): string[] — flat list of extensions plus "chunked".

Types

ILoader

ts
interface ILoader {
  readonly name: string;
  readonly supportedExtensions: string[]; // e.g. [".glb", ".gltf"]
  readonly description: string;
  canLoad(url: string, extension: string): boolean;
  load(url: string, options?: ILoaderOptions): Promise<LoadResult>;
  dispose?(): void;
}

ILoaderOptions

ts
interface ILoaderOptions {
  onProgress?: (progress: number) => void;
  signal?: AbortSignal;
}

LoadResult

ts
interface LoadResult {
  object3d: THREE.Object3D;
  metadata: {
    format: string;
    fileName: string;
    fileSize?: number;
    loadedAt?: string;
    loadedBy?: string;
    statistics?: { triangles: number; vertices: number; objects: number };
    [key: string]: any;
  };
}

Events

EventPayload
loader:registered{ loader: string; extensions: string[] }
model:loading-started{ fileSpec: FileSpec }
model:loading-progress{ fileSpec: FileSpec; progress: number }
model:loading-error{ error: LoaderError; fileSpec: FileSpec }
model:loaded{ model: THREE.Object3D; fileSpec: FileSpec }
model:chunked-loading-started{ manifestUrl; root; fileSpec; chunkCount }
model:chunk-loaded{ chunkId; root; group; fileSpec; loaded; total }
model:chunked-ready{ root; fileSpec; chunkCount }
model:edges-loaded{ scene; appliedCount }
model:edges-failed{ url; reason }

Example

ts
const loader = viewer.getService<LoaderService>("loader");
if (!loader) throw new Error("loader service unavailable");

const root = await loader.loadFile(
  { url: "/models/assembly.glb", type: "glb", filename: "assembly.glb" },
  { onProgress: (p) => console.log(`${(p * 100).toFixed(1)}%`) },
);
viewer.root.add(root);

// Chunked manifest
const chunked = await loader.loadChunkedModel("/chunks/manifest.json", {
  baselineLevel: "lod0",
  baselineConcurrency: 8,
  onChunkLoaded: (id, loaded, total) =>
    console.log(`chunk ${id}: ${loaded}/${total}`),
});
viewer.root.add(chunked);

XViewr SDK and xConvert CLI documentation.