diff --git a/src/App.tsx b/src/App.tsx
index 42240a4..8680423 100755
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,88 +1,8 @@
-import Layout from "./three/Layout";
-import { ThreeProvider } from "./three";
-import useLayoutGeometry from "./three/useLayoutGeometry";
-import NavMesh from "./three/NavMesh";
-
-const wallConfig = {
- wallThickness: 0.4,
- width: 20,
- length: 20,
- wallHeight: 1,
-};
-
-const walls = [
- [
- [1, -9.75],
- [1, 1.2],
- ],
- [
- [-4.6, 1.2],
- [1.02, 1.2],
- ],
- [
- [-9.55, 1.2],
- [-7.1, 1.2],
- ],
- [
- [4, -9.75],
- [4, -4],
- ],
- [
- [4, -0.6],
- [4, 0.75],
- ],
- [
- [4, 0.55],
- [8.34, 0.55],
- ],
- [
- [-9.65, 8.5],
- [-6.8, 8.5],
- ],
- [
- [-3.75, 8.5],
- [2.5, 8.5],
- ],
- [
- [5.55, 8.5],
- [8.34, 8.5],
- ],
- [
- [-9.9, -9.75],
- [1.2, -9.75],
- ],
- [
- [3.8, -9.75],
- [8.7, -9.75],
- ],
- [
- [-9.7, -9.75],
- [-9.7, 8.7],
- ],
- [
- [8.5, -9.75],
- [8.5, 8.7],
- ],
-].map(
- ([start, end]) =>
- [
- [start[0], 0, start[1]],
- [end[0], wallConfig.wallHeight, end[1]],
- ] as [number[], number[]]
-);
+import ThreeApp from "./ThreeApp";
+import { wallConfig, walls } from "./data";
const App = () => {
- const geometry = useLayoutGeometry({
- ...wallConfig,
- walls,
- });
-
- return (
-
-
-
-
- );
+ return ;
};
export default App;
diff --git a/src/ThreeApp.tsx b/src/ThreeApp.tsx
new file mode 100644
index 0000000..e6abcac
--- /dev/null
+++ b/src/ThreeApp.tsx
@@ -0,0 +1,20 @@
+import Layout from "./three/Layout";
+import { ThreeProvider } from "./three";
+import NavMesh from "./three/NavMesh";
+import { WallConfig, Walls } from "./data";
+
+interface ThreeAppProps {
+ wallConfig: WallConfig;
+ walls: Walls;
+}
+
+const ThreeApp = ({ wallConfig, walls }: ThreeAppProps) => {
+ return (
+
+
+
+
+ );
+};
+
+export default ThreeApp;
diff --git a/src/data.ts b/src/data.ts
new file mode 100644
index 0000000..ba7d254
--- /dev/null
+++ b/src/data.ts
@@ -0,0 +1,79 @@
+type Vector3Pair = [number[], number[]];
+
+export type Walls = Array;
+export interface WallConfig {
+ width: number;
+ length: number;
+ wallThickness: number;
+ wallHeight: number;
+}
+
+const wallConfig: WallConfig = {
+ wallThickness: 0.4,
+ width: 20,
+ length: 20,
+ wallHeight: 1,
+};
+
+const walls: Walls = [
+ [
+ [1, -9.75],
+ [1, 1.2],
+ ],
+ [
+ [-4.6, 1.2],
+ [1.02, 1.2],
+ ],
+ [
+ [-9.55, 1.2],
+ [-7.1, 1.2],
+ ],
+ [
+ [4, -9.75],
+ [4, -4],
+ ],
+ [
+ [4, -0.6],
+ [4, 0.75],
+ ],
+ [
+ [4, 0.55],
+ [8.34, 0.55],
+ ],
+ [
+ [-9.65, 8.5],
+ [-6.8, 8.5],
+ ],
+ [
+ [-3.75, 8.5],
+ [2.5, 8.5],
+ ],
+ [
+ [5.55, 8.5],
+ [8.34, 8.5],
+ ],
+ [
+ [-9.9, -9.75],
+ [1.2, -9.75],
+ ],
+ [
+ [3.8, -9.75],
+ [8.7, -9.75],
+ ],
+ [
+ [-9.7, -9.75],
+ [-9.7, 8.7],
+ ],
+ [
+ [8.5, -9.75],
+ [8.5, 8.7],
+ ],
+].map(
+ ([start, end]) =>
+ [
+ [start[0], 0, start[1]],
+ [end[0], wallConfig.wallHeight, end[1]],
+ ] as [number[], number[]]
+);
+
+export { wallConfig, walls };
diff --git a/src/stories/App.stories.ts b/src/stories/App.stories.ts
index f16bf17..8a3992e 100755
--- a/src/stories/App.stories.ts
+++ b/src/stories/App.stories.ts
@@ -1,15 +1,19 @@
import type { Meta, StoryObj } from "@storybook/react";
-import App from "../App";
+import ThreeApp from "../ThreeApp";
+import { wallConfig, walls } from "../data";
const meta = {
- title: "App",
- component: App,
-} satisfies Meta;
+ title: "ThreeApp",
+ component: ThreeApp,
+} satisfies Meta;
export default meta;
type Story = StoryObj;
export const Playground: Story = {
- args: {},
+ args: {
+ wallConfig,
+ walls,
+ },
};
diff --git a/src/three/Layout.ts b/src/three/Layout.ts
index 5376dd9..4b4bddb 100644
--- a/src/three/Layout.ts
+++ b/src/three/Layout.ts
@@ -2,12 +2,12 @@ import * as THREE from "three";
import { useThree } from ".";
import { useEffect } from "react";
import useWebGLRenderTarget from "./useWebGLRenderTarget";
+import { WallConfig, Walls } from "../data";
+import useLayoutGeometry from "./useLayoutGeometry";
interface LayoutProps {
- geometry: THREE.BufferGeometry;
- wallHeight: number;
- width: number;
- length: number;
+ wallConfig: WallConfig;
+ walls: Walls;
}
const vertexShader = `
@@ -57,19 +57,23 @@ class OutlineMaterial extends THREE.ShaderMaterial {
}
}
-const Layout = ({ geometry, width, length, wallHeight }: LayoutProps) => {
+const Layout = ({ wallConfig, walls }: LayoutProps) => {
const { scene } = useThree();
const topView = useWebGLRenderTarget();
+ const geometry = useLayoutGeometry({
+ ...wallConfig,
+ walls,
+ });
useEffect(() => {
if (!scene) return;
-
const material = new OutlineMaterial(topView.texture);
const mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false;
scene.add(mesh);
requestAnimationFrame(() => {
+ const { width, length, wallHeight } = wallConfig;
const topViewSene = new THREE.Scene();
const topViewMaterial = new THREE.MeshBasicMaterial({ color: "white" });
const topViewMesh = new THREE.Mesh(geometry, topViewMaterial);
@@ -91,7 +95,7 @@ const Layout = ({ geometry, width, length, wallHeight }: LayoutProps) => {
return () => {
scene.remove(mesh);
};
- }, [scene, geometry]);
+ }, [scene, geometry, wallConfig, walls]);
return null;
};
diff --git a/src/three/NavMesh.ts b/src/three/NavMesh.ts
index 4d93bf3..e5835ef 100644
--- a/src/three/NavMesh.ts
+++ b/src/three/NavMesh.ts
@@ -4,35 +4,50 @@ import { threeToSoloNavMesh, NavMeshHelper } from "recast-navigation/three";
import { useThree } from ".";
import { useEffect, useState } from "react";
+import useLayoutGeometry from "./useLayoutGeometry";
+import { WallConfig, Walls } from "../data";
interface NavMeshProps {
- geometry: THREE.BufferGeometry;
- wallThickness: number;
+ wallConfig: WallConfig;
+ walls: Walls;
}
-export const useNavMesh = ({ geometry, wallThickness }: NavMeshProps) => {
+export const useNavMesh = ({ wallConfig, walls }: NavMeshProps) => {
+ const [libReady, setLibReady] = useState(false);
const [navMesh, setNavMesh] = useState();
+ const geometry = useLayoutGeometry({
+ ...wallConfig,
+ walls,
+ });
+
+ useEffect(() => {
+ init().then(() => setLibReady(true));
+ }, []);
+
useEffect(() => {
+ if (!libReady) return;
if (!geometry) return;
- init().then(() => {
- const { navMesh } = threeToSoloNavMesh([new THREE.Mesh(geometry)], {
- ch: 1e-2,
- cs: wallThickness + 1e-2,
- walkableHeight: 1,
- });
- if (navMesh) {
- setNavMesh(navMesh);
- }
+ const { wallThickness } = wallConfig;
+ const { navMesh } = threeToSoloNavMesh([new THREE.Mesh(geometry)], {
+ ch: 1e-2,
+ cs: wallThickness + 1e-2,
+ walkableHeight: 1,
});
- }, [geometry, wallThickness]);
+ if (navMesh) {
+ setNavMesh(navMesh);
+ }
+ return () => {
+ navMesh?.destroy();
+ };
+ }, [geometry, libReady, wallConfig, walls]);
return navMesh;
};
-const NavMeshRenderer = ({ geometry, wallThickness }: NavMeshProps) => {
+const NavMeshRenderer = ({ wallConfig, walls }: NavMeshProps) => {
const { scene } = useThree();
- const navMesh = useNavMesh({ geometry, wallThickness });
+ const navMesh = useNavMesh({ wallConfig, walls });
useEffect(() => {
if (!navMesh) return;