flash55558817 downloadsTurn 3D models into linked knowledge assets.
A local-first Obsidian 3D viewer focused on knowledge workflows. It renders common 3D assets in a Babylon.js viewport, lets you annotate key parts, and turns models into linked notes. Common mesh formats load directly, while CAD, FBX, and interchange formats can be converted to GLB through local tools.
English | 简体中文
| Capability | Windows / macOS / Linux | iOS / iPadOS / Android |
|---|---|---|
| Direct formats (GLB, GLTF, OBJ, STL, PLY) | Yes | Yes |
| Direct file view | Yes | Yes |
| Inline embed / Live Preview for direct formats | Yes | Yes |
| Workbench layout | Full desktop layout | Simplified single-column mobile layout |
| Local conversion (CAD, FBX, 3MF, DAE, SLDPRT) | Yes | No |
| Converter diagnostics and local CLI checks | Yes | No |
Already converted .ai3d-converted.glb assets |
Yes | Yes |
npm install
npm run build
Open your local Obsidian vault folder on your computer.
Create this folder inside the vault:
<your-vault>/.obsidian/plugins/ai-model-workbench/
Copy main.js, manifest.json, and styles.css into that folder.
In Obsidian, open Settings > Community Plugins and enable AI Model Workbench.
Put a supported model file into the same vault, for example model.glb.
In any note inside that vault, embed it like this:
![[model.glb]]
![[model.glb|400x300]]
Use Quick Start if you only want the fastest setup.
<vault>/.obsidian/plugins/ai-model-workbench/
All install methods place the same three files in that folder:
| File | Size | Description |
|---|---|---|
main.js |
~1.7 MB | Plugin runtime (Babylon.js core) |
manifest.json |
~1 KB | Obsidian plugin manifest |
styles.css |
~10 KB | Plugin styles |
Direct rendering works on desktop and mobile. Local converter tools for CAD, FBX, 3MF, and DAE require desktop OS access.
git clone https://github.com/flash555588/ai-model-workbench.git
cd ai-model-workbench
npm install
npm run build
<vault>/.obsidian/plugins/ai-model-workbench/ if it does not exist.main.js, manifest.json, and styles.css into that folder.AI Model Workbench in Settings > Community Plugins.main.js, manifest.json, and styles.css from Releases.<vault>/.obsidian/plugins/ai-model-workbench/ if it does not exist.AI Model Workbench in Settings > Community Plugins.<vault>/.obsidian/plugins/ already exists.ai-model-workbench that points to this repository.Windows (PowerShell):
New-Item -ItemType SymbolicLink `
-Path "C:\path\to\your-vault\.obsidian\plugins\ai-model-workbench" `
-Target "C:\path\to\ai-model-workbench"
macOS / Linux:
ln -s /path/to/ai-model-workbench \
/path/to/your-vault/.obsidian/plugins/ai-model-workbench
npm install once if needed.npm run dev while developing.AI Model Workbench in Settings > Community Plugins.model.glb.![[model.glb]]
![[model.glb|400x300]]
AI Model Workbench does not collect telemetry, phone home, or run background network sync. Model previews are loaded from files already present in the Obsidian vault, and OBJ material/texture references are resolved from the vault instead of being fetched from the network.
The bundled Babylon.js runtime contains generic loader utilities that are capable of loading URLs for web applications. This plugin passes vault file bytes to Babylon as data URLs, overrides OBJ MTL loading to avoid remote fetches, and installs a runtime guard that rejects explicit http(s) / ws(s) asset or script URLs while disabling Babylon retry hooks for those requests. Optional converter diagnostics and conversions run only after a user action and execute local tools on desktop platforms.
Release assets are limited to the three files Obsidian downloads: main.js, manifest.json, and styles.css. GitHub Actions builds these files from source and publishes artifact attestations for provenance verification.
AI Model Workbench does not include donation prompts, payment flows, or cryptocurrency wallet addresses in the plugin bundle.
| Format | Extension | Features |
|---|---|---|
| GLB / GLTF | .glb .gltf |
PBR materials, animations, textures, scene hierarchy |
| STL | .stl |
Binary format, per-face colors (VisCAM/SolidView) |
| OBJ | .obj |
MTL materials, vault-relative texture resolution |
| PLY | .ply |
ASCII/binary, vertex colors, point cloud support |
SPLAT preview is temporarily disabled in packaged builds while its loader is replaced with a local-only implementation.
.splat loading; then reopen it after idle-render stability is improved for Windows and large scenes; finally evaluate .spz separately, and only re-enable it if the decoder dependencies can be bundled locally and reviewed as local assets.| Format | Extension | Converter | Output |
|---|---|---|---|
| STEP | .step .stp |
Python + CadQuery/OCCT | GLB |
| IGES | .iges .igs |
Python + CadQuery/OCCT | GLB |
| BREP | .brep |
Python + CadQuery/OCCT | GLB |
| SLDPRT | .sldprt |
FreeCAD | GLB |
| 3MF | .3mf |
Python + trimesh | GLB |
| DAE | .dae |
Python + trimesh | GLB |
| FBX | .fbx |
FBX2glTF | GLB |
| Feature | GLB/GLTF | STL | OBJ | PLY | FBX (converted) | CAD |
|---|---|---|---|---|---|---|
| Mesh | Yes | Yes | Yes | Yes | Yes | Yes |
| Point Cloud | No | No | No | Yes | No | No |
| Materials | PBR | Basic | MTL | Basic | Basic | No |
| Textures | Embedded | No | External | No | No | No |
| Colors | Vertex | Face | No | Vertex | No | Face (STEP) |
| Animation | Yes | No | No | No | Yes | No |
Write a wikilink anywhere in your note. Works in Reading and Live Preview.
![[model.glb]]
![[model.glb|400x300]]
3d Code BlockQuick — file path only:
```3d model.glb
```
Full config — camera, lights, scene, multi-model:
```3d
{
"models": [
{ "path": "model.glb" },
{ "path": "part.stl", "color": "#ff0000", "wireframe": true }
],
"camera": { "fov": 30, "position": [5, 5, 5] },
"lights": [
{ "type": "hemisphere", "color": "#fff", "intensity": 1 },
{ "type": "directional", "position": [10, 20, 10] }
],
"scene": { "autoRotate": true, "grid": true },
"width": "100%",
"height": 500
}
```
| Section | Key fields |
|---|---|
models[] |
path (required), color, wireframe |
camera |
fov, position, lookAt, mode ("perspective" / "orthographic") |
lights[] |
type ("hemisphere" "directional" "point" "spot" "ambient" "attachToCam"), color, intensity, position |
scene |
background, autoRotate, autoRotateSpeed, grid, axis, groundShadow, transparent |
stl |
color, wireframe (defaults for STL files) |
| top-level | width, height |
3dgrid Code BlockRender multiple models in one viewport using layout presets.
```3dgrid
{
"models": [
{ "path": "v1.step" },
{ "path": "v2.step" },
{ "path": "v3.step" }
],
"preset": "compare"
}
```
| Preset | Layout |
|---|---|
compare |
Side-by-side A/B |
showcase |
Multi-angle single model |
explode |
Ring arrangement |
timeline |
Horizontal strip |
gallery |
All in one scene (default) |
compose |
Custom sections |
3dgrid accepts the same camera, lights, scene fields as 3d, plus: preset, params, columns, rowHeight, gapX, gapY, sections, direction.
Click any .glb/.gltf/.stl/.obj/.ply file in the file explorer.
| Type | Formats |
|---|---|
| Direct | .glb .gltf .stl .obj .ply |
| Conversion | .step .stp .iges .igs .brep .sldprt .3mf .dae .fbx |
| Key | Action |
|---|---|
R |
Reset view |
W |
Toggle wireframe |
G |
Toggle orientation gizmo |
B |
Toggle bounding box |
Space |
Play/pause animation |
Esc |
Exit annotation mode |
Add labeled bookmarks directly on model surfaces. Annotations persist per model file.
Direct View & Workbench (edit mode):
Esc to exit annotation modeDepth-aware occlusion: Pins behind geometry display blurred and dimmed. When the camera stops moving for ~250ms, fully occluded pins are automatically hidden, leaving only visible bookmarks.
Code blocks & Live Preview: Saved annotations display as read-only overlays with the same occlusion behavior.
| Setting | Default | Description |
|---|---|---|
| Language | auto | UI language (English / Simplified Chinese / auto-detect) |
| Canvas height | 400 | Preview height in pixels |
| Auto-rotate | off | Start with turntable animation |
| Auto-rotate speed | 0.5 | Rotation speed (0.1-2.0) |
| Render quality | high | Quality preset (low/medium/high) |
| Render scale | 1.0 | Resolution multiplier (0.25-2.0) |
| Snapshot folder | Media/3D Previews | Export folder |
| Snapshot naming | model-name | File naming mode for exported PNG snapshots |
| Report folder | Analysis/3D Reports | Knowledge notes folder |
| Log level | warn | Console log verbosity |
| Setting | Description |
|---|---|
| Enable CAD converter | Enable STEP/IGES/BREP via CadQuery |
| Enable SLDPRT converter | Enable SolidWorks via FreeCAD |
| Enable mesh converter | Enable 3MF/DAE via trimesh |
| Enable OBJ2GLTF converter | Optional OBJ normalization through obj2gltf |
| Enable FBX2glTF converter | Enable FBX conversion through FBX2glTF |
| Python command path (for CAD conversion) | Override the Python executable used for STEP/IGES/BREP conversion |
| FreeCADCmd path (for SLDPRT conversion) | Override the FreeCAD executable used for .sldprt conversion |
| obj2gltf command path | Override the obj2gltf CLI path |
| FBX2glTF command path | Override the FBX2glTF CLI path |
| Python command path (for 3MF/DAE conversion) | Override the Python executable used for 3MF/DAE conversion |
| Converter command diagnostics | Show which executable path the plugin will actually use and run lightweight self-checks for Python environments and converter CLIs |
The rendering layer is cross-platform: direct formats like GLB, OBJ, STL, PLY, and already-converted .ai3d-converted.glb assets can render anywhere Obsidian Desktop can provide WebGL.
On iOS, iPadOS, and Android, the plugin now supports direct formats such as GLB, GLTF, OBJ, STL, and PLY. Local conversion routes for CAD, FBX, 3MF, DAE, and SLDPRT remain desktop-only because they depend on external CLI tools and Python environments.
The conversion layer is less portable because it depends on local tools and Python environments that vary by machine. Use the converter diagnostics panel in plugin settings as the first check when a CAD or mesh format fails. It verifies both the executable path the plugin resolved and whether the selected Python environment can import the required packages or the native converter CLI can launch.
For repository-level implementation rules, see docs/cross-platform-development.md.
On macOS in particular, the system Python at /usr/bin/python3 often exists but does not include CAD packages. If diagnostics show that path and the self-check fails, install a separate Python environment and point the plugin setting to that interpreter explicitly.
Only needed for CAD, FBX, and mesh conversion. Direct formats work without any external tools.
# Install
pip install cadquery trimesh
Verify with the Python command your OS uses:
py -c "import cadquery; print('OK')"python3 -c "import cadquery; print('OK')"If diagnostics resolve to /usr/bin/python3 on macOS and the import check fails, install a separate Python (for example Homebrew Python), install cadquery and trimesh there, then set that interpreter path in plugin settings.
Install FreeCAD for your platform:
brew install --cask freecadfreecadcmd is availableThe plugin prefers the explicit setting and environment variable first, then checks common user-managed install locations, then PATH, and finally system fallback hints such as:
%LOCALAPPDATA%\Programs\FreeCAD*\bin\FreeCADCmd.exe/Applications/FreeCAD.app/Contents/MacOS/FreeCADCmd, /usr/local/bin/FreeCADCmd, /opt/homebrew/bin/FreeCADCmd/usr/bin/freecadcmdpip install trimesh numpy networkx pycollada
Auto-discovery: Same Python as CadQuery (see above).
Override: Environment variable AI3D_ASSIMP_CMD.
The plugin already has a built-in OBJ loader. obj2gltf is an optional alternative that can produce higher-fidelity GLB output.
Install:
npm install -g obj2gltf
Resolution order: The plugin prefers the explicit setting and environment variable first, then checks common user-managed install locations, then PATH, and finally system fallback hints such as obj2gltf.cmd on Windows and obj2gltf in standard macOS/Linux locations like /usr/local/bin/obj2gltf and /opt/homebrew/bin/obj2gltf.
Enable: Settings > Enable OBJ2GLTF converter, or set "obj2gltf path".
FBX files are converted to GLB through the local FBX2glTF binary. The older community FBX loader is not bundled because its current release targets Babylon.js 8, while this plugin uses Babylon.js 9.
Install:
Download or build FBX2glTF for your platform and place the binary in a known location.
Resolution order: The plugin prefers the explicit setting and environment variable first, then checks common user-managed install locations, then PATH, and finally system fallback hints such as:
C:\Program Files\FBX2glTF\FBX2glTF-windows-x64.exe
C:\Program Files\FBX2glTF\FBX2glTF.exe
/usr/local/bin/FBX2glTF
/opt/homebrew/bin/FBX2glTF
/usr/local/bin/fbx2gltf
Enable: Settings > Enable FBX2glTF converter, or set "FBX2glTF path".
| Variable | Purpose |
|---|---|
AI3D_FREECAD_CMD |
Python command for CadQuery |
AI3D_FREECADCMD |
FreeCADCmd path |
AI3D_ASSIMP_CMD |
Python command for trimesh |
AI3D_OBJ2GLTF_CMD |
obj2gltf command path |
AI3D_FBX2GLTF_CMD |
FBX2glTF command path |
The legacy alias AI3D_FREECMDCMD is still accepted for compatibility, but new setups should use AI3D_FREECADCMD.
src/
├── main.ts # Plugin lifecycle, commands
├── domain/
│ ├── models.ts # Shared interfaces
│ └── constants.ts # Default settings, extensions
├── store/
│ ├── create-store.ts # Custom store primitive
│ └── plugin-store.ts # Obsidian saveData bridge
├── render/babylon/
│ ├── scene.ts # BabylonModelPreview class
│ ├── grid.ts # GridRenderer class
│ ├── annotations.ts # AnnotationManager (pin overlay + occlusion)
│ ├── picking.ts # Click-to-pick with highlight
│ ├── loaders/
│ │ ├── stl-loader.ts # Custom binary STL parser
│ │ ├── ply-loader.ts # Custom ASCII/binary PLY parser
│ │ └── register.ts # Babylon SceneLoader plugins
│ └── presets/ # Grid layout presets
├── io/
│ ├── formats/
│ │ └── registry.ts # Format capability registry
│ ├── conversion/
│ │ ├── manager.ts # Conversion orchestration
│ │ └── adapters/ # Converter implementations
│ └── model-pipeline.ts # Format routing logic
└── view/
├── workbench/ # Main workbench UI
├── inline/ # Code blocks, live preview
└── direct-view.ts # Direct file opening
┌─────────────────────────────────────────────────────────────┐
│ 1. Format Detection │
│ └─ getFormatCapability(ext) → { family, strategy } │
│ │
│ 2. Route Decision │
│ ├─ strategy: "direct" → prepareDirectLoad() │
│ └─ strategy: "convert" → convertForPreview() │
│ │
│ 3. Data Loading │
│ ├─ readBinaryPath() → ArrayBuffer │
│ └─ [if converted] → read converted .glb │
│ │
│ 4. Babylon Rendering │
│ ├─ GLB/GLTF/OBJ → SceneLoader.ImportMeshAsync() │
│ ├─ STL → loadSTLBuffer() (direct parse) │
│ └─ PLY → loadPLYBuffer() (direct parse) │
└─────────────────────────────────────────────────────────────┘
Babylon.js v9 SceneLoader has a bug where custom plugins receive data URL strings instead of ArrayBuffer when loading via SceneLoader.ImportMeshAsync(). Built-in loaders (GLTF and OBJ) are unaffected.
Workaround: STL and PLY parsers are called directly with the raw ArrayBuffer, bypassing SceneLoader entirely.
{filename}.ai3d-converted.glb| Issue | Affected Formats | Workaround |
|---|---|---|
| External converter required | FBX | Install and enable FBX2glTF |
| Binary-only STL | STL | Convert ASCII STL to binary |
| External tools required | STEP/IGES/BREP/SLDPRT | Install Python + CadQuery or FreeCAD |
| Texture path resolution | OBJ | Place textures in same directory as OBJ |
| Conversion timeout | SLDPRT | 10-minute timeout for complex assemblies |
npm install # Install dependencies
npm run dev # Development build with watch
npm run build # Production build
npm run typecheck # TypeScript type check
ai-model-workbench/
├── main.js # 1.7 MB (minified, Babylon.js core)
├── manifest.json # Plugin manifest
├── styles.css # Plugin styles
└── src/ # Source code
Releases are published by the GitHub Actions Release workflow. Push a tag that matches manifest.json, for example v0.1.7, or run the workflow manually. The workflow uploads only main.js, manifest.json, and styles.css, removes unsupported release assets, and generates GitHub artifact attestations for the published files.
| Platform | Status |
|---|---|
| Windows | Full support |
| macOS | Full support |
| Linux | Full support |
| Obsidian Mobile | Supported (reduced resolution) |
Babylon.js core is ~98% of the bundle size. The project uses:
@babylonjs/core/Engines/engine.js) instead of barrel importsWithout subpath imports, the bundle would be ~7 MB instead of 1.7 MB.
MIT