Skip to content

Commit

Permalink
feat: add v-always-look-at directive
Browse files Browse the repository at this point in the history
  • Loading branch information
JaimeTorrealba committed Sep 18, 2023
1 parent fff82fd commit ab3cfa3
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default defineConfig({
items: [
{ text: 'v-log', link: '/guide/directives/v-log' },
{ text: 'v-light-helper', link: '/guide/directives/v-light-helper' },
{ text: 'v-always-look-at', link: '/guide/directives/v-always-look-at' },
],
},
],
Expand Down
59 changes: 59 additions & 0 deletions docs/guide/directives/v-always-look-at.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# v-always-look-at 👀

With the new directive v-always-look-at provided by **TresJS**, you can add easily command an [Object3D](https://threejs.org/docs/index.html?q=object#api/en/core/Object3D) to always look at a specific position, this could be passed as a Vector3 or an Array.

```vue{3}
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { Box, vAlwaysLookAt } from '@tresjs/cientos'
</script>
<template>
<TresCanvas >
<TresPerspectiveCamera :position="[0, 2, 5]" />
<Box
v-always-look-at="new Vector3(0, 0, 0)"
/>
</TresCanvas>
</template>
```
No matter where the Box move will always look-at the position [0,0,0]

### Why not use the in built method look-at?

You could ask, this is fine but I can use the :look-at method directly in the component, why should I need this?

The answers is that with the method :look-at you will indicated to look at that position just once, when the instance is mounted, then if the object changes this will not get updated

## You can look at other instance too!

Another advantage is that you can look at an instance in movement, for example with the camera, like so:

```vue{3}
<script setup lang="ts">
import { shallowRef } from 'vue'
import { TresCanvas, useRenderLoop } from '@tresjs/core'
import { Box, vAlwaysLookAt } from '@tresjs/cientos'
const sphereRef = shallowRef()
const { onLoop } = useRenderLoop()
// here we update the position of the sphere and the camera will always follow the object
onLoop(({ elapsed }) => {
if (sphereRef.value) {
sphereRef.value.value.position.y = Math.sin(elapsed) * 1.5
}
})
</script>
<template>
<TresCanvas >
<TresPerspectiveCamera :position="[0, 2, 5]"
v-always-look-at="sphereRef"
/>
<Sphere
ref="sphereRef"
:scale="0.5"
/>
</TresCanvas>
</template>
```
60 changes: 60 additions & 0 deletions playground/src/pages/directives/vAlwaysLookAt.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script setup lang="ts">
import { shallowRef } from 'vue'
import { TresCanvas, useRenderLoop } from '@tresjs/core'
import { Stars, Sphere, Box, vAlwaysLookAt } from '@tresjs/cientos'
import { SRGBColorSpace, NoToneMapping, Vector3 } from 'three'
const gl = {
clearColor: '#333',
outputColorSpace: SRGBColorSpace,
toneMapping: NoToneMapping,
}
const sphereRef = shallowRef()
const box1Ref = shallowRef()
const box2Ref = shallowRef()
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (sphereRef.value && box1Ref.value && box2Ref.value) {
sphereRef.value.value.position.y = Math.sin(elapsed) * 1.5
box2Ref.value.value.position.y = Math.sin(elapsed * 1.2) * 1.5 + 2
const boxAngle = elapsed * 0.75
box1Ref.value.value.position.x = Math.cos(boxAngle) * 5
}
})
</script>

<template>
<TresCanvas v-bind="gl">
<!-- The camera observe a TresMesh -->
<TresPerspectiveCamera
v-always-look-at="sphereRef"
:position="[0, 2, 7.5]"
/>
<Stars />
<Sphere
ref="sphereRef"
:scale="0.5"
/>
<!-- This box use an array -->
<Box
ref="box1Ref"
v-always-look-at="[0, 0, 0]"
:color="0x00ff00"
:args="[1, 1, 0.1]"
name="greenBox"
:scale="1"
:position="[-2, 1, -3]"
/>
<!-- This box use a Vector3 -->
<Box
ref="box2Ref"
v-always-look-at="new Vector3(0, 0, 0)"
:color="0xff0000"
:scale="1"
:position="[-2, 1, -3]"
/>
<TresGridHelper :args="[10, 10]" />
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/src/router/routes/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ export const directivesRoutes = [
name: 'vLightHelper',
component: () => import('../../pages/directives/vLightHelper.vue'),
},
{
path: '/directives/v-always-look-at',
name: 'vAlwaysLookAt',
component: () => import('../../pages/directives/vAlwaysLookAt.vue'),
},
]
3 changes: 2 additions & 1 deletion src/core/directives/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { vLog } from './vLog'
import { vLightHelper } from './vLightHelper'
import { vAlwaysLookAt } from './vAlwaysLookAt'

export { vLog, vLightHelper }
export { vLog, vLightHelper, vAlwaysLookAt }
19 changes: 19 additions & 0 deletions src/core/directives/vAlwaysLookAt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRenderLoop } from '@tresjs/core'
import { Vector3 } from 'three'
import type { Object3D } from 'three'

export const vAlwaysLookAt = {
updated: (el: Object3D, binding: any) => {
let observer = binding.value
if (binding.value && binding.value?.value?.isMesh) {
observer = binding.value.value.position
}
if (Array.isArray(binding.value)) {
observer = new Vector3(...observer)
}
const { onLoop } = useRenderLoop()
onLoop(() => {
el.lookAt(observer)
})
},
}

0 comments on commit ab3cfa3

Please sign in to comment.