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