Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: edges #390

Merged
merged 13 commits into from
Dec 4, 2024
Merged
2 changes: 2 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export default defineConfig({
{ text: 'useFBO', link: '/guide/abstractions/use-fbo' },
{ text: 'useSurfaceSampler', link: '/guide/abstractions/use-surface-sampler' },
{ text: 'Sampler', link: '/guide/abstractions/sampler' },
{ text: 'Edges', link: '/guide/abstractions/edges' },
{ text: 'PositionalAudio', link: '/guide/abstractions/positional-audio' },
{ text: 'AnimatedSprite', link: '/guide/abstractions/animated-sprite' },
],
},
Expand Down
104 changes: 104 additions & 0 deletions docs/.vitepress/theme/components/EdgesDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<script setup lang="ts">
andretchen0 marked this conversation as resolved.
Show resolved Hide resolved
import { TresCanvas, useSeek } from '@tresjs/core'
import { Box, ContactShadows, Edges, OrbitControls } from '@tresjs/cientos'
import { gsap } from 'gsap'
import { MOUSE, TOUCH } from 'three'

const gl = {
clearColor: '#f6f6f6',
alpha: false,
}

const dataBoxes = [{
color: '#82DBC5',
edgeColor: '#292929',
}, {
color: '#505050',
edgeColor: '#292929',
}, {
color: '#F6B03B',
edgeColor: '#292929',
}]

const { seek } = useSeek()

// To be added when @pointer-enter and @pointer-leave are fixed. Currently it returns a loop of values.

// function onPointerEnter(ev) {
// const object = ev.object
// const edge = seek(object, 'type', 'LineSegments')

// gsap.to(object.position, {
// y: 0.25,
// duration: 1,
// overwrite: true,
// ease: 'elastic.out(1,0.4)',
// })

// gsap.to(edge?.scale, {
// x: 1.1,
// y: 1.1,
// z: 1.1,
// duration: 1,
// overwrite: true,
// ease: 'elastic.out(1,0.4)',
// })
// }

// function onPointerLeave(ev) {
// const object = ev
// const edge = seek(object, 'type', 'LineSegments')

// gsap.to(object.position, {
// y: 0,
// duration: 0.25,
// overwrite: true,
// ease: 'power3.out',
// })

// gsap.to(edge?.scale, {
// x: 1,
// y: 1,
// z: 1,
// duration: 0.25,
// overwrite: true,
// ease: 'power3.out',
// })
// }
</script>

<template>
<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera :position="[0, 2, 5]" />
<OrbitControls
make-default
auto-rotate
:enableZoom="false"
:auto-rotate-speed="1"
:mouseButtons="{ LEFT: MOUSE.ROTATE, RIGHT: MOUSE.NONE }"
:touches="{ ONE: TOUCH.ROTATE, TWO: TOUCH.NONE }"
/>

<Box
v-for="(x, index) in [-1.5, 0, 1.5]"
:key="`docs-edges-demo-box-${index}`"
:position="[x, 0, 0]"
>
<TresMeshBasicMaterial
:color="dataBoxes[index].color"
/>
<Edges :color="dataBoxes[index].edgeColor">
<TresMeshNormalMaterial />
</Edges>
</Box>

<ContactShadows
:blur="2"
:resolution="512"
:opacity=".25"
:position-y="-1"
/>
</TresCanvas>
</template>
60 changes: 60 additions & 0 deletions docs/guide/abstractions/edges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Edges

<DocsDemo>
<EdgesDemo />
</DocsDemo>

The `cientos` package provides an abstraction of [EdgesGeometry](https://threejs.org/docs/#api/en/geometries/EdgesGeometry) from Three.js, `<Edges>` is specifically designed for rendering visible edges of objects in a scene graph. This enhances the visual quality by highlighting contours and providing a stylized appearance which contributes to the artistic aspect of 3D visualizations.

## Usage

The `<Edges>` component is easy to set up as it automatically derives geometry from its parent. You can simply wrap it around any [Object3D](https://threejs.org/docs/#api/en/core/Object3D), [Mesh](https://threejs.org/docs/#api/en/objects/Mesh), or [primitive](https://docs.tresjs.org/advanced/primitive.html) to automatically apply edge rendering. You can give to `<Edges>` a custom material. *(see code bellow)*
andretchen0 marked this conversation as resolved.
Show resolved Hide resolved

```vue
<script setup lang="ts">
import { Box, Edges } from '@tresjs/cientos'
</script>

<template>
<Box>
<TresMeshNormalMaterial />

<!-- Usage with the default material (LineBasicMaterial) -->
<Edges color="#FF0000" />
<!-- ———— -->

<!-- Usage with an custom material -->
<Edges>
<TresMeshBasicMaterial color="#00FF00" />
</Edges>
<!-- ———— -->
</Box>
</template>
```

## Props

`<Edges>` is based on [LineSegments](https://threejs.org/docs/#api/en/objects/LineSegments) & [Line](https://threejs.org/docs/#api/en/objects/Line) and supports all of its props.

| Prop | Description | Default |
| :---------------- | :--------------------------------------------------- | ------------------------- |
| **color** | `THREE.Color` — Color of the edges. <br> More informations : [TresColor](https://docs.tresjs.org/api/instances-arguments-and-props.html#colors) — [THREE.Color](https://threejs.org/docs/#api/en/math/Color) | `#ff0000` |
| **threshold** | `number` — An edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value | `1` |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I would add one more column with the LineSegments as a general (properly indicated in the description) or all the linesSegment props individually (better to be explicit, trust me we target several non-advance users)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for knowledge which props support LineSegments? I couldn't find any :o
The ThreeJs Docs sends me to Line (but this doesn't have any specific props, I was spectic line width or line-width but couldn't find any)


## Exposed properties

| Event | Description |
| :---------- | :--------------------------------------------------------------- |
| `instance` | Instance reference — Inheritance of [LineSegments](https://threejs.org/docs/#api/en/objects/LineSegments).|

```typescript{1}
const edgesRef = shallowRef(null)

console.log(edgesRef.value.instance) // instance properties
```

```vue{2}
<template>
<Edges ref="edgesRef" />
</template>
```
67 changes: 67 additions & 0 deletions playground/vue/src/pages/abstractions/EdgesDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { Box, Edges, OrbitControls } from '@tresjs/cientos'
import { TresLeches, useControls } from '@tresjs/leches'
import '@tresjs/leches/styles'

const gl = {
powerPreference: 'high-performance',
precision: 'highp',
clearColor: '#F6B03B',
}

const { edgeColor, edgeThreshold } = useControls({
edgeColor: { value: '#292929', type: 'color', label: 'Color' },
edgeThreshold: {
label: 'Threshold Angle',
value: 15,
min: 1,
max: 100,
step: 1,
},
})
</script>

<template>
<TresLeches />

<TresCanvas
v-bind="gl"
>
<TresPerspectiveCamera
:position="[0, 2, 5]"
/>

<OrbitControls
make-default
/>

<TresGridHelper
:args="[10, 10]"
:position-y="-.5"
/>

<Box :position="[-1, 0, 0]">
<TresMeshBasicMaterial color="#f6f6f6" />

<Edges
andretchen0 marked this conversation as resolved.
Show resolved Hide resolved
:scale="1.1"
:threshold="edgeThreshold.value"
>
<TresMeshBasicMaterial
:color="edgeColor.value"
/>
</Edges>
</Box>

<Box :position="[1, 0, 0]">
<TresMeshBasicMaterial color="#292929" />

<Edges
:scale="1.1"
:threshold="edgeThreshold.value"
color="#f6f6f6"
/>
</Box>
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/vue/src/router/routes/abstractions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export const abstractionsRoutes = [
name: 'Sampler',
component: () => import('../../pages/abstractions/Sampler.vue'),
},
{
path: '/abstractions/edges',
name: 'Edges',
component: () => import('../../pages/abstractions/EdgesDemo.vue'),
},
{
path: '/abstractions/positional-audio',
name: 'PositionalAudio',
Expand Down
61 changes: 61 additions & 0 deletions src/core/abstractions/Edges.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script setup lang="ts">
import { ref, shallowRef, toRefs, watch } from 'vue'
import type { BufferGeometry, LineSegments } from 'three'
import { EdgesGeometry } from 'three'
import type { TresColor } from '@tresjs/core'

export interface EdgesProps {
color?: TresColor
threshold?: number
}

const props = withDefaults(defineProps<EdgesProps>(), {
color: '#ff0000',
threshold: 15,
})

const { color, threshold } = toRefs(props)

const lineSegmentsRef = shallowRef<LineSegments>()
const saveGeometry = ref<BufferGeometry | null>(null)
const saveThreshold = ref<number>(1)

defineExpose({
root: lineSegmentsRef,
andretchen0 marked this conversation as resolved.
Show resolved Hide resolved
})

// Watch for changes in lineSegments, thresholdAngle, and color.
watch(
() => [lineSegmentsRef.value, threshold.value],
() => {
if (lineSegmentsRef.value) {
const parent = lineSegmentsRef.value.parent

if (parent) {
const geometry = parent.geometry

// Update geometry and threshold if necessary.
if (
geometry !== saveGeometry.value || threshold.value !== saveThreshold.value
) {
saveGeometry.value = geometry
saveThreshold.value = threshold.value

lineSegmentsRef.value.geometry = new EdgesGeometry(geometry, threshold.value)
}
}
}
},
)
</script>

<template>
<TresLineSegments
ref="lineSegmentsRef"
v-bind="$attrs"
>
<slot>
<TresLineBasicMaterial :color="color" />
</slot>
</TresLineSegments>
</template>
2 changes: 2 additions & 0 deletions src/core/abstractions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import Text3D from './Text3D.vue'
import { useAnimations } from './useAnimations'
import Fbo from './useFBO/component.vue'
import Sampler from './useSurfaceSampler/component.vue'
import Edges from './Edges.vue'

export * from '../staging/useEnvironment'
export * from './useFBO/'
export * from './useSurfaceSampler'
export {
AnimatedSprite,
Edges,
Fbo,
GlobalAudio,
Lensflare,
Expand Down