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

Classes

struct  rcContourHole
 
struct  rcContourRegion
 
struct  rcPotentialDiagonal
 

Macros

#define _USE_MATH_DEFINES
 

Functions

static int getCornerHeight (int x, int y, int i, int dir, const rcCompactHeightfield &chf, bool &isBorderVertex)
 
static void walkContour (int x, int y, int i, rcCompactHeightfield &chf, unsigned char *flags, rcIntArray &points)
 
static float distancePtSeg (const int x, const int z, const int px, const int pz, const int qx, const int qz)
 
static void simplifyContour (rcIntArray &points, rcIntArray &simplified, const float maxError, const int maxEdgeLen, const int buildFlags)
 
static int calcAreaOfPolygon2D (const int *verts, const int nverts)
 
int prev (int i, int n)
 
int next (int i, int n)
 
int area2 (const int *a, const int *b, const int *c)
 
bool xorb (bool x, bool y)
 
bool left (const int *a, const int *b, const int *c)
 
bool leftOn (const int *a, const int *b, const int *c)
 
bool collinear (const int *a, const int *b, const int *c)
 
static bool intersectProp (const int *a, const int *b, const int *c, const int *d)
 
static bool between (const int *a, const int *b, const int *c)
 
static bool intersect (const int *a, const int *b, const int *c, const int *d)
 
static bool vequal (const int *a, const int *b)
 
static bool intersectSegCountour (const int *d0, const int *d1, int i, int n, const int *verts)
 
static bool inCone (int i, int n, const int *verts, const int *pj)
 
static void removeDegenerateSegments (rcIntArray &simplified)
 
static bool mergeContours (rcContour &ca, rcContour &cb, int ia, int ib)
 
static void findLeftMostVertex (rcContour *contour, int *minx, int *minz, int *leftmost)
 
static int compareHoles (const void *va, const void *vb)
 
static int compareDiagDist (const void *va, const void *vb)
 
static void mergeRegionHoles (rcContext *ctx, rcContourRegion &region)
 
bool rcBuildContours (rcContext *ctx, rcCompactHeightfield &chf, const float maxError, const int maxEdgeLen, rcContourSet &cset, const int buildFlags)
 

Macro Definition Documentation

#define _USE_MATH_DEFINES

Function Documentation

int area2 ( const int *  a,
const int *  b,
const int *  c 
)
inline
472 {
473  return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]);
474 }

+ Here is the caller graph for this function:

static bool between ( const int *  a,
const int *  b,
const int *  c 
)
static
518 {
519  if (!collinear(a, b, c))
520  return false;
521  // If ab not vertical, check betweenness on x; else on y.
522  if (a[0] != b[0])
523  return ((a[0] <= c[0]) && (c[0] <= b[0])) || ((a[0] >= c[0]) && (c[0] >= b[0]));
524  else
525  return ((a[2] <= c[2]) && (c[2] <= b[2])) || ((a[2] >= c[2]) && (c[2] >= b[2]));
526 }
bool collinear(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:497

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int calcAreaOfPolygon2D ( const int *  verts,
const int  nverts 
)
static
455 {
456  int area = 0;
457  for (int i = 0, j = nverts-1; i < nverts; j=i++)
458  {
459  const int* vi = &verts[i*4];
460  const int* vj = &verts[j*4];
461  area += vi[0] * vj[2] - vj[0] * vi[2];
462  }
463  return (area+1) / 2;
464 }

+ Here is the caller graph for this function:

bool collinear ( const int *  a,
const int *  b,
const int *  c 
)
inline
498 {
499  return area2(a, b, c) == 0;
500 }
int area2(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:471

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int compareDiagDist ( const void *  va,
const void *  vb 
)
static
711 {
712  const rcPotentialDiagonal* a = (const rcPotentialDiagonal*)va;
713  const rcPotentialDiagonal* b = (const rcPotentialDiagonal*)vb;
714  if (a->dist < b->dist)
715  return -1;
716  if (a->dist > b->dist)
717  return 1;
718  return 0;
719 }
Definition: RecastContour.cpp:663
int dist
Definition: RecastContour.cpp:666

+ Here is the caller graph for this function:

static int compareHoles ( const void *  va,
const void *  vb 
)
static
689 {
690  const rcContourHole* a = (const rcContourHole*)va;
691  const rcContourHole* b = (const rcContourHole*)vb;
692  if (a->minx == b->minx)
693  {
694  if (a->minz < b->minz)
695  return -1;
696  if (a->minz > b->minz)
697  return 1;
698  }
699  else
700  {
701  if (a->minx < b->minx)
702  return -1;
703  if (a->minx > b->minx)
704  return 1;
705  }
706  return 0;
707 }
int minz
Definition: RecastContour.cpp:653
Definition: RecastContour.cpp:650
int minx
Definition: RecastContour.cpp:653

+ Here is the caller graph for this function:

static float distancePtSeg ( const int  x,
const int  z,
const int  px,
const int  pz,
const int  qx,
const int  qz 
)
static
190 {
191  float pqx = (float)(qx - px);
192  float pqz = (float)(qz - pz);
193  float dx = (float)(x - px);
194  float dz = (float)(z - pz);
195  float d = pqx*pqx + pqz*pqz;
196  float t = pqx*dx + pqz*dz;
197  if (d > 0)
198  t /= d;
199  if (t < 0)
200  t = 0;
201  else if (t > 1)
202  t = 1;
203 
204  dx = px + t*pqx - x;
205  dz = pz + t*pqz - z;
206 
207  return dx*dx + dz*dz;
208 }
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the caller graph for this function:

static void findLeftMostVertex ( rcContour contour,
int *  minx,
int *  minz,
int *  leftmost 
)
static
671 {
672  *minx = contour->verts[0];
673  *minz = contour->verts[2];
674  *leftmost = 0;
675  for (int i = 1; i < contour->nverts; i++)
676  {
677  const int x = contour->verts[i*4+0];
678  const int z = contour->verts[i*4+2];
679  if (x < *minx || (x == *minx && z < *minz))
680  {
681  *minx = x;
682  *minz = z;
683  *leftmost = i;
684  }
685  }
686 }
int nverts
The number of vertices in the simplified contour.
Definition: Recast.h:359
int * verts
Simplified contour vertex and connection data. [Size: 4 * nverts].
Definition: Recast.h:358
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the caller graph for this function:

static int getCornerHeight ( int  x,
int  y,
int  i,
int  dir,
const rcCompactHeightfield chf,
bool isBorderVertex 
)
static
32 {
33  const rcCompactSpan& s = chf.spans[i];
34  int ch = (int)s.y;
35  int dirp = (dir+1) & 0x3;
36 
37  unsigned int regs[4] = {0,0,0,0};
38 
39  // Combine region and area codes in order to prevent
40  // border vertices which are in between two areas to be removed.
41  regs[0] = chf.spans[i].reg | (chf.areas[i] << 16);
42 
43  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
44  {
45  const int ax = x + rcGetDirOffsetX(dir);
46  const int ay = y + rcGetDirOffsetY(dir);
47  const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
48  const rcCompactSpan& as = chf.spans[ai];
49  ch = rcMax(ch, (int)as.y);
50  regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16);
51  if (rcGetCon(as, dirp) != RC_NOT_CONNECTED)
52  {
53  const int ax2 = ax + rcGetDirOffsetX(dirp);
54  const int ay2 = ay + rcGetDirOffsetY(dirp);
55  const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dirp);
56  const rcCompactSpan& as2 = chf.spans[ai2];
57  ch = rcMax(ch, (int)as2.y);
58  regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
59  }
60  }
61  if (rcGetCon(s, dirp) != RC_NOT_CONNECTED)
62  {
63  const int ax = x + rcGetDirOffsetX(dirp);
64  const int ay = y + rcGetDirOffsetY(dirp);
65  const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dirp);
66  const rcCompactSpan& as = chf.spans[ai];
67  ch = rcMax(ch, (int)as.y);
68  regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16);
69  if (rcGetCon(as, dir) != RC_NOT_CONNECTED)
70  {
71  const int ax2 = ax + rcGetDirOffsetX(dir);
72  const int ay2 = ay + rcGetDirOffsetY(dir);
73  const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dir);
74  const rcCompactSpan& as2 = chf.spans[ai2];
75  ch = rcMax(ch, (int)as2.y);
76  regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16);
77  }
78  }
79 
80  // Check if the vertex is special edge vertex, these vertices will be removed later.
81  for (int j = 0; j < 4; ++j)
82  {
83  const int a = j;
84  const int b = (j+1) & 0x3;
85  const int c = (j+2) & 0x3;
86  const int d = (j+3) & 0x3;
87 
88  // The vertex is a border vertex there are two same exterior cells in a row,
89  // followed by two interior cells and none of the regions are out of bounds.
90  const bool twoSameExts = (regs[a] & regs[b] & RC_BORDER_REG) != 0 && regs[a] == regs[b];
91  const bool twoInts = ((regs[c] | regs[d]) & RC_BORDER_REG) == 0;
92  const bool intsSameArea = (regs[c]>>16) == (regs[d]>>16);
93  const bool noZeros = regs[a] != 0 && regs[b] != 0 && regs[c] != 0 && regs[d] != 0;
94  if (twoSameExts && twoInts && intsSameArea && noZeros)
95  {
96  isBorderVertex = true;
97  break;
98  }
99  }
100 
101  return ch;
102 }
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
static const int RC_NOT_CONNECTED
Definition: Recast.h:547
unsigned short reg
The id of the region the span belongs to. (Or zero if not in a region.)
Definition: Recast.h:298
rcCompactCell * cells
Array of cells. [Size: width*height].
Definition: Recast.h:319
int rcGetDirOffsetY(int dir)
Definition: Recast.h:1048
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
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
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
T rcMax(T a, T b)
Definition: Recast.h:572
G3D::int16 x
Definition: Vector2int16.h:37
static const unsigned short RC_BORDER_REG
Definition: Recast.h:498

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool inCone ( int  i,
int  n,
const int *  verts,
const int *  pj 
)
static
566 {
567  const int* pi = &verts[i * 4];
568  const int* pi1 = &verts[next(i, n) * 4];
569  const int* pin1 = &verts[prev(i, n) * 4];
570 
571  // If P[i] is a convex vertex [ i+1 left or on (i-1,i) ].
572  if (leftOn(pin1, pi, pi1))
573  return left(pi, pj, pin1) && left(pj, pi, pi1);
574  // Assume (i-1,i,i+1) not collinear.
575  // else P[i] is reflex.
576  return !(leftOn(pi, pj, pi1) && leftOn(pj, pi, pin1));
577 }
int next(int i, int n)
Definition: RecastContour.cpp:469
double pi()
Definition: g3dmath.h:147
bool left(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:487
int prev(int i, int n)
Definition: RecastContour.cpp:468
bool leftOn(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:492

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool intersect ( const int *  a,
const int *  b,
const int *  c,
const int *  d 
)
static
530 {
531  if (intersectProp(a, b, c, d))
532  return true;
533  else if (between(a, b, c) || between(a, b, d) ||
534  between(c, d, a) || between(c, d, b))
535  return true;
536  else
537  return false;
538 }
static bool between(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:517
static bool intersectProp(const int *a, const int *b, const int *c, const int *d)
Definition: RecastContour.cpp:505

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool intersectProp ( const int *  a,
const int *  b,
const int *  c,
const int *  d 
)
static
506 {
507  // Eliminate improper cases.
508  if (collinear(a,b,c) || collinear(a,b,d) ||
509  collinear(c,d,a) || collinear(c,d,b))
510  return false;
511 
512  return xorb(left(a,b,c), left(a,b,d)) && xorb(left(c,d,a), left(c,d,b));
513 }
bool collinear(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:497
bool left(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:487
bool xorb(bool x, bool y)
Definition: RecastContour.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool intersectSegCountour ( const int *  d0,
const int *  d1,
int  i,
int  n,
const int *  verts 
)
static
546 {
547  // For each edge (k,k+1) of P
548  for (int k = 0; k < n; k++)
549  {
550  int k1 = next(k, n);
551  // Skip edges incident to i.
552  if (i == k || i == k1)
553  continue;
554  const int* p0 = &verts[k * 4];
555  const int* p1 = &verts[k1 * 4];
556  if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1))
557  continue;
558 
559  if (intersect(d0, d1, p0, p1))
560  return true;
561  }
562  return false;
563 }
int next(int i, int n)
Definition: RecastContour.cpp:469
static bool intersect(const int *a, const int *b, const int *c, const int *d)
Definition: RecastContour.cpp:529
static bool vequal(const int *a, const int *b)
Definition: RecastContour.cpp:540

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool left ( const int *  a,
const int *  b,
const int *  c 
)
inline
488 {
489  return area2(a, b, c) < 0;
490 }
int area2(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:471

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool leftOn ( const int *  a,
const int *  b,
const int *  c 
)
inline
493 {
494  return area2(a, b, c) <= 0;
495 }
int area2(const int *a, const int *b, const int *c)
Definition: RecastContour.cpp:471

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool mergeContours ( rcContour ca,
rcContour cb,
int  ia,
int  ib 
)
static
607 {
608  const int maxVerts = ca.nverts + cb.nverts + 2;
609  int* verts = (int*)rcAlloc(sizeof(int)*maxVerts*4, RC_ALLOC_PERM);
610  if (!verts)
611  return false;
612 
613  int nv = 0;
614 
615  // Copy contour A.
616  for (int i = 0; i <= ca.nverts; ++i)
617  {
618  int* dst = &verts[nv*4];
619  const int* src = &ca.verts[((ia+i)%ca.nverts)*4];
620  dst[0] = src[0];
621  dst[1] = src[1];
622  dst[2] = src[2];
623  dst[3] = src[3];
624  nv++;
625  }
626 
627  // Copy contour B
628  for (int i = 0; i <= cb.nverts; ++i)
629  {
630  int* dst = &verts[nv*4];
631  const int* src = &cb.verts[((ib+i)%cb.nverts)*4];
632  dst[0] = src[0];
633  dst[1] = src[1];
634  dst[2] = src[2];
635  dst[3] = src[3];
636  nv++;
637  }
638 
639  rcFree(ca.verts);
640  ca.verts = verts;
641  ca.nverts = nv;
642 
643  rcFree(cb.verts);
644  cb.verts = 0;
645  cb.nverts = 0;
646 
647  return true;
648 }
int nverts
The number of vertices in the simplified contour.
Definition: Recast.h:359
int * verts
Simplified contour vertex and connection data. [Size: 4 * nverts].
Definition: Recast.h:358
void rcFree(void *ptr)
Definition: RecastAlloc.cpp:55
void * rcAlloc(int size, rcAllocHint hint)
Definition: RecastAlloc.cpp:44
Memory will persist after a function call.
Definition: RecastAlloc.h:26

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void mergeRegionHoles ( rcContext ctx,
rcContourRegion region 
)
static
723 {
724  // Sort holes from left to right.
725  for (int i = 0; i < region.nholes; i++)
726  findLeftMostVertex(region.holes[i].contour, &region.holes[i].minx, &region.holes[i].minz, &region.holes[i].leftmost);
727 
728  qsort(region.holes, region.nholes, sizeof(rcContourHole), compareHoles);
729 
730  int maxVerts = region.outline->nverts;
731  for (int i = 0; i < region.nholes; i++)
732  maxVerts += region.holes[i].contour->nverts;
733 
735  if (!diags)
736  {
737  ctx->log(RC_LOG_WARNING, "mergeRegionHoles: Failed to allocated diags %d.", maxVerts);
738  return;
739  }
740 
741  rcContour* outline = region.outline;
742 
743  // Merge holes into the outline one by one.
744  for (int i = 0; i < region.nholes; i++)
745  {
746  rcContour* hole = region.holes[i].contour;
747 
748  int index = -1;
749  int bestVertex = region.holes[i].leftmost;
750  for (int iter = 0; iter < hole->nverts; iter++)
751  {
752  // Find potential diagonals.
753  // The 'best' vertex must be in the cone described by 3 cosequtive vertices of the outline.
754  // ..o j-1
755  // |
756  // | * best
757  // |
758  // j o-----o j+1
759  // :
760  int ndiags = 0;
761  const int* corner = &hole->verts[bestVertex*4];
762  for (int j = 0; j < outline->nverts; j++)
763  {
764  if (inCone(j, outline->nverts, outline->verts, corner))
765  {
766  int dx = outline->verts[j*4+0] - corner[0];
767  int dz = outline->verts[j*4+2] - corner[2];
768  diags[ndiags].vert = j;
769  diags[ndiags].dist = dx*dx + dz*dz;
770  ndiags++;
771  }
772  }
773  // Sort potential diagonals by distance, we want to make the connection as short as possible.
774  qsort(diags, ndiags, sizeof(rcPotentialDiagonal), compareDiagDist);
775 
776  // Find a diagonal that is not intersecting the outline not the remaining holes.
777  index = -1;
778  for (int j = 0; j < ndiags; j++)
779  {
780  const int* pt = &outline->verts[diags[j].vert*4];
781  bool intersect = intersectSegCountour(pt, corner, diags[i].vert, outline->nverts, outline->verts);
782  for (int k = i; k < region.nholes && !intersect; k++)
783  intersect |= intersectSegCountour(pt, corner, -1, region.holes[k].contour->nverts, region.holes[k].contour->verts);
784  if (!intersect)
785  {
786  index = diags[j].vert;
787  break;
788  }
789  }
790  // If found non-intersecting diagonal, stop looking.
791  if (index != -1)
792  break;
793  // All the potential diagonals for the current vertex were intersecting, try next vertex.
794  bestVertex = (bestVertex + 1) % hole->nverts;
795  }
796 
797  if (index == -1)
798  {
799  ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to find merge points for %p and %p.", region.outline, hole);
800  continue;
801  }
802  if (!mergeContours(*region.outline, *hole, index, bestVertex))
803  {
804  ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to merge contours %p and %p.", region.outline, hole);
805  continue;
806  }
807  }
808 }
static bool inCone(int i, int n, const int *verts, const int *pj)
Definition: RecastContour.cpp:565
int nverts
The number of vertices in the simplified contour.
Definition: Recast.h:359
int * verts
Simplified contour vertex and connection data. [Size: 4 * nverts].
Definition: Recast.h:358
static bool intersect(const int *a, const int *b, const int *c, const int *d)
Definition: RecastContour.cpp:529
Represents a simple, non-overlapping contour in field space.
Definition: Recast.h:356
Definition: RecastAlloc.h:105
void * rcAlloc(int size, rcAllocHint hint)
Definition: RecastAlloc.cpp:44
static void findLeftMostVertex(rcContour *contour, int *minx, int *minz, int *leftmost)
Definition: RecastContour.cpp:670
static bool mergeContours(rcContour &ca, rcContour &cb, int ia, int ib)
Definition: RecastContour.cpp:606
int minz
Definition: RecastContour.cpp:653
rcContour * contour
Definition: RecastContour.cpp:652
int leftmost
Definition: RecastContour.cpp:653
static int compareDiagDist(const void *va, const void *vb)
Definition: RecastContour.cpp:710
rcContourHole * holes
Definition: RecastContour.cpp:659
Definition: RecastContour.cpp:650
Definition: RecastContour.cpp:663
Memory used temporarily within a function.
Definition: RecastAlloc.h:27
void log(const rcLogCategory category, const char *format,...)
Definition: Recast.cpp:55
int minx
Definition: RecastContour.cpp:653
static bool intersectSegCountour(const int *d0, const int *d1, int i, int n, const int *verts)
Definition: RecastContour.cpp:545
int nholes
Definition: RecastContour.cpp:660
static int compareHoles(const void *va, const void *vb)
Definition: RecastContour.cpp:688
rcContour * outline
Definition: RecastContour.cpp:658
A warning log entry.
Definition: Recast.h:30

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int next ( int  i,
int  n 
)
inline
469 { return i+1 < n ? i+1 : 0; }

+ Here is the caller graph for this function:

int prev ( int  i,
int  n 
)
inline
468 { return i-1 >= 0 ? i-1 : n-1; }

+ Here is the caller graph for this function:

bool rcBuildContours ( rcContext ctx,
rcCompactHeightfield chf,
const float  maxError,
const int  maxEdgeLen,
rcContourSet cset,
const int  buildFlags 
)

The raw contours will match the region outlines exactly. The maxError and maxEdgeLen parameters control how closely the simplified contours will match the raw contours.

Simplified contours are generated such that the vertices for portals between areas match up. (They are considered mandatory vertices.)

Setting maxEdgeLength to zero will disabled the edge length feature.

See the rcConfig documentation for more information on the configuration parameters.

See also
rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
827 {
828  rcAssert(ctx);
829 
830  const int w = chf.width;
831  const int h = chf.height;
832  const int borderSize = chf.borderSize;
833 
835 
836  rcVcopy(cset.bmin, chf.bmin);
837  rcVcopy(cset.bmax, chf.bmax);
838  if (borderSize > 0)
839  {
840  // If the heightfield was build with bordersize, remove the offset.
841  const float pad = borderSize*chf.cs;
842  cset.bmin[0] += pad;
843  cset.bmin[2] += pad;
844  cset.bmax[0] -= pad;
845  cset.bmax[2] -= pad;
846  }
847  cset.cs = chf.cs;
848  cset.ch = chf.ch;
849  cset.width = chf.width - chf.borderSize*2;
850  cset.height = chf.height - chf.borderSize*2;
851  cset.borderSize = chf.borderSize;
852 
853  int maxContours = rcMax((int)chf.maxRegions, 8);
854  cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
855  if (!cset.conts)
856  return false;
857  cset.nconts = 0;
858 
859  rcScopedDelete<unsigned char> flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
860  if (!flags)
861  {
862  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount);
863  return false;
864  }
865 
867 
868  // Mark boundaries.
869  for (int y = 0; y < h; ++y)
870  {
871  for (int x = 0; x < w; ++x)
872  {
873  const rcCompactCell& c = chf.cells[x+y*w];
874  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
875  {
876  unsigned char res = 0;
877  const rcCompactSpan& s = chf.spans[i];
878  if (!chf.spans[i].reg || (chf.spans[i].reg & RC_BORDER_REG))
879  {
880  flags[i] = 0;
881  continue;
882  }
883  for (int dir = 0; dir < 4; ++dir)
884  {
885  unsigned short r = 0;
886  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
887  {
888  const int ax = x + rcGetDirOffsetX(dir);
889  const int ay = y + rcGetDirOffsetY(dir);
890  const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
891  r = chf.spans[ai].reg;
892  }
893  if (r == chf.spans[i].reg)
894  res |= (1 << dir);
895  }
896  flags[i] = res ^ 0xf; // Inverse, mark non connected edges.
897  }
898  }
899  }
900 
902 
903  rcIntArray verts(256);
904  rcIntArray simplified(64);
905 
906  for (int y = 0; y < h; ++y)
907  {
908  for (int x = 0; x < w; ++x)
909  {
910  const rcCompactCell& c = chf.cells[x+y*w];
911  for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
912  {
913  if (flags[i] == 0 || flags[i] == 0xf)
914  {
915  flags[i] = 0;
916  continue;
917  }
918  const unsigned short reg = chf.spans[i].reg;
919  if (!reg || (reg & RC_BORDER_REG))
920  continue;
921  const unsigned char area = chf.areas[i];
922 
923  verts.resize(0);
924  simplified.resize(0);
925 
927  walkContour(x, y, i, chf, flags, verts);
929 
931  simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
932  removeDegenerateSegments(simplified);
934 
935 
936  // Store region->contour remap info.
937  // Create contour.
938  if (simplified.size()/4 >= 3)
939  {
940  if (cset.nconts >= maxContours)
941  {
942  // Allocate more contours.
943  // This happens when a region has holes.
944  const int oldMax = maxContours;
945  maxContours *= 2;
946  rcContour* newConts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
947  for (int j = 0; j < cset.nconts; ++j)
948  {
949  newConts[j] = cset.conts[j];
950  // Reset source pointers to prevent data deletion.
951  cset.conts[j].verts = 0;
952  cset.conts[j].rverts = 0;
953  }
954  rcFree(cset.conts);
955  cset.conts = newConts;
956 
957  ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours);
958  }
959 
960  rcContour* cont = &cset.conts[cset.nconts++];
961 
962  cont->nverts = simplified.size()/4;
963  cont->verts = (int*)rcAlloc(sizeof(int)*cont->nverts*4, RC_ALLOC_PERM);
964  if (!cont->verts)
965  {
966  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts);
967  return false;
968  }
969  memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4);
970  if (borderSize > 0)
971  {
972  // If the heightfield was build with bordersize, remove the offset.
973  for (int j = 0; j < cont->nverts; ++j)
974  {
975  int* v = &cont->verts[j*4];
976  v[0] -= borderSize;
977  v[2] -= borderSize;
978  }
979  }
980 
981  cont->nrverts = verts.size()/4;
982  cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM);
983  if (!cont->rverts)
984  {
985  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts);
986  return false;
987  }
988  memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
989  if (borderSize > 0)
990  {
991  // If the heightfield was build with bordersize, remove the offset.
992  for (int j = 0; j < cont->nrverts; ++j)
993  {
994  int* v = &cont->rverts[j*4];
995  v[0] -= borderSize;
996  v[2] -= borderSize;
997  }
998  }
999 
1000  cont->reg = reg;
1001  cont->area = area;
1002  }
1003  }
1004  }
1005  }
1006 
1007  // Merge holes if needed.
1008  if (cset.nconts > 0)
1009  {
1010  // Calculate winding of all polygons.
1011  rcScopedDelete<char> winding = (char*)rcAlloc(sizeof(char)*cset.nconts, RC_ALLOC_TEMP);
1012  if (!winding)
1013  {
1014  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'hole' (%d).", cset.nconts);
1015  return false;
1016  }
1017  int nholes = 0;
1018  for (int i = 0; i < cset.nconts; ++i)
1019  {
1020  rcContour& cont = cset.conts[i];
1021  // If the contour is wound backwards, it is a hole.
1022  winding[i] = calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0 ? -1 : 1;
1023  if (winding[i] < 0)
1024  nholes++;
1025  }
1026 
1027  if (nholes > 0)
1028  {
1029  // Collect outline contour and holes contours per region.
1030  // We assume that there is one outline and multiple holes.
1031  const int nregions = chf.maxRegions+1;
1033  if (!regions)
1034  {
1035  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'regions' (%d).", nregions);
1036  return false;
1037  }
1038  memset(regions, 0, sizeof(rcContourRegion)*nregions);
1039 
1041  if (!holes)
1042  {
1043  ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'holes' (%d).", cset.nconts);
1044  return false;
1045  }
1046  memset(holes, 0, sizeof(rcContourHole)*cset.nconts);
1047 
1048  for (int i = 0; i < cset.nconts; ++i)
1049  {
1050  rcContour& cont = cset.conts[i];
1051  // Positively would contours are outlines, negative holes.
1052  if (winding[i] > 0)
1053  {
1054  if (regions[cont.reg].outline)
1055  ctx->log(RC_LOG_ERROR, "rcBuildContours: Multiple outlines for region %d.", cont.reg);
1056  regions[cont.reg].outline = &cont;
1057  }
1058  else
1059  {
1060  regions[cont.reg].nholes++;
1061  }
1062  }
1063  int index = 0;
1064  for (int i = 0; i < nregions; i++)
1065  {
1066  if (regions[i].nholes > 0)
1067  {
1068  regions[i].holes = &holes[index];
1069  index += regions[i].nholes;
1070  regions[i].nholes = 0;
1071  }
1072  }
1073  for (int i = 0; i < cset.nconts; ++i)
1074  {
1075  rcContour& cont = cset.conts[i];
1076  rcContourRegion& reg = regions[cont.reg];
1077  if (winding[i] < 0)
1078  reg.holes[reg.nholes++].contour = &cont;
1079  }
1080 
1081  // Finally merge each regions holes into the outline.
1082  for (int i = 0; i < nregions; i++)
1083  {
1084  rcContourRegion& reg = regions[i];
1085  if (!reg.nholes) continue;
1086 
1087  if (reg.outline)
1088  {
1089  mergeRegionHoles(ctx, reg);
1090  }
1091  else
1092  {
1093  // The region does not have an outline.
1094  // This can happen if the contour becaomes selfoverlapping because of
1095  // too aggressive simplification settings.
1096  ctx->log(RC_LOG_ERROR, "rcBuildContours: Bad outline for region %d, contour simplification is likely too aggressive.", i);
1097  }
1098  }
1099  }
1100 
1101  }
1102 
1104 
1105  return true;
1106 }
float bmin[3]
The minimum bounds in world space. [(x, y, z)].
Definition: Recast.h:372
int height
The height of the heightfield. (Along the z-axis in cell units.)
Definition: Recast.h:308
#define rcAssert
Definition: RecastAssert.h:30
The total time to build the contours. (See: rcBuildContours)
Definition: Recast.h:47
static void simplifyContour(rcIntArray &points, rcIntArray &simplified, const float maxError, const int maxEdgeLen, const int buildFlags)
Definition: RecastContour.cpp:210
int borderSize
The AABB border size used during the build of the field. (See: rcConfig::borderSize) ...
Definition: Recast.h:312
unsigned short maxRegions
The maximum region id of any span within the field.
Definition: Recast.h:314
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
int nrverts
The number of vertices in the raw contour.
Definition: Recast.h:361
static int calcAreaOfPolygon2D(const int *verts, const int nverts)
Definition: RecastContour.cpp:454
IntFormatSpec< int, AlignTypeSpec< TYPE_CODE >, Char > pad(int value, unsigned width, Char fill= ' ')
static const int RC_NOT_CONNECTED
Definition: Recast.h:547
unsigned short reg
The id of the region the span belongs to. (Or zero if not in a region.)
Definition: Recast.h:298
int nverts
The number of vertices in the simplified contour.
Definition: Recast.h:359
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 * rverts
Raw contour vertex and connection data. [Size: 4 * nrverts].
Definition: Recast.h:360
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
rcContour * conts
An array of the contours in the set. [Size: nconts].
Definition: Recast.h:370
int height
The height of the set. (Along the z-axis in cell units.)
Definition: Recast.h:377
Provides information on the content of a cell column in a compact heightfield.
Definition: Recast.h:288
The time to trace the boundaries of the contours. (See: rcBuildContours)
Definition: Recast.h:49
int nconts
The number of contours in the set.
Definition: Recast.h:371
int * verts
Simplified contour vertex and connection data. [Size: 4 * nverts].
Definition: Recast.h:358
static void walkContour(int x, int y, int i, rcCompactHeightfield &chf, unsigned char *flags, rcIntArray &points)
Definition: RecastContour.cpp:104
Represents a simple, non-overlapping contour in field space.
Definition: Recast.h:356
unsigned int count
Number of spans in the column.
Definition: Recast.h:291
An error log entry.
Definition: Recast.h:31
Definition: RecastAlloc.h:105
static void removeDegenerateSegments(rcIntArray &simplified)
Definition: RecastContour.cpp:580
void rcFree(void *ptr)
Definition: RecastAlloc.cpp:55
unsigned char area
The area id of the contour.
Definition: Recast.h:363
void * rcAlloc(int size, rcAllocHint hint)
Definition: RecastAlloc.cpp:44
int rcGetDirOffsetX(int dir)
Definition: Recast.h:1038
rcContour * contour
Definition: RecastContour.cpp:652
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
float bmax[3]
The maximum bounds in world space. [(x, y, z)].
Definition: Recast.h:373
G3D::int16 y
Definition: Vector2int16.h:38
float bmax[3]
The maximum bounds in world space. [(x, y, z)].
Definition: Recast.h:316
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
uint8 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID][8]
Definition: System.cpp:444
unsigned short reg
The region id of the contour.
Definition: Recast.h:362
void rcVcopy(float *dest, const float *v)
Definition: Recast.h:677
float cs
The size of each cell. (On the xz-plane.)
Definition: Recast.h:374
Definition: RecastContour.cpp:656
void startTimer(const rcTimerLabel label)
Definition: Recast.h:131
int spanCount
The number of spans in the heightfield.
Definition: Recast.h:309
Memory will persist after a function call.
Definition: RecastAlloc.h:26
rcContourHole * holes
Definition: RecastContour.cpp:659
float cs
The size of each cell. (On the xz-plane.)
Definition: Recast.h:317
Definition: RecastContour.cpp:650
int width
The width of the set. (Along the x-axis in cell units.)
Definition: Recast.h:376
float ch
The height of each cell. (The minimum increment along the y-axis.)
Definition: Recast.h:318
Memory used temporarily within a function.
Definition: RecastAlloc.h:27
T rcMax(T a, T b)
Definition: Recast.h:572
void log(const rcLogCategory category, const char *format,...)
Definition: Recast.cpp:55
uint8 flags
Definition: DisableMgr.cpp:44
int borderSize
The AABB border size used to generate the source data from which the contours were derived...
Definition: Recast.h:378
float ch
The height of each cell. (The minimum increment along the y-axis.)
Definition: Recast.h:375
G3D::int16 x
Definition: Vector2int16.h:37
void stopTimer(const rcTimerLabel label)
Definition: Recast.h:135
int nholes
Definition: RecastContour.cpp:660
rcContour * outline
Definition: RecastContour.cpp:658
static const unsigned short RC_BORDER_REG
Definition: Recast.h:498
A warning log entry.
Definition: Recast.h:30
A simple dynamic array of integers.
Definition: RecastAlloc.h:61
The time to simplify the contours. (See: rcBuildContours)
Definition: Recast.h:51
float bmin[3]
The minimum bounds in world space. [(x, y, z)].
Definition: Recast.h:315
static void mergeRegionHoles(rcContext *ctx, rcContourRegion &region)
Definition: RecastContour.cpp:722

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void removeDegenerateSegments ( rcIntArray simplified)
static
581 {
582  // Remove adjacent vertices which are equal on xz-plane,
583  // or else the triangulator will get confused.
584  int npts = simplified.size()/4;
585  for (int i = 0; i < npts; ++i)
586  {
587  int ni = next(i, npts);
588 
589  if (vequal(&simplified[i*4], &simplified[ni*4]))
590  {
591  // Degenerate segment, remove.
592  for (int j = i; j < simplified.size()/4-1; ++j)
593  {
594  simplified[j*4+0] = simplified[(j+1)*4+0];
595  simplified[j*4+1] = simplified[(j+1)*4+1];
596  simplified[j*4+2] = simplified[(j+1)*4+2];
597  simplified[j*4+3] = simplified[(j+1)*4+3];
598  }
599  simplified.resize(simplified.size()-4);
600  npts--;
601  }
602  }
603 }
int next(int i, int n)
Definition: RecastContour.cpp:469
int size() const
The current size of the integer array.
Definition: RecastAlloc.h:100
static bool vequal(const int *a, const int *b)
Definition: RecastContour.cpp:540
void resize(int n)
Definition: RecastAlloc.cpp:75

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void simplifyContour ( rcIntArray points,
rcIntArray simplified,
const float  maxError,
const int  maxEdgeLen,
const int  buildFlags 
)
static
212 {
213  // Add initial points.
214  bool hasConnections = false;
215  for (int i = 0; i < points.size(); i += 4)
216  {
217  if ((points[i+3] & RC_CONTOUR_REG_MASK) != 0)
218  {
219  hasConnections = true;
220  break;
221  }
222  }
223 
224  if (hasConnections)
225  {
226  // The contour has some portals to other regions.
227  // Add a new point to every location where the region changes.
228  for (int i = 0, ni = points.size()/4; i < ni; ++i)
229  {
230  int ii = (i+1) % ni;
231  const bool differentRegs = (points[i*4+3] & RC_CONTOUR_REG_MASK) != (points[ii*4+3] & RC_CONTOUR_REG_MASK);
232  const bool areaBorders = (points[i*4+3] & RC_AREA_BORDER) != (points[ii*4+3] & RC_AREA_BORDER);
233  if (differentRegs || areaBorders)
234  {
235  simplified.push(points[i*4+0]);
236  simplified.push(points[i*4+1]);
237  simplified.push(points[i*4+2]);
238  simplified.push(i);
239  }
240  }
241  }
242 
243  if (simplified.size() == 0)
244  {
245  // If there is no connections at all,
246  // create some initial points for the simplification process.
247  // Find lower-left and upper-right vertices of the contour.
248  int llx = points[0];
249  int lly = points[1];
250  int llz = points[2];
251  int lli = 0;
252  int urx = points[0];
253  int ury = points[1];
254  int urz = points[2];
255  int uri = 0;
256  for (int i = 0; i < points.size(); i += 4)
257  {
258  int x = points[i+0];
259  int y = points[i+1];
260  int z = points[i+2];
261  if (x < llx || (x == llx && z < llz))
262  {
263  llx = x;
264  lly = y;
265  llz = z;
266  lli = i/4;
267  }
268  if (x > urx || (x == urx && z > urz))
269  {
270  urx = x;
271  ury = y;
272  urz = z;
273  uri = i/4;
274  }
275  }
276  simplified.push(llx);
277  simplified.push(lly);
278  simplified.push(llz);
279  simplified.push(lli);
280 
281  simplified.push(urx);
282  simplified.push(ury);
283  simplified.push(urz);
284  simplified.push(uri);
285  }
286 
287  // Add points until all raw points are within
288  // error tolerance to the simplified shape.
289  const int pn = points.size()/4;
290  for (int i = 0; i < simplified.size()/4; )
291  {
292  int ii = (i+1) % (simplified.size()/4);
293 
294  int ax = simplified[i*4+0];
295  int az = simplified[i*4+2];
296  int ai = simplified[i*4+3];
297 
298  int bx = simplified[ii*4+0];
299  int bz = simplified[ii*4+2];
300  int bi = simplified[ii*4+3];
301 
302  // Find maximum deviation from the segment.
303  float maxd = 0;
304  int maxi = -1;
305  int ci, cinc, endi;
306 
307  // Traverse the segment in lexilogical order so that the
308  // max deviation is calculated similarly when traversing
309  // opposite segments.
310  if (bx > ax || (bx == ax && bz > az))
311  {
312  cinc = 1;
313  ci = (ai+cinc) % pn;
314  endi = bi;
315  }
316  else
317  {
318  cinc = pn-1;
319  ci = (bi+cinc) % pn;
320  endi = ai;
321  rcSwap(ax, bx);
322  rcSwap(az, bz);
323  }
324 
325  // Tessellate only outer edges or edges between areas.
326  if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 ||
327  (points[ci*4+3] & RC_AREA_BORDER))
328  {
329  while (ci != endi)
330  {
331  float d = distancePtSeg(points[ci*4+0], points[ci*4+2], ax, az, bx, bz);
332  if (d > maxd)
333  {
334  maxd = d;
335  maxi = ci;
336  }
337  ci = (ci+cinc) % pn;
338  }
339  }
340 
341 
342  // If the max deviation is larger than accepted error,
343  // add new point, else continue to next segment.
344  if (maxi != -1 && maxd > (maxError*maxError))
345  {
346  // Add space for the new point.
347  simplified.resize(simplified.size()+4);
348  const int n = simplified.size()/4;
349  for (int j = n-1; j > i; --j)
350  {
351  simplified[j*4+0] = simplified[(j-1)*4+0];
352  simplified[j*4+1] = simplified[(j-1)*4+1];
353  simplified[j*4+2] = simplified[(j-1)*4+2];
354  simplified[j*4+3] = simplified[(j-1)*4+3];
355  }
356  // Add the point.
357  simplified[(i+1)*4+0] = points[maxi*4+0];
358  simplified[(i+1)*4+1] = points[maxi*4+1];
359  simplified[(i+1)*4+2] = points[maxi*4+2];
360  simplified[(i+1)*4+3] = maxi;
361  }
362  else
363  {
364  ++i;
365  }
366  }
367 
368  // Split too long edges.
369  if (maxEdgeLen > 0 && (buildFlags & (RC_CONTOUR_TESS_WALL_EDGES|RC_CONTOUR_TESS_AREA_EDGES)) != 0)
370  {
371  for (int i = 0; i < simplified.size()/4; )
372  {
373  const int ii = (i+1) % (simplified.size()/4);
374 
375  const int ax = simplified[i*4+0];
376  const int az = simplified[i*4+2];
377  const int ai = simplified[i*4+3];
378 
379  const int bx = simplified[ii*4+0];
380  const int bz = simplified[ii*4+2];
381  const int bi = simplified[ii*4+3];
382 
383  // Find maximum deviation from the segment.
384  int maxi = -1;
385  int ci = (ai+1) % pn;
386 
387  // Tessellate only outer edges or edges between areas.
388  bool tess = false;
389  // Wall edges.
390  if ((buildFlags & RC_CONTOUR_TESS_WALL_EDGES) && (points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0)
391  tess = true;
392  // Edges between areas.
393  if ((buildFlags & RC_CONTOUR_TESS_AREA_EDGES) && (points[ci*4+3] & RC_AREA_BORDER))
394  tess = true;
395 
396  if (tess)
397  {
398  int dx = bx - ax;
399  int dz = bz - az;
400  if (dx*dx + dz*dz > maxEdgeLen*maxEdgeLen)
401  {
402  // Round based on the segments in lexilogical order so that the
403  // max tesselation is consistent regardles in which direction
404  // segments are traversed.
405  const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
406  if (n > 1)
407  {
408  if (bx > ax || (bx == ax && bz > az))
409  maxi = (ai + n/2) % pn;
410  else
411  maxi = (ai + (n+1)/2) % pn;
412  }
413  }
414  }
415 
416  // If the max deviation is larger than accepted error,
417  // add new point, else continue to next segment.
418  if (maxi != -1)
419  {
420  // Add space for the new point.
421  simplified.resize(simplified.size()+4);
422  const int n = simplified.size()/4;
423  for (int j = n-1; j > i; --j)
424  {
425  simplified[j*4+0] = simplified[(j-1)*4+0];
426  simplified[j*4+1] = simplified[(j-1)*4+1];
427  simplified[j*4+2] = simplified[(j-1)*4+2];
428  simplified[j*4+3] = simplified[(j-1)*4+3];
429  }
430  // Add the point.
431  simplified[(i+1)*4+0] = points[maxi*4+0];
432  simplified[(i+1)*4+1] = points[maxi*4+1];
433  simplified[(i+1)*4+2] = points[maxi*4+2];
434  simplified[(i+1)*4+3] = maxi;
435  }
436  else
437  {
438  ++i;
439  }
440  }
441  }
442 
443  for (int i = 0; i < simplified.size()/4; ++i)
444  {
445  // The edge vertex flag is take from the current raw point,
446  // and the neighbour region is take from the next raw point.
447  const int ai = (simplified[i*4+3]+1) % pn;
448  const int bi = simplified[i*4+3];
449  simplified[i*4+3] = (points[ai*4+3] & (RC_CONTOUR_REG_MASK|RC_AREA_BORDER)) | (points[bi*4+3] & RC_BORDER_VERTEX);
450  }
451 
452 }
Tessellate edges between areas during contour simplification.
Definition: Recast.h:521
Tessellate solid (impassable) edges during contour simplification.
Definition: Recast.h:520
void rcSwap(T &a, T &b)
Definition: Recast.h:560
int size() const
The current size of the integer array.
Definition: RecastAlloc.h:100
static const int RC_BORDER_VERTEX
Definition: Recast.h:507
G3D::int16 z
Definition: Vector3int16.h:46
G3D::int16 y
Definition: Vector2int16.h:38
static const int RC_CONTOUR_REG_MASK
Definition: Recast.h:528
static float distancePtSeg(const int x, const int z, const int px, const int pz, const int qx, const int qz)
Definition: RecastContour.cpp:187
static const int RC_AREA_BORDER
Definition: Recast.h:514
G3D::int16 x
Definition: Vector2int16.h:37
void resize(int n)
Definition: RecastAlloc.cpp:75
void push(int item)
Definition: RecastAlloc.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool vequal ( const int *  a,
const int *  b 
)
static
541 {
542  return a[0] == b[0] && a[2] == b[2];
543 }

+ Here is the caller graph for this function:

static void walkContour ( int  x,
int  y,
int  i,
rcCompactHeightfield chf,
unsigned char *  flags,
rcIntArray points 
)
static
107 {
108  // Choose the first non-connected edge
109  unsigned char dir = 0;
110  while ((flags[i] & (1 << dir)) == 0)
111  dir++;
112 
113  unsigned char startDir = dir;
114  int starti = i;
115 
116  const unsigned char area = chf.areas[i];
117 
118  int iter = 0;
119  while (++iter < 40000)
120  {
121  if (flags[i] & (1 << dir))
122  {
123  // Choose the edge corner
124  bool isBorderVertex = false;
125  bool isAreaBorder = false;
126  int px = x;
127  int py = getCornerHeight(x, y, i, dir, chf, isBorderVertex);
128  int pz = y;
129  switch(dir)
130  {
131  case 0: pz++; break;
132  case 1: px++; pz++; break;
133  case 2: px++; break;
134  }
135  int r = 0;
136  const rcCompactSpan& s = chf.spans[i];
137  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
138  {
139  const int ax = x + rcGetDirOffsetX(dir);
140  const int ay = y + rcGetDirOffsetY(dir);
141  const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
142  r = (int)chf.spans[ai].reg;
143  if (area != chf.areas[ai])
144  isAreaBorder = true;
145  }
146  if (isBorderVertex)
147  r |= RC_BORDER_VERTEX;
148  if (isAreaBorder)
149  r |= RC_AREA_BORDER;
150  points.push(px);
151  points.push(py);
152  points.push(pz);
153  points.push(r);
154 
155  flags[i] &= ~(1 << dir); // Remove visited edges
156  dir = (dir+1) & 0x3; // Rotate CW
157  }
158  else
159  {
160  int ni = -1;
161  const int nx = x + rcGetDirOffsetX(dir);
162  const int ny = y + rcGetDirOffsetY(dir);
163  const rcCompactSpan& s = chf.spans[i];
164  if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
165  {
166  const rcCompactCell& nc = chf.cells[nx+ny*chf.width];
167  ni = (int)nc.index + rcGetCon(s, dir);
168  }
169  if (ni == -1)
170  {
171  // Should not happen.
172  return;
173  }
174  x = nx;
175  y = ny;
176  i = ni;
177  dir = (dir+3) & 0x3; // Rotate CCW
178  }
179 
180  if (starti == i && startDir == dir)
181  {
182  break;
183  }
184  }
185 }
Represents a span of unobstructed space within a compact heightfield.
Definition: Recast.h:295
static const int RC_NOT_CONNECTED
Definition: Recast.h:547
unsigned short reg
The id of the region the span belongs to. (Or zero if not in a region.)
Definition: Recast.h:298
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
int rcGetDirOffsetX(int dir)
Definition: Recast.h:1038
static const int RC_BORDER_VERTEX
Definition: Recast.h:507
unsigned char * areas
Array containing area id data. [Size: spanCount].
Definition: Recast.h:322
G3D::int16 y
Definition: Vector2int16.h:38
static int getCornerHeight(int x, int y, int i, int dir, const rcCompactHeightfield &chf, bool &isBorderVertex)
Definition: RecastContour.cpp:29
int width
The width of the heightfield. (Along the x-axis in cell units.)
Definition: Recast.h:307
static const int RC_AREA_BORDER
Definition: Recast.h:514
uint8 flags
Definition: DisableMgr.cpp:44
G3D::int16 x
Definition: Vector2int16.h:37
void push(int item)
Definition: RecastAlloc.h:83

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool xorb ( bool  x,
bool  y 
)
inline
481 {
482  return !x ^ !y;
483 }
G3D::int16 y
Definition: Vector2int16.h:38
G3D::int16 x
Definition: Vector2int16.h:37

+ Here is the caller graph for this function: