From 2c2ec924943dc7db56845d211ec2c24b98433627 Mon Sep 17 00:00:00 2001 From: DrHepa Date: Fri, 5 Jun 2026 17:26:25 +0200 Subject: [PATCH] feat(scene): add selected mesh outline --- src/areas/generate/components/Viewer3D.tsx | 64 ++++++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/src/areas/generate/components/Viewer3D.tsx b/src/areas/generate/components/Viewer3D.tsx index 455ba49..981e6dd 100644 --- a/src/areas/generate/components/Viewer3D.tsx +++ b/src/areas/generate/components/Viewer3D.tsx @@ -2,6 +2,7 @@ import { Component, Suspense, useEffect, useMemo, useRef, useState } from 'react import type { ReactNode, ErrorInfo } from 'react' import { Canvas, useLoader, useThree } from '@react-three/fiber' import { Environment, GizmoHelper, Lightformer, OrbitControls, useGizmoContext, useGLTF } from '@react-three/drei' +import { EffectComposer, Outline, Select, Selection } from '@react-three/postprocessing' import * as THREE from 'three' import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js' import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh' @@ -16,6 +17,13 @@ import { ViewerToolbar, type ViewMode } from './ViewerToolbar' import type { LightSettings } from '../GeneratePage' import { DEFAULT_LIGHT_SETTINGS } from '../GeneratePage' +const SELECTION_OUTLINE_VISIBLE_COLOR = 0x8b5cf6 +const SELECTION_OUTLINE_HIDDEN_COLOR = 0x5b21b6 +const SELECTION_OUTLINE_EDGE_STRENGTH = 2.5 +const SELECTION_OUTLINE_BLUR = false +const SELECTION_OUTLINE_MULTISAMPLING = 0 +const SELECTION_OUTLINE_RESOLUTION_SCALE = 0.5 + // --------------------------------------------------------------------------- // Procedural textures // --------------------------------------------------------------------------- @@ -125,13 +133,14 @@ interface MeshModelProps { url: string jobId: string viewMode: ViewMode + selected: boolean onStats: (stats: { vertices: number; triangles: number }) => void onSelect: () => void } -function MeshModel({ url, jobId, viewMode, onStats, onSelect }: MeshModelProps): JSX.Element { +function MeshModel({ url, jobId, viewMode, selected, onStats, onSelect }: MeshModelProps): JSX.Element { const extension = url.split('?')[0]?.split('.').pop()?.toLowerCase() - const common = { url, jobId, viewMode, onStats, onSelect } + const common = { url, jobId, viewMode, selected, onStats, onSelect } return extension === 'obj' ? : } @@ -148,6 +157,7 @@ function ObjMeshModel(props: MeshModelProps): JSX.Element { function SceneMeshModel({ url, viewMode, + selected, onStats, onSelect, scene, @@ -267,10 +277,12 @@ function SceneMeshModel({ }, [scene, viewMode]) return ( - void }) => { e.stopPropagation(); onSelect() }} - /> + ) } @@ -444,17 +456,33 @@ export default function Viewer3D({ lightSettings = DEFAULT_LIGHT_SETTINGS }: { l {modelUrl && currentJob ? ( - - - - setSelected(true)} - /> - + + + + + + + + setSelected(true)} + /> + + ) : null} - +