angular-three-gltf gives you a CLI to that turn GLTF assets into declarative and reusable Angular Three components.
This helps with performance optimization for asset-heavy Angular Three apps. It also allows you to modify your GLTF assets as Angular components, instead of working with 3D software like Blender.
- GLTF is thrown wholesale into the scene which prevents re-use, in threejs objects can only be mounted once
- Contents can only be found by traversal which is cumbersome and slow
- Changes to queried nodes are made by mutation, which alters the source data and prevents re-use
- Re-structuring content, making nodes conditional or adding/removing is cumbersome
- Model compression is complex and not easily achieved
- Models often have unnecessary nodes that cause extra work and matrix updates
- 🧑💻 It creates a virtual graph of all objects and materials. Now you can easily alter contents and re-use.
- 🏎️ The graph gets pruned (empty groups, unnecessary transforms, ...) and will perform better.
- ⚡️ It will optionally compress your model with up to 70%-90% size reduction.
Usage
$ npx angular-three-gltf@latest [Model.glb] [options]
Options
--output, -o Output file name/path
--keepnames, -k Keep original names
--keepgroups, -K Keep (empty) groups, disable pruning
--meta, -m Include metadata (as userData)
--shadows, -s Let meshes cast and receive shadows
--printwidth, -w Prettier printWidth (default: 120)
--precision, -p Number of fractional digits (default: 2)
--draco, -d Draco binary path
--suspense -u Make the component suspense-ready
--root, -r Sets directory from which .gltf file is served
--transform, -T Transform the asset for the web (draco, prune, resize)
--resolution, -R Transform resolution for texture resizing (default: 1024)
--simplify, -S Transform simplification (default: false) (experimental!)
--weld Weld tolerance (default: 0.0001)
--ratio Simplifier ratio (default: 0.75)
--error Simplifier error threshold (default: 0.001)
--debug, -D Debug output
- NodeJS must be installed
- three (>= 148.x)
- angular-three > 2.0.0
First you run your model through angular-three-gltf
. npx
allows you to use npm packages without installing them.
npx angular-three-gltf@latest model.gltf --transform
Add your model to your /public
folder as you would normally do. With the --transform
flag it has created a compressed copy of it (in the above case model-transformed.glb
). Without the flag just copy the original model.
/public
model-transformed.glb
The component can now be dropped into your scene.
<script>
import { Canvas } from '@threlte/core'
import Model from './Model.svelte'
</script>
<Canvas>
<Model />
</Canvas>
You can re-use it, it will re-use geometries and materials out of the box:
<Model position={[0, 0, 0]} />
<Model position={[10, 0, -10]} />
Or make the model dynamic. Change its colors for example:
<T.Mesh geometry={$gltf.nodes.robot.geometry} material={$gltf.materials.metal} material.color="green" />
Or exchange materials:
<T.Mesh geometry={$gltf.nodes.robot.geometry}>
<T.MeshPhysicalMaterial color="hotpink" />
</T.Mesh>
Make contents conditional:
{#if condition}
<T.Mesh geometry={$gltf.nodes.robot.geometry} material={$gltf.materials.metal} />}
{/if}
You don't need to do anything if your models are draco compressed, since useGltf
defaults to a draco CDN. By adding the --draco
flag you can refer to local binaries which must reside in your /public folder.
With the --transform
flag it creates a binary-packed, draco-compressed, texture-resized (1024x1024), webp compressed, deduped, instanced and pruned *.glb ready to be consumed on a web site. It uses glTF-Transform. This can reduce the size of an asset by 70%-90%.
It will not alter the original but create a copy and append [modelname]-transformed.glb
.
Add the --types
flag and your component will be typesafe.
<!--
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@0.0.1 ./stacy.glb -t
-->
<script lang="ts">
import type * as THREE from 'three'
import { Group } from 'three'
import { T, type Props, type Events, type Slots } from '@threlte/core'
import { useGltf, useGltfAnimations } from '@threlte/extras'
type $$Props = Props<THREE.Group>
type $$Events = Events<THREE.Group>
type $$Slots = Slots<THREE.Group>
export const ref = new Group()
type ActionName = 'pockets' | 'rope' | 'swingdance' | 'jump' | 'react' | 'shrug' | 'wave' | 'golf' | 'idle'
type GLTFResult = {
nodes: {
stacy: THREE.SkinnedMesh
mixamorigHips: THREE.Bone
}
materials: {}
}
const gltf = useGltf<GLTFResult>('/stacy.glb')
export const { actions, mixer } = useGltfAnimations<ActionName>(gltf, ref)
</script>
{#if $gltf}
<T is={ref} {...$$restProps}>
<T.Group name="Scene">
<T.Group name="Stacy" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
<T is={$gltf.nodes.mixamorigHips} />
<T.SkinnedMesh
name="stacy"
geometry={$gltf.nodes.stacy.geometry}
material={$gltf.nodes.stacy.material}
skeleton={$gltf.nodes.stacy.skeleton}
rotation={[-Math.PI / 2, 0, 0]}
scale={100}
/>
</T.Group>
</T.Group>
<slot {ref} />
</T>
{/if}
If your GLTF contains animations it will add @threlte/extras's useGltfAnimations
hook, which extracts all clips and prepares them as actions:
const gltf = useGltf('/stacy.glb')
export const { actions, mixer } = useGltfAnimations(gltf, ref)
If you want to play an animation you can do so at any time:
const onEvent = () => {
$actions.jump.play();
};
import { parse } from "@threlte/gltf";
import { GLTFLoader, DRACOLoader } from "three-stdlib";
const gltfLoader = new GLTFLoader();
const dracoloader = new DRACOLoader();
dracoloader.setDecoderPath("https://www.gstatic.com/draco/v1/decoders/");
gltfLoader.setDRACOLoader(dracoloader);
gltfLoader.load(url, (gltf) => {
const component = parse(filename, gltf, config);
});
The MIT License (MIT). Please see the License File for more information.