made a wrapper for extrude polygons for code optimization
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useMemo } from "react";
|
||||
import { DoubleSide, Shape, Vector2 } from "three";
|
||||
import { Extrude, Html } from "@react-three/drei";
|
||||
import { DoubleSide, Vector2 } from "three";
|
||||
import { Html } from "@react-three/drei";
|
||||
import * as Constants from "../../../../../types/world/worldConstants";
|
||||
import getCenteroidPoint from "../../../functions/getCenteroid";
|
||||
import getArea from "../../../functions/getArea";
|
||||
import ExtrudePolygon from "../../../wrappers/geomentry/extrudePolygon";
|
||||
|
||||
function Floor2DInstance({ floor }: { readonly floor: Floor }) {
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
@@ -12,16 +13,6 @@ function Floor2DInstance({ floor }: { readonly floor: Floor }) {
|
||||
return floor.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [floor]);
|
||||
|
||||
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]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
@@ -31,23 +22,13 @@ function Floor2DInstance({ floor }: { readonly floor: Floor }) {
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh castShadow receiveShadow name={`Floor-2D-${floor.floorUuid}`} rotation={[Math.PI / 2, 0, 0]} position={[0, 0, 0]} userData={floor}>
|
||||
<Extrude name={`Floor-${floor.floorUuid}`} args={[shape, { depth: Constants.floorConfig.height }]} userData={floor}>
|
||||
<meshBasicMaterial
|
||||
color={savedTheme === "dark" ? Constants.lineConfig.floorColor : Constants.lineConfig.floorColor}
|
||||
side={DoubleSide}
|
||||
transparent
|
||||
opacity={0.4}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<ExtrudePolygon castShadow receiveShadow name={`Floor-2D-${floor.floorUuid}`} points={floor.points} options={{ depth: 0, bevelEnabled: false }} userData={floor}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.floorColor : Constants.lineConfig.floorColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</ExtrudePolygon>
|
||||
|
||||
<Html key={floor.floorUuid} position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useMemo } from "react";
|
||||
import { Shape, Vector2, DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace, NoColorSpace, ExtrudeGeometry } from "three";
|
||||
import { DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace, NoColorSpace } from "three";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import useModuleStore from "../../../../../store/ui/useModuleStore";
|
||||
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
|
||||
@@ -27,6 +26,7 @@ import material4Map from "../../../../../assets/textures/floor/tex3/metal_plate_
|
||||
import material4RoughnessMap from "../../../../../assets/textures/floor/tex3/metal_plate_rough_1k.png";
|
||||
import material4MetalicMap from "../../../../../assets/textures/floor/tex3/metal_plate_metal_1k.png";
|
||||
import material4NormalMap from "../../../../../assets/textures/floor/tex3/metal_plate_nor_gl_1k.png";
|
||||
import ExtrudePolygon from "../../../wrappers/geomentry/extrudePolygon";
|
||||
|
||||
function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
const { toggleView } = useToggleView();
|
||||
@@ -68,24 +68,6 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
},
|
||||
};
|
||||
|
||||
const shapeData = useMemo(() => {
|
||||
const points = floor.points.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
|
||||
const centroidX = points.reduce((sum, p) => sum + p.x, 0) / points.length;
|
||||
const centroidY = points.reduce((sum, p) => sum + p.y, 0) / points.length;
|
||||
|
||||
const relativePoints = points.map((p) => new Vector2(p.x - centroidX, p.y - centroidY));
|
||||
|
||||
const shape = new Shape();
|
||||
shape.moveTo(relativePoints[0].x, relativePoints[0].y);
|
||||
for (let i = 1; i < relativePoints.length; i++) {
|
||||
shape.lineTo(relativePoints[i].x, relativePoints[i].y);
|
||||
}
|
||||
|
||||
return { shape, center: [centroidX, centroidY] };
|
||||
}, [floor]);
|
||||
|
||||
const textureScale = Constants.floorConfig.textureScale;
|
||||
|
||||
function getMaterialMaps(material: any, defaultMap: any) {
|
||||
@@ -132,28 +114,23 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
});
|
||||
});
|
||||
|
||||
const geometry = useMemo(() => {
|
||||
if (!shapeData) return null;
|
||||
return new ExtrudeGeometry(shapeData.shape, {
|
||||
depth: !floor.isBeveled ? floor.floorDepth : floor.floorDepth - 0.1,
|
||||
bevelEnabled: floor.isBeveled,
|
||||
bevelSegments: floor.bevelStrength,
|
||||
bevelOffset: -0.1,
|
||||
bevelSize: 0.1,
|
||||
bevelThickness: 0.1,
|
||||
});
|
||||
}, [shapeData, floor]);
|
||||
|
||||
if (!geometry) return null;
|
||||
const extrudeOptions = {
|
||||
depth: !floor.isBeveled ? floor.floorDepth : floor.floorDepth - 0.1,
|
||||
bevelEnabled: floor.isBeveled,
|
||||
bevelSegments: floor.bevelStrength,
|
||||
bevelOffset: -0.1,
|
||||
bevelSize: 0.1,
|
||||
bevelThickness: 0.1,
|
||||
};
|
||||
|
||||
return (
|
||||
<mesh
|
||||
<ExtrudePolygon
|
||||
castShadow
|
||||
receiveShadow
|
||||
geometry={geometry}
|
||||
points={floor.points}
|
||||
options={extrudeOptions}
|
||||
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={[0, !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, 0]}
|
||||
userData={floor}
|
||||
onDoubleClick={(e) => {
|
||||
if (!toggleView && activeModule === "builder") {
|
||||
@@ -170,7 +147,7 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<meshPhysicalMaterial
|
||||
<meshStandardMaterial
|
||||
attach="material-0"
|
||||
color={Constants.floorConfig.defaultColor}
|
||||
map={topTexture}
|
||||
@@ -196,7 +173,7 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
{floor.decals.map((decal) => (
|
||||
<DecalInstance parent={floor} key={decal.decalUuid} decal={decal} />
|
||||
))}
|
||||
</mesh>
|
||||
</ExtrudePolygon>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import * as THREE from 'three';
|
||||
import { Base } from '@react-three/csg';
|
||||
import { useMemo, useRef, useState } from 'react';
|
||||
import { MeshDiscardMaterial } from '@react-three/drei';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import useModuleStore from '../../../../../store/ui/useModuleStore';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useWallClassification } from './helpers/useWallClassification';
|
||||
import { useToggleView, useWallVisibility } from '../../../../../store/builder/store';
|
||||
import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
|
||||
import * as Constants from '../../../../../types/world/worldConstants';
|
||||
import * as THREE from "three";
|
||||
import { Base } from "@react-three/csg";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { MeshDiscardMaterial } from "@react-three/drei";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import useModuleStore from "../../../../../store/ui/useModuleStore";
|
||||
import { useSceneContext } from "../../../../scene/sceneContext";
|
||||
import { useWallClassification } from "./helpers/useWallClassification";
|
||||
import { useToggleView, useWallVisibility } from "../../../../../store/builder/store";
|
||||
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
|
||||
import * as Constants from "../../../../../types/world/worldConstants";
|
||||
|
||||
import DecalInstance from '../../../Decal/decalInstance/decalInstance';
|
||||
import DecalInstance from "../../../Decal/decalInstance/decalInstance";
|
||||
|
||||
import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png';
|
||||
import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
|
||||
import defaultMaterial from "../../../../../assets/textures/floor/wall-tex.png";
|
||||
import material1 from "../../../../../assets/textures/floor/factory wall texture.jpg";
|
||||
|
||||
function Wall({ wall }: { readonly wall: Wall }) {
|
||||
const { wallStore, wallAssetStore } = useSceneContext();
|
||||
@@ -66,19 +66,19 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
|
||||
const materials = useMemo(() => {
|
||||
return [
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Left
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Right
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Top
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Bottom
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Left
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Right
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Top
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Bottom
|
||||
new THREE.MeshStandardMaterial({
|
||||
color: Constants.wallConfig.defaultColor,
|
||||
side: THREE.DoubleSide,
|
||||
map: wall.insideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture,
|
||||
map: wall.insideMaterial === "Default Material" ? defaultWallTexture : material1WallTexture,
|
||||
}),
|
||||
new THREE.MeshStandardMaterial({
|
||||
color: Constants.wallConfig.defaultColor,
|
||||
side: THREE.DoubleSide,
|
||||
map: wall.outsideMaterial === 'Default Material' ? defaultWallTexture : material1WallTexture,
|
||||
map: wall.outsideMaterial === "Default Material" ? defaultWallTexture : material1WallTexture,
|
||||
}),
|
||||
];
|
||||
}, [defaultWallTexture, material1WallTexture, wall, visible]);
|
||||
@@ -96,7 +96,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
meshRef.current.getWorldDirection(v);
|
||||
camera.getWorldDirection(u);
|
||||
if (!u || !v) return;
|
||||
nextVisible = (2 * v.dot(u)) <= 0.1;
|
||||
nextVisible = 2 * v.dot(u) <= 0.1;
|
||||
}
|
||||
|
||||
if (prevVisibleRef.current !== nextVisible) {
|
||||
@@ -104,19 +104,13 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
setVisible(nextVisible);
|
||||
assets.forEach((asset) => {
|
||||
setVisibility(asset.modelUuid, nextVisible);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
castShadow
|
||||
receiveShadow
|
||||
name={`Wall-${wall.wallUuid}`}
|
||||
key={wall.wallUuid}
|
||||
userData={wall}
|
||||
>
|
||||
{(assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0)) ?
|
||||
<mesh castShadow receiveShadow name={`Wall-${wall.wallUuid}`} key={wall.wallUuid} userData={wall}>
|
||||
{assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0) ? (
|
||||
<Base
|
||||
name={`BaseWall${wall.wallUuid}`}
|
||||
castShadow
|
||||
@@ -131,21 +125,13 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
<primitive key={index} visible={visible} object={material} attach={`material-${index}`} />
|
||||
))}
|
||||
</Base>
|
||||
:
|
||||
<mesh
|
||||
castShadow
|
||||
receiveShadow
|
||||
ref={meshRef}
|
||||
geometry={geometry}
|
||||
position={[centerX, centerY, centerZ]}
|
||||
rotation={[0, -angle, 0]}
|
||||
userData={wall}
|
||||
>
|
||||
) : (
|
||||
<mesh castShadow receiveShadow ref={meshRef} geometry={geometry} position={[centerX, centerY, centerZ]} rotation={[0, -angle, 0]} userData={wall}>
|
||||
{materials.map((material, index) => (
|
||||
<primitive key={index} visible={visible} object={material} attach={`material-${index}`} />
|
||||
))}
|
||||
</mesh>
|
||||
}
|
||||
)}
|
||||
<mesh
|
||||
castShadow
|
||||
receiveShadow
|
||||
@@ -155,7 +141,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
userData={wall}
|
||||
name={`WallReference_${wall.wallUuid}`}
|
||||
onDoubleClick={(e) => {
|
||||
if (visible && !toggleView && activeModule === 'builder') {
|
||||
if (visible && !toggleView && activeModule === "builder") {
|
||||
if (e.object.userData.wallUuid) {
|
||||
e.stopPropagation();
|
||||
setSelectedWall(e.object);
|
||||
@@ -179,4 +165,4 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default Wall;
|
||||
export default Wall;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from "three";
|
||||
import { Html, Extrude } from "@react-three/drei";
|
||||
import { DoubleSide, RepeatWrapping, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from "three";
|
||||
import { Html } from "@react-three/drei";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
@@ -16,6 +16,7 @@ import texturePathDark from "../../../../assets/textures/floor/black.png";
|
||||
import useModuleStore from "../../../../store/ui/useModuleStore";
|
||||
import getCenteroidPoint from "../../functions/getCenteroid";
|
||||
import getArea from "../../functions/getArea";
|
||||
import ExtrudePolygon from "../../wrappers/geomentry/extrudePolygon";
|
||||
|
||||
function WallInstances() {
|
||||
const { wallStore } = useSceneContext();
|
||||
@@ -135,25 +136,10 @@ function Floor3D({ room }: { readonly room: Point[] }) {
|
||||
floorTexture.repeat.set(textureScale, textureScale);
|
||||
floorTexture.colorSpace = SRGBColorSpace;
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new Shape();
|
||||
const points = room.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
shape.moveTo(points[0].x, points[0].y);
|
||||
points.forEach((pt) => {
|
||||
shape.lineTo(pt.x, pt.y);
|
||||
});
|
||||
return shape;
|
||||
}, [room]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
return (
|
||||
<mesh name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
|
||||
<Extrude receiveShadow castShadow name="Wall-Floor" args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]} position={[0, 0, 0]}>
|
||||
<meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<ExtrudePolygon points={room} receiveShadow castShadow name="Wall-Floor" options={{ depth: Constants.floorConfig.height, bevelEnabled: false }}>
|
||||
<meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
|
||||
</ExtrudePolygon>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -164,16 +150,6 @@ function Floor2D({ room }: { readonly room: Point[] }) {
|
||||
return room.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [room]);
|
||||
|
||||
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]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
@@ -183,17 +159,13 @@ function Floor2D({ room }: { readonly room: Point[] }) {
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh castShadow receiveShadow name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
|
||||
<Extrude receiveShadow castShadow name="Wall-Floor" args={[shape, { depth: Constants.floorConfig.height }]} position={[0, 0, 0]}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.wallColor : Constants.lineConfig.wallColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<ExtrudePolygon points={room} receiveShadow castShadow name="Wall-Floor" options={{ depth: 0, bevelEnabled: false }}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.wallColor : Constants.lineConfig.wallColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</ExtrudePolygon>
|
||||
|
||||
<Html position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">({formattedArea})</div>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import { useMemo, ReactNode } from "react";
|
||||
import { ExtrudeGeometryOptions, Shape, Vector2, Vector3, Euler } from "three";
|
||||
import { Extrude } from "@react-three/drei";
|
||||
import { ThreeEvent } from "@react-three/fiber";
|
||||
|
||||
function ExtrudePolygon({
|
||||
name,
|
||||
points,
|
||||
options,
|
||||
userData,
|
||||
children,
|
||||
castShadow,
|
||||
receiveShadow,
|
||||
position = [0, 0, 0],
|
||||
rotation = [Math.PI / 2, 0, 0],
|
||||
onClick,
|
||||
onContextMenu,
|
||||
onDoubleClick,
|
||||
onPointerUp,
|
||||
onPointerDown,
|
||||
onPointerOver,
|
||||
onPointerOut,
|
||||
onPointerEnter,
|
||||
onPointerLeave,
|
||||
onPointerMove,
|
||||
onPointerMissed,
|
||||
onPointerCancel,
|
||||
onWheel,
|
||||
}: Readonly<{
|
||||
name?: string;
|
||||
options?: ExtrudeGeometryOptions;
|
||||
userData?: Record<string, any>;
|
||||
points: Point[];
|
||||
children?: ReactNode;
|
||||
castShadow?: boolean;
|
||||
receiveShadow?: boolean;
|
||||
position?: [number, number, number] | Vector3;
|
||||
rotation?: [number, number, number] | Euler;
|
||||
onClick?: (event: ThreeEvent<MouseEvent>) => void;
|
||||
onContextMenu?: (event: ThreeEvent<MouseEvent>) => void;
|
||||
onDoubleClick?: (event: ThreeEvent<MouseEvent>) => void;
|
||||
onPointerUp?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerDown?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerOver?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerOut?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerEnter?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerLeave?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerMove?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onPointerMissed?: (event: MouseEvent) => void;
|
||||
onPointerCancel?: (event: ThreeEvent<PointerEvent>) => void;
|
||||
onWheel?: (event: ThreeEvent<WheelEvent>) => void;
|
||||
}>) {
|
||||
const points2D = useMemo(() => {
|
||||
return points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [points]);
|
||||
|
||||
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.closePath();
|
||||
return shape;
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
return (
|
||||
<Extrude
|
||||
name={name}
|
||||
args={[shape, options]}
|
||||
position={position}
|
||||
rotation={rotation}
|
||||
userData={userData}
|
||||
castShadow={castShadow}
|
||||
receiveShadow={receiveShadow}
|
||||
onClick={onClick}
|
||||
onContextMenu={onContextMenu}
|
||||
onDoubleClick={onDoubleClick}
|
||||
onPointerUp={onPointerUp}
|
||||
onPointerDown={onPointerDown}
|
||||
onPointerOver={onPointerOver}
|
||||
onPointerOut={onPointerOut}
|
||||
onPointerEnter={onPointerEnter}
|
||||
onPointerLeave={onPointerLeave}
|
||||
onPointerMove={onPointerMove}
|
||||
onPointerMissed={onPointerMissed}
|
||||
onPointerCancel={onPointerCancel}
|
||||
onWheel={onWheel}
|
||||
>
|
||||
{children}
|
||||
</Extrude>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExtrudePolygon;
|
||||
@@ -1,24 +1,41 @@
|
||||
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 { 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 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 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";
|
||||
import zone3Vertex from "../../../../assets/shaders/zone/zone3.vert.glsl";
|
||||
import zone3Fragment from "../../../../assets/shaders/zone/zone3.frag.glsl";
|
||||
|
||||
type PlaneMaterialProps = {
|
||||
color: string;
|
||||
color?: string;
|
||||
variant?: "zone1" | "zone2" | "zone3";
|
||||
transparent?: boolean;
|
||||
opacity?: number;
|
||||
depthWrite?: boolean;
|
||||
depthTest?: boolean;
|
||||
polygonOffset?: boolean;
|
||||
polygonOffsetFactor?: number;
|
||||
polygonOffsetUnits?: number;
|
||||
};
|
||||
|
||||
function PlaneMaterial({ color, variant = "zone1", ...props }: Readonly<PlaneMaterialProps>) {
|
||||
function PlaneMaterial({
|
||||
color = "white",
|
||||
variant = "zone1",
|
||||
transparent = false,
|
||||
opacity = 1,
|
||||
depthWrite,
|
||||
depthTest,
|
||||
polygonOffset = false,
|
||||
polygonOffsetFactor,
|
||||
polygonOffsetUnits,
|
||||
}: Readonly<PlaneMaterialProps>) {
|
||||
const { limitFps } = useSceneStore();
|
||||
const materialRef = useRef<ShaderMaterial | null>(null);
|
||||
|
||||
@@ -40,11 +57,15 @@ function PlaneMaterial({ color, variant = "zone1", ...props }: Readonly<PlaneMat
|
||||
uOuterColor: { value: new Color(color) },
|
||||
uTime: { value: 0 },
|
||||
},
|
||||
transparent: true,
|
||||
depthWrite: false,
|
||||
...props,
|
||||
transparent,
|
||||
opacity,
|
||||
depthWrite,
|
||||
depthTest,
|
||||
polygonOffset,
|
||||
polygonOffsetFactor,
|
||||
polygonOffsetUnits,
|
||||
});
|
||||
}, [color, vertexShader, fragmentShader]);
|
||||
}, [color, vertexShader, fragmentShader, transparent, opacity, depthWrite, depthTest, polygonOffset, polygonOffsetFactor, polygonOffsetUnits]);
|
||||
|
||||
useFrame(({ clock }) => {
|
||||
if (materialRef.current && !limitFps) {
|
||||
@@ -1,18 +1,37 @@
|
||||
import { useMemo } from "react";
|
||||
import { Color, DoubleSide, ShaderMaterial, Vector3, MeshStandardMaterial } from "three";
|
||||
import useShaderReader from "../../../utils/scene/useShaderReader";
|
||||
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";
|
||||
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;
|
||||
color?: string;
|
||||
transparent?: boolean;
|
||||
depthWrite?: boolean;
|
||||
depthTest?: boolean;
|
||||
opacity?: number;
|
||||
polygonOffset?: boolean;
|
||||
polygonOffsetFactor?: number;
|
||||
polygonOffsetUnits?: number;
|
||||
fadeDistance?: number;
|
||||
variant?: "edge" | "none";
|
||||
};
|
||||
|
||||
function PolygonMaterial({ points, color, fadeDistance = 2.0, variant = "edge", ...props }: Readonly<PolygonMaterialProps>) {
|
||||
function PolygonMaterial({
|
||||
points,
|
||||
color = "white",
|
||||
transparent = false,
|
||||
depthWrite,
|
||||
depthTest,
|
||||
opacity = 1,
|
||||
polygonOffset = false,
|
||||
polygonOffsetFactor,
|
||||
polygonOffsetUnits,
|
||||
fadeDistance = 2.0,
|
||||
variant = "none",
|
||||
}: Readonly<PolygonMaterialProps>) {
|
||||
const vertexShader = useShaderReader(edgeVertex);
|
||||
const fragmentShader = useShaderReader(edgeFragment);
|
||||
|
||||
@@ -41,13 +60,13 @@ function PolygonMaterial({ points, color, fadeDistance = 2.0, variant = "edge",
|
||||
uEdges: { value: edgeArray },
|
||||
uEdgeCount: { value: edges.length },
|
||||
},
|
||||
transparent: true,
|
||||
depthWrite: false,
|
||||
depthTest: true,
|
||||
polygonOffset: true,
|
||||
polygonOffsetFactor: -10,
|
||||
polygonOffsetUnits: -10,
|
||||
...props,
|
||||
transparent,
|
||||
depthWrite,
|
||||
depthTest,
|
||||
polygonOffset,
|
||||
polygonOffsetFactor,
|
||||
polygonOffsetUnits,
|
||||
opacity,
|
||||
});
|
||||
}, [color, fadeDistance, vertexShader, fragmentShader, edges]);
|
||||
|
||||
@@ -56,7 +75,13 @@ function PolygonMaterial({ points, color, fadeDistance = 2.0, variant = "edge",
|
||||
return new MeshStandardMaterial({
|
||||
color: new Color(color),
|
||||
side: DoubleSide,
|
||||
transparent: true,
|
||||
transparent,
|
||||
depthWrite,
|
||||
depthTest,
|
||||
polygonOffset,
|
||||
polygonOffsetFactor,
|
||||
polygonOffsetUnits,
|
||||
opacity,
|
||||
});
|
||||
}, [color]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from "react";
|
||||
import { DoubleSide, Shape, Vector2 } from "three";
|
||||
import { Extrude, Html } from "@react-three/drei";
|
||||
import { DoubleSide, Vector2 } from "three";
|
||||
import { Html } from "@react-three/drei";
|
||||
import ExtrudePolygon from "../../../wrappers/geomentry/extrudePolygon";
|
||||
import * as Constants from "../../../../../types/world/worldConstants";
|
||||
import getCenteroid from "../../../functions/getCenteroid";
|
||||
import getArea from "../../../functions/getArea";
|
||||
@@ -12,16 +13,6 @@ function Zone2DInstance({ zone }: { readonly zone: Zone }) {
|
||||
return zone.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [zone]);
|
||||
|
||||
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]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
@@ -31,17 +22,13 @@ function Zone2DInstance({ zone }: { readonly zone: Zone }) {
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh castShadow receiveShadow name={`Zone-2D-${zone.zoneUuid}`} rotation={[Math.PI / 2, 0, 0]} position={[0, 0, 0]} userData={zone}>
|
||||
<Extrude name={`Zone-${zone.zoneUuid}`} args={[shape, { depth: Constants.floorConfig.height }]} userData={zone}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.zoneColor : Constants.lineConfig.zoneColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<ExtrudePolygon points={zone.points} options={{ depth: 0, bevelEnabled: false }} castShadow receiveShadow name={`Zone-2D-${zone.zoneUuid}`} userData={zone}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.zoneColor : Constants.lineConfig.zoneColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</ExtrudePolygon>
|
||||
|
||||
<Html key={zone.zoneUuid} position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Vector3 } from "three";
|
||||
import { RoundedBox } from "@react-three/drei";
|
||||
|
||||
function CornerReference({
|
||||
function ZoneCornerReference({
|
||||
point,
|
||||
prevPoint,
|
||||
nextPoint,
|
||||
@@ -77,4 +77,4 @@ function CornerReference({
|
||||
);
|
||||
}
|
||||
|
||||
export default CornerReference;
|
||||
export default ZoneCornerReference;
|
||||
@@ -1,34 +1,27 @@
|
||||
import { useMemo } from "react";
|
||||
import { Extrude } from "@react-three/drei";
|
||||
import { Shape, Vector2, Vector3 } from "three";
|
||||
import CornerReference from "./cornerReference";
|
||||
import PlaneMaterial from "../../../materials/planeMaterial";
|
||||
import PolygonMaterial from "../../../materials/polygonMaterial";
|
||||
import { Vector3 } from "three";
|
||||
import ZoneCornerReference from "./zoneCornerReference";
|
||||
import ExtrudePolygon from "../../../wrappers/geomentry/extrudePolygon";
|
||||
import PlaneMaterial from "../../../wrappers/materials/planeMaterial";
|
||||
import PolygonMaterial from "../../../wrappers/materials/polygonMaterial";
|
||||
|
||||
function ZoneInstance({ zone }: { readonly zone: Zone }) {
|
||||
const zoneLayer = zone.points[0].layer;
|
||||
|
||||
const points2D = useMemo(() => {
|
||||
return zone.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [zone]);
|
||||
|
||||
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 (!shape) return null;
|
||||
|
||||
return (
|
||||
<group name={`Zone-${zone.zoneUuid}`} userData={zone}>
|
||||
<Extrude args={[shape, { depth: 0, bevelEnabled: false }]} rotation={[Math.PI / 2, 0, 0]}>
|
||||
<PolygonMaterial points={zone.points} color={zone.zoneColor} variant="edge" />
|
||||
</Extrude>
|
||||
<ExtrudePolygon options={{ depth: 0, bevelEnabled: false }} points={zone.points}>
|
||||
<PolygonMaterial
|
||||
transparent
|
||||
depthWrite={false}
|
||||
depthTest={true}
|
||||
polygonOffset
|
||||
polygonOffsetFactor={-10}
|
||||
polygonOffsetUnits={-10}
|
||||
points={zone.points}
|
||||
color={zone.zoneColor}
|
||||
variant="edge"
|
||||
/>
|
||||
</ExtrudePolygon>
|
||||
|
||||
{zone.points.map((point, index: number) => {
|
||||
const nextPoint = zone.points[(index + 1) % zone.points.length];
|
||||
@@ -47,10 +40,10 @@ function ZoneInstance({ zone }: { readonly zone: Zone }) {
|
||||
<group key={index}>
|
||||
<mesh position={midpoint} rotation={[0, -angle, 0]}>
|
||||
<planeGeometry args={[planeWidth, planeHeight]} />
|
||||
<PlaneMaterial color={zone.zoneColor} variant="zone1" />
|
||||
<PlaneMaterial transparent depthWrite={false} depthTest={true} color={zone.zoneColor} variant="zone1" />
|
||||
</mesh>
|
||||
|
||||
<CornerReference showTop={false} showBottom={false} point={point} prevPoint={prevPoint} nextPoint={nextPoint} zone={zone} cornerThickness={0.25} />
|
||||
<ZoneCornerReference showTop showBottom point={point} prevPoint={prevPoint} nextPoint={nextPoint} zone={zone} cornerThickness={0.25} />
|
||||
</group>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user