diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx index 924dcba..f28c97d 100644 --- a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx +++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx @@ -44,7 +44,7 @@ function FloorInstance({ floor }: { readonly floor: Floor }) { textureTileScale?: [number, number]; } > = { - "Default Material": { map: savedTheme === "dark" ? texturePathDark : texturePath, }, + "Default Material": { map: savedTheme === "dark" ? texturePathDark : texturePath }, "Material 1": { map: material1 }, "Material 2": { map: material2Map, @@ -111,30 +111,17 @@ function FloorInstance({ floor }: { readonly floor: Floor }) { const textureMaterialMap = [ { - textures: [ - topTexture, - topNormalTexture, - topRoughnessTexture, - topMetalicTexture, - ], + textures: [topTexture, topNormalTexture, topRoughnessTexture, topMetalicTexture], materialKey: floor.topMaterial, }, { - textures: [ - sideTexture, - sideNormalTexture, - sideRoughnessTexture, - sideMetalicTexture, - ], + textures: [sideTexture, sideNormalTexture, sideRoughnessTexture, sideMetalicTexture], materialKey: floor.sideMaterial, }, ]; textureMaterialMap.forEach(({ textures, materialKey }) => { - const tileScale = materials[materialKey]?.textureTileScale ?? [ - textureScale, - textureScale, - ]; + const tileScale = materials[materialKey]?.textureTileScale ?? [textureScale, textureScale]; textures.forEach((tex, idx) => { if (!tex) return; @@ -166,11 +153,7 @@ function FloorInstance({ floor }: { readonly floor: Floor }) { geometry={geometry} name={`Floor-${floor.floorUuid}`} rotation={[Math.PI / 2, 0, 0]} - position={[ - shapeData?.center[0] ?? 0, - !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, - shapeData?.center[1] ?? 0, - ]} + position={[shapeData?.center[0] ?? 0, !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, shapeData?.center[1] ?? 0]} userData={floor} onDoubleClick={(e) => { if (!toggleView && activeModule === "builder") { diff --git a/app/src/modules/builder/materials/planeMaterial.tsx b/app/src/modules/builder/materials/planeMaterial.tsx new file mode 100644 index 0000000..ef25ada --- /dev/null +++ b/app/src/modules/builder/materials/planeMaterial.tsx @@ -0,0 +1,59 @@ +import { useMemo, useRef } from "react"; +import { Color, DoubleSide, ShaderMaterial } from "three"; +import { useFrame } from "@react-three/fiber"; +import { useSceneStore } from "../../../store/scene/useSceneStore"; +import useShaderReader from "../../../utils/scene/useShaderReader"; + +import zone1Vertex from "../../../assets/shaders/zone/zone1.vert.glsl"; +import zone1Fragment from "../../../assets/shaders/zone/zone1.frag.glsl"; + +import zone2Vertex from "../../../assets/shaders/zone/zone2.vert.glsl"; +import zone2Fragment from "../../../assets/shaders/zone/zone2.frag.glsl"; + +import zone3Vertex from "../../../assets/shaders/zone/zone3.vert.glsl"; +import zone3Fragment from "../../../assets/shaders/zone/zone3.frag.glsl"; + +type PlaneMaterialProps = { + color: string; + variant?: "zone1" | "zone2" | "zone3"; +}; + +function PlaneMaterial({ color, variant = "zone1", ...props }: Readonly) { + const { limitFps } = useSceneStore(); + const materialRef = useRef(null); + + const vertexShaderUrl = variant === "zone1" ? zone1Vertex : variant === "zone2" ? zone2Vertex : variant === "zone3" ? zone3Vertex : zone1Vertex; + + const fragmentShaderUrl = variant === "zone1" ? zone1Fragment : variant === "zone2" ? zone2Fragment : variant === "zone3" ? zone3Fragment : zone1Fragment; + + const vertexShader = useShaderReader(vertexShaderUrl); + const fragmentShader = useShaderReader(fragmentShaderUrl); + + const material = useMemo(() => { + if (!vertexShader || !fragmentShader) return null; + + return new ShaderMaterial({ + side: DoubleSide, + vertexShader, + fragmentShader, + uniforms: { + uOuterColor: { value: new Color(color) }, + uTime: { value: 0 }, + }, + transparent: true, + depthWrite: false, + ...props, + }); + }, [color, vertexShader, fragmentShader]); + + useFrame(({ clock }) => { + if (materialRef.current && !limitFps) { + materialRef.current.uniforms.uTime.value = clock.getElapsedTime(); + } + }); + + if (!material) return null; + return ; +} + +export default PlaneMaterial; diff --git a/app/src/modules/builder/materials/polygonEdgeMaterial.tsx b/app/src/modules/builder/materials/polygonEdgeMaterial.tsx deleted file mode 100644 index 0eebb01..0000000 --- a/app/src/modules/builder/materials/polygonEdgeMaterial.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useMemo } from "react"; -import { Color, DoubleSide, ShaderMaterial, Shape, ShapeGeometry, Vector3 } from "three"; -import useShaderReader from "../../../utils/scene/useShaderReader"; - -import vertexShaderUrl from "../../../assets/shaders/edge/edge-fade.vert.glsl"; -import fragmentShaderUrl from "../../../assets/shaders/edge/edge-fade.frag.glsl"; - -type PolygonEdgeMaterialProps = { - points: { position: [number, number, number] }[]; - positionY: number; - color: string; -}; - -function PolygonEdgeMaterial({ points, positionY, color }: Readonly) { - const vertexShader = useShaderReader(vertexShaderUrl); - const fragmentShader = useShaderReader(fragmentShaderUrl); - - const geometry = useMemo(() => { - if (points.length < 3) return null; - - const shape = new Shape(); - points.forEach((p, i) => { - const v = new Vector3(...p.position); - if (i === 0) shape.moveTo(v.x, v.z); - else shape.lineTo(v.x, v.z); - }); - shape.closePath(); - - return new ShapeGeometry(shape); - }, [points]); - - const edges = useMemo(() => { - return points.map((p, i) => { - const next = points[(i + 1) % points.length]; - return [new Vector3(...p.position), new Vector3(...next.position)]; - }); - }, [points]); - - const material = useMemo(() => { - if (!vertexShader || !fragmentShader) return null; - - const edgeArray: number[] = []; - edges.forEach(([a, b]) => { - edgeArray.push(a.x, a.z, b.x, b.z); - }); - - return new ShaderMaterial({ - side: DoubleSide, - vertexShader, - fragmentShader, - uniforms: { - uColor: { value: new Color(color) }, - uFadeDistance: { value: 2.0 }, - uEdges: { value: edgeArray }, - uEdgeCount: { value: edges.length }, - }, - transparent: true, - depthWrite: false, - depthTest: true, - polygonOffset: true, - polygonOffsetFactor: -10, - polygonOffsetUnits: -10, - }); - }, [color, vertexShader, fragmentShader, edges]); - - if (!geometry || !material) return null; - - return ( - - - - ); -} - -export default PolygonEdgeMaterial; diff --git a/app/src/modules/builder/materials/polygonMaterial.tsx b/app/src/modules/builder/materials/polygonMaterial.tsx new file mode 100644 index 0000000..33e8197 --- /dev/null +++ b/app/src/modules/builder/materials/polygonMaterial.tsx @@ -0,0 +1,69 @@ +import { useMemo } from "react"; +import { Color, DoubleSide, ShaderMaterial, Vector3, MeshStandardMaterial } from "three"; +import useShaderReader from "../../../utils/scene/useShaderReader"; + +import edgeVertex from "../../../assets/shaders/edge/edge-fade.vert.glsl"; +import edgeFragment from "../../../assets/shaders/edge/edge-fade.frag.glsl"; + +type PolygonMaterialProps = { + points: { position: [number, number, number] }[]; + color: string; + fadeDistance?: number; + variant?: "edge" | "none"; +}; + +function PolygonMaterial({ points, color, fadeDistance = 2.0, variant = "edge", ...props }: Readonly) { + const vertexShader = useShaderReader(edgeVertex); + const fragmentShader = useShaderReader(edgeFragment); + + const edges = useMemo(() => { + return points.map((p, i) => { + const next = points[(i + 1) % points.length]; + return [new Vector3(...p.position), new Vector3(...next.position)]; + }); + }, [points]); + + const edgeMaterial = useMemo(() => { + if (!vertexShader || !fragmentShader || variant !== "edge") return null; + + const edgeArray: number[] = []; + edges.forEach(([a, b]) => { + edgeArray.push(a.x, a.z, b.x, b.z); + }); + + return new ShaderMaterial({ + side: DoubleSide, + vertexShader, + fragmentShader, + uniforms: { + uColor: { value: new Color(color) }, + uFadeDistance: { value: fadeDistance }, + uEdges: { value: edgeArray }, + uEdgeCount: { value: edges.length }, + }, + transparent: true, + depthWrite: false, + depthTest: true, + polygonOffset: true, + polygonOffsetFactor: -10, + polygonOffsetUnits: -10, + ...props, + }); + }, [color, fadeDistance, vertexShader, fragmentShader, edges]); + + const basicMaterial = useMemo(() => { + if (variant !== "none") return null; + return new MeshStandardMaterial({ + color: new Color(color), + side: DoubleSide, + transparent: true, + }); + }, [color]); + + if (variant === "none" && basicMaterial) return ; + if (variant === "edge" && edgeMaterial) return ; + + return null; +} + +export default PolygonMaterial; diff --git a/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx index b0a2d40..2a391f6 100644 --- a/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx +++ b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx @@ -1,54 +1,34 @@ -import { useMemo, useState } from "react"; -import { Color, DoubleSide, ShaderMaterial, Vector3 } from "three"; -import { useFrame } from "@react-three/fiber"; -import { useSceneStore } from "../../../../../store/scene/useSceneStore"; -import useShaderReader from "../../../../../utils/scene/useShaderReader"; +import { useMemo } from "react"; +import { Extrude } from "@react-three/drei"; +import { Shape, Vector2, Vector3 } from "three"; import CornerReference from "./cornerReference"; -import PolygonEdgeMaterial from "../../../materials/polygonEdgeMaterial"; - -import vertexShaderUrl from "../../../../../assets/shaders/zone/zone1.vert.glsl"; -import fragmentShaderUrl from "../../../../../assets/shaders/zone/zone1.frag.glsl"; - -// import vertexShaderUrl from "../../../../../assets/shaders/zone/zone2.vert.glsl"; -// import fragmentShaderUrl from "../../../../../assets/shaders/zone/zone2.frag.glsl"; - -// import vertexShaderUrl from "../../../../../assets/shaders/zone/zone2.vert.glsl"; -// import fragmentShaderUrl from "../../../../../assets/shaders/zone/zone2.frag.glsl"; +import PlaneMaterial from "../../../materials/planeMaterial"; +import PolygonMaterial from "../../../materials/polygonMaterial"; function ZoneInstance({ zone }: { readonly zone: Zone }) { - const vertexShader = useShaderReader(vertexShaderUrl); - const fragmentShader = useShaderReader(fragmentShaderUrl); const zoneLayer = zone.points[0].layer; - const { limitFps } = useSceneStore(); - const [time, setTime] = useState(0); - const zoneMaterial = useMemo(() => { - if (!vertexShader || !fragmentShader) return null; + const points2D = useMemo(() => { + return zone.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2)))); + }, [zone]); - return new ShaderMaterial({ - side: DoubleSide, - vertexShader, - fragmentShader, - uniforms: { - uOuterColor: { value: new Color(zone.zoneColor) }, - uTime: { value: time }, - }, - transparent: true, - depthWrite: false, - }); - }, [zone.zoneColor, time]); - - useFrame(({ clock }) => { - if (!limitFps) { - setTime(clock.getElapsedTime()); + const shape = useMemo(() => { + const shape = new Shape(); + shape.moveTo(points2D[0].x, points2D[0].y); + for (let i = 1; i < points2D.length; i++) { + shape.lineTo(points2D[i].x, points2D[i].y); } - }); + shape.lineTo(points2D[0].x, points2D[0].y); + return shape; + }, [points2D]); - if (!zoneMaterial) return null; + if (!shape) return null; return ( - + + + {zone.points.map((point, index: number) => { const nextPoint = zone.points[(index + 1) % zone.points.length]; @@ -67,7 +47,7 @@ function ZoneInstance({ zone }: { readonly zone: Zone }) { - +