@recast-navigation/core 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright © 2022 Isaac Mason
3
+ Copyright © 2025 Isaac Mason
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -39,5 +39,6 @@ export declare class DebugDrawerUtils {
39
39
  * Disposes of the debug drawer and releases resources.
40
40
  */
41
41
  dispose(): void;
42
+ private rgbToDuRgba;
42
43
  private vertex;
43
44
  }
package/dist/index.mjs CHANGED
@@ -1898,11 +1898,11 @@ class DebugDrawerUtils {
1898
1898
  return this.flush();
1899
1899
  }
1900
1900
  drawNavMeshPolysWithFlags(mesh, flags, col) {
1901
- Raw.DetourDebugDraw.debugDrawNavMeshPolysWithFlags(this.debugDrawImpl, mesh.raw.m_navMesh, flags, col);
1901
+ Raw.DetourDebugDraw.debugDrawNavMeshPolysWithFlags(this.debugDrawImpl, mesh.raw.m_navMesh, flags, this.rgbToDuRgba(col));
1902
1902
  return this.flush();
1903
1903
  }
1904
1904
  drawNavMeshPoly(mesh, ref, col) {
1905
- Raw.DetourDebugDraw.debugDrawNavMeshPoly(this.debugDrawImpl, mesh.raw.m_navMesh, ref, col);
1905
+ Raw.DetourDebugDraw.debugDrawNavMeshPoly(this.debugDrawImpl, mesh.raw.m_navMesh, ref, this.rgbToDuRgba(col));
1906
1906
  return this.flush();
1907
1907
  }
1908
1908
  /**
@@ -1911,10 +1911,17 @@ class DebugDrawerUtils {
1911
1911
  dispose() {
1912
1912
  Raw.Module.destroy(this.debugDrawImpl);
1913
1913
  }
1914
+ rgbToDuRgba(color) {
1915
+ // convert hexadecimal rgb color to duRGBA format
1916
+ const r = color & 0xff;
1917
+ const g = color >> 8 & 0xff;
1918
+ const b = color >> 16 & 0xff;
1919
+ return r | g << 8 | b << 16 | 255 << 24;
1920
+ }
1914
1921
  vertex(x, y, z, color) {
1915
- const r = (color >> 16 & 0xff) / 255;
1922
+ const r = (color & 0xff) / 255;
1916
1923
  const g = (color >> 8 & 0xff) / 255;
1917
- const b = (color & 0xff) / 255;
1924
+ const b = (color >> 16 & 0xff) / 255;
1918
1925
  const a = (color >> 24 & 0xff) / 255;
1919
1926
  this.currentVertices.push([x, y, z, r, g, b, a]);
1920
1927
  }
@@ -2287,43 +2294,6 @@ class NavMesh {
2287
2294
  restoreTileState(tile, data, maxDataSize) {
2288
2295
  return this.raw.restoreTileState(tile.raw, data, maxDataSize);
2289
2296
  }
2290
- /**
2291
- * Returns a triangle mesh that can be used to visualize the NavMesh.
2292
- */
2293
- getDebugNavMesh() {
2294
- const positions = [];
2295
- const indices = [];
2296
- let tri = 0;
2297
- const maxTiles = this.getMaxTiles();
2298
- for (let tileIndex = 0; tileIndex < maxTiles; tileIndex++) {
2299
- const tile = this.getTile(tileIndex);
2300
- const tileHeader = tile.header();
2301
- if (!tileHeader) continue;
2302
- const tilePolyCount = tileHeader.polyCount();
2303
- for (let tilePolyIndex = 0; tilePolyIndex < tilePolyCount; ++tilePolyIndex) {
2304
- const poly = tile.polys(tilePolyIndex);
2305
- if (poly.getType() === 1) continue;
2306
- const polyVertCount = poly.vertCount();
2307
- const polyDetail = tile.detailMeshes(tilePolyIndex);
2308
- const polyDetailTriBase = polyDetail.triBase();
2309
- const polyDetailTriCount = polyDetail.triCount();
2310
- for (let polyDetailTriIndex = 0; polyDetailTriIndex < polyDetailTriCount; ++polyDetailTriIndex) {
2311
- const detailTrisBaseIndex = (polyDetailTriBase + polyDetailTriIndex) * 4;
2312
- for (let trianglePoint = 0; trianglePoint < 3; ++trianglePoint) {
2313
- if (tile.detailTris(detailTrisBaseIndex + trianglePoint) < polyVertCount) {
2314
- const tileVertsBaseIndex = poly.verts(tile.detailTris(detailTrisBaseIndex + trianglePoint)) * 3;
2315
- positions.push(tile.verts(tileVertsBaseIndex), tile.verts(tileVertsBaseIndex + 1), tile.verts(tileVertsBaseIndex + 2));
2316
- } else {
2317
- const tileVertsBaseIndex = (polyDetail.vertBase() + tile.detailTris(detailTrisBaseIndex + trianglePoint) - poly.vertCount()) * 3;
2318
- positions.push(tile.detailVerts(tileVertsBaseIndex), tile.detailVerts(tileVertsBaseIndex + 1), tile.detailVerts(tileVertsBaseIndex + 2));
2319
- }
2320
- indices.push(tri++);
2321
- }
2322
- }
2323
- }
2324
- }
2325
- return [positions, indices];
2326
- }
2327
2297
  /**
2328
2298
  * Destroys the NavMesh.
2329
2299
  */
@@ -2332,6 +2302,107 @@ class NavMesh {
2332
2302
  Raw.Module.destroy(this.raw);
2333
2303
  }
2334
2304
  }
2305
+ /**
2306
+ * Gets the positions and indices of the nav mesh.
2307
+ * @param navMesh the nav mesh
2308
+ * @param flags poly flags to filter by, defaults to undefined to include all polys
2309
+ * @returns the positions and indices of the nav mesh
2310
+ */
2311
+ const getNavMeshPositionsAndIndices = (navMesh, flags) => {
2312
+ const positions = [];
2313
+ const indices = [];
2314
+ let tri = 0;
2315
+ const maxTiles = navMesh.getMaxTiles();
2316
+ for (let tileIndex = 0; tileIndex < maxTiles; tileIndex++) {
2317
+ const tile = navMesh.getTile(tileIndex);
2318
+ const tileHeader = tile.header();
2319
+ if (!tileHeader) continue;
2320
+ const tilePolyCount = tileHeader.polyCount();
2321
+ for (let tilePolyIndex = 0; tilePolyIndex < tilePolyCount; ++tilePolyIndex) {
2322
+ const poly = tile.polys(tilePolyIndex);
2323
+ if (flags !== undefined && (poly.flags() & flags) === 0) continue;
2324
+ if (poly.getType() === 1) continue;
2325
+ const polyVertCount = poly.vertCount();
2326
+ const polyDetail = tile.detailMeshes(tilePolyIndex);
2327
+ const polyDetailTriBase = polyDetail.triBase();
2328
+ const polyDetailTriCount = polyDetail.triCount();
2329
+ for (let polyDetailTriIndex = 0; polyDetailTriIndex < polyDetailTriCount; ++polyDetailTriIndex) {
2330
+ const detailTrisBaseIndex = (polyDetailTriBase + polyDetailTriIndex) * 4;
2331
+ for (let trianglePoint = 0; trianglePoint < 3; ++trianglePoint) {
2332
+ if (tile.detailTris(detailTrisBaseIndex + trianglePoint) < polyVertCount) {
2333
+ const tileVertsBaseIndex = poly.verts(tile.detailTris(detailTrisBaseIndex + trianglePoint)) * 3;
2334
+ positions.push(tile.verts(tileVertsBaseIndex), tile.verts(tileVertsBaseIndex + 1), tile.verts(tileVertsBaseIndex + 2));
2335
+ } else {
2336
+ const tileVertsBaseIndex = (polyDetail.vertBase() + tile.detailTris(detailTrisBaseIndex + trianglePoint) - poly.vertCount()) * 3;
2337
+ positions.push(tile.detailVerts(tileVertsBaseIndex), tile.detailVerts(tileVertsBaseIndex + 1), tile.detailVerts(tileVertsBaseIndex + 2));
2338
+ }
2339
+ indices.push(tri++);
2340
+ }
2341
+ }
2342
+ }
2343
+ }
2344
+ return [positions, indices];
2345
+ };
2346
+ /**
2347
+ * Disables all polys not connected to provided start poly refs.
2348
+ * @param navMesh the nav mesh to prune
2349
+ * @param startPolyRefs poly refs to start the flood fill from, can be retrieved with `navMeshQuery.findNearestPoly`
2350
+ *
2351
+ * @example
2352
+ * ```ts
2353
+ * const navMeshQuery = new NavMeshQuery(navMesh);
2354
+ *
2355
+ * const nearestPolyResult = navMeshQuery.findNearestPoly(point, {
2356
+ * halfExtents: { x: 2, y: 2, z: 2 },
2357
+ * });
2358
+ *
2359
+ * if (!nearestPolyResult.success) return;
2360
+ *
2361
+ * floodFillPruneNavMesh(navMesh, [nearestPolyResult.nearestRef]);
2362
+ * ```
2363
+ */
2364
+ const floodFillPruneNavMesh = (navMesh, startPolyRefs) => {
2365
+ /* find all polys connected to the nearest poly */
2366
+ const visited = new Set();
2367
+ const openList = [];
2368
+ for (const startPolyRef of startPolyRefs) {
2369
+ visited.add(startPolyRef);
2370
+ openList.push(startPolyRef);
2371
+ }
2372
+ while (openList.length > 0) {
2373
+ const ref = openList.pop();
2374
+ // get current poly and tile
2375
+ const {
2376
+ poly,
2377
+ tile
2378
+ } = navMesh.getTileAndPolyByRefUnsafe(ref);
2379
+ // visit linked polys
2380
+ for (let i = poly.firstLink(); i !== Detour.DT_NULL_LINK; i = tile.links(i).next()) {
2381
+ const neiRef = tile.links(i).ref();
2382
+ // skip invalid and already visited
2383
+ if (!neiRef || visited.has(neiRef)) continue;
2384
+ // mark as visited
2385
+ visited.add(neiRef);
2386
+ // visit neighbours
2387
+ openList.push(neiRef);
2388
+ }
2389
+ }
2390
+ /* disable unvisited polys */
2391
+ for (let tileIndex = 0; tileIndex < navMesh.getMaxTiles(); tileIndex++) {
2392
+ const tile = navMesh.getTile(tileIndex);
2393
+ if (!tile || !tile.header()) continue;
2394
+ const tileHeader = tile.header();
2395
+ const base = navMesh.getPolyRefBase(tile);
2396
+ for (let i = 0; i < tileHeader.polyCount(); i++) {
2397
+ const ref = base | i;
2398
+ if (!visited.has(ref)) {
2399
+ // set flag to 0
2400
+ // this could also be a custom 'disabled' area flag if using custom areas
2401
+ navMesh.setPolyFlags(ref, 0);
2402
+ }
2403
+ }
2404
+ }
2405
+ };
2335
2406
 
2336
2407
  const getRandomSeed = () => {
2337
2408
  return Raw.Module.FastRand.prototype.getSeed();
@@ -3205,4 +3276,4 @@ const importTileCache = (data, tileCacheMeshProcess) => {
3205
3276
  };
3206
3277
  };
3207
3278
 
3208
- export { ChunkIdsArray, Crowd, CrowdAgent, DebugDrawerUtils, Detour, DetourBVNode, DetourLink, DetourMeshHeader, DetourMeshTile, DetourOffMeshConnection, DetourPoly, DetourPolyDetail, DetourTileCacheParams, FloatArray, IntArray, NavMesh, NavMeshCalcTileLocResult, NavMeshCreateParams, NavMeshGetTilesAtResult, NavMeshParams, NavMeshQuery, NavMeshRemoveTileResult, NavMeshStoreTileStateResult, QueryFilter, Raw, Recast, RecastBuildContext, RecastChunkyTriMesh, RecastCompactCell, RecastCompactHeightfield, RecastCompactSpan, RecastContour, RecastContourSet, RecastHeightfield, RecastHeightfieldLayer, RecastHeightfieldLayerSet, RecastPolyMesh, RecastPolyMeshDetail, RecastSpan, RecastSpanPool, TileCache, TileCacheData, TileCacheMeshProcess, TriangleAreasArray, TrianglesArray, UnsignedCharArray, UnsignedIntArray, UnsignedShortArray, VerticesArray, allocCompactHeightfield, allocContourSet, allocHeightfield, allocHeightfieldLayerSet, allocPolyMesh, allocPolyMeshDetail, array, buildCompactHeightfield, buildContours, buildDistanceField, buildHeightfieldLayers, buildLayerRegions, buildPolyMesh, buildPolyMeshDetail, buildRegions, buildRegionsMonotone, buildTileCacheLayer, calcBounds, calcGridSize, clearUnwalkableTriangles, cloneRcConfig, copyPolyMesh, createHeightfield, createNavMeshData, createRcConfig, crowdAgentParamsDefaults, erodeWalkableArea, exportNavMesh, exportTileCache, filterLedgeSpans, filterLowHangingWalkableObstacles, filterWalkableLowHeightSpans, freeCompactHeightfield, freeContourSet, freeHeightfield, freeHeightfieldLayerSet, freePolyMesh, freePolyMeshDetail, getCon, getDirForOffset, getDirOffsetX, getDirOffsetY, getHeightFieldSpanCount, getHeightfieldLayerAreas, getHeightfieldLayerCons, getHeightfieldLayerHeights, getRandomSeed, importNavMesh, importTileCache, init, markBoxArea, markConvexPolyArea, markCylinderArea, markWalkableTriangles, medianFilterWalkableArea, mergePolyMeshDetails, mergePolyMeshes, rasterizeTriangles, recastConfigDefaults, setCon, setRandomSeed, statusDetail, statusFailed, statusInProgress, statusSucceed, statusToReadableString, vec3 };
3279
+ export { ChunkIdsArray, Crowd, CrowdAgent, DebugDrawerUtils, Detour, DetourBVNode, DetourLink, DetourMeshHeader, DetourMeshTile, DetourOffMeshConnection, DetourPoly, DetourPolyDetail, DetourTileCacheParams, FloatArray, IntArray, NavMesh, NavMeshCalcTileLocResult, NavMeshCreateParams, NavMeshGetTilesAtResult, NavMeshParams, NavMeshQuery, NavMeshRemoveTileResult, NavMeshStoreTileStateResult, QueryFilter, Raw, Recast, RecastBuildContext, RecastChunkyTriMesh, RecastCompactCell, RecastCompactHeightfield, RecastCompactSpan, RecastContour, RecastContourSet, RecastHeightfield, RecastHeightfieldLayer, RecastHeightfieldLayerSet, RecastPolyMesh, RecastPolyMeshDetail, RecastSpan, RecastSpanPool, TileCache, TileCacheData, TileCacheMeshProcess, TriangleAreasArray, TrianglesArray, UnsignedCharArray, UnsignedIntArray, UnsignedShortArray, VerticesArray, allocCompactHeightfield, allocContourSet, allocHeightfield, allocHeightfieldLayerSet, allocPolyMesh, allocPolyMeshDetail, array, buildCompactHeightfield, buildContours, buildDistanceField, buildHeightfieldLayers, buildLayerRegions, buildPolyMesh, buildPolyMeshDetail, buildRegions, buildRegionsMonotone, buildTileCacheLayer, calcBounds, calcGridSize, clearUnwalkableTriangles, cloneRcConfig, copyPolyMesh, createHeightfield, createNavMeshData, createRcConfig, crowdAgentParamsDefaults, erodeWalkableArea, exportNavMesh, exportTileCache, filterLedgeSpans, filterLowHangingWalkableObstacles, filterWalkableLowHeightSpans, floodFillPruneNavMesh, freeCompactHeightfield, freeContourSet, freeHeightfield, freeHeightfieldLayerSet, freePolyMesh, freePolyMeshDetail, getCon, getDirForOffset, getDirOffsetX, getDirOffsetY, getHeightFieldSpanCount, getHeightfieldLayerAreas, getHeightfieldLayerCons, getHeightfieldLayerHeights, getNavMeshPositionsAndIndices, getRandomSeed, importNavMesh, importTileCache, init, markBoxArea, markConvexPolyArea, markCylinderArea, markWalkableTriangles, medianFilterWalkableArea, mergePolyMeshDetails, mergePolyMeshes, rasterizeTriangles, recastConfigDefaults, setCon, setRandomSeed, statusDetail, statusFailed, statusInProgress, statusSucceed, statusToReadableString, vec3 };
@@ -267,12 +267,34 @@ export declare class NavMesh {
267
267
  * @returns
268
268
  */
269
269
  restoreTileState(tile: DetourMeshTile, data: number[], maxDataSize: number): number;
270
- /**
271
- * Returns a triangle mesh that can be used to visualize the NavMesh.
272
- */
273
- getDebugNavMesh(): [positions: number[], indices: number[]];
274
270
  /**
275
271
  * Destroys the NavMesh.
276
272
  */
277
273
  destroy(): void;
278
274
  }
275
+ /**
276
+ * Gets the positions and indices of the nav mesh.
277
+ * @param navMesh the nav mesh
278
+ * @param flags poly flags to filter by, defaults to undefined to include all polys
279
+ * @returns the positions and indices of the nav mesh
280
+ */
281
+ export declare const getNavMeshPositionsAndIndices: (navMesh: NavMesh, flags?: number) => [positions: number[], indices: number[]];
282
+ /**
283
+ * Disables all polys not connected to provided start poly refs.
284
+ * @param navMesh the nav mesh to prune
285
+ * @param startPolyRefs poly refs to start the flood fill from, can be retrieved with `navMeshQuery.findNearestPoly`
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * const navMeshQuery = new NavMeshQuery(navMesh);
290
+ *
291
+ * const nearestPolyResult = navMeshQuery.findNearestPoly(point, {
292
+ * halfExtents: { x: 2, y: 2, z: 2 },
293
+ * });
294
+ *
295
+ * if (!nearestPolyResult.success) return;
296
+ *
297
+ * floodFillPruneNavMesh(navMesh, [nearestPolyResult.nearestRef]);
298
+ * ```
299
+ */
300
+ export declare const floodFillPruneNavMesh: (navMesh: NavMesh, startPolyRefs: number[]) => void;
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "email": "isaac@isaacmason.com",
7
7
  "url": "https://isaacmason.com/"
8
8
  },
9
- "version": "0.38.0",
9
+ "version": "0.40.0",
10
10
  "license": "MIT",
11
11
  "homepage": "https://github.com/isaac-mason/recast-navigation-js",
12
12
  "bugs": {
@@ -27,7 +27,7 @@
27
27
  "lint": "eslint src"
28
28
  },
29
29
  "dependencies": {
30
- "@recast-navigation/wasm": "0.38.0"
30
+ "@recast-navigation/wasm": "0.40.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@babel/core": "^7.24.5",
@@ -38,7 +38,6 @@
38
38
  "@rollup/plugin-commonjs": "^25.0.7",
39
39
  "@rollup/plugin-node-resolve": "^15.0.1",
40
40
  "@rollup/plugin-typescript": "^11.1.6",
41
- "@types/three": "^0.169.0",
42
41
  "babel-loader": "^9.1.3",
43
42
  "eslint": "^9.6.0",
44
43
  "prettier": "^3.1.0",