8000 GitHub - OmnomnomTee/gltfvue: 🎮 Turns GLTFs into Vue (TresJS) components
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

OmnomnomTee/gltfvue

 
 

Repository files navigation

Note

Work in progress. Should already work though. If you find any bugs please open an issue.

gltfjsx-preview.mp4


A small command-line tool that turns GLTF assets into declarative and re-usable Trejs Vue components.

The GLTF workflow on the web is not ideal ...

  • GLTF is thrown whole 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

GLTFJSX fixes that

  • 🧑‍💻 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

Usage
  $ node cli.js [Model.glb] [options]

Options
  --output, -o        Output file name/path
  --types, -t         Add Typescript definitions
  --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: 3)
  --draco, -d         Draco binary path
  --root, -r          Sets directory from which .gltf file is served
  --instance, -i      Instance re-occuring geometry
  --instanceall, -I   Instance every geometry (for cheaper re-use)
  --transform, -T     Transform the asset for the web (draco, prune, resize)
    --resolution, -R  Resolution for texture resizing (default: 1024)
    --keepmeshes, -j  Do not join compatible meshes
    --keepmaterials, -M Do not palette join materials
    --format, -f      Texture format (default: "webp")
    --simplify, -S    Mesh simplification (default: false)
      --weld          Weld tolerance (default: 0.00005)
      --ratio         Simplifier ratio (default: 0)
      --error         Simplifier error threshold (default: 0.0001)
  --debug, -D         Debug output

A typical use-case

First you run your model through gltfvue.

node cli.js model.gltf --transform

This will create a Model.vue file that plots out all of the assets contents.

/*
auto-generated by: https://github.com/OmnomnomTee/gltfvue
author: abcdef (https://sketchfab.com/abcdef)
license: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
source: https://sketchfab.com/models/...
title: Model
*/

<script setup>
  import { useGLTF } from '@tresjs/cientos'
  
  const { nodes, materials } = await useGLTF('/model-transformed.glb', { draco: true })
</script>

<template>
  <TresGroup>
    <TresGroup>
      <TresMesh :geometry="nodes.model.geometry" :material="materials['default']" />
    </TresGroup>
  </TresGroup>
</template>

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.

import { TresCanvas } from '@tresjs/core'
import Model from '@/components/Model.vue'

<template>
  <TresCanvas>
  <Model />

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:

<TresMesh :geometry="nodes.robot.geometry" :material="materials.metal" material-color="green" />

Add events:

<TresMesh :geometry="nodes.robot.geometry" :material="materials.metal" @click="handleClick" />

Features

⚡️ Draco and meshopt compression ootb

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.

⚡️ Auto-transform (compression, resize)

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.

⚡️ Type-safety

Add the --types flag and your GLTF will be typesafe.

type GLTFResult = GLTF & {
  nodes: { robot: THREE.Mesh; rocket: THREE.Mesh }
  materials: { metal: THREE.MeshStandardMaterial; wood: THREE.MeshStandardMaterial }
}

export default function Model(props: JSX.IntrinsicElements['group']) {
  const { nodes, materials } = useGLTF<GLTFResult>('/model.gltf')

⚡️ Easier access to animations

If your GLTF contains animations it will add Clientos useAnimations hook, which extracts all clips and prepares them as actions:

const { scene:model, nodes, materials, animations } = await useGLTF('/model.gltf')
const { actions } = useAnimations(animations, model)

If you want to play an animation you can do so at any time:

<TresMesh @click="(e) => {actions.jump.play()}" />

Using the parser stand-alone

import { parse } from 'gltfvue'
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 jsx = parse(gltf, optionalConfig)
})

Using the parser stand-alone for scenes (object3d's)

const jsx = parse(scene, optionalConfig)

Using GLTFStructureLoader stand-alone

The GLTFStructureLoader can come in handy while testing gltf assets. It allows you to extract the structure without the actual binaries and textures making it possible to run in a testing environment.

import { GLTFStructureLoader } from 'gltfjsx'
import fs from 'fs/promises'

it('should have a scene with a blue mesh', async () => {
  const loader = new GLTFStructureLoader()
  const data = await fs.readFile('./model.glb')
  const { scene } = await new Promise((res) => loader.parse(data, '', res))
  expect(() => scene.children.length).toEqual(1)
  expect(() => scene.children[0].type).toEqual('mesh')
  expect(() => scene.children[0].material.color).toEqual('blue')  
})

Requirements

About

🎮 Turns GLTFs into Vue (TresJS) components

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%
0