Skip to content

Commit

Permalink
feat: add gltfExporter composable
Browse files Browse the repository at this point in the history
  • Loading branch information
JaimeTorrealba committed Nov 25, 2023
1 parent 712f940 commit 0c77d33
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 1 deletion.
63 changes: 63 additions & 0 deletions playground/src/pages/misc/GLTFExporterDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<script setup lang="ts">
import { TresCanvas, useRenderLoop } from '@tresjs/core'
import { CameraControls, useTweakPane, useGLTFExporter } from '@tresjs/cientos'
import { MeshStandardMaterial, TorusGeometry } from 'three'
import { shallowRef } from 'vue'
const donutMaterial = new MeshStandardMaterial({})
const donutGeometry = new TorusGeometry(1, 0.5, 16, 32)
const boxRef = shallowRef()
const { pane } = useTweakPane()
const btn1 = pane.addButton({
title: 'Scene',
label: 'Download',
})
btn1.on('click', () => useGLTFExporter(boxRef.value.parent))
const btn2 = pane.addButton({
title: 'Cube',
label: 'Download', // optional
})
btn2.on('click', () => useGLTFExporter(boxRef.value, { fileName: 'cube', binary: true }))
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (boxRef.value) {
boxRef.value.rotation.x = elapsed
boxRef.value.rotation.y = elapsed
}
})
</script>

<template>
<TresCanvas
clear-color="#82DBC5"
window-size
>
<TresPerspectiveCamera :position="[0, 2, 5]" />
<TresMesh
v-for="i in 20"
:key="i"
:geometry="donutGeometry"
:material="donutMaterial"
:position="[0.5 + (i * (Math.random() - 0.5) * 5),
0.5 + (i * (Math.random() - 0.5) * 5),
0.5 + (i * (Math.random() - 0.5) * 5)]"
:scale="(i * 0.5) + 1"
/>
<TresMesh
ref="boxRef"
:position-z="30"
:scale="10"
>
<TresBoxGeometry :args="[1, 1, 1]" />
<TresMeshStandardMaterial :color="0x00ff00" />
</TresMesh>
<CameraControls :distance="75" />
<TresDirectionalLight :position="[0, 10, 10]" />
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/src/router/routes/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ export const miscRoutes = [
name: 'Stats',
component: () => import('../../pages/misc/StatsDemo.vue'),
},
{
path: '/misc/gltfExporter',
name: 'GLTFExporter',
component: () => import('../../pages/misc/GLTFExporterDemo.vue'),
},
]
3 changes: 2 additions & 1 deletion src/core/misc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import { useTweakPane } from './useTweakPane'
import { Stats } from './Stats'
import { StatsGl } from './StatsGl'
import Html from './html/HTML.vue'
import { useGLTFExporter } from './useGLTFExporter'

export { useTweakPane, Html, Stats, StatsGl }
export { useTweakPane, Html, Stats, StatsGl, useGLTFExporter }
58 changes: 58 additions & 0 deletions src/core/misc/useGLTFExporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js'
import { ref } from 'vue'
import type { AnimationClip, Object3D } from 'three'
import { useLogger } from '@tresjs/core'

const { logError } = useLogger()

interface gltfExporterOptions {
fileName?: string
trs?: boolean
onlyVisible?: boolean
binary?: boolean
maxTextureSize?: number
animations?: AnimationClip[]
includeCustomExtensions?: boolean
}

export async function useGLTFExporter(object3D: Object3D, options?: gltfExporterOptions ) {
const exporter = new GLTFExporter()
const objectToDownload = ref(object3D)
const name = options?.fileName || object3D.name || 'scene'

exporter.parse(
objectToDownload.value,
( gltf: Object3D ) => {
if ( gltf instanceof ArrayBuffer ) {
saveArrayBuffer( gltf, `${name}.glb` )
}
else {
const output = JSON.stringify( gltf, null, 2 )
saveString( output, `${name}.gltf` )
}
},
( error: any ) => {
logError( 'An error happened', error )
},
options,
)
return true
}

function saveString( text: string, filename: string ) {
save( new Blob( [ text ], { type: 'text/plain' } ), filename )
}

function saveArrayBuffer( buffer: any, filename: string ) {
save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename )
}

function save( blob: Blob, filename: string ) {
const link = document.createElement( 'a' )
link.style.display = 'none'
document.body.appendChild( link )
link.href = URL.createObjectURL( blob )
link.download = filename
link.click()
link.remove()
}

0 comments on commit 0c77d33

Please sign in to comment.