recast-navigation 0.13.2 → 0.14.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 +104 -47
- package/generators.cjs +2 -0
- package/generators.d.ts +1 -0
- package/generators.mjs +2 -0
- package/package.json +22 -11
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,11 @@ const { success, navMesh } = generateSoloNavMesh(
|
|
|
102
92
|
);
|
|
103
93
|
```
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
#### Advanced Usage
|
|
96
|
+
|
|
97
|
+
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
|
|
98
|
+
|
|
99
|
+
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
100
|
|
|
107
101
|
### Querying a NavMesh
|
|
108
102
|
|
|
@@ -128,7 +122,7 @@ const path: Vector3[] = navMeshQuery.computePath(
|
|
|
128
122
|
|
|
129
123
|
### Crowds and Agents
|
|
130
124
|
|
|
131
|
-
First, create a `Crowd
|
|
125
|
+
First, create a `Crowd`:
|
|
132
126
|
|
|
133
127
|
```ts
|
|
134
128
|
import { Crowd } from 'recast-navigation';
|
|
@@ -139,17 +133,7 @@ const maxAgentRadius = 0.6;
|
|
|
139
133
|
const crowd = new Crowd({ maxAgents, maxAgentRadius, navMesh });
|
|
140
134
|
```
|
|
141
135
|
|
|
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.
|
|
136
|
+
Next, create and interface with agents in the crowd.
|
|
153
137
|
|
|
154
138
|
```ts
|
|
155
139
|
const initialAgentPosition = navMeshQuery.getRandomPointAround(
|
|
@@ -185,9 +169,12 @@ agent.resetMoveTarget();
|
|
|
185
169
|
/* teleport the agent to a position */
|
|
186
170
|
agent.teleport(targetPosition);
|
|
187
171
|
|
|
188
|
-
/* update
|
|
172
|
+
/* update an agent parameter */
|
|
173
|
+
agent.maxAcceleration = 4;
|
|
174
|
+
|
|
175
|
+
/* update multiple parameters for an agent */
|
|
189
176
|
agent.updateParameters({
|
|
190
|
-
maxAcceleration:
|
|
177
|
+
maxAcceleration: 2,
|
|
191
178
|
});
|
|
192
179
|
|
|
193
180
|
/* set all parameters for an agent */
|
|
@@ -199,16 +186,24 @@ agent.setParameters({
|
|
|
199
186
|
crowd.removeAgent(agent);
|
|
200
187
|
```
|
|
201
188
|
|
|
202
|
-
|
|
189
|
+
To update the crowd, first set a timeStep, then call `update` each frame with the delta time.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const dt = 1 / 60;
|
|
193
|
+
crowd.timeStep = dt;
|
|
194
|
+
|
|
195
|
+
// you should call this every frame
|
|
196
|
+
crowd.update(dt);
|
|
197
|
+
```
|
|
203
198
|
|
|
204
|
-
|
|
199
|
+
### Temporary Obstacles
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
Recast Navigation supports temporary Box and Cylinder obstacles via a `TileCache`.
|
|
207
202
|
|
|
208
203
|
`TileCache` assumes small tiles (around 32-64 squared). Using `tileSize` values outside this range may result in unexpected behaviour.
|
|
209
204
|
|
|
210
205
|
```ts
|
|
211
|
-
import { generateTileCache } from 'recast-navigation';
|
|
206
|
+
import { generateTileCache } from 'recast-navigation/generators';
|
|
212
207
|
|
|
213
208
|
/* create a tile cache */
|
|
214
209
|
const { success, navMesh, tileCache } = generateTileCache(positions, indices, {
|
|
@@ -246,7 +241,7 @@ Off mesh connections are user-defined connections between two points on a NavMes
|
|
|
246
241
|
|
|
247
242
|
Off mesh connections can be bidirectional or unidirectional.
|
|
248
243
|
|
|
249
|
-
You can provide list of off mesh connections to the high level generator functions.
|
|
244
|
+
You can provide a list of off mesh connections to the `generateSoloNavMesh` and `generateTiledNavMesh` high level generator functions.
|
|
250
245
|
|
|
251
246
|
```ts
|
|
252
247
|
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
|
@@ -267,6 +262,43 @@ const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
|
|
267
262
|
|
|
268
263
|
You can use `agent.state()` to determine if an agent is currently traversing an off mesh connection.
|
|
269
264
|
|
|
265
|
+
#### Adding Off Mesh Connections to a TileCache
|
|
266
|
+
|
|
267
|
+
To add off mesh connections to a TileCache using `generateTileCache`, you must provide a TileCacheMeshProcess implementation that creates off mesh connections. For example:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
const tileCacheMeshProcess = new TileCacheMeshProcess(
|
|
271
|
+
(navMeshCreateParams, polyAreas, polyFlags) => {
|
|
272
|
+
for (let i = 0; i < navMeshCreateParams.polyCount(); ++i) {
|
|
273
|
+
polyAreas.set(i, 0);
|
|
274
|
+
polyFlags.set(i, 1);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
navMeshCreateParams.setOffMeshConnections([
|
|
278
|
+
{
|
|
279
|
+
startPosition: { x: 0, y: 5, z: 0 },
|
|
280
|
+
endPosition: { x: 2, y: 0, z: 0 },
|
|
281
|
+
radius: 0.5,
|
|
282
|
+
bidirectional: false,
|
|
283
|
+
area: 0,
|
|
284
|
+
flags: 1,
|
|
285
|
+
},
|
|
286
|
+
]);
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const tileCacheGeneratorConfig = {
|
|
291
|
+
// ... other config ...
|
|
292
|
+
tileCacheMeshProcess,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const { success, navMesh, tileCache } = generateTileCache(
|
|
296
|
+
positions,
|
|
297
|
+
indices,
|
|
298
|
+
tileCacheGeneratorConfig
|
|
299
|
+
);
|
|
300
|
+
```
|
|
301
|
+
|
|
270
302
|
### Debugging
|
|
271
303
|
|
|
272
304
|
You can use `getDebugNavMesh` to get a debug representation of the NavMesh.
|
|
@@ -277,30 +309,45 @@ const debugNavMesh = navMesh.getDebugNavMesh();
|
|
|
277
309
|
const { positions, indices } = debugNavMesh;
|
|
278
310
|
```
|
|
279
311
|
|
|
280
|
-
If you are using `@recast-navigation/three`, you can use `NavMeshHelper` and `CrowdHelper` to visualize NavMeshes and
|
|
312
|
+
If you are using `@recast-navigation/three`, you can use `NavMeshHelper` and `CrowdHelper` to visualize NavMeshes, Crowds, and NavMesh generation intermediates.
|
|
281
313
|
|
|
282
|
-
|
|
314
|
+
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.
|
|
283
315
|
|
|
284
|
-
|
|
316
|
+
### Importing and Exporting
|
|
317
|
+
|
|
318
|
+
A NavMesh and TileCache can be imported and exported as a Uint8Array.
|
|
319
|
+
|
|
320
|
+
See below for an example of exporting then importing a NavMesh:
|
|
285
321
|
|
|
286
322
|
```ts
|
|
287
323
|
import { exportNavMesh, importNavMesh } from 'recast-navigation';
|
|
288
324
|
|
|
289
|
-
/*
|
|
290
|
-
const navMeshExport: Uint8Array = exportNavMesh(
|
|
291
|
-
navMesh,
|
|
292
|
-
tileCache // optional
|
|
293
|
-
);
|
|
325
|
+
/* export */
|
|
326
|
+
const navMeshExport: Uint8Array = exportNavMesh(navMesh);
|
|
294
327
|
|
|
295
|
-
/*
|
|
296
|
-
const { navMesh
|
|
328
|
+
/* import */
|
|
329
|
+
const { navMesh } = importNavMesh(navMeshExport);
|
|
297
330
|
```
|
|
298
331
|
|
|
299
|
-
|
|
332
|
+
To export a TileCache and NavMesh, the usage varies slightly:
|
|
300
333
|
|
|
301
|
-
|
|
334
|
+
```ts
|
|
335
|
+
import { exportNavMesh, importNavMesh } from 'recast-navigation';
|
|
302
336
|
|
|
303
|
-
|
|
337
|
+
/* exporting */
|
|
338
|
+
// pass both the navMesh and the tileCache
|
|
339
|
+
const navMeshExport: Uint8Array = exportNavMesh(navMesh, tileCache);
|
|
340
|
+
|
|
341
|
+
/* importing */
|
|
342
|
+
// also pass the TileCacheMeshProcess implementation for the tile cache
|
|
343
|
+
// if you used `generateTileCache` and didn't provide one, `createDefaultTileCacheMeshProcess` returns the default TileCacheMeshProcess `generateTileCache` uses
|
|
344
|
+
const tileCacheMeshProcess = createDefaultTileCacheMeshProcess();
|
|
345
|
+
|
|
346
|
+
const { navMesh, tileCache } = importNavMesh(
|
|
347
|
+
navMeshExport,
|
|
348
|
+
tileCacheMeshProcess
|
|
349
|
+
);
|
|
350
|
+
```
|
|
304
351
|
|
|
305
352
|
## Documentation
|
|
306
353
|
|
|
@@ -352,6 +399,16 @@ The core library!
|
|
|
352
399
|
> npm install @recast-navigation/core
|
|
353
400
|
```
|
|
354
401
|
|
|
402
|
+
### [**`@recast-navigation/generators`**](https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-generators)
|
|
403
|
+
|
|
404
|
+
[](https://www.npmjs.com/package/@recast-navigation/generators)
|
|
405
|
+
|
|
406
|
+
NavMesh generator implementations. Use these to get started, and as a basis for your own NavMesh generator.
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
> npm install @recast-navigation/generators
|
|
410
|
+
```
|
|
411
|
+
|
|
355
412
|
### [**`@recast-navigation/three`**](https://github.com/isaac-mason/recast-navigation-js/tree/main/packages/recast-navigation-three)
|
|
356
413
|
|
|
357
414
|
[](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),{raw:R}=e.RecastConfig.create({...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},{raw:H}=e.RecastConfig.create(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,{raw:r}=new e.RecastConfig(H).clone(),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.RecastConfig.create({...o,...s}),{raw:u}=m,{bbMin:b,bbMax:w}=t(l,r),C=e.calcGridSize(b,w,u.cs);u.width=C.width,u.height=C.height,u.minRegionArea=u.minRegionArea*u.minRegionArea,u.mergeRegionArea=u.mergeRegionArea*u.mergeRegionArea,u.tileSize=Math.floor(u.tileSize),u.borderSize=u.walkableRadius+3,u.width=u.tileSize+2*u.borderSize,u.height=u.tileSize+2*u.borderSize,u.detailSampleDist=u.detailSampleDist<.9?0:u.cs*u.detailSampleDist,u.detailSampleMaxError=u.ch*u.detailSampleMaxError;const R=Math.floor(u.tileSize),S=Math.floor((C.width+R-1)/R),y=Math.floor((C.height+R-1)/R),M=u.tileSize*u.cs,p=l,x=r.length,A=new e.Arrays.FloatArray;A.copy(p,p.length);const k=r,H=r.length/3,v=new e.Arrays.IntArray;v.copy(k,k.length);const T=e.vec3.fromArray(b);let z=Math.min(Math.floor(i(a(S*y))),14);z>14&&(z=14);const _=1<<z,L=1<<22-z,D=e.NavMeshParams.create({orig:T,tileWidth:u.tileSize*u.cs,tileHeight:u.tileSize*u.cs,maxTiles:_,maxPolys:L});if(!c.initTiled(D))return f("Could not init nav mesh for tiled use");const E=new e.RecastChunkyTriMesh;if(h.chunkyTriMesh=E,!E.init(A,v,H,256))return f("Failed to build chunky triangle mesh");const P=(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{raw:c}=m.clone(),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,` - ${u.width} x ${u.height} cells`),d.log(e.Raw.Module.RC_LOG_PROGRESS,` - ${x/1e3}fK verts, ${H/1e3}K tris`);const b=e.allocHeightfield();if(o.heightfield=b,!e.createHeightfield(d,b,c.width,c.height,g,f,c.cs,c.ch))return r("Could not create heightfield");(new e.Arrays.UnsignedCharArray).resize(E.maxTrisPerChunk());const w=[g[0],g[2]],C=[f[0],f[2]],R=new e.Arrays.IntArray;R.resize(512);const S=E.getChunksOverlappingRect(w,C,R,512);if(0===S)return{success:!0};for(let t=0;t<S;++t){const i=R.get_data(t),a=E.nodes(i).n,l=E.getNodeTris(i),s=new e.Arrays.UnsignedCharArray;s.resize(a),e.markWalkableTriangles(d,c.walkableSlopeAngle,A,x,l,a,s);const o=e.rasterizeTriangles(d,A,x,l,s,a,b,c.walkableClimb);if(s.free(),!o)return r("Could not rasterize triangles")}e.filterLowHangingWalkableObstacles(d,c.walkableClimb,b),e.filterLedgeSpans(d,c.walkableHeight,c.walkableClimb,b),e.filterWalkableLowHeightSpans(d,c.walkableHeight,b);const y=e.allocCompactHeightfield();if(o.compactHeightfield=y,!e.buildCompactHeightfield(d,c.walkableHeight,c.walkableClimb,b,y))return r("Could not build compact heightfield");if(n||(e.freeHeightfield(o.heightfield),o.heightfield=void 0),!e.erodeWalkableArea(d,c.walkableRadius,y))return r("Could not erode walkable area");if(!e.buildDistanceField(d,y))return r("Failed to build distance field");if(!e.buildRegions(d,y,c.borderSize,c.minRegionArea,c.mergeRegionArea))return r("Failed to build regions");const M=e.allocContourSet();if(o.contourSet=M,!e.buildContours(d,y,c.maxSimplificationError,c.maxEdgeLen,M,e.Raw.Module.RC_CONTOUR_TESS_WALL_EDGES))return r("Failed to create contours");const p=e.allocPolyMesh();if(!e.buildPolyMesh(d,M,c.maxVertsPerPoly,p))return r("Failed to triangulate contours");const k=e.allocPolyMeshDetail();if(!e.buildPolyMeshDetail(d,p,y,c.detailSampleDist,c.detailSampleMaxError,k))return r("Failed to build detail mesh");n||(e.freeCompactHeightfield(y),o.compactHeightfield=void 0,e.freeContourSet(M),o.contourSet=void 0);for(let t=0;t<p.npolys();t++)p.areas(t)==e.Raw.Recast.WALKABLE_AREA&&p.setAreas(t,0),0==p.areas(t)&&p.setFlags(t,1);const v=new e.NavMeshCreateParams;v.setPolyMeshCreateParams(p),v.setPolyMeshDetailCreateParams(k),v.setWalkableHeight(c.walkableHeight),v.setWalkableRadius(c.walkableRadius),v.setWalkableClimb(c.walkableClimb),v.setCellSize(c.cs),v.setCellHeight(c.ch),v.setBuildBvTree(!0),s.offMeshConnections&&v.setOffMeshConnections(s.offMeshConnections),v.setTileX(t),v.setTileY(i);const T=e.createNavMeshData(v);return T.success?(d.log(e.Raw.Module.RC_LOG_PROGRESS,`>> Polymesh: ${p.nverts()} vertices ${p.npolys()} polygons`),{success:!0,data:T.navMeshData}):r("Failed to create Detour navmesh data")};d.startTimer(e.Raw.Module.RC_TIMER_TEMP);let F=[0,0,0],N=[0,0,0];for(let t=0;t<y;t++)for(let i=0;i<S;i++){F[0]=b[0]+i*M,F[1]=b[1],F[2]=b[2]+t*M,N[0]=b[0]+(i+1)*M,N[1]=w[1],N[2]=b[2]+(t+1)*M;const a=P(i,t,F,N);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,RecastConfig 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 w,buildDistanceField as S,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,allocHeightfieldLayerSet as O,buildHeightfieldLayers as G,getHeightfieldLayerHeights as N,getHeightfieldLayerAreas as $,getHeightfieldLayerCons as W,buildTileCacheLayer as B}from"@recast-navigation/core";const U=(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)}},K=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},V=e=>(e--,e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,++e),X={...e},Y=(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}=U(e,t),{raw:K}=r.create({...X,...T});K.minRegionArea=K.minRegionArea*K.minRegionArea,K.mergeRegionArea=K.mergeRegionArea*K.mergeRegionArea,K.detailSampleDist=K.detailSampleDist<.9?0:K.cs*K.detailSampleDist,K.detailSampleMaxError=K.ch*K.detailSampleMaxError;const V=s.Recast.calcGridSize(W,B,K.cs);K.width=V.width,K.height=V.height;const Y=o();if(F.heightfield=Y,!n(H,Y,K.width,K.height,W,B,K.cs,K.ch))return L("Could not create heightfield");const Z=new l.UnsignedCharArray;if(Z.resize(N),d(H,K.walkableSlopeAngle,O,I,$,N,Z),!h(H,O,I,$,Z,N,Y,K.walkableClimb))return L("Could not rasterize triangles");Z.free(),c(H,K.walkableClimb,Y),m(H,K.walkableHeight,K.walkableClimb,Y),g(H,K.walkableHeight,Y);const j=u();if(F.compactHeightfield=j,!b(H,K.walkableHeight,K.walkableClimb,Y,j))return L("Failed to build compact data");if(E||(f(Y),F.heightfield=void 0),!w(H,K.walkableRadius,j))return L("Failed to erode walkable area");if(!S(H,j))return L("Failed to build distance field");if(!M(H,j,K.borderSize,K.minRegionArea,K.mergeRegionArea))return L("Failed to build regions");const q=C();if(F.contourSet=q,!y(H,j,K.maxSimplificationError,K.maxEdgeLen,q,s.Module.RC_CONTOUR_TESS_WALL_EDGES))return L("Failed to create contours");const J=R();if(!x(H,q,K.maxVertsPerPoly,J))return L("Failed to triangulate contours");const Q=p();if(!A(H,J,j,K.detailSampleDist,K.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(K.walkableHeight),ee.setWalkableRadius(K.walkableRadius),ee.setWalkableClimb(K.walkableClimb),ee.setCellSize(K.cs),ee.setCellHeight(K.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")},Z={...e,tileSize:32,expectedLayersPerTile:4,maxObstacles:128},j=()=>new T(((e,t,i)=>{for(let a=0;a<e.polyCount();++a)t.set(a,0),i.set(a,1)})),q=(e,S,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=S.length,T=new l.FloatArray;T.copy(_,_.length);const P=S,X=S.length/3,Y=new l.IntArray;Y.copy(P,P.length);const{bbMin:q,bbMax:J}=U(e,S),{expectedLayersPerTile:Q,maxObstacles:ee,...te}={...Z,...M},{raw:ie}=r.create(te),ae=H(q,J,ie.cs);ie.width=ae.width,ie.height=ae.height,ie.minRegionArea=ie.minRegionArea*ie.minRegionArea,ie.mergeRegionArea=ie.mergeRegionArea*ie.mergeRegionArea,ie.detailSampleDist=ie.detailSampleDist<.9?0:ie.cs*ie.detailSampleDist,ie.detailSampleMaxError=ie.ch*ie.detailSampleMaxError;const le=Math.floor(ie.tileSize),re=Math.floor((ie.width+le-1)/le),se=Math.floor((ie.height+le-1)/le);ie.borderSize=ie.walkableRadius+3,ie.width=ie.tileSize+2*ie.borderSize,ie.height=ie.tileSize+2*ie.borderSize;const oe=F.create({orig:q,cs:ie.cs,ch:ie.ch,width:ie.tileSize,height:ie.tileSize,walkableHeight:ie.walkableHeight,walkableRadius:ie.walkableRadius,walkableClimb:ie.walkableClimb,maxSimplificationError:ie.maxSimplificationError,maxTiles:re*se*Q,maxObstacles:ee}),ne=new s.RecastLinearAllocator(32e3),de=new s.RecastFastLZCompressor,he=M.tileCacheMeshProcess??j();if(!x.init(oe,ne,de,he))return z("Failed to initialize tile cache");const ce=t.fromArray(q);let me=Math.min(Math.floor(K(V(re*se*Q))),14);me>14&&(me=14);const ge=1<<me,ue=1<<22-me,be=D.create({orig:ce,tileWidth:ie.tileSize*ie.cs,tileHeight:ie.tileSize*ie.cs,maxTiles:ge,maxPolys:ue});if(!p.initTiled(be))return z("Failed to initialize tiled navmesh");const fe=new L;if(R.chunkyTriMesh=fe,!fe.init(T,Y,X,256))return z("Failed to build chunky triangle mesh");const we=(e,t)=>{const i={tileX:e,tileY:t},a=ie.tileSize*ie.cs,{raw:S}=new r(ie).clone(),M=[q[0]+e*a,q[1],q[2]+t*a],x=[q[0]+(e+1)*a,J[1],q[2]+(t+1)*a];M[0]-=S.borderSize*S.cs,M[2]-=S.borderSize*S.cs,x[0]+=S.borderSize*S.cs,x[2]+=S.borderSize*S.cs,S.set_bmin(0,M[0]),S.set_bmin(1,M[1]),S.set_bmin(2,M[2]),S.set_bmax(0,x[0]),S.set_bmax(1,x[1]),S.set_bmax(2,x[2]);const p=o();if(i.heightfield=p,!n(y,p,S.width,S.height,M,x,S.cs,S.ch))return{n:0};const A=[M[0],M[2]],z=[x[0],x[2]],_=new l.IntArray;_.resize(512);const E=fe.getChunksOverlappingRect(A,z,_,512);if(0===E)return{n:0};for(let e=0;e<E;++e){const t=_.get_data(e),i=fe.nodes(t).n,a=fe.getNodeTris(t),r=new l.UnsignedCharArray;r.resize(i),d(y,S.walkableSlopeAngle,T,v,a,i,r);const s=h(y,T,v,a,r,i,p,S.walkableClimb);if(r.free(),!s)return{n:0}}c(y,ie.walkableClimb,p),m(y,ie.walkableHeight,ie.walkableClimb,p),g(y,ie.walkableHeight,p);const H=u();if(!b(y,ie.walkableHeight,ie.walkableClimb,p,H))return{n:0};if(C||(f(i.heightfield),i.heightfield=void 0),!w(y,ie.walkableRadius,H))return{n:0};const F=O();if(!G(y,H,ie.borderSize,ie.walkableHeight,F))return{n:0};C||(k(H),i.compactHeightfield=void 0);const D=[];for(let i=0;i<F.nlayers();i++){const a=new l.UnsignedCharArray,r=F.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=N(r),c=$(r),m=W(r),g=B(de,o,h,c,m,a);if(s.Detour.statusFailed(g))return{n:0};D.push(a)}return C||(I(F),i.heightfieldLayerSet=void 0),R.tileIntermediates.push(i),{n:D.length,tiles:D}};for(let e=0;e<se;++e)for(let t=0;t<re;++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<se;e++)for(let t=0;t<re;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}},J={...e},Q=(e,T,E={},F=!1)=>{const I=new i,O={type:"tiled",buildContext:I,chunkyTriMesh:void 0,tileIntermediates:[]},G=new a,N=()=>{if(!F){for(let e=0;e<O.tileIntermediates.length;e++){const t=O.tileIntermediates[e];t.compactHeightfield&&k(t.compactHeightfield),t.heightfield&&f(t.heightfield),t.contourSet&&z(t.contourSet)}O.chunkyTriMesh&&(O.chunkyTriMesh=void 0)}},$=e=>(N(),G.destroy(),{success:!1,navMesh:void 0,intermediates:O,error:e}),W=r.create({...J,...E}),{raw:B}=W,{bbMin:X,bbMax:Y}=U(e,T),Z=H(X,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),Q=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(X);let ne=Math.min(Math.floor(K(V(q*Q))),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(!G.initTiled(ce))return $("Could not init nav mesh for tiled use");const me=new L;if(O.chunkyTriMesh=me,!me.init(ae,se,re,256))return $("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};O.tileIntermediates.push(T);const{raw:H}=W.clone(),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 ${O.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 G=[D[0],D[2]],N=[L[0],L[2]],$=new l.IntArray;$.resize(512);const U=me.getChunksOverlappingRect(G,N,$,512);if(0===U)return{success:!0};for(let e=0;e<U;++e){const t=$.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),!w(I,H.walkableRadius,K))return r("Could not erode walkable area");if(!S(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<Q;e++)for(let t=0;t<q;t++){ue[0]=X[0]+t*ee,ue[1]=X[1],ue[2]=X[2]+e*ee,be[0]=X[0]+(t+1)*ee,be[1]=Y[1],be[2]=X[2]+(e+1)*ee;const i=ge(t,e,ue,be);if(i.success&&i.data){G.removeTile(G.getTileRefAt(t,e,0));const a=G.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||N(),{success:!0,navMesh:G,intermediates:O}};export{j as createDefaultTileCacheMeshProcess,K as dtIlog2,V as dtNextPow2,Y as generateSoloNavMesh,q as generateTileCache,Q as generateTiledNavMesh,U as getBoundingBox,X as soloNavMeshGeneratorConfigDefaults,Z as tileCacheGeneratorConfigDefaults,J 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.14.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.14.0",
|
|
69
|
+
"@recast-navigation/generators": "0.14.0",
|
|
70
|
+
"@recast-navigation/three": "0.14.0"
|
|
61
71
|
},
|
|
62
72
|
"devDependencies": {
|
|
63
73
|
"@babel/core": "^7.22.11",
|
|
@@ -65,19 +75,19 @@
|
|
|
65
75
|
"@pmndrs/assets": "^1.6.0",
|
|
66
76
|
"@react-three/csg": "^3.1.0",
|
|
67
77
|
"@react-three/drei": "^9.87.1",
|
|
68
|
-
"@react-three/fiber": "^8.14.
|
|
69
|
-
"@rollup/plugin-commonjs": "^25.0.
|
|
78
|
+
"@react-three/fiber": "^8.14.5",
|
|
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",
|
|
73
|
-
"@rollup/plugin-typescript": "^11.1.
|
|
83
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
74
84
|
"@storybook/addon-actions": "^7.4.5",
|
|
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
|
}
|