@trikomi/core · Three.js WebGPU · React · Vite

TRIKOMI 3D SDK Documentation

A modular 3D rendering SDK built on Three.js (WebGPU renderer), React, MobX, and Vite. The SDK ships as a pre-compiled package (@trikomi/core) consumed by six demo applications in a PNPM workspace monorepo.

ℹ Info
The core source code is private. The demo repo consumes the compiled SDK packages via NPM dependencies. Local development (pnpm dev:sdk) supports dynamic source-code mapping if the private repository is adjacent. App developers build on top of the public plugin API.

Quick Start

Prerequisites

Install & Run Dev Server

# Clone the monorepo
git clone <repo-url> 3dviewer
cd 3dviewer

# Install all workspaces
pnpm install

# Start the root dev server (serves all apps at their paths)
pnpm dev

The Vite dev server starts at http://localhost:5173. Individual apps are accessible at:

  • logo/apps/viewer/ — 3D Core Viewer
  • logo/apps/sportswear-configurator/ — Sportswear Configurator
  • logo/apps/eyewear-tryon/ — Eyewear Try-on
  • logo/apps/face-mocap/ — Face Motion Capture
  • logo/apps/jewelry-configurator/ — Jewelry Configurator
  • logo/apps/box-configurator/ — Box Configurator
  • logo/apps/360tour/ — 360 Virtual Tour

Production Build

# Builds core SDK + all apps → ./dist/
pnpm build

# Serve the built output locally
pnpm serve
# → http://localhost:3000
✓ Tip
To build and preview a single app without rebuilding everything, use the workspace shortcuts: pnpm build:viewer, pnpm build:sportswear, pnpm build:eyewear, etc.

Project Structure

3dviewer/ ├── apps/ ← Demo applications (each is a Vite+React workspace) │ ├── box-configurator/ │ ├── eyewear-tryon/ │ ├── face-mocap/ │ ├── jewelry-configurator/ │ ├── sportswear-configurator/ │ └── viewer/ │ ├── npm-staging/ ← Pre-built SDK bundles (consumed by Vite) │ ├── public/ ← Shared static assets served by all apps │ ├── assets/wasm/ ← MediaPipe WASM files (face tracking) │ ├── draco/gltf/ ← Draco GLTF decoder binaries │ ├── textures/ ← Shared textures (fabric normals, SVGs) │ └── js/ ← Third-party scripts (jQuery, Kendo, Pako) │ ├── build-monorepo.js ← Merges all app builds into ./dist/ ├── index.html ← Root hub page (links to all apps) └── package.json ← PNPM workspaces root

Why a Shared public/?

All six apps share a single public/ directory at the monorepo root. Each app's vite.config.* sets publicDir: '../../public', so static assets like WASM binaries, Draco decoders, and textures are always available without duplicating them per app.


ThreeViewer

ThreeViewer is the core engine class. It sets up the Three.js WebGPU renderer, scene, camera, lighting, and render loop. It is the central object that all plugins attach to.

Constructor

import { ThreeViewer, viewerStore } from '@trikomi/core';

const viewer = new ThreeViewer(
  containerElement,  // HTMLDivElement to mount the canvas into
  viewerStore,       // MobX ViewerStore instance (shared across components)
  {
    assetBaseUrl?: string,       // Path prefix for built-in 3D assets
  }
);

Key Properties

Property Type Description
viewer.scene THREE.Scene The Three.js scene. Add your meshes here.
viewer.camera THREE.PerspectiveCamera Main perspective camera (45° FOV by default).
viewer.renderer THREE.WebGPURenderer WebGPU renderer with ACESFilmic tone mapping.
viewer.store ViewerStore Reactive MobX store driving UI state.
viewer.directionalLight THREE.DirectionalLight Primary directional light (adjustable).
viewer.ambientLight THREE.AmbientLight Ambient fill light.
viewer.secureSdk SecureWasmSdk WASM sandbox for premium shader execution.
viewer.authStatus AuthStatus 'AUTHENTICATING' | 'AUTHORIZED' | 'UNAUTHORIZED' | 'TAMPERED'

Key Methods

Method Description
viewer.addPlugin(plugin) Attaches a plugin to the viewer. Calls plugin.onAttach(viewer).
viewer.getPlugin(PluginClass) Returns a plugin by its class constructor, or undefined.
viewer.removePlugin(PluginClass) Detaches and removes a plugin by its class constructor.
viewer.mount(container) Mounts the canvas into a new DOM element (re-mount after navigation).
viewer.dispose() Cleans up all resources, cancels animation frame, disposes plugins.
viewer.handleResize() Updates camera aspect ratio and renderer size. Called automatically on resize.

Plugin System

Every feature of the viewer — from orbit controls to diamond shaders — is encapsulated in a plugin. Plugins are decoupled, composable, and lifecycle-managed by ThreeViewer.

Creating a Custom Plugin

import { ViewerPlugin, ThreeViewer } from '@trikomi/core';

export class MyPlugin extends ViewerPlugin {
  readonly id = 'MyPlugin';  // Unique identifier

  onAttach(viewer: ThreeViewer): void {
    super.onAttach(viewer);
    // Setup code here – viewer.scene, viewer.camera, etc. are available
  }

  onUpdate(deltaTime: number): void {
    // Called every animation frame with seconds since last frame
  }

  onDetach(): void {
    // Cleanup resources (remove event listeners, dispose geometries, etc.)
    super.onDetach();
  }
}

// Attach to a viewer instance:
viewer.addPlugin(new MyPlugin());

// Retrieve later:
const myPlugin = viewer.getPlugin(MyPlugin);

Plugin Lifecycle

  • onAttach(viewer) — called immediately when the plugin is added via addPlugin(). Sets up Three.js objects, event listeners, reactions.
  • onUpdate(deltaTime) — called each animation frame (optional). Use for animations and per-frame logic.
  • onRender() — called after the Three.js render call (optional). Use for post-render operations.
  • onDetach() — called when plugin is removed. Must dispose all resources to prevent memory leaks.

Plugin Reference

GLTFPlugin
Loads .glb/.gltf files with Draco and Meshopt decompression. Call plugin.loadModel(url) to swap models at runtime.
Free
OrbitControlsPlugin
Mouse/touch orbit, pan, and zoom. Configurable damping, polar angle limits, and auto-rotate.
Free
EnvironmentPlugin
Loads HDR/EXR environment maps for Image-Based Lighting. Includes several built-in env maps from the core assets.
Premium
DiamondPlugin
Physically-based diamond ray-tracing shader. Multi-bounce internal reflections, dispersion, and fire effects.
Premium
SSGIPlugin
Screen-Space Global Illumination for indirect lighting bounces. Significant realism boost for metallic scenes.
Premium
SSRPlugin
Screen-Space Reflections for glossy surfaces. Works best with environment maps.
Premium
ProgressiveShadowPlugin
Accumulates soft ground shadows over multiple frames. Provides studio-quality contact shadows.
Premium
FloorPlugin
Adds a reflective ground plane. Configurable opacity, color, and roughness.
Premium
BloomPlugin
HDR bloom post-processing using Three.js TSL. Configurable threshold, strength, and radius.
Premium
CinematicPlugin
Premium cinematic grading and post-processing. Controls Vignette, Chromatic Aberration, Film Grain, Exposure, Contrast, and Saturation.
Premium
DOFPlugin
Depth of Field (bokeh) post-processing. Configurable focus distance and aperture.
Premium
FaceMocapPlugin
Real-time face tracking via MediaPipe. Drives 3D avatar blend shapes. Supports live video, LiveLink, and debug overlays.
Premium
AnimationPlugin
Plays and controls GLTF animation clips. Supports blend weights, cross-fading, and speed control.
Premium
CenterModelPlugin
Centers and floors a model based on its bounding box. Auto-adjusts camera distance.
Free
TransformGizmoPlugin
Translate / rotate / scale gizmo for selected objects. Keyboard shortcuts: G, R, S.
Premium
MaterialRaycasterPlugin
Click-to-select mesh by raycasting. Fires selection events consumed by MaterialEditor UI.
Premium
MeasurementPlugin
Click two points to measure distance in 3D space. Renders line and label in scene.
Premium
OutlinePlugin
Post-process outline effect for selected objects. Configurable color and thickness.
Premium
ExportPlugin
Exports the scene as PNG screenshot or GLTF file.
Premium
GridHelperPlugin
Toggleable infinite grid overlay for spatial reference.
Free
StatsPlugin
Overlays FPS, draw calls, and memory stats. Uses stats.js internally.
Free
CameraPlugin
Save and recall named camera positions. Smooth tween between viewpoints.
Premium
TourPlugin
Renders 360-degree spherical panoramas and manages interactive room-linking hotspots.
Premium

ViewerStore

viewerStore is a singleton MobX observable store exported from @trikomi/core. It acts as the reactive bridge between the 3D engine and React UI components. Wrap components with MobX's observer() to auto-render on store changes.

import { viewerStore } from '@trikomi/core';
import { observer } from 'mobx-react-lite';

// In React components:
const MyUI = observer(() => (
  <div>{viewerStore.activeModelName}</div>
));

// Update from anywhere – UI auto-updates:
viewerStore.setBackgroundColor('#1a1a2e');
viewerStore.setActiveModelName('My Model');

Key observable properties include activeModelName, backgroundColor, isModelLoading, modelError, floorTransparent, and environmentIntensity.


Demo Applications

Each app is an independent Vite + React workspace under apps/ that imports @trikomi/core as a dependency.

ℹ Info
All apps share a root public/ directory via publicDir: '../../public' in their vite.config. This means static assets (WASM, Draco, textures) are never duplicated.

logo3D Viewer (apps/viewer)

Full-featured model viewer

A complete 3D model viewer with a full plugin suite. Demonstrates using nearly all available plugins together. Features a side panel MaterialEditor for PBR material editing, a ModelLoader for drag-and-drop GLTF uploads, and a DiamondTest page for showcasing the ray-tracing diamond shader.

File Purpose
src/components/ThreeCanvas.tsx Engine init, plugin attachment, auth-gating pattern
src/components/MaterialEditor.tsx PBR material property editor panel
src/pages/DiamondTest.tsx Diamond shader demo page

logoSportswear Configurator (apps/sportswear-configurator)

Product customization

An interactive jersey configurator. Users can change panel colors, upload logos, add text, switch fabric normal maps (mesh / knit / smooth), and move graphics freely on the UV canvas. Uses a custom TextureCompositor to composite SVG layers onto a WebGL canvas texture in real time.

Key architecture

  • TextureCompositor — composites SVG base + user logos + text into a single THREE.CanvasTexture.
  • ConfiguratorStore — MobX store tracking parts, colors, logos, and text items.
  • Fabric normal maps loaded from public/textures/; SVG base from public/textures/JSY-85 RL.svg.

logoEyewear Try-on (apps/eyewear-tryon)

AR face try-on

Augmented Reality eyewear try-on using FaceMocapPlugin and a live webcam feed. Tracks 478 facial landmarks via MediaPipe and positions/orients 3D glasses onto the face in real time. Allows material editing of lens and frame properties. Includes a natural lighting mode that samples the webcam background for environment-matched reflections.

Setup notes

  • Requires HTTPS (webcam permission). In dev, uses @vitejs/plugin-basic-ssl for a self-signed cert.
  • MediaPipe WASM is loaded from public/assets/wasm/. In prod the path resolves to ../assets/wasm/.
  • The face occluder (head_occluder.obj) is rendered as a depth mask to hide the glasses behind the face boundary.

logoFace Motion Capture (apps/face-mocap)

Unreal/Unity LiveLink

Full-face motion capture streaming blend shapes to Unreal Engine or Unity via a WebSocket LiveLink protocol. Tracks 52 ARKit-compatible blend shapes. Supports raccoon and glasses avatar modes for local preview. Blend shapes are displayed in real time in the UI panel.

LiveLink

Enter your Unreal/Unity LiveLink server address (e.g. 192.168.1.100:11111) in the panel and click Connect. Blend shape data is streamed over WebSocket.

logoJewelry Configurator (apps/jewelry-configurator)

Diamond rendering

Showcases the DiamondPlugin with an engagement ring model. Demonstrates multi-bounce ray-traced internal reflections with wavelength-accurate dispersion (fire). Supports switching gem cut styles and adjusting render quality settings.

logoBox Configurator (apps/box-configurator)

Parametric packaging

A parametric 3D box builder. Users set width, height, depth, wall thickness, and flap style. The box geometry is procedurally generated by the BoxBuilder class from scratch using THREE.BufferGeometry. Supports switching between different lid types.

logo360 Virtual Tour (apps/360tour)

Interactive tour builder

An interactive 360-degree virtual tour editor and viewer. Uses the TourPlugin from the @trikomi/tour package to render spherical panorama images and place interactive hotspots. Features a TourEditor interface for dragging and connecting hotspots to link rooms together, and a VirtualTour viewer for navigating the finalized tours.


Build Pipeline

1. Packages Build (Core SDK & Plugins)

The core SDK and all separated plugin packages (like @trikomi/face-mocap, @trikomi/tour, etc.) are bundled with esbuild, not Vite. This keeps them modular, framework-agnostic, and produces clean ES modules. The core build also:

  • Performs security hardening and integrity checks on the compiled output.
  • Copies 3D assets (.glb, .hdr, .exr) to dist/assets/.
  • Generates TypeScript type declarations.

2. App Builds (Vite)

Each app is built independently with vite build. All apps use these key config values:

// apps/<any-app>/vite.config.ts
defineConfig({
  base: './',               // Relative asset references → works in any subfolder
  publicDir: '../../public', // Shared WASM, Draco, textures
  build: {
    outDir: '../../dist/<appname>',
  }
})

3. Monorepo Merge (build-monorepo.js)

After all apps are built, this script:

  1. Creates a shared dist/assets/ directory.
  2. Rewrites index.html asset references from ./assets/../assets/ so they point to the shared root.
  3. Moves each app's hashed JS/CSS/WASM chunks into the shared dist/assets/ folder.
  4. Copies the root index.html hub page to dist/index.html.

Final dist layout

dist/ ├── index.html ← Hub page ├── assets/ ← All hashed JS/CSS/WASM chunks (shared) │ ├── index-XXX.js ├── draco/ ← Draco decoder binaries (from public/) ├── textures/ ← Fabric/SVG textures (from public/) ├── assets/wasm/ ← MediaPipe WASM (from public/) ├── viewer/ │ └── index.html ← App entry (references ../assets/) ├── sportswear-configurator/ ├── eyewear-tryon/ ├── face-mocap/ ├── jewelry-configurator/ ├── box-configurator/ ├── 360tour/ └── ...

Asset Path Strategy

Because apps are built with base: './' and deployed in subfolders (e.g. /demos/viewer/), absolute paths like /draco/ would resolve to the domain root — not the demo subfolder root. The following pattern is used throughout:

Environment Path Used Resolves To
Dev (pnpm dev) '/draco/gltf/' http://localhost:5173/draco/gltf/ — served from public/draco/gltf/
Prod (any subfolder) '../draco/gltf/' Navigates up from dist/viewer/dist/draco/gltf/

The same pattern applies to:

  • Draco decoder: GLTFPluginimport.meta.env.DEV ? '/draco/gltf/' : '../draco/gltf/'
  • MediaPipe WASM: FaceMocapPlugin constructor arg — DEV ? '/assets/wasm' : '../assets/wasm'
  • Textures: Sportswear ThreeCanvas — DEV ? '/textures/' : '../textures/'
✓ Rule of thumb
When adding new static assets: place them in public/, then reference them as import.meta.env.DEV ? '/your-path' : '../your-path' in JavaScript. For assets imported via Vite (images, SVGs, models), use a standard ES import — Vite handles hashing and path resolution automatically.

@trikomi/core SDK — Internal Developer Documentation