Skip to content

Commit

Permalink
feat: expose duDebugDraw, add temporary duplicate NavMeshHelper2 that…
Browse files Browse the repository at this point in the history
… uses duDebugDrawNavMesh
  • Loading branch information
isaac-mason committed Apr 23, 2024
1 parent c1fca72 commit b503744
Show file tree
Hide file tree
Showing 9 changed files with 521 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/recast-navigation-core/src/raw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const instances = [
'NavMeshExporter',
'CrowdUtils',
'ChunkyTriMeshUtils',
'RecastDebugDraw',
'DetourDebugDraw',
] as const satisfies readonly ModuleKey[];

const classes = [
Expand All @@ -32,6 +34,7 @@ const classes = [
'UnsignedCharRef',
'UnsignedShortRef',
'FloatRef',

] as const satisfies readonly ModuleKey[];

const arrays = [
Expand Down
266 changes: 266 additions & 0 deletions packages/recast-navigation-three/src/debug-draw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
import { Raw } from '@recast-navigation/core';
import * as THREE from 'three';
import {
LineMaterial,
LineSegments2,
LineSegmentsGeometry,
} from 'three-stdlib';

type VertexData = {
x: number;
y: number;
z: number;
r: number;
g: number;
b: number;
a: number;
};

const _color = new THREE.Color();

export type DebugDrawParams = {
triMaterial?: THREE.Material;
pointMaterial?: THREE.Material;
lineMaterial?: LineMaterial;
};

export class DebugDraw {
raw: InstanceType<typeof Raw.Module.DebugDrawImpl>;

group: THREE.Group = new THREE.Group();

currentVertices: VertexData[] = [];
currentPrimitive = 0;
currentSize = 1;

triMaterial: THREE.Material;
pointMaterial: THREE.Material;
lineMaterial: LineMaterial;

pointGeometry = new THREE.SphereGeometry(0.02, 32, 32);

constructor({
triMaterial,
pointMaterial,
lineMaterial,
}: DebugDrawParams = {}) {
this.triMaterial =
triMaterial ??
new THREE.MeshBasicMaterial({
vertexColors: true,
transparent: true,
opacity: 0.4,
depthWrite: false,
});

this.pointMaterial = pointMaterial ?? new THREE.MeshBasicMaterial();

this.lineMaterial =
lineMaterial ??
new LineMaterial({
color: 0xffffff,
linewidth: 3,
vertexColors: true,
transparent: true,
opacity: 0.4,
depthWrite: false,
});

this.raw = new Raw.Module.DebugDrawImpl();

/**
* DU_DRAW_POINTS = 0
* DU_DRAW_LINES = 1
* DU_DRAW_TRIS = 2
* DU_DRAW_QUADS = 3
*/
this.raw.handleBegin = (primitive: number, size: number) => {
this.currentPrimitive = primitive;
this.currentSize = size;
this.currentVertices = [];
};

this.raw.handleDepthMask = (_state: number) => {
// all methods must be implemented
};

this.raw.handleTexture = (_state: number) => {
// all methods must be implemented
};

this.raw.handleVertexWithColor = (
x: number,
y: number,
z: number,
color: number
) => {
this.vertex(x, y, z, color);
};

this.raw.handleVertexWithColorAndUV = (
x: number,
y: number,
z: number,
color: number,
_u: number,
_v: number
) => {
this.vertex(x, y, z, color);
};

this.raw.handleEnd = () => {
if (this.currentPrimitive === Raw.Module.DU_DRAW_LINES) {
this.endLines();
} else if (this.currentPrimitive === Raw.Module.DU_DRAW_TRIS) {
this.endTris();
} else if (this.currentPrimitive === Raw.Module.DU_DRAW_QUADS) {
this.endQuads();
} else if (this.currentPrimitive === Raw.Module.DU_DRAW_POINTS) {
this.endPoints();
}
};
}

resize(width: number, height: number): void {
this.lineMaterial.resolution.set(width, height);
}

vertex(x: number, y: number, z: number, color: number) {
const r = ((color >> 16) & 0xff) / 255;
const g = ((color >> 8) & 0xff) / 255;
const b = (color & 0xff) / 255;
const a = ((color >> 24) & 0xff) / 255;

this.currentVertices.push({ x, y, z, r, g, b, a });
}

endPoints(): void {
const geometry = this.pointGeometry;

const instancedMesh = new THREE.InstancedMesh(
geometry,
this.pointMaterial,
this.currentVertices.length
);

for (let i = 0; i < this.currentVertices.length; i++) {
const point = this.currentVertices[i];

instancedMesh.setMatrixAt(
i,
new THREE.Matrix4().setPosition(point.x, point.y, point.z)
);

instancedMesh.setColorAt(i, _color.setRGB(point.r, point.g, point.b));
}

instancedMesh.instanceMatrix.needsUpdate = true;

this.group.add(instancedMesh);
}

endLines(): void {
const lineSegmentsGeometry = new LineSegmentsGeometry();

const positions: number[] = [];
const colors: number[] = [];

for (let i = 0; i < this.currentVertices.length; i += 2) {
const p1 = this.currentVertices[i];
const p2 = this.currentVertices[i + 1];

positions.push(p1.x, p1.y, p1.z);
positions.push(p2.x, p2.y, p2.z);

colors.push(p1.r, p1.g, p1.b);
colors.push(p2.r, p2.g, p2.b);
}

lineSegmentsGeometry.setPositions(positions);
lineSegmentsGeometry.setColors(colors);

const lineSegments = new LineSegments2(
lineSegmentsGeometry,
this.lineMaterial
);

this.group.add(lineSegments);
}

endTris(): void {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(this.currentVertices.length * 3);
const colors = new Float32Array(this.currentVertices.length * 3);

for (let i = 0; i < this.currentVertices.length; i++) {
const point = this.currentVertices[i];
positions[i * 3 + 0] = point.x;
positions[i * 3 + 1] = point.y;
positions[i * 3 + 2] = point.z;

colors[i * 3 + 0] = point.r;
colors[i * 3 + 1] = point.g;
colors[i * 3 + 2] = point.b;
}

geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

const material = this.triMaterial;
const mesh = new THREE.Mesh(geometry, material);

this.group.add(mesh);
}

endQuads(): void {
const positions: number[] = [];
const colors: number[] = [];

for (let i = 0; i < this.currentVertices.length; i += 4) {
const vertices = [
this.currentVertices[i],
this.currentVertices[i + 1],
this.currentVertices[i + 2],

this.currentVertices[i],
this.currentVertices[i + 2],
this.currentVertices[i + 3],
];

for (const vertex of vertices) {
positions.push(vertex.x, vertex.y, vertex.z);
colors.push(vertex.r, vertex.g, vertex.b);
}
}

const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
'position',
new THREE.BufferAttribute(new Float32Array(positions), 3)
);
geometry.setAttribute(
'color',
new THREE.BufferAttribute(new Float32Array(colors), 3)
);

const material = this.triMaterial;

const mesh = new THREE.Mesh(geometry, material);

this.group.add(mesh);
}

reset(): void {
for (const child of this.group.children) {
if (child instanceof THREE.Mesh || child instanceof LineSegments2) {
child.geometry.dispose();
}

this.group.remove(child);
}
}

dispose(): void {
Raw.Module.destroy(this.raw);
}
}
46 changes: 46 additions & 0 deletions packages/recast-navigation-three/src/helpers/nav-mesh-helper-2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { NavMesh, Raw } from '@recast-navigation/core';
import { Object3D } from 'three';
import { DebugDraw } from '../debug-draw';

export type NavMeshHelperParams = {
navMesh: NavMesh;
};

export class NavMeshHelper2 extends Object3D {
private navMesh: NavMesh;

private debugDraw: DebugDraw;

constructor({ navMesh }: NavMeshHelperParams) {
super();

this.navMesh = navMesh;

this.debugDraw = new DebugDraw();
this.add(this.debugDraw.group);

this.update();
}

/**
* Handle resizing the canvas.
* @param width canvas width
* @param height canvas height
*/
resize(width: number, height: number) {
this.debugDraw.resize(width, height);
}

/**
* Update the three debug nav mesh.
*
* This should be called after updating the nav mesh.
*/
update() {
Raw.DetourDebugDraw.debugDrawNavMesh(
this.debugDraw.raw,
this.navMesh.raw.getNavMesh(),
0
);
}
}
1 change: 1 addition & 0 deletions packages/recast-navigation-wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ file(GLOB_RECURSE RECASTDETOUR_FILES
${CMAKE_SOURCE_DIR}/recastnavigation/DetourCrowd/*
${CMAKE_SOURCE_DIR}/recastnavigation/DetourTileCache/*
${CMAKE_SOURCE_DIR}/recastnavigation/Recast/*
${CMAKE_SOURCE_DIR}/recastnavigation/DebugUtils/*
${CMAKE_SOURCE_DIR}/recastnavigation/RecastDemo/Source/ChunkyTriMesh.cpp
${CMAKE_SOURCE_DIR}/recastnavigation/RecastDemo/Contrib/fastlz/fastlz.c
)
Expand Down
38 changes: 38 additions & 0 deletions packages/recast-navigation-wasm/recast-navigation.idl
Original file line number Diff line number Diff line change
Expand Up @@ -1173,3 +1173,41 @@ interface NavMeshExporter {
[Value] NavMeshExport exportNavMesh(NavMesh navMesh, TileCache tileCache);
void freeNavMeshExport(NavMeshExport navMeshExport);
};

enum duDebugDrawPrimitives {
"duDebugDrawPrimitives::DU_DRAW_POINTS",
"duDebugDrawPrimitives::DU_DRAW_LINES",
"duDebugDrawPrimitives::DU_DRAW_TRIS",
"duDebugDrawPrimitives::DU_DRAW_QUADS"
};

interface duDebugDraw {
};

interface DebugDraw {
};
DebugDraw implements duDebugDraw;

[JSImplementation="DebugDraw"]
interface DebugDrawImpl {
void DebugDrawImpl();

void handleDepthMask(boolean state);
void handleTexture(boolean state);
void handleBegin([Const] duDebugDrawPrimitives prim, float size);
void handleVertexWithColor([Const] float x, [Const] float y, [Const] float z, [Const] unsigned long color);
void handleVertexWithColorAndUV([Const] float x, [Const] float y, [Const] float z, [Const] unsigned long color, [Const] float u, [Const] float v);
void handleEnd();
};

interface RecastDebugDraw {
void RecastDebugDraw();

void debugDrawPolyMesh(duDebugDraw dd, [Const, Ref] rcPolyMesh mesh);
};

interface DetourDebugDraw {
void DetourDebugDraw();

void debugDrawNavMesh(duDebugDraw dd, [Const, Ref] dtNavMesh mesh, [Const] unsigned long flags);
};
Loading

0 comments on commit b503744

Please sign in to comment.