TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
RecastArea.cpp File Reference
#include <float.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Recast.h"
#include "RecastAlloc.h"
#include "RecastAssert.h"
+ Include dependency graph for RecastArea.cpp:

Macros

#define _USE_MATH_DEFINES
 

Functions

bool rcErodeWalkableArea (rcContext *ctx, int radius, rcCompactHeightfield &chf)
 
static void insertSort (unsigned char *a, const int n)
 
bool rcMedianFilterWalkableArea (rcContext *ctx, rcCompactHeightfield &chf)
 
void rcMarkBoxArea (rcContext *ctx, const float *bmin, const float *bmax, unsigned char areaId, rcCompactHeightfield &chf)
 
static int pointInPoly (int nvert, const float *verts, const float *p)
 
void rcMarkConvexPolyArea (rcContext *ctx, const float *verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield &chf)
 
int rcOffsetPoly (const float *verts, const int nverts, const float offset, float *outVerts, const int maxOutVerts)
 
void rcMarkCylinderArea (rcContext *ctx, const float *pos, const float r, const float h, unsigned char areaId, rcCompactHeightfield &chf)
 

Macro Definition Documentation

#define _USE_MATH_DEFINES

Function Documentation

static void insertSort ( unsigned char *  a,
const int  n 
)
static
224 {
225  int i, j;
226  for (i = 1; i < n; i++)
227  {
228  const unsigned char value = a[i];
229  for (j = i - 1; j >= 0 && a[j] > value; j--)
230  a[j+1] = a[j];
231  a[j+1] = value;
232  }
233 }
const FieldDescriptor value
Definition: descriptor.h:1522

+ Here is the caller graph for this function:

static int pointInPoly ( int  nvert,
const float *  verts,
const float *  p 
)
static
367 {
368  int i, j, c = 0;
369  for (i = 0, j = nvert-1; i < nvert; j = i++)
370  {
371  const float* vi = &verts[i*3];
372  const float* vj = &verts[j*3];
373  if (((vi[2] > p[2]) != (vj[2] > p[2])) &&
374  (p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) )
375  c = !c;
376  }
377  return c;
378 }

+ Here is the caller graph for this function:

bool rcErodeWalkableArea ( rcContext ctx,
int  radius,
rcCompactHeightfield chf 
)

Basically, any spans that are closer to a boundary or obstruction than the specified radius are marked as unwalkable.

This method is usually called immediately after the heightfield has been built.

See also
rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius
38 {
39  rcAssert(ctx);
40 
41  const int w = chf.width;
42  const int h = chf.height;
43 
45 
46  unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
47  if (!dist)
48  {
49  ctx->log(RC_LOG_ERROR, "erodeWalkableArea: Out of memory 'dist' (%d).", chf.spanCount);
50  return false;
51  }
52 
53  // Init distance.
54  memset(dist, 0xff, sizeof(unsigned char)*chf.spanCount);
55 
56  // Mark boundary cells.
57  for (int y = 0; y < h; ++y)
58  {
59  for (int x = 0; x < w; ++x)
60  {
61  const rcCompactCell& c = chf.cells[x+y*w];
62  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
63  {
64  if (chf.areas[i] == RC_NULL_AREA)
65  {
66  dist[i] = 0;
67  }
68  else
69  {
70  const rcCompactSpan& s = chf.spans[i];
71  int nc = 0;
72  for (int dir = 0; dir < 4; ++dir)
73  {
74  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
75  {
76  const int nx = x + rcGetDirOffsetX(dir);
77  const int ny = y + rcGetDirOffsetY(dir);
78  const int nidx = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir);
79  if (chf.areas[nidx] != RC_NULL_AREA)
80  {
81  nc++;
82  }
83  }
84  }
85  // At least one missing neighbour.
86  if (nc != 4)
87  dist[i] = 0;
88  }
89  }
90  }
91  }
92 
93  unsigned char nd;
94 
95  // Pass 1
96  for (int y = 0; y < h; ++y)
97  {
98  for (int x = 0; x < w; ++x)
99  {
100  const rcCompactCell& c = chf.cells[x+y*w];
101  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
102  {
103  const rcCompactSpan& s = chf.spans[i];
104 
105  if (rcGetCon(s, 0) != RC_NOT_CONNECTED)
106  {
107  // (-1,0)
108  const int ax = x + rcGetDirOffsetX(0);
109  const int ay = y + rcGetDirOffsetY(0);
110  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0);
111  const rcCompactSpan& as = chf.spans[ai];
112  nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
113  if (nd < dist[i])
114  dist[i] = nd;
115 
116  // (-1,-1)
117  if (rcGetCon(as, 3) != RC_NOT_CONNECTED)
118  {
119  const int aax = ax + rcGetDirOffsetX(3);
120  const int aay = ay + rcGetDirOffsetY(3);
121  const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 3);
122  nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
123  if (nd < dist[i])
124  dist[i] = nd;
125  }
126  }
127  if (rcGetCon(s, 3) != RC_NOT_CONNECTED)
128  {
129  // (0,-1)
130  const int ax = x + rcGetDirOffsetX(3);
131  const int ay = y + rcGetDirOffsetY(3);
132  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3);
133  const rcCompactSpan& as = chf.spans[ai];
134  nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
135  if (nd < dist[i])
136  dist[i] = nd;
137 
138  // (1,-1)
139  if (rcGetCon(as, 2) != RC_NOT_CONNECTED)
140  {
141  const int aax = ax + rcGetDirOffsetX(2);
142  const int aay = ay + rcGetDirOffsetY(2);
143  const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 2);
144  nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
145  if (nd < dist[i])
146  dist[i] = nd;
147  }
148  }
149  }
150  }
151  }
152 
153  // Pass 2
154  for (int y = h-1; y >= 0; --y)
155  {
156  for (int x = w-1; x >= 0; --x)
157  {
158  const rcCompactCell& c = chf.cells[x+y*w];
159  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
160  {
161  const rcCompactSpan& s = chf.spans[i];
162 
163  if (rcGetCon(s, 2) != RC_NOT_CONNECTED)
164  {
165  // (1,0)
166  const int ax = x + rcGetDirOffsetX(2);
167  const int ay = y + rcGetDirOffsetY(2);
168  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 2);
169  const rcCompactSpan& as = chf.spans[ai];
170  nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
171  if (nd < dist[i])
172  dist[i] = nd;
173 
174  // (1,1)
175  if (rcGetCon(as, 1) != RC_NOT_CONNECTED)
176  {
177  const int aax = ax + rcGetDirOffsetX(1);
178  const int aay = ay + rcGetDirOffsetY(1);
179  const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 1);
180  nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
181  if (nd < dist[i])
182  dist[i] = nd;
183  }
184  }
185  if (rcGetCon(s, 1) != RC_NOT_CONNECTED)
186  {
187  // (0,1)
188  const int ax = x + rcGetDirOffsetX(1);
189  const int ay = y + rcGetDirOffsetY(1);
190  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 1);
191  const rcCompactSpan& as = chf.spans[ai];
192  nd = (unsigned char)rcMin((int)dist[ai]+2, 255);
193  if (nd < dist[i])
194  dist[i] = nd;
195 
196  // (-1,1)
197  if (rcGetCon(as, 0) != RC_NOT_CONNECTED)
198  {
199  const int aax = ax + rcGetDirOffsetX(0);
200  const int aay = ay + rcGetDirOffsetY(0);
201  const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 0);
202  nd = (unsigned char)rcMin((int)dist[aai]+3, 255);
203  if (nd < dist[i])
204  dist[i] = nd;
205  }
206  }
207  }
208  }
209  }
210 
211  const unsigned char thr = (unsigned char)(radius*2);
212  for (int i = 0; i < chf.spanCount; ++i)
213  if (dist[i] < thr)
214  chf.areas[i] = RC_NULL_AREA;
215 
216  rcFree(dist);
217 
219 
220  return true;
221 }
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
static const int RC_NOT_CONNECTED
Definition: Recast.h:547
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
int rcGetDirOffsetY(int dir)
Definition: Recast.h:1048
rcCompactSpan * spans
Array of spans. [Size: spanCount].
Definition: Recast.h:320
T rcMin(T a, T b)
Definition: Recast.h:566
int rcGetCon(const rcCompactSpan &s, int dir)
Definition: Recast.h:1028
unsigned int index
Index to the first span in the column.
Definition: Recast.h:290
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
An error log entry.
Definition: Recast.h:31
void rcFree(void *ptr)
Definition: RecastAlloc.cpp:55
void * rcAlloc(int size, rcAllocHint hint)
Definition: RecastAlloc.cpp:44
int rcGetDirOffsetX(int dir)
Definition: Recast.h:1038
The time to erode the walkable area. (See: rcErodeWalkableArea)
Definition: Recast.h:65
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
G3D::int16 y
Definition: Vector2int16.h:38
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
int spanCount
The number of spans in the heightfield.
Definition: Recast.h:309
static const unsigned char RC_NULL_AREA
Definition: Recast.h:538
Memory used temporarily within a function.
Definition: RecastAlloc.h:27
void log(const rcLogCategory category, const char *format,...)
Definition: Recast.cpp:55
G3D::int16 x
Definition: Vector2int16.h:37
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void rcMarkBoxArea ( rcContext ctx,
const float *  bmin,
const float *  bmax,
unsigned char  areaId,
rcCompactHeightfield chf 
)

The value of spacial parameters are in world units.

See also
rcCompactHeightfield, rcMedianFilterWalkableArea
322 {
323  rcAssert(ctx);
324 
326 
327  int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
328  int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
329  int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
330  int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
331  int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
332  int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
333 
334  if (maxx < 0) return;
335  if (minx >= chf.width) return;
336  if (maxz < 0) return;
337  if (minz >= chf.height) return;
338 
339  if (minx < 0) minx = 0;
340  if (maxx >= chf.width) maxx = chf.width-1;
341  if (minz < 0) minz = 0;
342  if (maxz >= chf.height) maxz = chf.height-1;
343 
344  for (int z = minz; z <= maxz; ++z)
345  {
346  for (int x = minx; x <= maxx; ++x)
347  {
348  const rcCompactCell& c = chf.cells[x+z*chf.width];
349  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
350  {
351  rcCompactSpan& s = chf.spans[i];
352  if ((int)s.y >= miny && (int)s.y <= maxy)
353  {
354  if (chf.areas[i] != RC_NULL_AREA)
355  chf.areas[i] = areaId;
356  }
357  }
358  }
359  }
360 
362 
363 }
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
unsigned short y
The lower extent of the span. (Measured from the heightfield's base.)
Definition: Recast.h:297
rcCompactSpan * spans
Array of spans. [Size: spanCount].
Definition: Recast.h:320
unsigned int index
Index to the first span in the column.
Definition: Recast.h:290
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
The time to mark a box area. (See: rcMarkBoxArea)
Definition: Recast.h:67
G3D::int16 z
Definition: Vector3int16.h:46
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
float cs
The size of each cell. (On the xz-plane.)
Definition: Recast.h:317
float ch
The height of each cell. (The minimum increment along the y-axis.)
Definition: Recast.h:318
static const unsigned char RC_NULL_AREA
Definition: Recast.h:538
G3D::int16 x
Definition: Vector2int16.h:37
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135
float bmin[3]
The minimum bounds in world space. [(x, y, z)].
Definition: Recast.h:315

+ Here is the call graph for this function:

void rcMarkConvexPolyArea ( rcContext ctx,
const float *  verts,
const int  nverts,
const float  hmin,
const float  hmax,
unsigned char  areaId,
rcCompactHeightfield chf 
)

The value of spacial parameters are in world units.

The y-values of the polygon vertices are ignored. So the polygon is effectively projected onto the xz-plane at hmin, then extruded to hmax.

See also
rcCompactHeightfield, rcMedianFilterWalkableArea
391 {
392  rcAssert(ctx);
393 
395 
396  float bmin[3], bmax[3];
397  rcVcopy(bmin, verts);
398  rcVcopy(bmax, verts);
399  for (int i = 1; i < nverts; ++i)
400  {
401  rcVmin(bmin, &verts[i*3]);
402  rcVmax(bmax, &verts[i*3]);
403  }
404  bmin[1] = hmin;
405  bmax[1] = hmax;
406 
407  int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
408  int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
409  int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
410  int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
411  int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
412  int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
413 
414  if (maxx < 0) return;
415  if (minx >= chf.width) return;
416  if (maxz < 0) return;
417  if (minz >= chf.height) return;
418 
419  if (minx < 0) minx = 0;
420  if (maxx >= chf.width) maxx = chf.width-1;
421  if (minz < 0) minz = 0;
422  if (maxz >= chf.height) maxz = chf.height-1;
423 
424 
425  // TODO: Optimize.
426  for (int z = minz; z <= maxz; ++z)
427  {
428  for (int x = minx; x <= maxx; ++x)
429  {
430  const rcCompactCell& c = chf.cells[x+z*chf.width];
431  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
432  {
433  rcCompactSpan& s = chf.spans[i];
434  if (chf.areas[i] == RC_NULL_AREA)
435  continue;
436  if ((int)s.y >= miny && (int)s.y <= maxy)
437  {
438  float p[3];
439  p[0] = chf.bmin[0] + (x+0.5f)*chf.cs;
440  p[1] = 0;
441  p[2] = chf.bmin[2] + (z+0.5f)*chf.cs;
442 
443  if (pointInPoly(nverts, verts, p))
444  {
445  chf.areas[i] = areaId;
446  }
447  }
448  }
449  }
450  }
451 
453 }
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
unsigned short y
The lower extent of the span. (Measured from the heightfield's base.)
Definition: Recast.h:297
rcCompactSpan * spans
Array of spans. [Size: spanCount].
Definition: Recast.h:320
unsigned int index
Index to the first span in the column.
Definition: Recast.h:290
void rcVmin(float *mn, const float *v)
Definition: Recast.h:657
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
static int pointInPoly(int nvert, const float *verts, const float *p)
Definition: RecastArea.cpp:366
G3D::int16 z
Definition: Vector3int16.h:46
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
void rcVcopy(float *dest, const float *v)
Definition: Recast.h:677
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
float cs
The size of each cell. (On the xz-plane.)
Definition: Recast.h:317
float ch
The height of each cell. (The minimum increment along the y-axis.)
Definition: Recast.h:318
static const unsigned char RC_NULL_AREA
Definition: Recast.h:538
G3D::int16 x
Definition: Vector2int16.h:37
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135
The time to mark a convex polygon area. (See: rcMarkConvexPolyArea)
Definition: Recast.h:71
void rcVmax(float *mx, const float *v)
Definition: Recast.h:667
float bmin[3]
The minimum bounds in world space. [(x, y, z)].
Definition: Recast.h:315

+ Here is the call graph for this function:

void rcMarkCylinderArea ( rcContext ctx,
const float *  pos,
const float  r,
const float  h,
unsigned char  areaId,
rcCompactHeightfield chf 
)

The value of spacial parameters are in world units.

See also
rcCompactHeightfield, rcMedianFilterWalkableArea
541 {
542  rcAssert(ctx);
543 
545 
546  float bmin[3], bmax[3];
547  bmin[0] = pos[0] - r;
548  bmin[1] = pos[1];
549  bmin[2] = pos[2] - r;
550  bmax[0] = pos[0] + r;
551  bmax[1] = pos[1] + h;
552  bmax[2] = pos[2] + r;
553  const float r2 = r*r;
554 
555  int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
556  int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
557  int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
558  int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
559  int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
560  int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
561 
562  if (maxx < 0) return;
563  if (minx >= chf.width) return;
564  if (maxz < 0) return;
565  if (minz >= chf.height) return;
566 
567  if (minx < 0) minx = 0;
568  if (maxx >= chf.width) maxx = chf.width-1;
569  if (minz < 0) minz = 0;
570  if (maxz >= chf.height) maxz = chf.height-1;
571 
572 
573  for (int z = minz; z <= maxz; ++z)
574  {
575  for (int x = minx; x <= maxx; ++x)
576  {
577  const rcCompactCell& c = chf.cells[x+z*chf.width];
578  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
579  {
580  rcCompactSpan& s = chf.spans[i];
581 
582  if (chf.areas[i] == RC_NULL_AREA)
583  continue;
584 
585  if ((int)s.y >= miny && (int)s.y <= maxy)
586  {
587  const float sx = chf.bmin[0] + (x+0.5f)*chf.cs;
588  const float sz = chf.bmin[2] + (z+0.5f)*chf.cs;
589  const float dx = sx - pos[0];
590  const float dz = sz - pos[2];
591 
592  if (dx*dx + dz*dz < r2)
593  {
594  chf.areas[i] = areaId;
595  }
596  }
597  }
598  }
599  }
600 
602 }
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
unsigned short y
The lower extent of the span. (Measured from the heightfield's base.)
Definition: Recast.h:297
rcCompactSpan * spans
Array of spans. [Size: spanCount].
Definition: Recast.h:320
unsigned int index
Index to the first span in the column.
Definition: Recast.h:290
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
G3D::int16 z
Definition: Vector3int16.h:46
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
float cs
The size of each cell. (On the xz-plane.)
Definition: Recast.h:317
float ch
The height of each cell. (The minimum increment along the y-axis.)
Definition: Recast.h:318
static const unsigned char RC_NULL_AREA
Definition: Recast.h:538
G3D::int16 x
Definition: Vector2int16.h:37
The time to mark a cylinder area. (See: rcMarkCylinderArea)
Definition: Recast.h:69
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135
float bmin[3]
The minimum bounds in world space. [(x, y, z)].
Definition: Recast.h:315

+ Here is the call graph for this function:

bool rcMedianFilterWalkableArea ( rcContext ctx,
rcCompactHeightfield chf 
)

This filter is usually applied after applying area id's using functions such as rcMarkBoxArea, rcMarkConvexPolyArea, and rcMarkCylinderArea.

See also
rcCompactHeightfield
242 {
243  rcAssert(ctx);
244 
245  const int w = chf.width;
246  const int h = chf.height;
247 
249 
250  unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
251  if (!areas)
252  {
253  ctx->log(RC_LOG_ERROR, "medianFilterWalkableArea: Out of memory 'areas' (%d).", chf.spanCount);
254  return false;
255  }
256 
257  // Init distance.
258  memset(areas, 0xff, sizeof(unsigned char)*chf.spanCount);
259 
260  for (int y = 0; y < h; ++y)
261  {
262  for (int x = 0; x < w; ++x)
263  {
264  const rcCompactCell& c = chf.cells[x+y*w];
265  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
266  {
267  const rcCompactSpan& s = chf.spans[i];
268  if (chf.areas[i] == RC_NULL_AREA)
269  {
270  areas[i] = chf.areas[i];
271  continue;
272  }
273 
274  unsigned char nei[9];
275  for (int j = 0; j < 9; ++j)
276  nei[j] = chf.areas[i];
277 
278  for (int dir = 0; dir < 4; ++dir)
279  {
280  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
281  {
282  const int ax = x + rcGetDirOffsetX(dir);
283  const int ay = y + rcGetDirOffsetY(dir);
284  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
285  if (chf.areas[ai] != RC_NULL_AREA)
286  nei[dir*2+0] = chf.areas[ai];
287 
288  const rcCompactSpan& as = chf.spans[ai];
289  const int dir2 = (dir+1) & 0x3;
290  if (rcGetCon(as, dir2) != RC_NOT_CONNECTED)
291  {
292  const int ax2 = ax + rcGetDirOffsetX(dir2);
293  const int ay2 = ay + rcGetDirOffsetY(dir2);
294  const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
295  if (chf.areas[ai2] != RC_NULL_AREA)
296  nei[dir*2+1] = chf.areas[ai2];
297  }
298  }
299  }
300  insertSort(nei, 9);
301  areas[i] = nei[4];
302  }
303  }
304  }
305 
306  memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount);
307 
308  rcFree(areas);
309 
311 
312  return true;
313 }
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
static const int RC_NOT_CONNECTED
Definition: Recast.h:547
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
int rcGetDirOffsetY(int dir)
Definition: Recast.h:1048
rcCompactSpan * spans
Array of spans. [Size: spanCount].
Definition: Recast.h:320
int rcGetCon(const rcCompactSpan &s, int dir)
Definition: Recast.h:1028
unsigned int index
Index to the first span in the column.
Definition: Recast.h:290
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
An error log entry.
Definition: Recast.h:31
static void insertSort(unsigned char *a, const int n)
Definition: RecastArea.cpp:223
void rcFree(void *ptr)
Definition: RecastAlloc.cpp:55
void * rcAlloc(int size, rcAllocHint hint)
Definition: RecastAlloc.cpp:44
int rcGetDirOffsetX(int dir)
Definition: Recast.h:1038
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
G3D::int16 y
Definition: Vector2int16.h:38
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
int spanCount
The number of spans in the heightfield.
Definition: Recast.h:309
static const unsigned char RC_NULL_AREA
Definition: Recast.h:538
Memory used temporarily within a function.
Definition: RecastAlloc.h:27
void log(const rcLogCategory category, const char *format,...)
Definition: Recast.cpp:55
The time to apply the median filter. (See: rcMedianFilterWalkableArea)
Definition: Recast.h:57
G3D::int16 x
Definition: Vector2int16.h:37
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135

+ Here is the call graph for this function:

int rcOffsetPoly ( const float *  verts,
const int  nverts,
const float  offset,
float *  outVerts,
const int  maxOutVerts 
)

Helper function to offset voncex polygons for rcMarkConvexPolyArea.

Parameters
[in]vertsThe vertices of the polygon [Form: (x, y, z) * nverts]
[in]nvertsThe number of vertices in the polygon.
[out]outVertsThe offset vertices (should hold up to 2 * nverts) [Form: (x, y, z) * return value]
[in]maxOutVertsThe max number of vertices that can be stored to outVerts.
Returns
Number of vertices in the offset polygon or 0 if too few vertices in outVerts.
457 {
458  const float MITER_LIMIT = 1.20f;
459 
460  int n = 0;
461 
462  for (int i = 0; i < nverts; i++)
463  {
464  const int a = (i+nverts-1) % nverts;
465  const int b = i;
466  const int c = (i+1) % nverts;
467  const float* va = &verts[a*3];
468  const float* vb = &verts[b*3];
469  const float* vc = &verts[c*3];
470  float dx0 = vb[0] - va[0];
471  float dy0 = vb[2] - va[2];
472  float d0 = dx0*dx0 + dy0*dy0;
473  if (d0 > 1e-6f)
474  {
475  d0 = 1.0f/rcSqrt(d0);
476  dx0 *= d0;
477  dy0 *= d0;
478  }
479  float dx1 = vc[0] - vb[0];
480  float dy1 = vc[2] - vb[2];
481  float d1 = dx1*dx1 + dy1*dy1;
482  if (d1 > 1e-6f)
483  {
484  d1 = 1.0f/rcSqrt(d1);
485  dx1 *= d1;
486  dy1 *= d1;
487  }
488  const float dlx0 = -dy0;
489  const float dly0 = dx0;
490  const float dlx1 = -dy1;
491  const float dly1 = dx1;
492  float cross = dx1*dy0 - dx0*dy1;
493  float dmx = (dlx0 + dlx1) * 0.5f;
494  float dmy = (dly0 + dly1) * 0.5f;
495  float dmr2 = dmx*dmx + dmy*dmy;
496  bool bevel = dmr2 * MITER_LIMIT*MITER_LIMIT < 1.0f;
497  if (dmr2 > 1e-6f)
498  {
499  const float scale = 1.0f / dmr2;
500  dmx *= scale;
501  dmy *= scale;
502  }
503 
504  if (bevel && cross < 0.0f)
505  {
506  if (n+2 >= maxOutVerts)
507  return 0;
508  float d = (1.0f - (dx0*dx1 + dy0*dy1))*0.5f;
509  outVerts[n*3+0] = vb[0] + (-dlx0+dx0*d)*offset;
510  outVerts[n*3+1] = vb[1];
511  outVerts[n*3+2] = vb[2] + (-dly0+dy0*d)*offset;
512  n++;
513  outVerts[n*3+0] = vb[0] + (-dlx1-dx1*d)*offset;
514  outVerts[n*3+1] = vb[1];
515  outVerts[n*3+2] = vb[2] + (-dly1-dy1*d)*offset;
516  n++;
517  }
518  else
519  {
520  if (n+1 >= maxOutVerts)
521  return 0;
522  outVerts[n*3+0] = vb[0] - dmx*offset;
523  outVerts[n*3+1] = vb[1];
524  outVerts[n*3+2] = vb[2] - dmy*offset;
525  n++;
526  }
527  }
528 
529  return n;
530 }
float rcSqrt(float x)
Definition: Recast.cpp:30
Vector3 cross(const Vector3 &v1, const Vector3 &v2)
Definition: vectorMath.h:144

+ Here is the call graph for this function: