Skip to content

Commit

Permalink
feat: edges (#390)
Browse files Browse the repository at this point in the history
* feat: add edges component

* feat(cientos/edges): rework code and playground demo

* feat(cientos/edges): rework code and playground demo - fix lint

* feat(cientos/edges): wip doc

* feat(cientos/edges): wip documentation and demo

* update edge component

* update merge main

* review fix

---------

Co-authored-by: Alvaro Saburido <[email protected]>
  • Loading branch information
damienmontastier and alvarosabu authored Dec 4, 2024
1 parent 418e6ae commit 60c200d
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 0 deletions.
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' },
{ text: 'Billboard', link: '/guide/abstractions/billboard' },
],
Expand Down
55 changes: 55 additions & 0 deletions docs/.vitepress/theme/components/EdgesDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script setup lang="ts">
import { TresCanvas, useSeek } from '@tresjs/core'

Check failure on line 2 in docs/.vitepress/theme/components/EdgesDemo.vue

View workflow job for this annotation

GitHub Actions / Lint (20)

'useSeek' is defined but never used
import { Box, ContactShadows, Edges, OrbitControls } from '@tresjs/cientos'
import { MOUSE, TOUCH } from 'three'
const gl = {
clearColor: '#f6f6f6',
alpha: false,
}
const dataBoxes = [{
color: '#82DBC5',
edgeColor: '#505050',
}, {
color: '#505050',
edgeColor: 'white',
}, {
color: '#F6B03B',
edgeColor: '#505050',
}]
</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" />
</Box>

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

Check failure on line 7 in docs/guide/abstractions/edges.md

View workflow job for this annotation

GitHub Actions / Lint (20)

Irregular whitespace not allowed

Check failure on line 7 in docs/guide/abstractions/edges.md

View workflow job for this annotation

GitHub Actions / Lint (20)

Irregular whitespace not allowed

## Usage

<<< @/.vitepress/theme/components/EdgesDemo.vue

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 provide a custom material to `<Edges>`. When a custom material is used, the color prop has no effect. *(see code bellow)*

```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` |

## 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>
```
69 changes: 69 additions & 0 deletions playground/vue/src/pages/abstractions/EdgesDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<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 { enabled, edgeColor, edgeThreshold } = useControls({
enabled: { value: true, type: 'boolean', label: 'Enabled' },
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
v-if="enabled.value"
: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'),
},

Check failure on line 56 in playground/vue/src/router/routes/abstractions.ts

View workflow job for this annotation

GitHub Actions / Lint (20)

Trailing spaces not allowed
{
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({
instance: lineSegmentsRef,
})
// 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 @@ -10,12 +10,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,
Billboard,

Check failure on line 21 in src/core/abstractions/index.ts

View workflow job for this annotation

GitHub Actions / Lint (20)

Expected "Billboard" to come before "Edges"
Fbo,
GlobalAudio,
Expand Down

0 comments on commit 60c200d

Please sign in to comment.