recast-navigation 0.13.3 → 0.15.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/README.md +101 -45
- package/generators.cjs +2 -0
- package/generators.d.ts +1 -0
- package/generators.mjs +2 -0
- package/package.json +20 -9
package/README.md
CHANGED
|
@@ -27,22 +27,12 @@ This library provides high level APIs that make it easy to get started creating
|
|
|
27
27
|
|
|
28
28
|
## Installation
|
|
29
29
|
|
|
30
|
-
This package ships as both ECMAScript modules and CJS, and is compatible with Node.js and browser environments.
|
|
31
|
-
|
|
32
|
-
**CDN**
|
|
33
|
-
|
|
34
|
-
```html
|
|
35
|
-
<script type="module">
|
|
36
|
-
import { generateSoloNavMesh } from 'https://www.unpkg.com/@recast-navigation/core@0.9.0/dist/index.mjs';
|
|
37
|
-
</script>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**NPM**
|
|
41
|
-
|
|
42
30
|
```sh
|
|
43
31
|
npm install recast-navigation
|
|
44
32
|
```
|
|
45
33
|
|
|
34
|
+
This package ships as both ECMAScript modules and CJS, and is compatible with Node.js and browser environments.
|
|
35
|
+
|
|
46
36
|
If you are using Vite, you may need to opt `recast-navigation` out of pre-bundling:
|
|
47
37
|
|
|
48
38
|
```js
|
|
@@ -67,7 +57,7 @@ await init();
|
|
|
67
57
|
|
|
68
58
|
### Generating a NavMesh
|
|
69
59
|
|
|
70
|
-
The easiest way to generate a NavMesh is using the high level generator functions
|
|
60
|
+
The easiest way to generate a NavMesh is using the high level generator functions from `recast-navigation/generators`:
|
|
71
61
|
|
|
72
62
|
- `generateSoloNavMesh` - Generates a NavMesh with a single tile. You can use this for smaller environments.
|
|
73
63
|
- `generateTiledNavMesh` - Generates a NavMesh with multiple tiles. You should use this for larger environments.
|
|
@@ -80,7 +70,7 @@ The input positions and indices should adhere to OpenGL conventions:
|
|
|
80
70
|
- The `positions` and `indices` arguments should be flat arrays of numbers
|
|
81
71
|
|
|
82
72
|
```ts
|
|
83
|
-
import { generateSoloNavMesh } from 'recast-navigation';
|
|
73
|
+
import { generateSoloNavMesh } from 'recast-navigation/generators';
|
|
84
74
|
|
|
85
75
|
const positions = [
|
|
86
76
|
/* flat array of positions */
|
|
@@ -102,7 +92,13 @@ const { success, navMesh } = generateSoloNavMesh(
|
|
|
102
92
|
);
|
|
103
93
|
```
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
See the docs for more information on generator options: https://docs.recast-navigation-js.isaacmason.com/modules/generators.html
|
|
96
|
+
|
|
97
|
+
#### Advanced Usage
|
|
98
|
+
|
|
99
|
+
This library provides low-level APIs that aim to match the recast and detour c++ api, allowing you to create custom navigation mesh generators based on your specific needs. You can use the NavMesh generators provided by `@recast-navigation/generators` as a basis: https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-generators/src/generators
|
|
100
|
+
|
|
101
|
+
Please note that this functionality is experimental, and not all everything is exposed. Familiarity with the recast and detour C++ libraries is required. If you require unexposed functionality, please submit an issue or a pull request.
|
|
106
102
|
|
|
107
103
|
### Querying a NavMesh
|
|
108
104
|
|
|
@@ -128,7 +124,7 @@ const path: Vector3[] = navMeshQuery.computePath(
|
|
|
128
124
|
|
|
129
125
|
### Crowds and Agents
|
|
130
126
|
|
|
131
|
-
First, create a `Crowd
|
|
127
|
+
First, create a `Crowd`:
|
|
132
128
|
|
|
133
129
|
```ts
|
|
134
130
|
import { Crowd } from 'recast-navigation';
|
|
@@ -139,17 +135,7 @@ const maxAgentRadius = 0.6;
|
|
|
139
135
|
const crowd = new Crowd({ maxAgents, maxAgentRadius, navMesh });
|
|
140
136
|
```
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
```ts
|
|
145
|
-
const dt = 1 / 60;
|
|
146
|
-
crowd.timeStep = dt;
|
|
147
|
-
|
|
148
|
-
// you should call this every frame
|
|
149
|
-
crowd.update(dt);
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Next, you can create and interface with agents in the crowd.
|
|
138
|
+
Next, create and interface with agents in the crowd.
|
|
153
139
|
|
|
154
140
|
```ts
|
|
155
141
|
const initialAgentPosition = navMeshQuery.getRandomPointAround(
|
|
@@ -202,16 +188,24 @@ agent.setParameters({
|
|
|
202
188
|
crowd.removeAgent(agent);
|
|
203
189
|
```
|
|
204
190
|
|
|
205
|
-
|
|
191
|
+
To update the crowd, first set a timeStep, then call `update` each frame with the delta time.
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
const dt = 1 / 60;
|
|
195
|
+
crowd.timeStep = dt;
|
|
196
|
+
|
|
197
|
+
// you should call this every frame
|
|
198
|
+
crowd.update(dt);
|
|
199
|
+
```
|
|
206
200
|
|
|
207
|
-
|
|
201
|
+
### Temporary Obstacles
|
|
208
202
|
|
|
209
|
-
|
|
203
|
+
Recast Navigation supports temporary Box and Cylinder obstacles via a `TileCache`.
|
|
210
204
|
|
|
211
205
|
`TileCache` assumes small tiles (around 32-64 squared). Using `tileSize` values outside this range may result in unexpected behaviour.
|
|
212
206
|
|
|
213
207
|
```ts
|
|
214
|
-
import { generateTileCache } from 'recast-navigation';
|
|
208
|
+
import { generateTileCache } from 'recast-navigation/generators';
|
|
215
209
|
|
|
216
210
|
/* create a tile cache */
|
|
217
211
|
const { success, navMesh, tileCache } = generateTileCache(positions, indices, {
|
|
@@ -249,7 +243,7 @@ Off mesh connections are user-defined connections between two points on a NavMes
|
|
|
249
243
|
|
|
250
244
|
Off mesh connections can be bidirectional or unidirectional.
|
|
251
245
|
|
|
252
|
-
You can provide list of off mesh connections to the high level generator functions.
|
|
246
|
+
You can provide a list of off mesh connections to the `generateSoloNavMesh` and `generateTiledNavMesh` high level generator functions.
|
|
253
247
|
|
|
254
248
|
```ts
|
|
255
249
|
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
|
@@ -270,6 +264,43 @@ const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
|
|
270
264
|
|
|
271
265
|
You can use `agent.state()` to determine if an agent is currently traversing an off mesh connection.
|
|
272
266
|
|
|
267
|
+
#### Adding Off Mesh Connections to a TileCache
|
|
268
|
+
|
|
269
|
+
To add off mesh connections to a TileCache using `generateTileCache`, you must provide a TileCacheMeshProcess implementation that creates off mesh connections. For example:
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
const tileCacheMeshProcess = new TileCacheMeshProcess(
|
|
273
|
+
(navMeshCreateParams, polyAreas, polyFlags) => {
|
|
274
|
+
for (let i = 0; i < navMeshCreateParams.polyCount(); ++i) {
|
|
275
|
+
polyAreas.set(i, 0);
|
|
276
|
+
polyFlags.set(i, 1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
navMeshCreateParams.setOffMeshConnections([
|
|
280
|
+
{
|
|
281
|
+
startPosition: { x: 0, y: 5, z: 0 },
|
|
282
|
+
endPosition: { x: 2, y: 0, z: 0 },
|
|
283
|
+
radius: 0.5,
|
|
284
|
+
bidirectional: false,
|
|
285
|
+
area: 0,
|
|
286
|
+
flags: 1,
|
|
287
|
+
},
|
|
288
|
+
]);
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const tileCacheGeneratorConfig = {
|
|
293
|
+
// ... other config ...
|
|
294
|
+
tileCacheMeshProcess,
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const { success, navMesh, tileCache } = generateTileCache(
|
|
298
|
+
positions,
|
|
299
|
+
indices,
|
|
300
|
+
tileCacheGeneratorConfig
|
|
301
|
+
);
|
|
302
|
+
```
|
|
303
|
+
|
|
273
304
|
### Debugging
|
|
274
305
|
|
|
275
306
|
You can use `getDebugNavMesh` to get a debug representation of the NavMesh.
|
|
@@ -280,30 +311,45 @@ const debugNavMesh = navMesh.getDebugNavMesh();
|
|
|
280
311
|
const { positions, indices } = debugNavMesh;
|
|
281
312
|
```
|
|
282
313
|
|
|
283
|
-
If you are using
|
|
314
|
+
If you are using three.js, you can use `NavMeshHelper` and `CrowdHelper` to visualize NavMeshes, Crowds, and NavMesh generation intermediates.
|
|
284
315
|
|
|
285
|
-
|
|
316
|
+
See the [`@recast-navigation/three` package README](https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-three/README.md) for usage information.
|
|
286
317
|
|
|
287
|
-
|
|
318
|
+
### Importing and Exporting
|
|
319
|
+
|
|
320
|
+
A NavMesh and TileCache can be imported and exported as a Uint8Array.
|
|
321
|
+
|
|
322
|
+
See below for an example of exporting then importing a NavMesh:
|
|
288
323
|
|
|
289
324
|
```ts
|
|
290
325
|
import { exportNavMesh, importNavMesh } from 'recast-navigation';
|
|
291
326
|
|
|
292
|
-
/*
|
|
293
|
-
const navMeshExport: Uint8Array = exportNavMesh(
|
|
294
|
-
navMesh,
|
|
295
|
-
tileCache // optional
|
|
296
|
-
);
|
|
327
|
+
/* export */
|
|
328
|
+
const navMeshExport: Uint8Array = exportNavMesh(navMesh);
|
|
297
329
|
|
|
298
|
-
/*
|
|
299
|
-
const { navMesh
|
|
330
|
+
/* import */
|
|
331
|
+
const { navMesh } = importNavMesh(navMeshExport);
|
|
300
332
|
```
|
|
301
333
|
|
|
302
|
-
|
|
334
|
+
To export a TileCache and NavMesh, the usage varies slightly:
|
|
303
335
|
|
|
304
|
-
|
|
336
|
+
```ts
|
|
337
|
+
import { exportNavMesh, importNavMesh } from 'recast-navigation';
|
|
305
338
|
|
|
306
|
-
|
|
339
|
+
/* exporting */
|
|
340
|
+
// pass both the navMesh and the tileCache
|
|
341
|
+
const navMeshExport: Uint8Array = exportNavMesh(navMesh, tileCache);
|
|
342
|
+
|
|
343
|
+
/* importing */
|
|
344
|
+
// also pass the TileCacheMeshProcess implementation for the tile cache
|
|
345
|
+
// if you used `generateTileCache` and didn't provide one, `createDefaultTileCacheMeshProcess` returns the default TileCacheMeshProcess `generateTileCache` uses
|
|
346
|
+
const tileCacheMeshProcess = createDefaultTileCacheMeshProcess();
|
|
347
|
+
|
|
348
|
+
const { navMesh, tileCache } = importNavMesh(
|
|
349
|
+
navMeshExport,
|
|
350
|
+
tileCacheMeshProcess
|
|
351
|
+
);
|
|
352
|
+
```
|
|
307
353
|
|
|
308
354
|
## Documentation
|
|
309
355
|
|
|
@@ -355,6 +401,16 @@ The core library!
|
|
|
355
401
|
> npm install @recast-navigation/core
|
|
356
402
|
```
|
|
357
403
|
|
|
404
|
+
### [**`@recast-navigation/generators`**](https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-generators)
|
|
405
|
+
|
|
406
|
+
[](https://www.npmjs.com/package/@recast-navigation/generators)
|
|
407
|
+
|
|
408
|
+
NavMesh generator implementations. Use these to get started, and as a basis for your own NavMesh generator.
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
> npm install @recast-navigation/generators
|
|
412
|
+
```
|
|
413
|
+
|
|
358
414
|
### [**`@recast-navigation/three`**](https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-three)
|
|
359
415
|
|
|
360
416
|
[](https://www.npmjs.com/package/@recast-navigation/three)
|
package/generators.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("@recast-navigation/core");const t=(t,i)=>{const a={x:1/0,y:1/0,z:1/0},l={x:-1/0,y:-1/0,z:-1/0};for(let e=0;e<i.length;e++){const r=i[e],s=t[3*r],o=t[3*r+1],n=t[3*r+2];a.x=Math.min(a.x,s),a.y=Math.min(a.y,o),a.z=Math.min(a.z,n),l.x=Math.max(l.x,s),l.y=Math.max(l.y,o),l.z=Math.max(l.z,n)}return{bbMin:e.vec3.toArray(a),bbMax:e.vec3.toArray(l)}},i=e=>{let t=0,i=0;return t=Number(e>65535)<<4,e>>=t,i=Number(e>255)<<3,e>>=i,t|=i,i=Number(e>15)<<2,e>>=i,t|=i,i=Number(e>3)<<1,t|=i,t|=(e>>=i)>>1,t},a=e=>(e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,++e),l={...e.recastConfigDefaults},r={...e.recastConfigDefaults,tileSize:32,expectedLayersPerTile:4,maxObstacles:128},s=()=>new e.TileCacheMeshProcess(((e,t,i)=>{for(let a=0;a<e.polyCount();++a)t.set(a,0),i.set(a,1)})),o={...e.recastConfigDefaults};exports.createDefaultTileCacheMeshProcess=s,exports.dtIlog2=i,exports.dtNextPow2=a,exports.generateSoloNavMesh=(i,a,r={},s=!1)=>{const o=new e.RecastBuildContext,n={type:"solo",buildContext:o},d=new e.NavMesh,h=t=>(s||(n.heightfield&&(e.freeHeightfield(n.heightfield),n.heightfield=void 0),n.compactHeightfield&&(e.freeCompactHeightfield(n.compactHeightfield),n.compactHeightfield=void 0),n.contourSet&&(e.freeContourSet(n.contourSet),n.contourSet=void 0)),d.destroy(),{navMesh:void 0,success:!1,intermediates:n,error:t}),c=i,g=a.length,f=new e.Arrays.FloatArray;f.copy(c,c.length);const m=a,u=a.length/3,b=new e.Arrays.IntArray;b.copy(m,m.length);const{bbMin:w,bbMax:C}=t(i,a),R=e.createRcConfig({...l,...r});R.minRegionArea=R.minRegionArea*R.minRegionArea,R.mergeRegionArea=R.mergeRegionArea*R.mergeRegionArea,R.detailSampleDist=R.detailSampleDist<.9?0:R.cs*R.detailSampleDist,R.detailSampleMaxError=R.ch*R.detailSampleMaxError;const S=e.Raw.Recast.calcGridSize(w,C,R.cs);R.width=S.width,R.height=S.height;const y=e.allocHeightfield();if(n.heightfield=y,!e.createHeightfield(o,y,R.width,R.height,w,C,R.cs,R.ch))return h("Could not create heightfield");const M=new e.Arrays.UnsignedCharArray;if(M.resize(u),e.markWalkableTriangles(o,R.walkableSlopeAngle,f,g,b,u,M),!e.rasterizeTriangles(o,f,g,b,M,u,y,R.walkableClimb))return h("Could not rasterize triangles");M.free(),e.filterLowHangingWalkableObstacles(o,R.walkableClimb,y),e.filterLedgeSpans(o,R.walkableHeight,R.walkableClimb,y),e.filterWalkableLowHeightSpans(o,R.walkableHeight,y);const p=e.allocCompactHeightfield();if(n.compactHeightfield=p,!e.buildCompactHeightfield(o,R.walkableHeight,R.walkableClimb,y,p))return h("Failed to build compact data");if(s||(e.freeHeightfield(y),n.heightfield=void 0),!e.erodeWalkableArea(o,R.walkableRadius,p))return h("Failed to erode walkable area");if(!e.buildDistanceField(o,p))return h("Failed to build distance field");if(!e.buildRegions(o,p,R.borderSize,R.minRegionArea,R.mergeRegionArea))return h("Failed to build regions");const x=e.allocContourSet();if(n.contourSet=x,!e.buildContours(o,p,R.maxSimplificationError,R.maxEdgeLen,x,e.Raw.Module.RC_CONTOUR_TESS_WALL_EDGES))return h("Failed to create contours");const A=e.allocPolyMesh();if(!e.buildPolyMesh(o,x,R.maxVertsPerPoly,A))return h("Failed to triangulate contours");const k=e.allocPolyMeshDetail();if(!e.buildPolyMeshDetail(o,A,p,R.detailSampleDist,R.detailSampleMaxError,k))return h("Failed to build detail mesh");s||(e.freeCompactHeightfield(p),n.compactHeightfield=void 0,e.freeContourSet(x),n.contourSet=void 0);for(let t=0;t<A.npolys();t++)A.areas(t)==e.Raw.Recast.WALKABLE_AREA&&A.setAreas(t,0),0==A.areas(t)&&A.setFlags(t,1);const H=new e.NavMeshCreateParams;H.setPolyMeshCreateParams(A),H.setPolyMeshDetailCreateParams(k),H.setWalkableHeight(R.walkableHeight),H.setWalkableRadius(R.walkableRadius),H.setWalkableClimb(R.walkableClimb),H.setCellSize(R.cs),H.setCellHeight(R.ch),H.setBuildBvTree(!0),r.offMeshConnections&&H.setOffMeshConnections(r.offMeshConnections);const v=e.createNavMeshData(H);if(!v.success)return h("Failed to create Detour navmesh data");const{navMeshData:T}=v;return d.initSolo(T)?{success:!0,navMesh:d,intermediates:n}:h("Failed to create Detour navmesh")},exports.generateTileCache=(l,o,n={},d=!1)=>{const h=new e.RecastBuildContext;let c={type:"tilecache",buildContext:h,chunkyTriMesh:void 0,tileIntermediates:[]};const g=new e.TileCache,f=new e.NavMesh,m=()=>{if(!d)for(let t=0;t<c.tileIntermediates.length;t++){const i=c.tileIntermediates[t];i.heightfield&&(e.freeHeightfield(i.heightfield),i.heightfield=void 0),i.compactHeightfield&&(e.freeCompactHeightfield(i.compactHeightfield),i.compactHeightfield=void 0),i.heightfieldLayerSet&&(e.freeHeightfieldLayerSet(i.heightfieldLayerSet),i.heightfieldLayerSet=void 0)}},u=e=>(m(),g.destroy(),f.destroy(),{success:!1,navMesh:void 0,tileCache:void 0,intermediates:c,error:e}),b=l,w=o.length,C=new e.Arrays.FloatArray;C.copy(b,b.length);const R=o,S=o.length/3,y=new e.Arrays.IntArray;y.copy(R,R.length);const{bbMin:M,bbMax:p}=t(l,o),{expectedLayersPerTile:x,maxObstacles:A,...k}={...r,...n},H=e.createRcConfig(k),v=e.calcGridSize(M,p,H.cs);H.width=v.width,H.height=v.height,H.minRegionArea=H.minRegionArea*H.minRegionArea,H.mergeRegionArea=H.mergeRegionArea*H.mergeRegionArea,H.detailSampleDist=H.detailSampleDist<.9?0:H.cs*H.detailSampleDist,H.detailSampleMaxError=H.ch*H.detailSampleMaxError;const T=Math.floor(H.tileSize),z=Math.floor((H.width+T-1)/T),_=Math.floor((H.height+T-1)/T);H.borderSize=H.walkableRadius+3,H.width=H.tileSize+2*H.borderSize,H.height=H.tileSize+2*H.borderSize;const L=e.DetourTileCacheParams.create({orig:M,cs:H.cs,ch:H.ch,width:H.tileSize,height:H.tileSize,walkableHeight:H.walkableHeight,walkableRadius:H.walkableRadius,walkableClimb:H.walkableClimb,maxSimplificationError:H.maxSimplificationError,maxTiles:z*_*x,maxObstacles:A}),D=new e.Raw.RecastLinearAllocator(32e3),E=new e.Raw.RecastFastLZCompressor,P=n.tileCacheMeshProcess??s();if(!g.init(L,D,E,P))return u("Failed to initialize tile cache");const F=e.vec3.fromArray(M);let N=Math.min(Math.floor(i(a(z*_*x))),14);N>14&&(N=14);const O=1<<N,W=1<<22-N,I=e.NavMeshParams.create({orig:F,tileWidth:H.tileSize*H.cs,tileHeight:H.tileSize*H.cs,maxTiles:O,maxPolys:W});if(!f.initTiled(I))return u("Failed to initialize tiled navmesh");const G=new e.RecastChunkyTriMesh;if(c.chunkyTriMesh=G,!G.init(C,y,S,256))return u("Failed to build chunky triangle mesh");const $=(t,i)=>{const a={tileX:t,tileY:i},l=H.tileSize*H.cs,r=e.cloneRcConfig(H),s=[M[0]+t*l,M[1],M[2]+i*l],o=[M[0]+(t+1)*l,p[1],M[2]+(i+1)*l];s[0]-=r.borderSize*r.cs,s[2]-=r.borderSize*r.cs,o[0]+=r.borderSize*r.cs,o[2]+=r.borderSize*r.cs,r.set_bmin(0,s[0]),r.set_bmin(1,s[1]),r.set_bmin(2,s[2]),r.set_bmax(0,o[0]),r.set_bmax(1,o[1]),r.set_bmax(2,o[2]);const n=e.allocHeightfield();if(a.heightfield=n,!e.createHeightfield(h,n,r.width,r.height,s,o,r.cs,r.ch))return{n:0};const g=[s[0],s[2]],f=[o[0],o[2]],m=new e.Arrays.IntArray;m.resize(512);const u=G.getChunksOverlappingRect(g,f,m,512);if(0===u)return{n:0};for(let t=0;t<u;++t){const i=m.get_data(t),a=G.nodes(i).n,l=G.getNodeTris(i),s=new e.Arrays.UnsignedCharArray;s.resize(a),e.markWalkableTriangles(h,r.walkableSlopeAngle,C,w,l,a,s);const o=e.rasterizeTriangles(h,C,w,l,s,a,n,r.walkableClimb);if(s.free(),!o)return{n:0}}e.filterLowHangingWalkableObstacles(h,H.walkableClimb,n),e.filterLedgeSpans(h,H.walkableHeight,H.walkableClimb,n),e.filterWalkableLowHeightSpans(h,H.walkableHeight,n);const b=e.allocCompactHeightfield();if(!e.buildCompactHeightfield(h,H.walkableHeight,H.walkableClimb,n,b))return{n:0};if(d||(e.freeHeightfield(a.heightfield),a.heightfield=void 0),!e.erodeWalkableArea(h,H.walkableRadius,b))return{n:0};const R=e.allocHeightfieldLayerSet();if(!e.buildHeightfieldLayers(h,b,H.borderSize,H.walkableHeight,R))return{n:0};d||(e.freeCompactHeightfield(b),a.compactHeightfield=void 0);const S=[];for(let a=0;a<R.nlayers();a++){const l=new e.Arrays.UnsignedCharArray,r=R.layers(a),s=new e.Raw.dtTileCacheLayerHeader;s.magic=e.Raw.Detour.TILECACHE_MAGIC,s.version=e.Raw.Detour.TILECACHE_VERSION,s.tx=t,s.ty=i,s.tlayer=a;const o=r.bmin(),n=r.bmax();s.set_bmin(0,o.x),s.set_bmin(1,o.y),s.set_bmin(2,o.z),s.set_bmax(0,n.x),s.set_bmax(1,n.y),s.set_bmax(2,n.z),s.width=r.width(),s.height=r.height(),s.minx=r.minx(),s.maxx=r.maxx(),s.miny=r.miny(),s.maxy=r.maxy(),s.hmin=r.hmin(),s.hmax=r.hmax();const d=e.getHeightfieldLayerHeights(r),h=e.getHeightfieldLayerAreas(r),c=e.getHeightfieldLayerCons(r),g=e.buildTileCacheLayer(E,s,d,h,c,l);if(e.Raw.Detour.statusFailed(g))return{n:0};S.push(l)}return d||(e.freeHeightfieldLayerSet(R),a.heightfieldLayerSet=void 0),c.tileIntermediates.push(a),{n:S.length,tiles:S}};for(let t=0;t<_;++t)for(let i=0;i<z;++i){const{n:a,tiles:l}=$(i,t);if(a>0&&l)for(let r=0;r<a;r++){const a=l[r],s=g.addTile(a);e.Raw.Detour.statusFailed(s.status)&&h.log(e.Raw.Module.RC_LOG_WARNING,`Failed to add tile to tile cache - tx: ${i}, ty: ${t}`)}}for(let t=0;t<_;t++)for(let i=0;i<z;i++){const a=g.buildNavMeshTilesAt(i,t,f);if(e.Raw.Detour.statusFailed(a))return u(`Failed to build nav mesh tiles at ${i}, ${t}`)}return m(),{success:!0,tileCache:g,navMesh:f,intermediates:c}},exports.generateTiledNavMesh=(l,r,s={},n=!1)=>{const d=new e.RecastBuildContext,h={type:"tiled",buildContext:d,chunkyTriMesh:void 0,tileIntermediates:[]},c=new e.NavMesh,g=()=>{if(!n){for(let t=0;t<h.tileIntermediates.length;t++){const i=h.tileIntermediates[t];i.compactHeightfield&&e.freeCompactHeightfield(i.compactHeightfield),i.heightfield&&e.freeHeightfield(i.heightfield),i.contourSet&&e.freeContourSet(i.contourSet)}h.chunkyTriMesh&&(h.chunkyTriMesh=void 0)}},f=e=>(g(),c.destroy(),{success:!1,navMesh:void 0,intermediates:h,error:e}),m=e.createRcConfig({...o,...s}),{bbMin:u,bbMax:b}=t(l,r),w=e.calcGridSize(u,b,m.cs);m.width=w.width,m.height=w.height,m.minRegionArea=m.minRegionArea*m.minRegionArea,m.mergeRegionArea=m.mergeRegionArea*m.mergeRegionArea,m.tileSize=Math.floor(m.tileSize),m.borderSize=m.walkableRadius+3,m.width=m.tileSize+2*m.borderSize,m.height=m.tileSize+2*m.borderSize,m.detailSampleDist=m.detailSampleDist<.9?0:m.cs*m.detailSampleDist,m.detailSampleMaxError=m.ch*m.detailSampleMaxError;const C=Math.floor(m.tileSize),R=Math.floor((w.width+C-1)/C),S=Math.floor((w.height+C-1)/C),y=m.tileSize*m.cs,M=l,p=r.length,x=new e.Arrays.FloatArray;x.copy(M,M.length);const A=r,k=r.length/3,H=new e.Arrays.IntArray;H.copy(A,A.length);const v=e.vec3.fromArray(u);let T=Math.min(Math.floor(i(a(R*S))),14);T>14&&(T=14);const z=1<<T,_=1<<22-T,L=e.NavMeshParams.create({orig:v,tileWidth:m.tileSize*m.cs,tileHeight:m.tileSize*m.cs,maxTiles:z,maxPolys:_});if(!c.initTiled(L))return f("Could not init nav mesh for tiled use");const D=new e.RecastChunkyTriMesh;if(h.chunkyTriMesh=D,!D.init(x,H,k,256))return f("Failed to build chunky triangle mesh");const E=(t,i,a,l)=>{const r=t=>(d.log(e.Raw.Module.RC_LOG_ERROR,t),{success:!1,error:t}),o={tileX:t,tileY:i};h.tileIntermediates.push(o);const c=e.cloneRcConfig(m),g=[...a],f=[...l];g[0]-=c.borderSize*c.cs,g[2]-=c.borderSize*c.cs,f[0]+=c.borderSize*c.cs,f[2]+=c.borderSize*c.cs,c.set_bmin(0,g[0]),c.set_bmin(1,g[1]),c.set_bmin(2,g[2]),c.set_bmax(0,f[0]),c.set_bmax(1,f[1]),c.set_bmax(2,f[2]),d.resetTimers(),d.startTimer(e.Raw.Module.RC_TIMER_TOTAL),d.log(e.Raw.Module.RC_LOG_PROGRESS,`Building tile ${h.tileIntermediates.length} at x: ${t}, y: ${i}`),d.log(e.Raw.Module.RC_LOG_PROGRESS,` - ${m.width} x ${m.height} cells`),d.log(e.Raw.Module.RC_LOG_PROGRESS,` - ${p/1e3}fK verts, ${k/1e3}K tris`);const u=e.allocHeightfield();if(o.heightfield=u,!e.createHeightfield(d,u,c.width,c.height,g,f,c.cs,c.ch))return r("Could not create heightfield");(new e.Arrays.UnsignedCharArray).resize(D.maxTrisPerChunk());const b=[g[0],g[2]],w=[f[0],f[2]],C=new e.Arrays.IntArray;C.resize(512);const R=D.getChunksOverlappingRect(b,w,C,512);if(0===R)return{success:!0};for(let t=0;t<R;++t){const i=C.get_data(t),a=D.nodes(i).n,l=D.getNodeTris(i),s=new e.Arrays.UnsignedCharArray;s.resize(a),e.markWalkableTriangles(d,c.walkableSlopeAngle,x,p,l,a,s);const o=e.rasterizeTriangles(d,x,p,l,s,a,u,c.walkableClimb);if(s.free(),!o)return r("Could not rasterize triangles")}e.filterLowHangingWalkableObstacles(d,c.walkableClimb,u),e.filterLedgeSpans(d,c.walkableHeight,c.walkableClimb,u),e.filterWalkableLowHeightSpans(d,c.walkableHeight,u);const S=e.allocCompactHeightfield();if(o.compactHeightfield=S,!e.buildCompactHeightfield(d,c.walkableHeight,c.walkableClimb,u,S))return r("Could not build compact heightfield");if(n||(e.freeHeightfield(o.heightfield),o.heightfield=void 0),!e.erodeWalkableArea(d,c.walkableRadius,S))return r("Could not erode walkable area");if(!e.buildDistanceField(d,S))return r("Failed to build distance field");if(!e.buildRegions(d,S,c.borderSize,c.minRegionArea,c.mergeRegionArea))return r("Failed to build regions");const y=e.allocContourSet();if(o.contourSet=y,!e.buildContours(d,S,c.maxSimplificationError,c.maxEdgeLen,y,e.Raw.Module.RC_CONTOUR_TESS_WALL_EDGES))return r("Failed to create contours");const M=e.allocPolyMesh();if(!e.buildPolyMesh(d,y,c.maxVertsPerPoly,M))return r("Failed to triangulate contours");const A=e.allocPolyMeshDetail();if(!e.buildPolyMeshDetail(d,M,S,c.detailSampleDist,c.detailSampleMaxError,A))return r("Failed to build detail mesh");n||(e.freeCompactHeightfield(S),o.compactHeightfield=void 0,e.freeContourSet(y),o.contourSet=void 0);for(let t=0;t<M.npolys();t++)M.areas(t)==e.Raw.Recast.WALKABLE_AREA&&M.setAreas(t,0),0==M.areas(t)&&M.setFlags(t,1);const H=new e.NavMeshCreateParams;H.setPolyMeshCreateParams(M),H.setPolyMeshDetailCreateParams(A),H.setWalkableHeight(c.walkableHeight),H.setWalkableRadius(c.walkableRadius),H.setWalkableClimb(c.walkableClimb),H.setCellSize(c.cs),H.setCellHeight(c.ch),H.setBuildBvTree(!0),s.offMeshConnections&&H.setOffMeshConnections(s.offMeshConnections),H.setTileX(t),H.setTileY(i);const v=e.createNavMeshData(H);return v.success?(d.log(e.Raw.Module.RC_LOG_PROGRESS,`>> Polymesh: ${M.nverts()} vertices ${M.npolys()} polygons`),{success:!0,data:v.navMeshData}):r("Failed to create Detour navmesh data")};d.startTimer(e.Raw.Module.RC_TIMER_TEMP);let P=[0,0,0],F=[0,0,0];for(let t=0;t<S;t++)for(let i=0;i<R;i++){P[0]=u[0]+i*y,P[1]=u[1],P[2]=u[2]+t*y,F[0]=u[0]+(i+1)*y,F[1]=b[1],F[2]=u[2]+(t+1)*y;const a=E(i,t,P,F);if(a.success&&a.data){c.removeTile(c.getTileRefAt(i,t,0));const l=c.addTile(a.data,e.Raw.Module.DT_TILE_FREE_DATA,0);e.Raw.Detour.statusFailed(l.status)&&(d.log(e.Raw.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${i}, ty: ${t},status: ${e.dtStatusToReadableString(l.status)} (${l.status})`),a.data.free())}}return d.stopTimer(e.Raw.Module.RC_TIMER_TEMP),n||g(),{success:!0,navMesh:c,intermediates:h}},exports.getBoundingBox=t,exports.soloNavMeshGeneratorConfigDefaults=l,exports.tileCacheGeneratorConfigDefaults=r,exports.tiledNavMeshGeneratorConfigDefaults=o;
|
|
2
|
+
//# sourceMappingURL=generators.cjs.map
|
package/generators.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@recast-navigation/generators';
|
package/generators.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{recastConfigDefaults as e,vec3 as t,RecastBuildContext as i,NavMesh as a,Arrays as l,createRcConfig as r,Raw as s,allocHeightfield as o,createHeightfield as n,markWalkableTriangles as d,rasterizeTriangles as h,filterLowHangingWalkableObstacles as c,filterLedgeSpans as m,filterWalkableLowHeightSpans as g,allocCompactHeightfield as u,buildCompactHeightfield as b,freeHeightfield as f,erodeWalkableArea as S,buildDistanceField as w,buildRegions as M,allocContourSet as C,buildContours as y,allocPolyMesh as R,buildPolyMesh as x,allocPolyMeshDetail as p,buildPolyMeshDetail as A,freeCompactHeightfield as k,freeContourSet as z,NavMeshCreateParams as _,createNavMeshData as v,TileCacheMeshProcess as T,TileCache as E,calcGridSize as H,DetourTileCacheParams as F,NavMeshParams as D,RecastChunkyTriMesh as L,dtStatusToReadableString as P,freeHeightfieldLayerSet as I,cloneRcConfig as O,allocHeightfieldLayerSet as G,buildHeightfieldLayers as N,getHeightfieldLayerHeights as $,getHeightfieldLayerAreas as W,getHeightfieldLayerCons as B,buildTileCacheLayer as U}from"@recast-navigation/core";const K=(e,i)=>{const a={x:1/0,y:1/0,z:1/0},l={x:-1/0,y:-1/0,z:-1/0};for(let t=0;t<i.length;t++){const r=i[t],s=e[3*r],o=e[3*r+1],n=e[3*r+2];a.x=Math.min(a.x,s),a.y=Math.min(a.y,o),a.z=Math.min(a.z,n),l.x=Math.max(l.x,s),l.y=Math.max(l.y,o),l.z=Math.max(l.z,n)}return{bbMin:t.toArray(a),bbMax:t.toArray(l)}},V=e=>{let t=0,i=0;return t=Number(e>65535)<<4,e>>=t,i=Number(e>255)<<3,e>>=i,t|=i,i=Number(e>15)<<2,e>>=i,t|=i,i=Number(e>3)<<1,t|=i,t|=(e>>=i)>>1,t},X=e=>(e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,++e),Y={...e},Z=(e,t,T={},E=!1)=>{const H=new i,F={type:"solo",buildContext:H},D=new a,L=e=>(E||(F.heightfield&&(f(F.heightfield),F.heightfield=void 0),F.compactHeightfield&&(k(F.compactHeightfield),F.compactHeightfield=void 0),F.contourSet&&(z(F.contourSet),F.contourSet=void 0)),D.destroy(),{navMesh:void 0,success:!1,intermediates:F,error:e}),P=e,I=t.length,O=new l.FloatArray;O.copy(P,P.length);const G=t,N=t.length/3,$=new l.IntArray;$.copy(G,G.length);const{bbMin:W,bbMax:B}=K(e,t),U=r({...Y,...T});U.minRegionArea=U.minRegionArea*U.minRegionArea,U.mergeRegionArea=U.mergeRegionArea*U.mergeRegionArea,U.detailSampleDist=U.detailSampleDist<.9?0:U.cs*U.detailSampleDist,U.detailSampleMaxError=U.ch*U.detailSampleMaxError;const V=s.Recast.calcGridSize(W,B,U.cs);U.width=V.width,U.height=V.height;const X=o();if(F.heightfield=X,!n(H,X,U.width,U.height,W,B,U.cs,U.ch))return L("Could not create heightfield");const Z=new l.UnsignedCharArray;if(Z.resize(N),d(H,U.walkableSlopeAngle,O,I,$,N,Z),!h(H,O,I,$,Z,N,X,U.walkableClimb))return L("Could not rasterize triangles");Z.free(),c(H,U.walkableClimb,X),m(H,U.walkableHeight,U.walkableClimb,X),g(H,U.walkableHeight,X);const j=u();if(F.compactHeightfield=j,!b(H,U.walkableHeight,U.walkableClimb,X,j))return L("Failed to build compact data");if(E||(f(X),F.heightfield=void 0),!S(H,U.walkableRadius,j))return L("Failed to erode walkable area");if(!w(H,j))return L("Failed to build distance field");if(!M(H,j,U.borderSize,U.minRegionArea,U.mergeRegionArea))return L("Failed to build regions");const q=C();if(F.contourSet=q,!y(H,j,U.maxSimplificationError,U.maxEdgeLen,q,s.Module.RC_CONTOUR_TESS_WALL_EDGES))return L("Failed to create contours");const J=R();if(!x(H,q,U.maxVertsPerPoly,J))return L("Failed to triangulate contours");const Q=p();if(!A(H,J,j,U.detailSampleDist,U.detailSampleMaxError,Q))return L("Failed to build detail mesh");E||(k(j),F.compactHeightfield=void 0,z(q),F.contourSet=void 0);for(let e=0;e<J.npolys();e++)J.areas(e)==s.Recast.WALKABLE_AREA&&J.setAreas(e,0),0==J.areas(e)&&J.setFlags(e,1);const ee=new _;ee.setPolyMeshCreateParams(J),ee.setPolyMeshDetailCreateParams(Q),ee.setWalkableHeight(U.walkableHeight),ee.setWalkableRadius(U.walkableRadius),ee.setWalkableClimb(U.walkableClimb),ee.setCellSize(U.cs),ee.setCellHeight(U.ch),ee.setBuildBvTree(!0),T.offMeshConnections&&ee.setOffMeshConnections(T.offMeshConnections);const te=v(ee);if(!te.success)return L("Failed to create Detour navmesh data");const{navMeshData:ie}=te;return D.initSolo(ie)?{success:!0,navMesh:D,intermediates:F}:L("Failed to create Detour navmesh")},j={...e,tileSize:32,expectedLayersPerTile:4,maxObstacles:128},q=()=>new T(((e,t,i)=>{for(let a=0;a<e.polyCount();++a)t.set(a,0),i.set(a,1)})),J=(e,w,M={},C=!1)=>{const y=new i;let R={type:"tilecache",buildContext:y,chunkyTriMesh:void 0,tileIntermediates:[]};const x=new E,p=new a,A=()=>{if(!C)for(let e=0;e<R.tileIntermediates.length;e++){const t=R.tileIntermediates[e];t.heightfield&&(f(t.heightfield),t.heightfield=void 0),t.compactHeightfield&&(k(t.compactHeightfield),t.compactHeightfield=void 0),t.heightfieldLayerSet&&(I(t.heightfieldLayerSet),t.heightfieldLayerSet=void 0)}},z=e=>(A(),x.destroy(),p.destroy(),{success:!1,navMesh:void 0,tileCache:void 0,intermediates:R,error:e}),_=e,v=w.length,T=new l.FloatArray;T.copy(_,_.length);const P=w,Y=w.length/3,Z=new l.IntArray;Z.copy(P,P.length);const{bbMin:J,bbMax:Q}=K(e,w),{expectedLayersPerTile:ee,maxObstacles:te,...ie}={...j,...M},ae=r(ie),le=H(J,Q,ae.cs);ae.width=le.width,ae.height=le.height,ae.minRegionArea=ae.minRegionArea*ae.minRegionArea,ae.mergeRegionArea=ae.mergeRegionArea*ae.mergeRegionArea,ae.detailSampleDist=ae.detailSampleDist<.9?0:ae.cs*ae.detailSampleDist,ae.detailSampleMaxError=ae.ch*ae.detailSampleMaxError;const re=Math.floor(ae.tileSize),se=Math.floor((ae.width+re-1)/re),oe=Math.floor((ae.height+re-1)/re);ae.borderSize=ae.walkableRadius+3,ae.width=ae.tileSize+2*ae.borderSize,ae.height=ae.tileSize+2*ae.borderSize;const ne=F.create({orig:J,cs:ae.cs,ch:ae.ch,width:ae.tileSize,height:ae.tileSize,walkableHeight:ae.walkableHeight,walkableRadius:ae.walkableRadius,walkableClimb:ae.walkableClimb,maxSimplificationError:ae.maxSimplificationError,maxTiles:se*oe*ee,maxObstacles:te}),de=new s.RecastLinearAllocator(32e3),he=new s.RecastFastLZCompressor,ce=M.tileCacheMeshProcess??q();if(!x.init(ne,de,he,ce))return z("Failed to initialize tile cache");const me=t.fromArray(J);let ge=Math.min(Math.floor(V(X(se*oe*ee))),14);ge>14&&(ge=14);const ue=1<<ge,be=1<<22-ge,fe=D.create({orig:me,tileWidth:ae.tileSize*ae.cs,tileHeight:ae.tileSize*ae.cs,maxTiles:ue,maxPolys:be});if(!p.initTiled(fe))return z("Failed to initialize tiled navmesh");const Se=new L;if(R.chunkyTriMesh=Se,!Se.init(T,Z,Y,256))return z("Failed to build chunky triangle mesh");const we=(e,t)=>{const i={tileX:e,tileY:t},a=ae.tileSize*ae.cs,r=O(ae),w=[J[0]+e*a,J[1],J[2]+t*a],M=[J[0]+(e+1)*a,Q[1],J[2]+(t+1)*a];w[0]-=r.borderSize*r.cs,w[2]-=r.borderSize*r.cs,M[0]+=r.borderSize*r.cs,M[2]+=r.borderSize*r.cs,r.set_bmin(0,w[0]),r.set_bmin(1,w[1]),r.set_bmin(2,w[2]),r.set_bmax(0,M[0]),r.set_bmax(1,M[1]),r.set_bmax(2,M[2]);const x=o();if(i.heightfield=x,!n(y,x,r.width,r.height,w,M,r.cs,r.ch))return{n:0};const p=[w[0],w[2]],A=[M[0],M[2]],z=new l.IntArray;z.resize(512);const _=Se.getChunksOverlappingRect(p,A,z,512);if(0===_)return{n:0};for(let e=0;e<_;++e){const t=z.get_data(e),i=Se.nodes(t).n,a=Se.getNodeTris(t),s=new l.UnsignedCharArray;s.resize(i),d(y,r.walkableSlopeAngle,T,v,a,i,s);const o=h(y,T,v,a,s,i,x,r.walkableClimb);if(s.free(),!o)return{n:0}}c(y,ae.walkableClimb,x),m(y,ae.walkableHeight,ae.walkableClimb,x),g(y,ae.walkableHeight,x);const E=u();if(!b(y,ae.walkableHeight,ae.walkableClimb,x,E))return{n:0};if(C||(f(i.heightfield),i.heightfield=void 0),!S(y,ae.walkableRadius,E))return{n:0};const H=G();if(!N(y,E,ae.borderSize,ae.walkableHeight,H))return{n:0};C||(k(E),i.compactHeightfield=void 0);const F=[];for(let i=0;i<H.nlayers();i++){const a=new l.UnsignedCharArray,r=H.layers(i),o=new s.dtTileCacheLayerHeader;o.magic=s.Detour.TILECACHE_MAGIC,o.version=s.Detour.TILECACHE_VERSION,o.tx=e,o.ty=t,o.tlayer=i;const n=r.bmin(),d=r.bmax();o.set_bmin(0,n.x),o.set_bmin(1,n.y),o.set_bmin(2,n.z),o.set_bmax(0,d.x),o.set_bmax(1,d.y),o.set_bmax(2,d.z),o.width=r.width(),o.height=r.height(),o.minx=r.minx(),o.maxx=r.maxx(),o.miny=r.miny(),o.maxy=r.maxy(),o.hmin=r.hmin(),o.hmax=r.hmax();const h=$(r),c=W(r),m=B(r),g=U(he,o,h,c,m,a);if(s.Detour.statusFailed(g))return{n:0};F.push(a)}return C||(I(H),i.heightfieldLayerSet=void 0),R.tileIntermediates.push(i),{n:F.length,tiles:F}};for(let e=0;e<oe;++e)for(let t=0;t<se;++t){const{n:i,tiles:a}=we(t,e);if(i>0&&a)for(let l=0;l<i;l++){const i=a[l],r=x.addTile(i);s.Detour.statusFailed(r.status)&&y.log(s.Module.RC_LOG_WARNING,`Failed to add tile to tile cache - tx: ${t}, ty: ${e}`)}}for(let e=0;e<oe;e++)for(let t=0;t<se;t++){const i=x.buildNavMeshTilesAt(t,e,p);if(s.Detour.statusFailed(i))return z(`Failed to build nav mesh tiles at ${t}, ${e}`)}return A(),{success:!0,tileCache:x,navMesh:p,intermediates:R}},Q={...e},ee=(e,T,E={},F=!1)=>{const I=new i,G={type:"tiled",buildContext:I,chunkyTriMesh:void 0,tileIntermediates:[]},N=new a,$=()=>{if(!F){for(let e=0;e<G.tileIntermediates.length;e++){const t=G.tileIntermediates[e];t.compactHeightfield&&k(t.compactHeightfield),t.heightfield&&f(t.heightfield),t.contourSet&&z(t.contourSet)}G.chunkyTriMesh&&(G.chunkyTriMesh=void 0)}},W=e=>($(),N.destroy(),{success:!1,navMesh:void 0,intermediates:G,error:e}),B=r({...Q,...E}),{bbMin:U,bbMax:Y}=K(e,T),Z=H(U,Y,B.cs);B.width=Z.width,B.height=Z.height,B.minRegionArea=B.minRegionArea*B.minRegionArea,B.mergeRegionArea=B.mergeRegionArea*B.mergeRegionArea,B.tileSize=Math.floor(B.tileSize),B.borderSize=B.walkableRadius+3,B.width=B.tileSize+2*B.borderSize,B.height=B.tileSize+2*B.borderSize,B.detailSampleDist=B.detailSampleDist<.9?0:B.cs*B.detailSampleDist,B.detailSampleMaxError=B.ch*B.detailSampleMaxError;const j=Math.floor(B.tileSize),q=Math.floor((Z.width+j-1)/j),J=Math.floor((Z.height+j-1)/j),ee=B.tileSize*B.cs,te=e,ie=T.length,ae=new l.FloatArray;ae.copy(te,te.length);const le=T,re=T.length/3,se=new l.IntArray;se.copy(le,le.length);const oe=t.fromArray(U);let ne=Math.min(Math.floor(V(X(q*J))),14);ne>14&&(ne=14);const de=1<<ne,he=1<<22-ne,ce=D.create({orig:oe,tileWidth:B.tileSize*B.cs,tileHeight:B.tileSize*B.cs,maxTiles:de,maxPolys:he});if(!N.initTiled(ce))return W("Could not init nav mesh for tiled use");const me=new L;if(G.chunkyTriMesh=me,!me.init(ae,se,re,256))return W("Failed to build chunky triangle mesh");const ge=(e,t,i,a)=>{const r=e=>(I.log(s.Module.RC_LOG_ERROR,e),{success:!1,error:e}),T={tileX:e,tileY:t};G.tileIntermediates.push(T);const H=O(B),D=[...i],L=[...a];D[0]-=H.borderSize*H.cs,D[2]-=H.borderSize*H.cs,L[0]+=H.borderSize*H.cs,L[2]+=H.borderSize*H.cs,H.set_bmin(0,D[0]),H.set_bmin(1,D[1]),H.set_bmin(2,D[2]),H.set_bmax(0,L[0]),H.set_bmax(1,L[1]),H.set_bmax(2,L[2]),I.resetTimers(),I.startTimer(s.Module.RC_TIMER_TOTAL),I.log(s.Module.RC_LOG_PROGRESS,`Building tile ${G.tileIntermediates.length} at x: ${e}, y: ${t}`),I.log(s.Module.RC_LOG_PROGRESS,` - ${B.width} x ${B.height} cells`),I.log(s.Module.RC_LOG_PROGRESS,` - ${ie/1e3}fK verts, ${re/1e3}K tris`);const P=o();if(T.heightfield=P,!n(I,P,H.width,H.height,D,L,H.cs,H.ch))return r("Could not create heightfield");(new l.UnsignedCharArray).resize(me.maxTrisPerChunk());const N=[D[0],D[2]],$=[L[0],L[2]],W=new l.IntArray;W.resize(512);const U=me.getChunksOverlappingRect(N,$,W,512);if(0===U)return{success:!0};for(let e=0;e<U;++e){const t=W.get_data(e),i=me.nodes(t).n,a=me.getNodeTris(t),s=new l.UnsignedCharArray;s.resize(i),d(I,H.walkableSlopeAngle,ae,ie,a,i,s);const o=h(I,ae,ie,a,s,i,P,H.walkableClimb);if(s.free(),!o)return r("Could not rasterize triangles")}c(I,H.walkableClimb,P),m(I,H.walkableHeight,H.walkableClimb,P),g(I,H.walkableHeight,P);const K=u();if(T.compactHeightfield=K,!b(I,H.walkableHeight,H.walkableClimb,P,K))return r("Could not build compact heightfield");if(F||(f(T.heightfield),T.heightfield=void 0),!S(I,H.walkableRadius,K))return r("Could not erode walkable area");if(!w(I,K))return r("Failed to build distance field");if(!M(I,K,H.borderSize,H.minRegionArea,H.mergeRegionArea))return r("Failed to build regions");const V=C();if(T.contourSet=V,!y(I,K,H.maxSimplificationError,H.maxEdgeLen,V,s.Module.RC_CONTOUR_TESS_WALL_EDGES))return r("Failed to create contours");const X=R();if(!x(I,V,H.maxVertsPerPoly,X))return r("Failed to triangulate contours");const Y=p();if(!A(I,X,K,H.detailSampleDist,H.detailSampleMaxError,Y))return r("Failed to build detail mesh");F||(k(K),T.compactHeightfield=void 0,z(V),T.contourSet=void 0);for(let e=0;e<X.npolys();e++)X.areas(e)==s.Recast.WALKABLE_AREA&&X.setAreas(e,0),0==X.areas(e)&&X.setFlags(e,1);const Z=new _;Z.setPolyMeshCreateParams(X),Z.setPolyMeshDetailCreateParams(Y),Z.setWalkableHeight(H.walkableHeight),Z.setWalkableRadius(H.walkableRadius),Z.setWalkableClimb(H.walkableClimb),Z.setCellSize(H.cs),Z.setCellHeight(H.ch),Z.setBuildBvTree(!0),E.offMeshConnections&&Z.setOffMeshConnections(E.offMeshConnections),Z.setTileX(e),Z.setTileY(t);const j=v(Z);return j.success?(I.log(s.Module.RC_LOG_PROGRESS,`>> Polymesh: ${X.nverts()} vertices ${X.npolys()} polygons`),{success:!0,data:j.navMeshData}):r("Failed to create Detour navmesh data")};I.startTimer(s.Module.RC_TIMER_TEMP);let ue=[0,0,0],be=[0,0,0];for(let e=0;e<J;e++)for(let t=0;t<q;t++){ue[0]=U[0]+t*ee,ue[1]=U[1],ue[2]=U[2]+e*ee,be[0]=U[0]+(t+1)*ee,be[1]=Y[1],be[2]=U[2]+(e+1)*ee;const i=ge(t,e,ue,be);if(i.success&&i.data){N.removeTile(N.getTileRefAt(t,e,0));const a=N.addTile(i.data,s.Module.DT_TILE_FREE_DATA,0);s.Detour.statusFailed(a.status)&&(I.log(s.Module.RC_LOG_WARNING,`Failed to add tile to nav mesh\n\ttx: ${t}, ty: ${e},status: ${P(a.status)} (${a.status})`),i.data.free())}}return I.stopTimer(s.Module.RC_TIMER_TEMP),F||$(),{success:!0,navMesh:N,intermediates:G}};export{q as createDefaultTileCacheMeshProcess,V as dtIlog2,X as dtNextPow2,Z as generateSoloNavMesh,J as generateTileCache,ee as generateTiledNavMesh,K as getBoundingBox,Y as soloNavMeshGeneratorConfigDefaults,j as tileCacheGeneratorConfigDefaults,Q as tiledNavMeshGeneratorConfigDefaults};
|
|
2
|
+
//# sourceMappingURL=generators.mjs.map
|
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"email": "isaac@isaacmason.com",
|
|
19
19
|
"url": "https://isaacmason.com/"
|
|
20
20
|
},
|
|
21
|
-
"version": "0.
|
|
21
|
+
"version": "0.15.0",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"homepage": "https://github.com/isaac-mason/recast-navigation-js",
|
|
24
24
|
"bugs": {
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"import": "./index.mjs",
|
|
34
34
|
"require": "./index.cjs"
|
|
35
35
|
},
|
|
36
|
+
"./generators": {
|
|
37
|
+
"types": "./generators.d.ts",
|
|
38
|
+
"import": "./generators.mjs",
|
|
39
|
+
"require": "./generators.cjs"
|
|
40
|
+
},
|
|
36
41
|
"./three": {
|
|
37
42
|
"types": "./three.d.ts",
|
|
38
43
|
"import": "./three.mjs",
|
|
@@ -43,6 +48,9 @@
|
|
|
43
48
|
"index.mjs",
|
|
44
49
|
"index.cjs",
|
|
45
50
|
"index.d.ts",
|
|
51
|
+
"generators.mjs",
|
|
52
|
+
"generators.cjs",
|
|
53
|
+
"generators.d.ts",
|
|
46
54
|
"three.mjs",
|
|
47
55
|
"three.cjs",
|
|
48
56
|
"three.d.ts",
|
|
@@ -50,14 +58,16 @@
|
|
|
50
58
|
"README.md"
|
|
51
59
|
],
|
|
52
60
|
"scripts": {
|
|
53
|
-
"clean": "(rm index.mjs index.cjs index.d.ts three.mjs three.cjs three.d.ts || true)",
|
|
61
|
+
"clean": "(rm index.mjs index.cjs index.d.ts generators.mjs generators.cjs generators.d.ts three.mjs three.cjs three.d.ts || true)",
|
|
54
62
|
"build": "yarn clean && rollup --config rollup.config.js --bundleConfigAsCjs",
|
|
55
63
|
"storybook": "storybook dev -p 6006",
|
|
56
|
-
"build-storybook": "storybook build"
|
|
64
|
+
"build-storybook": "storybook build",
|
|
65
|
+
"test": "vitest run"
|
|
57
66
|
},
|
|
58
67
|
"dependencies": {
|
|
59
|
-
"@recast-navigation/core": "0.
|
|
60
|
-
"@recast-navigation/
|
|
68
|
+
"@recast-navigation/core": "0.15.0",
|
|
69
|
+
"@recast-navigation/generators": "0.15.0",
|
|
70
|
+
"@recast-navigation/three": "0.15.0"
|
|
61
71
|
},
|
|
62
72
|
"devDependencies": {
|
|
63
73
|
"@babel/core": "^7.22.11",
|
|
@@ -66,7 +76,7 @@
|
|
|
66
76
|
"@react-three/csg": "^3.1.0",
|
|
67
77
|
"@react-three/drei": "^9.87.1",
|
|
68
78
|
"@react-three/fiber": "^8.14.5",
|
|
69
|
-
"@rollup/plugin-commonjs": "^25.0.
|
|
79
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
70
80
|
"@rollup/plugin-multi-entry": "^6.0.0",
|
|
71
81
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
72
82
|
"@rollup/plugin-terser": "^0.4.3",
|
|
@@ -75,9 +85,9 @@
|
|
|
75
85
|
"@storybook/addon-essentials": "^7.4.5",
|
|
76
86
|
"@storybook/addon-interactions": "^7.4.5",
|
|
77
87
|
"@storybook/addon-links": "^7.4.5",
|
|
78
|
-
"@storybook/addon-mdx-gfm": "^7.
|
|
88
|
+
"@storybook/addon-mdx-gfm": "^7.5.1",
|
|
79
89
|
"@storybook/react": "^7.4.5",
|
|
80
|
-
"@storybook/react-vite": "^7.
|
|
90
|
+
"@storybook/react-vite": "^7.5.1",
|
|
81
91
|
"@types/react": "^18.2.11",
|
|
82
92
|
"@types/react-dom": "^18.2.8",
|
|
83
93
|
"@types/three": "^0.155.0",
|
|
@@ -91,7 +101,8 @@
|
|
|
91
101
|
"storybook": "^7.4.5",
|
|
92
102
|
"suspend-react": "^0.1.3",
|
|
93
103
|
"three": "^0.156.1",
|
|
94
|
-
"three-pathfinding": "^1.2.0"
|
|
104
|
+
"three-pathfinding": "^1.2.0",
|
|
105
|
+
"vitest": "^0.34.6"
|
|
95
106
|
},
|
|
96
107
|
"packageManager": "yarn@3.2.2"
|
|
97
108
|
}
|