Skip to content

Commit

Permalink
doc: add threeApp document.
Browse files Browse the repository at this point in the history
  • Loading branch information
tsengyushiang committed Sep 22, 2024
1 parent 30d6e12 commit 8d46e5e
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 110 deletions.
86 changes: 3 additions & 83 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ThreeProvider>
<Layout geometry={geometry} {...wallConfig} />
<NavMesh geometry={geometry} wallThickness={wallConfig.wallThickness} />
</ThreeProvider>
);
return <ThreeApp wallConfig={wallConfig} walls={walls} />;
};

export default App;
20 changes: 20 additions & 0 deletions src/ThreeApp.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ThreeProvider>
<Layout wallConfig={wallConfig} walls={walls} />
<NavMesh wallConfig={wallConfig} walls={walls} />
</ThreeProvider>
);
};

export default ThreeApp;
79 changes: 79 additions & 0 deletions src/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
type Vector3Pair = [number[], number[]];

export type Walls = Array<Vector3Pair>;
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 };
14 changes: 9 additions & 5 deletions src/stories/App.stories.ts
Original file line number Diff line number Diff line change
@@ -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<typeof App>;
title: "ThreeApp",
component: ThreeApp,
} satisfies Meta<typeof ThreeApp>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Playground: Story = {
args: {},
args: {
wallConfig,
walls,
},
};
18 changes: 11 additions & 7 deletions src/three/Layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = `
Expand Down Expand Up @@ -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);
Expand All @@ -91,7 +95,7 @@ const Layout = ({ geometry, width, length, wallHeight }: LayoutProps) => {
return () => {
scene.remove(mesh);
};
}, [scene, geometry]);
}, [scene, geometry, wallConfig, walls]);

return null;
};
Expand Down
45 changes: 30 additions & 15 deletions src/three/NavMesh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<NavMesh | undefined>();
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;
Expand Down

0 comments on commit 8d46e5e

Please sign in to comment.