Browse Source

feat(cientos): useAnimations

Alvaro 2 years ago
parent
commit
2704288fd8

+ 31 - 0
packages/cientos/src/core/useAnimations.ts

@@ -0,0 +1,31 @@
+import { AnimationMixer, Clock, Object3D } from 'three'
+import { useRenderLoop } from '@tresjs/core'
+import { ref, Ref, shallowReactive } from 'vue'
+
+export function useAnimations<T extends Animation>(animations: T[], modelRef?: Ref<Object3D | undefined | null>) {
+  const reference: Ref<Object3D> = ref(modelRef) as Ref<Object3D>
+
+  const mixer = new AnimationMixer(reference.value)
+
+  const actions = shallowReactive({})
+
+  animations.forEach(animation => {
+    const action = mixer.clipAction(animation, reference.value)
+    actions[animation.name] = action
+  })
+
+  const { onLoop } = useRenderLoop()
+
+  // TODO: Workaround for https://github.com/Tresjs/tres/issues/81
+  const clock = new Clock()
+
+  onLoop(() => {
+    const delta = clock.getDelta()
+    mixer.update(delta)
+  })
+
+  return {
+    actions,
+    mixer,
+  }
+}

+ 2 - 1
packages/cientos/src/index.ts

@@ -1,6 +1,7 @@
 import OrbitControls from './core/OrbitControls.vue'
 import TransformControls from './core/TransformControls.vue'
 import { useTweakPane } from './core/useTweakPane'
+import { useAnimations } from './core/useAnimations'
 import { GLTFModel } from './core/useGLTF/component'
 import { FBXModel } from './core/useFBX/component'
 import Text3D from './core/Text3D.vue'
@@ -9,4 +10,4 @@ import Plane from './core/Plane.vue'
 export * from './core/useGLTF'
 export * from './core/useFBX'
 export * from './types'
-export { OrbitControls, TransformControls, useTweakPane, GLTFModel, FBXModel, Text3D, Plane }
+export { OrbitControls, TransformControls, useTweakPane, GLTFModel, FBXModel, Text3D, Plane, useAnimations }

BIN
packages/tres/public/models/ugly-naked-bunny/Face_29.png


BIN
packages/tres/public/models/ugly-naked-bunny/assets/Face_1.png


BIN
packages/tres/public/models/ugly-naked-bunny/assets/Face_2.png


BIN
packages/tres/public/models/ugly-naked-bunny/assets/Face_3.png


BIN
packages/tres/public/models/ugly-naked-bunny/assets/Face_4.png


BIN
packages/tres/public/models/ugly-naked-bunny/assets/Face_5.png


File diff suppressed because it is too large
+ 3350 - 0
packages/tres/public/models/ugly-naked-bunny/ugly-naked-bunny-animated.gltf


File diff suppressed because it is too large
+ 371 - 0
packages/tres/public/models/ugly-naked-bunny/ugly-naked-bunny-join.gltf


BIN
packages/tres/public/models/ugly-naked-bunny/ugly-naked-bunny.bin


BIN
packages/tres/public/models/ugly-naked-bunny/ugly-naked-bunny.glb


File diff suppressed because it is too large
+ 3350 - 0
packages/tres/public/models/ugly-naked-bunny/ugly-naked-bunny.gltf


+ 2 - 2
packages/tres/src/App.vue

@@ -1,12 +1,12 @@
 <script setup lang="ts">
 import { useTweakPane } from '@tresjs/cientos'
-import Shapes from '/@/components/Shapes.vue'
+import AnimatedModel from '/@/components/AnimatedModel.vue'
 
 useTweakPane()
 </script>
 
 <template>
   <Suspense>
-    <Shapes />
+    <AnimatedModel />
   </Suspense>
 </template>

+ 65 - 0
packages/tres/src/components/AnimatedModel.vue

@@ -0,0 +1,65 @@
+<script setup lang="ts">
+import { AnimationMixer, Clock, Color, sRGBEncoding } from 'three'
+
+/* import { OrbitControls, useTweakPane, useGLTF, useAnimations } from '../../../cientos/src/' */
+import { OrbitControls, useTweakPane, useGLTF, useAnimations } from '@tresjs/cientos'
+import { useRenderLoop } from '../core'
+
+const bgColor = new Color('#F78B3D')
+useTweakPane()
+
+/* const jeepRef = ref() */
+
+const { scene: model, animations } = await useGLTF('/models/ugly-naked-bunny/ugly-naked-bunny-animated.gltf')
+
+const { actions, mixer } = useAnimations(animations, model)
+
+console.log({ animations, actions, mixer })
+
+actions.Greeting.play()
+
+/* const mixer = new AnimationMixer(model)
+
+const actions = {}
+
+animations.forEach(animation => {
+  const action = mixer.clipAction(animation)
+  actions[animation.name] = action
+})
+
+actions.Greeting.play()
+
+const { onLoop } = useRenderLoop()
+const clock = new Clock()
+onLoop(({ elapsed }) => {
+  const delta = clock.getDelta()
+  mixer.update(delta)
+}) */
+
+/* watch(jeepRef, ({ getModel }) => {
+  const model = getModel()
+  model.scale.set(0.01, 0.01, 0.01)
+  model.rotation.y = -Math.PI / 2
+}) */
+</script>
+
+<template>
+  <Suspense>
+    <TresCanvas
+      :clear-color="bgColor"
+      shadows
+      alpha
+      window-size
+      power-preference="high-performance"
+      :output-encoding="sRGBEncoding"
+    >
+      <OrbitControls />
+      <TresPerspectiveCamera :position="8" :fov="45" :near="0.1" :far="10000" />
+      <TresScene :fog="bgColor">
+        <TresAmbientLight :color="0xffffff" :intensity="0.75" />
+        <TresMesh v-bind="model" />
+        <!--   <FBXModel ref="jeepRef" path="/models/low-poly-truck/Jeep_done.fbx" /> -->
+      </TresScene>
+    </TresCanvas>
+  </Suspense>
+</template>

+ 5 - 3
packages/tres/src/core/useRenderLoop/index.ts

@@ -5,6 +5,7 @@ import { Ref } from 'vue'
 export interface RenderLoop {
   delta: number
   elapsed: number
+  clock: Clock
 }
 
 export interface UseRenderLoopReturn {
@@ -20,6 +21,7 @@ const onBeforeLoop = createEventHook<RenderLoop>()
 const onLoop = createEventHook<RenderLoop>()
 const onAfterLoop = createEventHook<RenderLoop>()
 
+console.count('clock')
 const clock = new Clock()
 
 const { pause, resume, isActive } = useRafFn(
@@ -27,9 +29,9 @@ const { pause, resume, isActive } = useRafFn(
     const elapsed = clock.getElapsedTime()
     const delta = clock.getDelta()
 
-    onBeforeLoop.trigger({ delta, elapsed })
-    onLoop.trigger({ delta, elapsed })
-    onAfterLoop.trigger({ delta, elapsed })
+    onBeforeLoop.trigger({ delta, elapsed, clock })
+    onLoop.trigger({ delta, elapsed, clock })
+    onAfterLoop.trigger({ delta, elapsed, clock })
   },
   { immediate: false },
 )

+ 1 - 1
packages/tres/src/core/useScene/component.ts

@@ -17,7 +17,7 @@ export const Scene = defineComponent({
 
     provide('local-scene', scene)
 
-    onLoop(() => {
+    onLoop(({ clock }) => {
       if (renderer?.value && activeCamera?.value && scene?.value) {
         renderer.value.render(scene?.value, activeCamera.value)
       }

Some files were not shown because too many files changed in this diff