Skip to content

Latest commit

 

History

History
310 lines (228 loc) · 15.5 KB

README.md

File metadata and controls

310 lines (228 loc) · 15.5 KB

gltf-type-toolkit

npm version npm downloads license

This plugin generates type-safe glTF file representations in TypeScript and optimizes the loading and bundling of models in web projects, while being bundler-agnostic (Vite, Rollup, Webpack, esbuild, Rspack, ...).

project overview

This plugin scans all model files in the project source, deconstructs the glTF JSON representation, and places generated type files next to them. It creates three.js types and uses it internally to parse the glTF files, including modifications like path resolutions etc.

With this plugin you get:

  • ✅ Type safe glTF file representations with correct inner three.js types like Object3D, Mesh, etc..
    • ❗ Currently, we primarily support and generate the three.js types Object3D, Group, and Mesh. Support for generating types for lights, cameras, materials, and other components is not yet implemented. See and subscribe to Issue #22 to stay updated on this development and be notified when these features are added.
  • ✅ Building will fail if a model is missing due to type-safe workflow.
  • ✅ Only the used models are bundled in the final product, not all included in your dev project.
  • ⚠️ Detects and handles Draco Compression during type generation automatically, see Draco Compression handling below for more information.
  • ✅ Works with glTF Seperate (.gltf + .bin + textures), glTF Embedded (only .gltf) and glTF Binary (.glb) files, see glTF Versions and Representations below for more information.
  • ✅ ESM ready.
  • ⚠️ Build tool & bundler agnostic thanks to Unplugin, so use it with your favorite one, but see chapter Build Tool, Bundler and Framework Compatibility below for more details like compatibility or known problems:
  • ✅ Use it with your favorite framework built on top of the listed build tools above, such as:

Sponsoring

If you like this plugin and want to support us, we would be very happy to see you as a sponsor on GitHub ❤️
You can find the Sponsor button on the top right of the GitHub project page.
Thanks a lot for the support <3

Developer Documentation

For development-related information, including setup instructions for contributors, please refer to the Developer README README-dev.md.

Getting Started

Installation

  1. Install with your package manager (we use pnpm and recommend it):

    # choose your package manager
    pnpm add -D @todde.tv/gltf-type-toolkit
    npm install --save-dev @todde.tv/gltf-type-toolkit
    yarn add --dev @todde.tv/gltf-type-toolkit
    bun add --dev @todde.tv/gltf-type-toolkit
  2. Extend your .gitignore file to exclude generated files:

    # Generated glTF model files
    *.gltf.d.ts
    *.gltf.js
  3. Add the plugin to your build tool, for example with Vite:

    // vite.config.ts
    import gltf from '@todde.tv/gltf-type-toolkit/vite.js'
    
    export default defineConfig({
      plugins: [
        gltf({ // Plugin options are defined in: `@todde.tv/gltf-type-toolkit/src/entries/types.ts`
          /**
           * Module that provides an instance of a three.js GLTFLoader as the default export.
           */
          // customGltfLoaderModule: '@/utils/customGltfLoader.ts',
    
          /**
           * Print extra information.
           */
          // verbose: true,
        }),
      ],
    })

usage example with explanations

The plugin will run on:

  • on dependency installation
  • on dev server start
  • on project build

Here's an example of how to use the plugin. You can customize this example to suit your needs, such as saving models to different folders, changing paths, or adjusting how the model is handled after import.

  1. Install the plugin (See Installation above).

  2. Add a model to your project, here in the project source under @/assets/models. We copy the following in it:

    1. MyModel.gltf The glTF JSON representation that describes the model.
    2. MyModel.bin The binary file of the model, compressed with the Draco Compression.
    3. MyModel-texture1.png A texture that the model uses.
    4. MyModel-texture2.png A second texture that the model uses.
  3. Start your dev to generate all files. With our example model we get:

     @/assets/models/MyModel.gltf
     @/assets/models/MyModel.bin
     @/assets/models/MyModel-texture1.png
     @/assets/models/MyModel-texture2.png
    +@/assets/models/MyModel.gltf.d.ts    <- the typing
    +@/assets/models/MyModel.gltf.js      <- actual code with node get helper function and model graph representation

    Alternatively, you can run the script gltf-codegen supplied by the package to manually create those files. More details at Binary scripts.

  4. Import the type safe model in your code and use it, e.g.:

    // yourCustomFile.ts
    import { getNode, MyModelScene } from '@/assets/models/MyModel.gltf.js'
    
    // load the main model, so to say the wrapper in the scene
    const model = await getNode(MyModelScene)
    
    // load a child
    const innerModel = await getNode(MyModelScene.someInnerModel)
    
    // work with a model
    innerModel.receiveShadow = true
    innerModel.castShadow = true

Build Tool, Bundler and Framework Compatibility

Thanks to Unplugin, we support a wide variety of build tools and bundlers, resulting in the following compatibility in our project:

(Legend: 🟢 Tested & Supported | 🟡 Not Yet Tested | 🔴 Not Supported)

Build Tool Status Note
esbuild 🟢
Nuxt3 🟢
Rolldown 🟢 ⚠️ currently experimental in Unplugin
Rollup 🟢
Rspack 🟢
Vite 🟢
Astro 🟡
Farm 🔴 Tested & model files are not emitted (see Issue #27). Contributions welcome! ❤️
Webpack 🔴 Tested & model files are borked (see Issue #30). Contributions welcome! ❤️

glTF Versions and Representations

(Legend: 🟢 Tested & Supported | 🟡 Partially Supported | 🔴 Not Supported)

glTF Version File Representation Status Note
glTF 1.0 Any 🔴 glTF 2.0 was introduced in 2017 with major improvements. Avoid using the outdated glTF 1.0 standard in your projects.
glTF 2.0 Separate (.gltf + .bin + textures) 🟢 Recommended! Offers better performance, version control, caching, transferability, and debugging.
glTF 2.0 Embedded (only .gltf) 🟢 Assets are embedded directly into the .gltf file as base64 encoded data: sources within the uri fields, making single-file management simpler.
glTF 2.0 Binary (.glb) 🟡 Currently, only works with models that contain all referenced files in the binary chunk without external file references. Contributions welcome! ❤️

Draco Compression handling

This plugin can handle the Draco Compression during the type generation and handles your draco compressed models just fine.

On runtime though, you have to handle the draco compression yourself depending on your architecture and setup.
You can do this by creating a custom gltfLoader and pass it in the customGltfLoaderModule prop whn initializing the plugin. In this loader, you can handle the draco loader.

For example with Vite:

// vite.config.ts
import gltf from '@todde.tv/gltf-type-toolkit/vite.js'

export default defineConfig({
  plugins: [
    gltf({
      customGltfLoaderModule: '@/utils/gltfLoader.ts',
    }),
  ],
})
// @/utils/gltfLoader.ts
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'

const dracoLoader = undefined // use an existing draco loader or create a custom one by extending `DRACOLoader`

const gltfLoader = new GLTFLoader().setDRACOLoader(dracoLoader)

export default gltfLoader

Binary scripts

In addition to the commands in the scripts section of the package.json, this plugin also provides binary scripts.

Run them by adding this plugin to your project, be sure to have the dependencies installed and then add npx or pnpx before the commands.

gltf-codegen [DIR]

This script generates types and runtime code for all models found in DIR and sub-directories. DIR defaults to the current directory.

Run gltf-codegen --help for more options and details.

idea behind the scenes

On runtime it runs the default glTF loader mechanics of three.js under the hood. So, there is no extra layer of processing and therefore correct objects that three.js would give you when importing it yourself in your application.

To achieve this, we use patched versions of DRACOLoader and GLTFLoader to be able to run it in CLI because originally you can only use them in a browser runtime.

So we do not parse the glTF JSON file ourself but work with the representation after the three.js parsing. For code completion and for working with the model graph, we store the paths in the graph by caching the child indices in the children array from each object. With this, we can O(1) look up what the user requests without the need of traversing - neither depth first (default approach from three.js), nor breadth first.

One of the biggest challenges was making the plugin build tool agnostic bc not every build tool handles inner path references the same. Therefore, we have to reconstruct the buffers that link the glTF file with the binary and textures by text string & replace - kinda hacky, but reliable and the additional runtime is only performed in dev and build, not in the production runtime.

Troubleshooting with Known Problems and Limitations

If you have problems, maybe one of the following will help:

  • Delete your build output folder (maybe some old builds copied model files in there and our plugin is now scanning them).
  • We currently do not provide a watcher. Restart your dev environment when changing model files.

Attribution/ Contribution

Project founder & head of project:

Honorable mentions to people that helped this project:

  • Andreas Fehn as contributor who helped incredible with the project. Thank you mate, you rock <3

Respectable mentions to projects that helped this project:

  • zlig (zen-landscape-idle-game): A Japanese zen-inspired idle browser game that showcases lightweight web technologies like Vue and Three.js to create fully browser-based games. The idea and initial implementation of this plugin @todde.tv/gltf-type-toolkit originated during the development of zlig, where we required type-safe glTF representations to enable faster and more reliable development.

Used programs/ softwares, services and dependencies - besides the ones in ./package.json:

Used assets/ materials including images and 3D models:

  • [currently none]

License

Copyright (c) 2025-PRESENT Thorsten Seyschab
This project is licensed under the MIT License, see the LICENSE.md file for more details.