1
0
Эх сурвалжийг харах

Merge pull request #651 from Tresjs/feature/v-rotate

feat: v-rotate
Jaime A Torrealba C 1 жил өмнө
parent
commit
4905e6591a

+ 1 - 0
docs/.vitepress/config/de.ts

@@ -77,6 +77,7 @@ export const deConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/de/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/de/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/de/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 1 - 0
docs/.vitepress/config/en.ts

@@ -78,6 +78,7 @@ export const enConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 1 - 0
docs/.vitepress/config/es.ts

@@ -78,6 +78,7 @@ export const esConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/es/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/es/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/es/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 1 - 0
docs/.vitepress/config/fr.ts

@@ -79,6 +79,7 @@ export const frConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/fr/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/fr/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/fr/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 1 - 0
docs/.vitepress/config/nl.ts

@@ -78,6 +78,7 @@ export const nlConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/nl/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/nl/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/nl/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 1 - 0
docs/.vitepress/config/zh.ts

@@ -77,6 +77,7 @@ export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
           { text: 'v-light-helper', link: '/zh/directives/v-light-helper' },
           { text: 'v-always-look-at', link: '/zh/directives/v-always-look-at' },
           { text: 'v-distance-to', link: '/zh/directives/v-distance-to' },
+          { text: 'v-rotate', link: '/directives/v-rotate' },
         ],
       },
       {

+ 4 - 4
docs/directives/v-always-look-at.md

@@ -6,8 +6,8 @@ With the new directive v-always-look-at provided by **TresJS**, you can add easi
 
 ```vue{3,9}
 <script setup lang="ts">
-import { TresCanvas } from '@tresjs/core'
-import { Box, vAlwaysLookAt } from '@tresjs/cientos'
+import { TresCanvas, vAlwaysLookAt } from '@tresjs/core'
+import { Box } from '@tresjs/cientos'
 </script>
 <template>
     <TresCanvas >
@@ -33,8 +33,8 @@ Another advantage is that you can look at an instance in movement, for example w
 ```vue{4,6,20,23}
 <script setup lang="ts">
 import { shallowRef } from 'vue'
-import { TresCanvas, useRenderLoop } from '@tresjs/core'
-import { Box, vAlwaysLookAt } from '@tresjs/cientos'
+import { TresCanvas, useRenderLoop, vAlwaysLookAt } from '@tresjs/core'
+import { Box } from '@tresjs/cientos'
 
 const sphereRef = shallowRef()
 

+ 2 - 1
docs/directives/v-distance-to.md

@@ -8,7 +8,8 @@ In addition, an arrow will be created to indicate which objects you're measuring
 
 ```vue{2,8,13}
 <script setup lang="ts">
-import { OrbitControls, Sphere, vLog } from '@tresjs/cientos'
+import { vDistanceTo } from '@tresjs/core'
+import { OrbitControls, Sphere } from '@tresjs/cientos'
 </script>
 <template>
   <TresCanvas v-bind="gl">

+ 2 - 1
docs/directives/v-light-helper.md

@@ -12,7 +12,8 @@ The following lights are supported:
 
 ```vue{2,8,11,14,17}
 <script setup lang="ts">
-import { OrbitControls, Sphere, vLightHelper } from '@tresjs/cientos'
+import { vLightHelper } from '@tresjs/core'
+import { OrbitControls, Sphere,  } from '@tresjs/cientos'
 </script>
 <template>
   <TresCanvas >

+ 2 - 1
docs/directives/v-log.md

@@ -35,7 +35,8 @@ With the new directive v-log provided by **TresJS**, you can do this by just add
 
 ```vue{2,10,12}
 <script setup lang="ts">
-import { OrbitControls, Sphere, vLog } from '@tresjs/cientos'
+import { vLog } from '@tresjs/core'
+import { OrbitControls, Sphere } from '@tresjs/cientos'
 </script>
 <template>
     <TresCanvas >

+ 80 - 0
docs/directives/v-rotate.md

@@ -0,0 +1,80 @@
+# v-rotate
+
+## Problem
+
+When you want to simply add rotation to your mesh, you have to use the template reference, [useRenderLoop](/api/composables#userenderloop) and then assign the axis and the speed, but before check if you mesh is already available:
+
+```vue
+<script setup lang="ts">
+import { shallowRef, watch } from 'vue'
+import { useRenderLoop } from '@tresjs/core'
+
+const boxRef = shallowRef()
+
+const { onLoop } = useRenderLoop()
+
+onLoop(({ elapsed }) => {
+  if (boxRef.value) {
+    boxRef.value.rotation.x = elapsed
+  }
+})
+</script>
+
+<template>
+  <TresCanvas>
+    <TresPerspectiveCamera :position="[0, 2, 5]" />
+    <TresMesh
+      ref="boxRef"
+      :scale="0.5"
+    >
+      <TresBoxGeometry />
+      <TresMesh>
+        <OrbitControls />
+      </TresMesh>
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+
+And is A LOT of code just for a simple rotation right? Normally we need something fast to see if something is working
+
+## Usage
+
+With the new directive v-rotate provided by **TresJS**, you can do this by just adding `v-rotate` to the instance.
+
+```vue{2,8}
+<script setup lang="ts">
+import { vRotate } from '@tresjs/core'
+</script>
+<template>
+    <TresCanvas >
+    <TresPerspectiveCamera :position="[0, 2, 5]" />
+    <TresMesh
+      v-rotate // 😍
+    >
+      <TresBoxGeometry />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```
+By default `v-rotate` uses [Quaternions](https://threejs.org/docs/index.html?q=quater#api/en/math/Quaternion) so you don't have to worry by [Gimbal Lock](https://en.wikipedia.org/wiki/Gimbal_lock), or check if you mesh is available in the first frames.
+
+## Modifiers
+
+You can control the axis and the rotation speed by adding modifiers
+
+```vue{2,8}
+<script setup lang="ts">
+import { vRotate } from '@tresjs/core'
+</script>
+<template>
+    <TresCanvas >
+    <TresPerspectiveCamera :position="[0, 2, 5]" />
+    <TresMesh
+      v-rotate:x.y="0.1" // the axis will be x and y with a speed of 0.1
+    >
+      <TresBoxGeometry />
+    </TresMesh>
+  </TresCanvas>
+</template>
+```

+ 13 - 3
playground/src/pages/lights.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import type { TresObject } from '@tresjs/core'
-import { TresCanvas, vAlwaysLookAt, vDistanceTo, vLightHelper, vLog } from '@tresjs/core'
+import { TresCanvas, vAlwaysLookAt, vDistanceTo, vLightHelper, vLog, vRotate } from '@tresjs/core'
 import { BasicShadowMap, NoToneMapping, SRGBColorSpace } from 'three'
 
 import { OrbitControls } from '@tresjs/cientos'
@@ -22,7 +22,11 @@ const planeRef: Ref<TresObject | null> = ref(null)
 
     v-bind="gl"
   >
-    <TresPerspectiveCamera :position="[3, 3, 3]" />
+    <TresPerspectiveCamera
+      v-distance-to="planeRef"
+      v-rotate
+      :position="[3, 3, 3]"
+    />
     <OrbitControls />
 
     <TresDirectionalLight
@@ -43,7 +47,13 @@ const planeRef: Ref<TresObject | null> = ref(null)
       <TresMeshToonMaterial />
     </TresMesh>
     <TresMesh
-      v-distance-to="planeRef"
+      v-rotate.x="0.005"
+      :position="[-2, 2, 0]"
+    >
+      <TresBoxGeometry :args="[1, 1, 1]" />
+      <TresMeshToonMaterial color="red" />
+    </TresMesh>
+    <TresMesh
       :position="[2, 4, 0]"
       cast-shadow
     >

+ 2 - 1
src/directives/index.ts

@@ -2,5 +2,6 @@ import { vLog } from './vLog'
 import { vLightHelper } from './vLightHelper'
 import { vAlwaysLookAt } from './vAlwaysLookAt'
 import { vDistanceTo } from './vDistanceTo'
+import { vRotate } from './vRotate'
 
-export { vLog, vLightHelper, vAlwaysLookAt, vDistanceTo }
+export { vLog, vLightHelper, vAlwaysLookAt, vDistanceTo, vRotate }

+ 40 - 0
src/directives/vRotate.ts

@@ -0,0 +1,40 @@
+import { ref } from 'vue'
+import { Quaternion, Vector3 } from 'three'
+import type { TresObject } from '../types'
+import { useLogger, useRenderLoop } from '../composables'
+
+const { logWarning } = useLogger()
+
+export const vRotate = {
+  mounted: (
+    el: TresObject,
+    binding: {
+      arg: 'x' | 'y' | 'z'
+      value: number
+      modifiers: Partial<{ x: boolean, y: boolean, z: boolean }>
+    },
+  ) => {
+    if (el.isCamera) {
+      logWarning(`Rotate the ${el.type} is not a good idea`)
+      return
+    }
+    const radiansPerFrame = binding.value ?? 0.01
+    const x = ref(binding.modifiers.x || binding.arg === 'x' ? 1 : 0)
+    const y = ref(binding.modifiers.y || binding.arg === 'y' ? 1 : 0)
+    const z = ref(binding.modifiers.z || binding.arg === 'z' ? 1 : 0)
+
+    if (x.value + y.value + z.value === 0) {
+      x.value = 1
+      y.value = 1
+    }
+
+    const quaternion = new Quaternion().setFromAxisAngle(new Vector3(x.value, y.value, z.value)
+      .normalize(), radiansPerFrame)
+
+    const { onLoop } = useRenderLoop()
+
+    onLoop(() => {
+      el.applyQuaternion(quaternion)
+    })
+  },
+}