Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

Diff Revisions 336 vs 337 for /trunk/Source Code/Libs/src/ReCast/DetourTileCache/Source/DetourTileCache.cpp

Diff revisions: vs.
  @@ -11,694 +11,694 @@
11 11
12 12 dtTileCache* dtAllocTileCache()
13 13 {
14 - void* mem = dtAlloc(sizeof(dtTileCache), DT_ALLOC_PERM);
15 - if (!mem) return 0;
16 - return new(mem) dtTileCache;
14 + void* mem = dtAlloc(sizeof(dtTileCache), DT_ALLOC_PERM);
15 + if (!mem) return 0;
16 + return new(mem) dtTileCache;
17 17 }
18 18
19 19 void dtFreeTileCache(dtTileCache* tc)
20 20 {
21 - if (!tc) return;
22 - tc->~dtTileCache();
23 - dtFree(tc);
21 + if (!tc) return;
22 + tc->~dtTileCache();
23 + dtFree(tc);
24 24 }
25 25
26 26 static bool contains(const dtCompressedTileRef* a, const int n, const dtCompressedTileRef v)
27 27 {
28 - for (int i = 0; i < n; ++i)
29 - if (a[i] == v)
30 - return true;
31 - return false;
28 + for (int i = 0; i < n; ++i)
29 + if (a[i] == v)
30 + return true;
31 + return false;
32 32 }
33 33
34 34 inline int computeTileHash(int x, int y, const int mask)
35 35 {
36 - const unsigned int h1 = 0x8da6b343; // Large multiplicative constants;
37 - const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes
38 - unsigned int n = h1 * x + h2 * y;
39 - return (int)(n & mask);
36 + const unsigned int h1 = 0x8da6b343; // Large multiplicative constants;
37 + const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes
38 + unsigned int n = h1 * x + h2 * y;
39 + return (int)(n & mask);
40 40 }
41 41
42 42
43 43 struct BuildContext
44 44 {
45 - inline BuildContext(struct dtTileCacheAlloc* a) : layer(0), lcset(0), lmesh(0), alloc(a) {}
46 - inline ~BuildContext() { purge(); }
47 - void purge()
48 - {
49 - dtFreeTileCacheLayer(alloc, layer);
50 - layer = 0;
51 - dtFreeTileCacheContourSet(alloc, lcset);
52 - lcset = 0;
53 - dtFreeTileCachePolyMesh(alloc, lmesh);
54 - lmesh = 0;
55 - }
56 - struct dtTileCacheLayer* layer;
57 - struct dtTileCacheContourSet* lcset;
58 - struct dtTileCachePolyMesh* lmesh;
59 - struct dtTileCacheAlloc* alloc;
45 + inline BuildContext(struct dtTileCacheAlloc* a) : layer(0), lcset(0), lmesh(0), alloc(a) {}
46 + inline ~BuildContext() { purge(); }
47 + void purge()
48 + {
49 + dtFreeTileCacheLayer(alloc, layer);
50 + layer = 0;
51 + dtFreeTileCacheContourSet(alloc, lcset);
52 + lcset = 0;
53 + dtFreeTileCachePolyMesh(alloc, lmesh);
54 + lmesh = 0;
55 + }
56 + struct dtTileCacheLayer* layer;
57 + struct dtTileCacheContourSet* lcset;
58 + struct dtTileCachePolyMesh* lmesh;
59 + struct dtTileCacheAlloc* alloc;
60 60 };
61 61
62 62
63 63 dtTileCache::dtTileCache() :
64 - m_tileLutSize(0),
65 - m_tileLutMask(0),
66 - m_posLookup(0),
67 - m_nextFreeTile(0),
68 - m_tiles(0),
69 - m_saltBits(0),
70 - m_tileBits(0),
71 - m_talloc(0),
72 - m_tcomp(0),
73 - m_tmproc(0),
74 - m_obstacles(0),
75 - m_nextFreeObstacle(0),
76 - m_nreqs(0),
77 - m_nupdate(0)
64 + m_tileLutSize(0),
65 + m_tileLutMask(0),
66 + m_posLookup(0),
67 + m_nextFreeTile(0),
68 + m_tiles(0),
69 + m_saltBits(0),
70 + m_tileBits(0),
71 + m_talloc(0),
72 + m_tcomp(0),
73 + m_tmproc(0),
74 + m_obstacles(0),
75 + m_nextFreeObstacle(0),
76 + m_nreqs(0),
77 + m_nupdate(0)
78 78 {
79 - memset(&m_params, 0, sizeof(m_params));
79 + memset(&m_params, 0, sizeof(m_params));
80 80 }
81 -
81 +
82 82 dtTileCache::~dtTileCache()
83 83 {
84 - for (int i = 0; i < m_params.maxTiles; ++i)
85 - {
86 - if (m_tiles[i].flags & DT_COMPRESSEDTILE_FREE_DATA)
87 - {
88 - dtFree(m_tiles[i].data);
89 - m_tiles[i].data = 0;
90 - }
91 - }
92 - dtFree(m_obstacles);
93 - m_obstacles = 0;
94 - dtFree(m_posLookup);
95 - m_posLookup = 0;
96 - dtFree(m_tiles);
97 - m_tiles = 0;
98 - m_nreqs = 0;
99 - m_nupdate = 0;
84 + for (int i = 0; i < m_params.maxTiles; ++i)
85 + {
86 + if (m_tiles[i].flags & DT_COMPRESSEDTILE_FREE_DATA)
87 + {
88 + dtFree(m_tiles[i].data);
89 + m_tiles[i].data = 0;
90 + }
91 + }
92 + dtFree(m_obstacles);
93 + m_obstacles = 0;
94 + dtFree(m_posLookup);
95 + m_posLookup = 0;
96 + dtFree(m_tiles);
97 + m_tiles = 0;
98 + m_nreqs = 0;
99 + m_nupdate = 0;
100 100 }
101 101
102 102 const dtCompressedTile* dtTileCache::getTileByRef(dtCompressedTileRef ref) const
103 103 {
104 - if (!ref)
105 - return 0;
106 - unsigned int tileIndex = decodeTileIdTile(ref);
107 - unsigned int tileSalt = decodeTileIdSalt(ref);
108 - if ((int)tileIndex >= m_params.maxTiles)
109 - return 0;
110 - const dtCompressedTile* tile = &m_tiles[tileIndex];
111 - if (tile->salt != tileSalt)
112 - return 0;
113 - return tile;
104 + if (!ref)
105 + return 0;
106 + unsigned int tileIndex = decodeTileIdTile(ref);
107 + unsigned int tileSalt = decodeTileIdSalt(ref);
108 + if ((int)tileIndex >= m_params.maxTiles)
109 + return 0;
110 + const dtCompressedTile* tile = &m_tiles[tileIndex];
111 + if (tile->salt != tileSalt)
112 + return 0;
113 + return tile;
114 114 }
115 115
116 116
117 117 dtStatus dtTileCache::init(const dtTileCacheParams* params,
118 - dtTileCacheAlloc* talloc,
119 - dtTileCacheCompressor* tcomp,
120 - dtTileCacheMeshProcess* tmproc)
121 - {
122 - m_talloc = talloc;
123 - m_tcomp = tcomp;
124 - m_tmproc = tmproc;
125 - m_nreqs = 0;
126 - memcpy(&m_params, params, sizeof(m_params));
127 -
128 - // Alloc space for obstacles.
129 - m_obstacles = (dtTileCacheObstacle*)dtAlloc(sizeof(dtTileCacheObstacle)*m_params.maxObstacles, DT_ALLOC_PERM);
130 - if (!m_obstacles)
131 - return DT_FAILURE | DT_OUT_OF_MEMORY;
132 - memset(m_obstacles, 0, sizeof(dtTileCacheObstacle)*m_params.maxObstacles);
133 - m_nextFreeObstacle = 0;
134 - for (int i = m_params.maxObstacles-1; i >= 0; --i)
135 - {
136 - m_obstacles[i].salt = 1;
137 - m_obstacles[i].next = m_nextFreeObstacle;
138 - m_nextFreeObstacle = &m_obstacles[i];
139 - }
140 -
141 - // Init tiles
142 - m_tileLutSize = dtNextPow2(m_params.maxTiles/4);
143 - if (!m_tileLutSize) m_tileLutSize = 1;
144 - m_tileLutMask = m_tileLutSize-1;
145 -
146 - m_tiles = (dtCompressedTile*)dtAlloc(sizeof(dtCompressedTile)*m_params.maxTiles, DT_ALLOC_PERM);
147 - if (!m_tiles)
148 - return DT_FAILURE | DT_OUT_OF_MEMORY;
149 - m_posLookup = (dtCompressedTile**)dtAlloc(sizeof(dtCompressedTile*)*m_tileLutSize, DT_ALLOC_PERM);
150 - if (!m_posLookup)
151 - return DT_FAILURE | DT_OUT_OF_MEMORY;
152 - memset(m_tiles, 0, sizeof(dtCompressedTile)*m_params.maxTiles);
153 - memset(m_posLookup, 0, sizeof(dtCompressedTile*)*m_tileLutSize);
154 - m_nextFreeTile = 0;
155 - for (int i = m_params.maxTiles-1; i >= 0; --i)
156 - {
157 - m_tiles[i].salt = 1;
158 - m_tiles[i].next = m_nextFreeTile;
159 - m_nextFreeTile = &m_tiles[i];
160 - }
161 -
162 - // Init ID generator values.
163 - m_tileBits = dtIlog2(dtNextPow2((unsigned int)m_params.maxTiles));
164 - // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
165 - m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits);
166 - if (m_saltBits < 10)
167 - return DT_FAILURE | DT_INVALID_PARAM;
168 -
169 - return DT_SUCCESS;
118 + dtTileCacheAlloc* talloc,
119 + dtTileCacheCompressor* tcomp,
120 + dtTileCacheMeshProcess* tmproc)
121 + {
122 + m_talloc = talloc;
123 + m_tcomp = tcomp;
124 + m_tmproc = tmproc;
125 + m_nreqs = 0;
126 + memcpy(&m_params, params, sizeof(m_params));
127 +
128 + // Alloc space for obstacles.
129 + m_obstacles = (dtTileCacheObstacle*)dtAlloc(sizeof(dtTileCacheObstacle)*m_params.maxObstacles, DT_ALLOC_PERM);
130 + if (!m_obstacles)
131 + return DT_FAILURE | DT_OUT_OF_MEMORY;
132 + memset(m_obstacles, 0, sizeof(dtTileCacheObstacle)*m_params.maxObstacles);
133 + m_nextFreeObstacle = 0;
134 + for (int i = m_params.maxObstacles-1; i >= 0; --i)
135 + {
136 + m_obstacles[i].salt = 1;
137 + m_obstacles[i].next = m_nextFreeObstacle;
138 + m_nextFreeObstacle = &m_obstacles[i];
139 + }
140 +
141 + // Init tiles
142 + m_tileLutSize = dtNextPow2(m_params.maxTiles/4);
143 + if (!m_tileLutSize) m_tileLutSize = 1;
144 + m_tileLutMask = m_tileLutSize-1;
145 +
146 + m_tiles = (dtCompressedTile*)dtAlloc(sizeof(dtCompressedTile)*m_params.maxTiles, DT_ALLOC_PERM);
147 + if (!m_tiles)
148 + return DT_FAILURE | DT_OUT_OF_MEMORY;
149 + m_posLookup = (dtCompressedTile**)dtAlloc(sizeof(dtCompressedTile*)*m_tileLutSize, DT_ALLOC_PERM);
150 + if (!m_posLookup)
151 + return DT_FAILURE | DT_OUT_OF_MEMORY;
152 + memset(m_tiles, 0, sizeof(dtCompressedTile)*m_params.maxTiles);
153 + memset(m_posLookup, 0, sizeof(dtCompressedTile*)*m_tileLutSize);
154 + m_nextFreeTile = 0;
155 + for (int i = m_params.maxTiles-1; i >= 0; --i)
156 + {
157 + m_tiles[i].salt = 1;
158 + m_tiles[i].next = m_nextFreeTile;
159 + m_nextFreeTile = &m_tiles[i];
160 + }
161 +
162 + // Init ID generator values.
163 + m_tileBits = dtIlog2(dtNextPow2((unsigned int)m_params.maxTiles));
164 + // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
165 + m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits);
166 + if (m_saltBits < 10)
167 + return DT_FAILURE | DT_INVALID_PARAM;
168 +
169 + return DT_SUCCESS;
170 170 }
171 171
172 172 int dtTileCache::getTilesAt(const int tx, const int ty, dtCompressedTileRef* tiles, const int maxTiles) const
173 173 {
174 - int n = 0;
175 -
176 - // Find tile based on hash.
177 - int h = computeTileHash(tx,ty,m_tileLutMask);
178 - dtCompressedTile* tile = m_posLookup[h];
179 - while (tile)
180 - {
181 - if (tile->header &&
182 - tile->header->tx == tx &&
183 - tile->header->ty == ty)
184 - {
185 - if (n < maxTiles)
186 - tiles[n++] = getTileRef(tile);
187 - }
188 - tile = tile->next;
189 - }
190 -
191 - return n;
174 + int n = 0;
175 +
176 + // Find tile based on hash.
177 + int h = computeTileHash(tx,ty,m_tileLutMask);
178 + dtCompressedTile* tile = m_posLookup[h];
179 + while (tile)
180 + {
181 + if (tile->header &&
182 + tile->header->tx == tx &&
183 + tile->header->ty == ty)
184 + {
185 + if (n < maxTiles)
186 + tiles[n++] = getTileRef(tile);
187 + }
188 + tile = tile->next;
189 + }
190 +
191 + return n;
192 192 }
193 193
194 194 dtCompressedTile* dtTileCache::getTileAt(const int tx, const int ty, const int tlayer)
195 195 {
196 - // Find tile based on hash.
197 - int h = computeTileHash(tx,ty,m_tileLutMask);
198 - dtCompressedTile* tile = m_posLookup[h];
199 - while (tile)
200 - {
201 - if (tile->header &&
202 - tile->header->tx == tx &&
203 - tile->header->ty == ty &&
204 - tile->header->tlayer == tlayer)
205 - {
206 - return tile;
207 - }
208 - tile = tile->next;
209 - }
210 - return 0;
196 + // Find tile based on hash.
197 + int h = computeTileHash(tx,ty,m_tileLutMask);
198 + dtCompressedTile* tile = m_posLookup[h];
199 + while (tile)
200 + {
201 + if (tile->header &&
202 + tile->header->tx == tx &&
203 + tile->header->ty == ty &&
204 + tile->header->tlayer == tlayer)
205 + {
206 + return tile;
207 + }
208 + tile = tile->next;
209 + }
210 + return 0;
211 211 }
212 212
213 213 dtCompressedTileRef dtTileCache::getTileRef(const dtCompressedTile* tile) const
214 214 {
215 - if (!tile) return 0;
216 - const unsigned int it = (unsigned int)(tile - m_tiles);
217 - return (dtCompressedTileRef)encodeTileId(tile->salt, it);
215 + if (!tile) return 0;
216 + const unsigned int it = (unsigned int)(tile - m_tiles);
217 + return (dtCompressedTileRef)encodeTileId(tile->salt, it);
218 218 }
219 219
220 220 dtObstacleRef dtTileCache::getObstacleRef(const dtTileCacheObstacle* ob) const
221 221 {
222 - if (!ob) return 0;
223 - const unsigned int idx = (unsigned int)(ob - m_obstacles);
224 - return encodeObstacleId(ob->salt, idx);
222 + if (!ob) return 0;
223 + const unsigned int idx = (unsigned int)(ob - m_obstacles);
224 + return encodeObstacleId(ob->salt, idx);
225 225 }
226 226
227 227 const dtTileCacheObstacle* dtTileCache::getObstacleByRef(dtObstacleRef ref)
228 228 {
229 - if (!ref)
230 - return 0;
231 - unsigned int idx = decodeObstacleIdObstacle(ref);
232 - if ((int)idx >= m_params.maxObstacles)
233 - return 0;
234 - const dtTileCacheObstacle* ob = &m_obstacles[idx];
235 - unsigned int salt = decodeObstacleIdSalt(ref);
236 - if (ob->salt != salt)
237 - return 0;
238 - return ob;
229 + if (!ref)
230 + return 0;
231 + unsigned int idx = decodeObstacleIdObstacle(ref);
232 + if ((int)idx >= m_params.maxObstacles)
233 + return 0;
234 + const dtTileCacheObstacle* ob = &m_obstacles[idx];
235 + unsigned int salt = decodeObstacleIdSalt(ref);
236 + if (ob->salt != salt)
237 + return 0;
238 + return ob;
239 239 }
240 240
241 241 dtStatus dtTileCache::addTile(unsigned char* data, const int dataSize, unsigned char flags, dtCompressedTileRef* result)
242 242 {
243 - // Make sure the data is in right format.
244 - dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)data;
245 - if (header->magic != DT_TILECACHE_MAGIC)
246 - return DT_FAILURE | DT_WRONG_MAGIC;
247 - if (header->version != DT_TILECACHE_VERSION)
248 - return DT_FAILURE | DT_WRONG_VERSION;
249 -
250 - // Make sure the location is free.
251 - if (getTileAt(header->tx, header->ty, header->tlayer))
252 - return DT_FAILURE;
253 -
254 - // Allocate a tile.
255 - dtCompressedTile* tile = 0;
256 - if (m_nextFreeTile)
257 - {
258 - tile = m_nextFreeTile;
259 - m_nextFreeTile = tile->next;
260 - tile->next = 0;
261 - }
262 -
263 - // Make sure we could allocate a tile.
264 - if (!tile)
265 - return DT_FAILURE | DT_OUT_OF_MEMORY;
266 -
267 - // Insert tile into the position lut.
268 - int h = computeTileHash(header->tx, header->ty, m_tileLutMask);
269 - tile->next = m_posLookup[h];
270 - m_posLookup[h] = tile;
271 -
272 - // Init tile.
273 - const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
274 - tile->header = (dtTileCacheLayerHeader*)data;
275 - tile->data = data;
276 - tile->dataSize = dataSize;
277 - tile->compressed = tile->data + headerSize;
278 - tile->compressedSize = tile->dataSize - headerSize;
279 - tile->flags = flags;
280 -
281 - if (result)
282 - *result = getTileRef(tile);
283 -
284 - return DT_SUCCESS;
243 + // Make sure the data is in right format.
244 + dtTileCacheLayerHeader* header = (dtTileCacheLayerHeader*)data;
245 + if (header->magic != DT_TILECACHE_MAGIC)
246 + return DT_FAILURE | DT_WRONG_MAGIC;
247 + if (header->version != DT_TILECACHE_VERSION)
248 + return DT_FAILURE | DT_WRONG_VERSION;
249 +
250 + // Make sure the location is free.
251 + if (getTileAt(header->tx, header->ty, header->tlayer))
252 + return DT_FAILURE;
253 +
254 + // Allocate a tile.
255 + dtCompressedTile* tile = 0;
256 + if (m_nextFreeTile)
257 + {
258 + tile = m_nextFreeTile;
259 + m_nextFreeTile = tile->next;
260 + tile->next = 0;
261 + }
262 +
263 + // Make sure we could allocate a tile.
264 + if (!tile)
265 + return DT_FAILURE | DT_OUT_OF_MEMORY;
266 +
267 + // Insert tile into the position lut.
268 + int h = computeTileHash(header->tx, header->ty, m_tileLutMask);
269 + tile->next = m_posLookup[h];
270 + m_posLookup[h] = tile;
271 +
272 + // Init tile.
273 + const int headerSize = dtAlign4(sizeof(dtTileCacheLayerHeader));
274 + tile->header = (dtTileCacheLayerHeader*)data;
275 + tile->data = data;
276 + tile->dataSize = dataSize;
277 + tile->compressed = tile->data + headerSize;
278 + tile->compressedSize = tile->dataSize - headerSize;
279 + tile->flags = flags;
280 +
281 + if (result)
282 + *result = getTileRef(tile);
283 +
284 + return DT_SUCCESS;
285 285 }
286 286
287 287 dtStatus dtTileCache::removeTile(dtCompressedTileRef ref, unsigned char** data, int* dataSize)
288 288 {
289 - if (!ref)
290 - return DT_FAILURE | DT_INVALID_PARAM;
291 - unsigned int tileIndex = decodeTileIdTile(ref);
292 - unsigned int tileSalt = decodeTileIdSalt(ref);
293 - if ((int)tileIndex >= m_params.maxTiles)
294 - return DT_FAILURE | DT_INVALID_PARAM;
295 - dtCompressedTile* tile = &m_tiles[tileIndex];
296 - if (tile->salt != tileSalt)
297 - return DT_FAILURE | DT_INVALID_PARAM;
298 -
299 - // Remove tile from hash lookup.
300 - const int h = computeTileHash(tile->header->tx,tile->header->ty,m_tileLutMask);
301 - dtCompressedTile* prev = 0;
302 - dtCompressedTile* cur = m_posLookup[h];
303 - while (cur)
304 - {
305 - if (cur == tile)
306 - {
307 - if (prev)
308 - prev->next = cur->next;
309 - else
310 - m_posLookup[h] = cur->next;
311 - break;
312 - }
313 - prev = cur;
314 - cur = cur->next;
315 - }
316 -
317 - // Reset tile.
318 - if (tile->flags & DT_COMPRESSEDTILE_FREE_DATA)
319 - {
320 - // Owns data
321 - dtFree(tile->data);
322 - tile->data = 0;
323 - tile->dataSize = 0;
324 - if (data) *data = 0;
325 - if (dataSize) *dataSize = 0;
326 - }
327 - else
328 - {
329 - if (data) *data = tile->data;
330 - if (dataSize) *dataSize = tile->dataSize;
331 - }
332 -
333 - tile->header = 0;
334 - tile->data = 0;
335 - tile->dataSize = 0;
336 - tile->compressed = 0;
337 - tile->compressedSize = 0;
338 - tile->flags = 0;
339 -
340 - // Update salt, salt should never be zero.
341 - tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
342 - if (tile->salt == 0)
343 - tile->salt++;
344 -
345 - // Add to free list.
346 - tile->next = m_nextFreeTile;
347 - m_nextFreeTile = tile;
348 -
349 - return DT_SUCCESS;
289 + if (!ref)
290 + return DT_FAILURE | DT_INVALID_PARAM;
291 + unsigned int tileIndex = decodeTileIdTile(ref);
292 + unsigned int tileSalt = decodeTileIdSalt(ref);
293 + if ((int)tileIndex >= m_params.maxTiles)
294 + return DT_FAILURE | DT_INVALID_PARAM;
295 + dtCompressedTile* tile = &m_tiles[tileIndex];
296 + if (tile->salt != tileSalt)
297 + return DT_FAILURE | DT_INVALID_PARAM;
298 +
299 + // Remove tile from hash lookup.
300 + const int h = computeTileHash(tile->header->tx,tile->header->ty,m_tileLutMask);
301 + dtCompressedTile* prev = 0;
302 + dtCompressedTile* cur = m_posLookup[h];
303 + while (cur)
304 + {
305 + if (cur == tile)
306 + {
307 + if (prev)
308 + prev->next = cur->next;
309 + else
310 + m_posLookup[h] = cur->next;
311 + break;
312 + }
313 + prev = cur;
314 + cur = cur->next;
315 + }
316 +
317 + // Reset tile.
318 + if (tile->flags & DT_COMPRESSEDTILE_FREE_DATA)
319 + {
320 + // Owns data
321 + dtFree(tile->data);
322 + tile->data = 0;
323 + tile->dataSize = 0;
324 + if (data) *data = 0;
325 + if (dataSize) *dataSize = 0;
326 + }
327 + else
328 + {
329 + if (data) *data = tile->data;
330 + if (dataSize) *dataSize = tile->dataSize;
331 + }
332 +
333 + tile->header = 0;
334 + tile->data = 0;
335 + tile->dataSize = 0;
336 + tile->compressed = 0;
337 + tile->compressedSize = 0;
338 + tile->flags = 0;
339 +
340 + // Update salt, salt should never be zero.
341 + tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
342 + if (tile->salt == 0)
343 + tile->salt++;
344 +
345 + // Add to free list.
346 + tile->next = m_nextFreeTile;
347 + m_nextFreeTile = tile;
348 +
349 + return DT_SUCCESS;
350 350 }
351 351
352 352
353 353 dtObstacleRef dtTileCache::addObstacle(const float* pos, const float radius, const float height, dtObstacleRef* result)
354 354 {
355 - if (m_nreqs >= MAX_REQUESTS)
356 - return DT_FAILURE | DT_BUFFER_TOO_SMALL;
357 -
358 - dtTileCacheObstacle* ob = 0;
359 - if (m_nextFreeObstacle)
360 - {
361 - ob = m_nextFreeObstacle;
362 - m_nextFreeObstacle = ob->next;
363 - ob->next = 0;
364 - }
365 - if (!ob)
366 - return DT_FAILURE | DT_OUT_OF_MEMORY;
367 -
368 - unsigned short salt = ob->salt;
369 - memset(ob, 0, sizeof(dtTileCacheObstacle));
370 - ob->salt = salt;
371 - ob->state = DT_OBSTACLE_PROCESSING;
372 - dtVcopy(ob->pos, pos);
373 - ob->radius = radius;
374 - ob->height = height;
375 -
376 - ObstacleRequest* req = &m_reqs[m_nreqs++];
377 - memset(req, 0, sizeof(ObstacleRequest));
378 - req->action = REQUEST_ADD;
379 - req->ref = getObstacleRef(ob);
380 -
381 - if (result)
382 - *result = req->ref;
383 -
384 - return DT_SUCCESS;
355 + if (m_nreqs >= MAX_REQUESTS)
356 + return DT_FAILURE | DT_BUFFER_TOO_SMALL;
357 +
358 + dtTileCacheObstacle* ob = 0;
359 + if (m_nextFreeObstacle)
360 + {
361 + ob = m_nextFreeObstacle;
362 + m_nextFreeObstacle = ob->next;
363 + ob->next = 0;
364 + }
365 + if (!ob)
366 + return DT_FAILURE | DT_OUT_OF_MEMORY;
367 +
368 + unsigned short salt = ob->salt;
369 + memset(ob, 0, sizeof(dtTileCacheObstacle));
370 + ob->salt = salt;
371 + ob->state = DT_OBSTACLE_PROCESSING;
372 + dtVcopy(ob->pos, pos);
373 + ob->radius = radius;
374 + ob->height = height;
375 +
376 + ObstacleRequest* req = &m_reqs[m_nreqs++];
377 + memset(req, 0, sizeof(ObstacleRequest));
378 + req->action = REQUEST_ADD;
379 + req->ref = getObstacleRef(ob);
380 +
381 + if (result)
382 + *result = req->ref;
383 +
384 + return DT_SUCCESS;
385 385 }
386 386
387 387 dtObstacleRef dtTileCache::removeObstacle(const dtObstacleRef ref)
388 388 {
389 - if (!ref)
390 - return DT_SUCCESS;
391 - if (m_nreqs >= MAX_REQUESTS)
392 - return DT_FAILURE | DT_BUFFER_TOO_SMALL;
393 -
394 - ObstacleRequest* req = &m_reqs[m_nreqs++];
395 - memset(req, 0, sizeof(ObstacleRequest));
396 - req->action = REQUEST_REMOVE;
397 - req->ref = ref;
398 -
399 - return DT_SUCCESS;
389 + if (!ref)
390 + return DT_SUCCESS;
391 + if (m_nreqs >= MAX_REQUESTS)
392 + return DT_FAILURE | DT_BUFFER_TOO_SMALL;
393 +
394 + ObstacleRequest* req = &m_reqs[m_nreqs++];
395 + memset(req, 0, sizeof(ObstacleRequest));
396 + req->action = REQUEST_REMOVE;
397 + req->ref = ref;
398 +
399 + return DT_SUCCESS;
400 400 }
401 401
402 402 dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax,
403 - dtCompressedTileRef* results, int* resultCount, const int maxResults) const
403 + dtCompressedTileRef* results, int* resultCount, const int maxResults) const
404 404 {
405 - const int MAX_TILES = 32;
406 - dtCompressedTileRef tiles[MAX_TILES];
407 -
408 - int n = 0;
409 -
410 - const float tw = m_params.width * m_params.cs;
411 - const float th = m_params.height * m_params.cs;
412 - const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / tw);
413 - const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / tw);
414 - const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / th);
415 - const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / th);
416 -
417 - for (int ty = ty0; ty <= ty1; ++ty)
418 - {
419 - for (int tx = tx0; tx <= tx1; ++tx)
420 - {
421 - const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
422 -
423 - for (int i = 0; i < ntiles; ++i)
424 - {
425 - const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])];
426 - float tbmin[3], tbmax[3];
427 - calcTightTileBounds(tile->header, tbmin, tbmax);
428 -
429 - if (dtOverlapBounds(bmin,bmax, tbmin,tbmax))
430 - {
431 - if (n < maxResults)
432 - results[n++] = tiles[i];
433 - }
434 - }
435 - }
436 - }
437 -
438 - *resultCount = n;
439 -
440 - return DT_SUCCESS;
405 + const int MAX_TILES = 32;
406 + dtCompressedTileRef tiles[MAX_TILES];
407 +
408 + int n = 0;
409 +
410 + const float tw = m_params.width * m_params.cs;
411 + const float th = m_params.height * m_params.cs;
412 + const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / tw);
413 + const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / tw);
414 + const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / th);
415 + const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / th);
416 +
417 + for (int ty = ty0; ty <= ty1; ++ty)
418 + {
419 + for (int tx = tx0; tx <= tx1; ++tx)
420 + {
421 + const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
422 +
423 + for (int i = 0; i < ntiles; ++i)
424 + {
425 + const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])];
426 + float tbmin[3], tbmax[3];
427 + calcTightTileBounds(tile->header, tbmin, tbmax);
428 +
429 + if (dtOverlapBounds(bmin,bmax, tbmin,tbmax))
430 + {
431 + if (n < maxResults)
432 + results[n++] = tiles[i];
433 + }
434 + }
435 + }
436 + }
437 +
438 + *resultCount = n;
439 +
440 + return DT_SUCCESS;
441 441 }
442 442
443 443 dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
444 444 {
445 - if (m_nupdate == 0)
446 - {
447 - // Process requests.
448 - for (int i = 0; i < m_nreqs; ++i)
449 - {
450 - ObstacleRequest* req = &m_reqs[i];
451 -
452 - unsigned int idx = decodeObstacleIdObstacle(req->ref);
453 - if ((int)idx >= m_params.maxObstacles)
454 - continue;
455 - dtTileCacheObstacle* ob = &m_obstacles[idx];
456 - unsigned int salt = decodeObstacleIdSalt(req->ref);
457 - if (ob->salt != salt)
458 - continue;
459 -
460 - if (req->action == REQUEST_ADD)
461 - {
462 - // Find touched tiles.
463 - float bmin[3], bmax[3];
464 - getObstacleBounds(ob, bmin, bmax);
465 -
466 - int ntouched = 0;
467 - queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
468 - ob->ntouched = (unsigned char)ntouched;
469 - // Add tiles to update list.
470 - ob->npending = 0;
471 - for (int j = 0; j < ob->ntouched; ++j)
472 - {
473 - if (m_nupdate < MAX_UPDATE)
474 - {
475 - if (!contains(m_update, m_nupdate, ob->touched[j]))
476 - m_update[m_nupdate++] = ob->touched[j];
477 - ob->pending[ob->npending++] = ob->touched[j];
478 - }
479 - }
480 - }
481 - else if (req->action == REQUEST_REMOVE)
482 - {
483 - // Prepare to remove obstacle.
484 - ob->state = DT_OBSTACLE_REMOVING;
485 - // Add tiles to update list.
486 - ob->npending = 0;
487 - for (int j = 0; j < ob->ntouched; ++j)
488 - {
489 - if (m_nupdate < MAX_UPDATE)
490 - {
491 - if (!contains(m_update, m_nupdate, ob->touched[j]))
492 - m_update[m_nupdate++] = ob->touched[j];
493 - ob->pending[ob->npending++] = ob->touched[j];
494 - }
495 - }
496 - }
497 - }
498 -
499 - m_nreqs = 0;
500 - }
501 -
502 - // Process updates
503 - if (m_nupdate)
504 - {
505 - // Build mesh
506 - const dtCompressedTileRef ref = m_update[0];
507 - dtStatus status = buildNavMeshTile(ref, navmesh);
508 - m_nupdate--;
509 - if (m_nupdate > 0)
510 - memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
511 -
512 - // Update obstacle states.
513 - for (int i = 0; i < m_params.maxObstacles; ++i)
514 - {
515 - dtTileCacheObstacle* ob = &m_obstacles[i];
516 - if (ob->state == DT_OBSTACLE_PROCESSING || ob->state == DT_OBSTACLE_REMOVING)
517 - {
518 - // Remove handled tile from pending list.
519 - for (int j = 0; j < (int)ob->npending; j++)
520 - {
521 - if (ob->pending[j] == ref)
522 - {
523 - ob->pending[j] = ob->pending[(int)ob->npending-1];
524 - ob->npending--;
525 - break;
526 - }
527 - }
528 -
529 - // If all pending tiles processed, change state.
530 - if (ob->npending == 0)
531 - {
532 - if (ob->state == DT_OBSTACLE_PROCESSING)
533 - {
534 - ob->state = DT_OBSTACLE_PROCESSED;
535 - }
536 - else if (ob->state == DT_OBSTACLE_REMOVING)
537 - {
538 - ob->state = DT_OBSTACLE_EMPTY;
539 - // Update salt, salt should never be zero.
540 - ob->salt = (ob->salt+1) & ((1<<16)-1);
541 - if (ob->salt == 0)
542 - ob->salt++;
543 - // Return obstacle to free list.
544 - ob->next = m_nextFreeObstacle;
545 - m_nextFreeObstacle = ob;
546 - }
547 - }
548 - }
549 - }
550 -
551 - if (dtStatusFailed(status))
552 - return status;
553 - }
554 -
555 - return DT_SUCCESS;
445 + if (m_nupdate == 0)
446 + {
447 + // Process requests.
448 + for (int i = 0; i < m_nreqs; ++i)
449 + {
450 + ObstacleRequest* req = &m_reqs[i];
451 +
452 + unsigned int idx = decodeObstacleIdObstacle(req->ref);
453 + if ((int)idx >= m_params.maxObstacles)
454 + continue;
455 + dtTileCacheObstacle* ob = &m_obstacles[idx];
456 + unsigned int salt = decodeObstacleIdSalt(req->ref);
457 + if (ob->salt != salt)
458 + continue;
459 +
460 + if (req->action == REQUEST_ADD)
461 + {
462 + // Find touched tiles.
463 + float bmin[3], bmax[3];
464 + getObstacleBounds(ob, bmin, bmax);
465 +
466 + int ntouched = 0;
467 + queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
468 + ob->ntouched = (unsigned char)ntouched;
469 + // Add tiles to update list.
470 + ob->npending = 0;
471 + for (int j = 0; j < ob->ntouched; ++j)
472 + {
473 + if (m_nupdate < MAX_UPDATE)
474 + {
475 + if (!contains(m_update, m_nupdate, ob->touched[j]))
476 + m_update[m_nupdate++] = ob->touched[j];
477 + ob->pending[ob->npending++] = ob->touched[j];
478 + }
479 + }
480 + }
481 + else if (req->action == REQUEST_REMOVE)
482 + {
483 + // Prepare to remove obstacle.
484 + ob->state = DT_OBSTACLE_REMOVING;
485 + // Add tiles to update list.
486 + ob->npending = 0;
487 + for (int j = 0; j < ob->ntouched; ++j)
488 + {
489 + if (m_nupdate < MAX_UPDATE)
490 + {
491 + if (!contains(m_update, m_nupdate, ob->touched[j]))
492 + m_update[m_nupdate++] = ob->touched[j];
493 + ob->pending[ob->npending++] = ob->touched[j];
494 + }
495 + }
496 + }
497 + }
498 +
499 + m_nreqs = 0;
500 + }
501 +
502 + // Process updates
503 + if (m_nupdate)
504 + {
505 + // Build mesh
506 + const dtCompressedTileRef ref = m_update[0];
507 + dtStatus status = buildNavMeshTile(ref, navmesh);
508 + m_nupdate--;
509 + if (m_nupdate > 0)
510 + memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
511 +
512 + // Update obstacle states.
513 + for (int i = 0; i < m_params.maxObstacles; ++i)
514 + {
515 + dtTileCacheObstacle* ob = &m_obstacles[i];
516 + if (ob->state == DT_OBSTACLE_PROCESSING || ob->state == DT_OBSTACLE_REMOVING)
517 + {
518 + // Remove handled tile from pending list.
519 + for (int j = 0; j < (int)ob->npending; j++)
520 + {
521 + if (ob->pending[j] == ref)
522 + {
523 + ob->pending[j] = ob->pending[(int)ob->npending-1];
524 + ob->npending--;
525 + break;
526 + }
527 + }
528 +
529 + // If all pending tiles processed, change state.
530 + if (ob->npending == 0)
531 + {
532 + if (ob->state == DT_OBSTACLE_PROCESSING)
533 + {
534 + ob->state = DT_OBSTACLE_PROCESSED;
535 + }
536 + else if (ob->state == DT_OBSTACLE_REMOVING)
537 + {
538 + ob->state = DT_OBSTACLE_EMPTY;
539 + // Update salt, salt should never be zero.
540 + ob->salt = (ob->salt+1) & ((1<<16)-1);
541 + if (ob->salt == 0)
542 + ob->salt++;
543 + // Return obstacle to free list.
544 + ob->next = m_nextFreeObstacle;
545 + m_nextFreeObstacle = ob;
546 + }
547 + }
548 + }
549 + }
550 +
551 + if (dtStatusFailed(status))
552 + return status;
553 + }
554 +
555 + return DT_SUCCESS;
556 556 }
557 557
558 558
559 559 dtStatus dtTileCache::buildNavMeshTilesAt(const int tx, const int ty, dtNavMesh* navmesh)
560 560 {
561 - const int MAX_TILES = 32;
562 - dtCompressedTileRef tiles[MAX_TILES];
563 - const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
564 -
565 - for (int i = 0; i < ntiles; ++i)
566 - {
567 - dtStatus status = buildNavMeshTile(tiles[i], navmesh);
568 - if (dtStatusFailed(status))
569 - return status;
570 - }
571 -
572 - return DT_SUCCESS;
561 + const int MAX_TILES = 32;
562 + dtCompressedTileRef tiles[MAX_TILES];
563 + const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES);
564 +
565 + for (int i = 0; i < ntiles; ++i)
566 + {
567 + dtStatus status = buildNavMeshTile(tiles[i], navmesh);
568 + if (dtStatusFailed(status))
569 + return status;
570 + }
571 +
572 + return DT_SUCCESS;
573 573 }
574 574
575 575 dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh* navmesh)
576 - {
577 - dtAssert(m_talloc);
578 - dtAssert(m_tcomp);
579 -
580 - unsigned int idx = decodeTileIdTile(ref);
581 - if (idx > (unsigned int)m_params.maxTiles)
582 - return DT_FAILURE | DT_INVALID_PARAM;
583 - const dtCompressedTile* tile = &m_tiles[idx];
584 - unsigned int salt = decodeTileIdSalt(ref);
585 - if (tile->salt != salt)
586 - return DT_FAILURE | DT_INVALID_PARAM;
587 -
588 - m_talloc->reset();
589 -
590 - BuildContext bc(m_talloc);
591 - const int walkableClimbVx = (int)(m_params.walkableClimb / m_params.ch);
592 - dtStatus status;
593 -
594 - // Decompress tile layer data.
595 - status = dtDecompressTileCacheLayer(m_talloc, m_tcomp, tile->data, tile->dataSize, &bc.layer);
596 - if (dtStatusFailed(status))
597 - return status;
598 -
599 - // Rasterize obstacles.
600 - for (int i = 0; i < m_params.maxObstacles; ++i)
601 - {
602 - const dtTileCacheObstacle* ob = &m_obstacles[i];
603 - if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
604 - continue;
605 - if (contains(ob->touched, ob->ntouched, ref))
606 - {
607 - dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
608 - ob->pos, ob->radius, ob->height, 0);
609 - }
610 - }
611 -
612 - // Build navmesh
613 - status = dtBuildTileCacheRegions(m_talloc, *bc.layer, walkableClimbVx);
614 - if (dtStatusFailed(status))
615 - return status;
616 -
617 - bc.lcset = dtAllocTileCacheContourSet(m_talloc);
618 - if (!bc.lcset)
619 - return status;
620 - status = dtBuildTileCacheContours(m_talloc, *bc.layer, walkableClimbVx,
621 - m_params.maxSimplificationError, *bc.lcset);
622 - if (dtStatusFailed(status))
623 - return status;
624 -
625 - bc.lmesh = dtAllocTileCachePolyMesh(m_talloc);
626 - if (!bc.lmesh)
627 - return status;
628 - status = dtBuildTileCachePolyMesh(m_talloc, *bc.lcset, *bc.lmesh);
629 - if (dtStatusFailed(status))
630 - return status;
631 -
632 - // Early out if the mesh tile is empty.
633 - if (!bc.lmesh->npolys)
634 - return DT_SUCCESS;
635 -
636 - dtNavMeshCreateParams params;
637 - memset(&params, 0, sizeof(params));
638 - params.verts = bc.lmesh->verts;
639 - params.vertCount = bc.lmesh->nverts;
640 - params.polys = bc.lmesh->polys;
641 - params.polyAreas = bc.lmesh->areas;
642 - params.polyFlags = bc.lmesh->flags;
643 - params.polyCount = bc.lmesh->npolys;
644 - params.nvp = DT_VERTS_PER_POLYGON;
645 - params.walkableHeight = m_params.walkableHeight;
646 - params.walkableRadius = m_params.walkableRadius;
647 - params.walkableClimb = m_params.walkableClimb;
648 - params.tileX = tile->header->tx;
649 - params.tileY = tile->header->ty;
650 - params.tileLayer = tile->header->tlayer;
651 - params.cs = m_params.cs;
652 - params.ch = m_params.ch;
653 - params.buildBvTree = false;
654 - dtVcopy(params.bmin, tile->header->bmin);
655 - dtVcopy(params.bmax, tile->header->bmax);
656 -
657 - if (m_tmproc)
658 - {
659 - m_tmproc->process(&params, bc.lmesh->areas, bc.lmesh->flags);
660 - }
661 -
662 - unsigned char* navData = 0;
663 - int navDataSize = 0;
664 - if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
665 - return DT_FAILURE;
666 -
667 - // Remove existing tile.
668 - navmesh->removeTile(navmesh->getTileRefAt(tile->header->tx,tile->header->ty,tile->header->tlayer),0,0);
669 -
670 - // Add new tile, or leave the location empty.
671 - if (navData)
672 - {
673 - // Let the navmesh own the data.
674 - status = navmesh->addTile(navData,navDataSize,DT_TILE_FREE_DATA,0,0);
675 - if (dtStatusFailed(status))
676 - {
677 - dtFree(navData);
678 - return status;
679 - }
680 - }
681 -
682 - return DT_SUCCESS;
576 + {
577 + dtAssert(m_talloc);
578 + dtAssert(m_tcomp);
579 +
580 + unsigned int idx = decodeTileIdTile(ref);
581 + if (idx > (unsigned int)m_params.maxTiles)
582 + return DT_FAILURE | DT_INVALID_PARAM;
583 + const dtCompressedTile* tile = &m_tiles[idx];
584 + unsigned int salt = decodeTileIdSalt(ref);
585 + if (tile->salt != salt)
586 + return DT_FAILURE | DT_INVALID_PARAM;
587 +
588 + m_talloc->reset();
589 +
590 + BuildContext bc(m_talloc);
591 + const int walkableClimbVx = (int)(m_params.walkableClimb / m_params.ch);
592 + dtStatus status;
593 +
594 + // Decompress tile layer data.
595 + status = dtDecompressTileCacheLayer(m_talloc, m_tcomp, tile->data, tile->dataSize, &bc.layer);
596 + if (dtStatusFailed(status))
597 + return status;
598 +
599 + // Rasterize obstacles.
600 + for (int i = 0; i < m_params.maxObstacles; ++i)
601 + {
602 + const dtTileCacheObstacle* ob = &m_obstacles[i];
603 + if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
604 + continue;
605 + if (contains(ob->touched, ob->ntouched, ref))
606 + {
607 + dtMarkCylinderArea(*bc.layer, tile->header->bmin, m_params.cs, m_params.ch,
608 + ob->pos, ob->radius, ob->height, 0);
609 + }
610 + }
611 +
612 + // Build navmesh
613 + status = dtBuildTileCacheRegions(m_talloc, *bc.layer, walkableClimbVx);
614 + if (dtStatusFailed(status))
615 + return status;
616 +
617 + bc.lcset = dtAllocTileCacheContourSet(m_talloc);
618 + if (!bc.lcset)
619 + return status;
620 + status = dtBuildTileCacheContours(m_talloc, *bc.layer, walkableClimbVx,
621 + m_params.maxSimplificationError, *bc.lcset);
622 + if (dtStatusFailed(status))
623 + return status;
624 +
625 + bc.lmesh = dtAllocTileCachePolyMesh(m_talloc);
626 + if (!bc.lmesh)
627 + return status;
628 + status = dtBuildTileCachePolyMesh(m_talloc, *bc.lcset, *bc.lmesh);
629 + if (dtStatusFailed(status))
630 + return status;
631 +
632 + // Early out if the mesh tile is empty.
633 + if (!bc.lmesh->npolys)
634 + return DT_SUCCESS;
635 +
636 + dtNavMeshCreateParams params;
637 + memset(&params, 0, sizeof(params));
638 + params.verts = bc.lmesh->verts;
639 + params.vertCount = bc.lmesh->nverts;
640 + params.polys = bc.lmesh->polys;
641 + params.polyAreas = bc.lmesh->areas;
642 + params.polyFlags = bc.lmesh->flags;
643 + params.polyCount = bc.lmesh->npolys;
644 + params.nvp = DT_VERTS_PER_POLYGON;
645 + params.walkableHeight = m_params.walkableHeight;
646 + params.walkableRadius = m_params.walkableRadius;
647 + params.walkableClimb = m_params.walkableClimb;
648 + params.tileX = tile->header->tx;
649 + params.tileY = tile->header->ty;
650 + params.tileLayer = tile->header->tlayer;
651 + params.cs = m_params.cs;
652 + params.ch = m_params.ch;
653 + params.buildBvTree = false;
654 + dtVcopy(params.bmin, tile->header->bmin);
655 + dtVcopy(params.bmax, tile->header->bmax);
656 +
657 + if (m_tmproc)
658 + {
659 + m_tmproc->process(&params, bc.lmesh->areas, bc.lmesh->flags);
660 + }
661 +
662 + unsigned char* navData = 0;
663 + int navDataSize = 0;
664 + if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
665 + return DT_FAILURE;
666 +
667 + // Remove existing tile.
668 + navmesh->removeTile(navmesh->getTileRefAt(tile->header->tx,tile->header->ty,tile->header->tlayer),0,0);
669 +
670 + // Add new tile, or leave the location empty.
671 + if (navData)
672 + {
673 + // Let the navmesh own the data.
674 + status = navmesh->addTile(navData,navDataSize,DT_TILE_FREE_DATA,0,0);
675 + if (dtStatusFailed(status))
676 + {
677 + dtFree(navData);
678 + return status;
679 + }
680 + }
681 +
682 + return DT_SUCCESS;
683 683 }
684 684
685 685 void dtTileCache::calcTightTileBounds(const dtTileCacheLayerHeader* header, float* bmin, float* bmax) const
686 686 {
687 - const float cs = m_params.cs;
688 - bmin[0] = header->bmin[0] + header->minx*cs;
689 - bmin[1] = header->bmin[1];
690 - bmin[2] = header->bmin[2] + header->miny*cs;
691 - bmax[0] = header->bmin[0] + (header->maxx+1)*cs;
692 - bmax[1] = header->bmax[1];
693 - bmax[2] = header->bmin[2] + (header->maxy+1)*cs;
687 + const float cs = m_params.cs;
688 + bmin[0] = header->bmin[0] + header->minx*cs;
689 + bmin[1] = header->bmin[1];
690 + bmin[2] = header->bmin[2] + header->miny*cs;
691 + bmax[0] = header->bmin[0] + (header->maxx+1)*cs;
692 + bmax[1] = header->bmax[1];
693 + bmax[2] = header->bmin[2] + (header->maxy+1)*cs;
694 694 }
695 695
696 696 void dtTileCache::getObstacleBounds(const struct dtTileCacheObstacle* ob, float* bmin, float* bmax) const
697 697 {
698 - bmin[0] = ob->pos[0] - ob->radius;
699 - bmin[1] = ob->pos[1];
700 - bmin[2] = ob->pos[2] - ob->radius;
701 - bmax[0] = ob->pos[0] + ob->radius;
702 - bmax[1] = ob->pos[1] + ob->height;
703 - bmax[2] = ob->pos[2] + ob->radius;
698 + bmin[0] = ob->pos[0] - ob->radius;
699 + bmin[1] = ob->pos[1];
700 + bmin[2] = ob->pos[2] - ob->radius;
701 + bmax[0] = ob->pos[0] + ob->radius;
702 + bmax[1] = ob->pos[1] + ob->height;
703 + bmax[2] = ob->pos[2] + ob->radius;
704 704 }