本文整理汇总了C++中rcIntArray::push方法的典型用法代码示例。如果您正苦于以下问题:C++ rcIntArray::push方法的具体用法?C++ rcIntArray::push怎么用?C++ rcIntArray::push使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类rcIntArray
的用法示例。
在下文中一共展示了rcIntArray::push方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: appendStacks
static void appendStacks(rcIntArray& srcStack, rcIntArray& dstStack,
unsigned short* srcReg)
{
for (int j=0; j<srcStack.size(); j+=3)
{
int i = srcStack[j+2];
if ((i < 0) || (srcReg[i] != 0))
continue;
dstStack.push(srcStack[j]);
dstStack.push(srcStack[j+1]);
dstStack.push(srcStack[j+2]);
}
}
示例2: addUnique
static void addUnique(rcIntArray& a, int v)
{
if (!a.contains(v))
{
a.push(v);
}
}
示例3: getHeightData
static void getHeightData(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts, const int bs,
rcHeightPatch& hp, rcIntArray& stack,
int region)
{
// Note: Reads to the compact heightfield are offset by border size (bs)
// since border size offset is already removed from the polymesh vertices.
stack.resize(0);
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
bool empty = true;
// Copy the height from the same region, and mark region borders
// as seed points to fill the rest.
for (int hy = 0; hy < hp.height; hy++)
{
int y = hp.ymin + hy + bs;
for (int hx = 0; hx < hp.width; hx++)
{
int x = hp.xmin + hx + bs;
const rcCompactCell& c = chf.cells[x+y*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
if (s.reg == region)
{
// Store height
hp.data[hx + hy*hp.width] = s.y;
empty = false;
// If any of the neighbours is not in same region,
// add the current location as flood fill start
bool border = false;
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
{
const int ax = x + rcGetDirOffsetX(dir);
const int ay = y + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
const rcCompactSpan& as = chf.spans[ai];
if (as.reg != region)
{
border = true;
break;
}
}
}
if (border)
{
stack.push(x);
stack.push(y);
stack.push(i);
}
break;
}
}
}
}
// if the polygon does not contian any points from the current region (rare, but happens)
// then use the cells closest to the polygon vertices as seeds to fill the height field
if (empty)
getHeightDataSeedsFromVertices(chf, poly, npoly, verts, bs, hp, stack);
static const int RETRACT_SIZE = 256;
int head = 0;
while (head*3 < stack.size())
{
int cx = stack[head*3+0];
int cy = stack[head*3+1];
int ci = stack[head*3+2];
head++;
if (head >= RETRACT_SIZE)
{
head = 0;
if (stack.size() > RETRACT_SIZE*3)
memmove(&stack[0], &stack[RETRACT_SIZE*3], sizeof(int)*(stack.size()-RETRACT_SIZE*3));
stack.resize(stack.size()-RETRACT_SIZE*3);
}
const rcCompactSpan& cs = chf.spans[ci];
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue;
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
const int hx = ax - hp.xmin - bs;
const int hy = ay - hp.ymin - bs;
if (hx < 0 || hx >= hp.width || hy < 0 || hy >= hp.height)
continue;
if (hp.data[hx + hy*hp.width] != RC_UNSET_HEIGHT)
continue;
//.........这里部分代码省略.........
示例4: getHeightDataSeedsFromVertices
static void getHeightDataSeedsFromVertices(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts, const int bs,
rcHeightPatch& hp, rcIntArray& stack)
{
// Floodfill the heightfield to get 2D height data,
// starting at vertex locations as seeds.
// Note: Reads to the compact heightfield are offset by border size (bs)
// since border size offset is already removed from the polymesh vertices.
memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height);
stack.resize(0);
static const int offset[9*2] =
{
0,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0,
};
// Use poly vertices as seed points for the flood fill.
for (int j = 0; j < npoly; ++j)
{
int cx = 0, cz = 0, ci =-1;
int dmin = RC_UNSET_HEIGHT;
for (int k = 0; k < 9; ++k)
{
const int ax = (int)verts[poly[j]*3+0] + offset[k*2+0];
const int ay = (int)verts[poly[j]*3+1];
const int az = (int)verts[poly[j]*3+2] + offset[k*2+1];
if (ax < hp.xmin || ax >= hp.xmin+hp.width ||
az < hp.ymin || az >= hp.ymin+hp.height)
continue;
const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
int d = rcAbs(ay - (int)s.y);
if (d < dmin)
{
cx = ax;
cz = az;
ci = i;
dmin = d;
}
}
}
if (ci != -1)
{
stack.push(cx);
stack.push(cz);
stack.push(ci);
}
}
// Find center of the polygon using flood fill.
int pcx = 0, pcz = 0;
for (int j = 0; j < npoly; ++j)
{
pcx += (int)verts[poly[j]*3+0];
pcz += (int)verts[poly[j]*3+2];
}
pcx /= npoly;
pcz /= npoly;
for (int i = 0; i < stack.size(); i += 3)
{
int cx = stack[i+0];
int cy = stack[i+1];
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
hp.data[idx] = 1;
}
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
// Check if close to center of the polygon.
if (rcAbs(cx-pcx) <= 1 && rcAbs(cy-pcz) <= 1)
{
stack.resize(0);
stack.push(cx);
stack.push(cy);
stack.push(ci);
break;
}
const rcCompactSpan& cs = chf.spans[ci];
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue;
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
if (ax < hp.xmin || ax >= (hp.xmin+hp.width) ||
//.........这里部分代码省略.........
示例5: buildPolyDetail
//.........这里部分代码省略.........
triangulateHull(nverts, verts, nhull, hull, tris);
if (tris.size() == 0)
{
// Could not triangulate the poly, make sure there is some valid data there.
ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon (%d verts).", nverts);
return true;
}
if (sampleDist > 0)
{
// Create sample locations in a grid.
float bmin[3], bmax[3];
rcVcopy(bmin, in);
rcVcopy(bmax, in);
for (int i = 1; i < nin; ++i)
{
rcVmin(bmin, &in[i*3]);
rcVmax(bmax, &in[i*3]);
}
int x0 = (int)floorf(bmin[0]/sampleDist);
int x1 = (int)ceilf(bmax[0]/sampleDist);
int z0 = (int)floorf(bmin[2]/sampleDist);
int z1 = (int)ceilf(bmax[2]/sampleDist);
samples.resize(0);
for (int z = z0; z < z1; ++z)
{
for (int x = x0; x < x1; ++x)
{
float pt[3];
pt[0] = x*sampleDist;
pt[1] = (bmax[1]+bmin[1])*0.5f;
pt[2] = z*sampleDist;
// Make sure the samples are not too close to the edges.
if (distToPoly(nin,in,pt) > -sampleDist/2) continue;
samples.push(x);
samples.push(getHeight(pt[0], pt[1], pt[2], cs, ics, chf.ch, hp));
samples.push(z);
samples.push(0); // Not added
}
}
// Add the samples starting from the one that has the most
// error. The procedure stops when all samples are added
// or when the max error is within treshold.
const int nsamples = samples.size()/4;
for (int iter = 0; iter < nsamples; ++iter)
{
if (nverts >= MAX_VERTS)
break;
// Find sample with most error.
float bestpt[3] = {0,0,0};
float bestd = 0;
int besti = -1;
for (int i = 0; i < nsamples; ++i)
{
const int* s = &samples[i*4];
if (s[3]) continue; // skip added.
float pt[3];
// The sample location is jittered to get rid of some bad triangulations
// which are cause by symmetrical data from the grid structure.
pt[0] = s[0]*sampleDist + getJitterX(i)*cs*0.1f;
pt[1] = s[1]*chf.ch;
pt[2] = s[2]*sampleDist + getJitterY(i)*cs*0.1f;
float d = distToTriMesh(pt, verts, nverts, &tris[0], tris.size()/4);
if (d < 0) continue; // did not hit the mesh.
if (d > bestd)
{
bestd = d;
besti = i;
rcVcopy(bestpt,pt);
}
}
// If the max error is within accepted threshold, stop tesselating.
if (bestd <= sampleMaxError || besti == -1)
break;
// Mark sample as added.
samples[besti*4+3] = 1;
// Add the new sample point.
rcVcopy(&verts[nverts*3],bestpt);
nverts++;
// Create new triangulation.
// TODO: Incremental add instead of full rebuild.
edges.resize(0);
tris.resize(0);
delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges);
}
}
const int ntris = tris.size()/4;
if (ntris > MAX_TRIS)
{
tris.resize(MAX_TRIS*4);
ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Shrinking triangle count from %d to max %d.", ntris, MAX_TRIS);
}
return true;
}
示例6: triangulateHull
static void triangulateHull(const int nverts, const float* verts, const int nhull, const int* hull, rcIntArray& tris)
{
int start = 0, left = 1, right = nhull-1;
// Start from an ear with shortest perimeter.
// This tends to favor well formed triangles as starting point.
float dmin = 0;
for (int i = 0; i < nhull; i++)
{
int pi = prev(i, nhull);
int ni = next(i, nhull);
const float* pv = &verts[hull[pi]*3];
const float* cv = &verts[hull[i]*3];
const float* nv = &verts[hull[ni]*3];
const float d = vdist2(pv,cv) + vdist2(cv,nv) + vdist2(nv,pv);
if (d < dmin)
{
start = i;
left = ni;
right = pi;
dmin = d;
}
}
// Add first triangle
tris.push(hull[start]);
tris.push(hull[left]);
tris.push(hull[right]);
tris.push(0);
// Triangulate the polygon by moving left or right,
// depending on which triangle has shorter perimeter.
// This heuristic was chose emprically, since it seems
// handle tesselated straight edges well.
while (next(left, nhull) != right)
{
// Check to see if se should advance left or right.
int nleft = next(left, nhull);
int nright = prev(right, nhull);
const float* cvleft = &verts[hull[left]*3];
const float* nvleft = &verts[hull[nleft]*3];
const float* cvright = &verts[hull[right]*3];
const float* nvright = &verts[hull[nright]*3];
const float dleft = vdist2(cvleft, nvleft) + vdist2(nvleft, cvright);
const float dright = vdist2(cvright, nvright) + vdist2(cvleft, nvright);
if (dleft < dright)
{
tris.push(hull[left]);
tris.push(hull[nleft]);
tris.push(hull[right]);
tris.push(0);
left = nleft;
}
else
{
tris.push(hull[left]);
tris.push(hull[nright]);
tris.push(hull[right]);
tris.push(0);
right = nright;
}
}
}
示例7: getHeightData
static void getHeightData(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts,
rcHeightPatch& hp, rcIntArray& stack)
{
// Floodfill the heightfield to get 2D height data,
// starting at vertex locations as seeds.
memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height);
stack.resize(0);
static const int offset[9*2] =
{
0,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0,
};
// Use poly vertices as seed points for the flood fill.
for (int j = 0; j < npoly; ++j)
{
int cx = 0, cz = 0, ci =-1;
int dmin = RC_UNSET_HEIGHT;
for (int k = 0; k < 9; ++k)
{
const int ax = (int)verts[poly[j]*3+0] + offset[k*2+0];
const int ay = (int)verts[poly[j]*3+1];
const int az = (int)verts[poly[j]*3+2] + offset[k*2+1];
if (ax < hp.xmin || ax >= hp.xmin+hp.width ||
az < hp.ymin || az >= hp.ymin+hp.height)
continue;
const rcCompactCell& c = chf.cells[ax+az*chf.width];
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
int d = rcAbs(ay - (int)s.y);
if (d < dmin)
{
cx = ax;
cz = az;
ci = i;
dmin = d;
}
}
}
if (ci != -1)
{
stack.push(cx);
stack.push(cz);
stack.push(ci);
}
}
// Find center of the polygon using flood fill.
int pcx = 0, pcz = 0;
for (int j = 0; j < npoly; ++j)
{
pcx += (int)verts[poly[j]*3+0];
pcz += (int)verts[poly[j]*3+2];
}
pcx /= npoly;
pcz /= npoly;
for (int i = 0; i < stack.size(); i += 3)
{
int cx = stack[i+0];
int cy = stack[i+1];
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
hp.data[idx] = 1;
}
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
// Check if close to center of the polygon.
if (rcAbs(cx-pcx) <= 1 && rcAbs(cy-pcz) <= 1)
{
stack.resize(0);
stack.push(cx);
stack.push(cy);
stack.push(ci);
break;
}
const rcCompactSpan& cs = chf.spans[ci];
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue;
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
if (ax < hp.xmin || ax >= (hp.xmin+hp.width) ||
ay < hp.ymin || ay >= (hp.ymin+hp.height))
continue;
//.........这里部分代码省略.........
示例8: buildPolyDetail
//.........这里部分代码省略.........
{
for (int k = nidx-2; k > 0; --k)
{
rcVcopy(verts[nverts], edge[idx[k]]);
hull[nhull++] = nverts;
nverts++;
}
}
else
{
for (int k = 1; k < nidx-1; ++k)
{
rcVcopy(verts[nverts], edge[idx[k]]);
hull[nhull++] = nverts;
nverts++;
}
}
}
}
// Tessellate the base mesh.
edges.resize(0);
tris.resize(0);
delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges);
if (tris.size() == 0)
{
// Could not triangulate the poly, make sure there is some valid data there.
ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data.");
for (int i = 2; i < nverts; ++i)
{
tris.push(0);
tris.push(i-1);
tris.push(i);
tris.push(0);
}
return true;
}
#ifdef MODIFY_VOXEL_FLAG
if( 0 < sampleDist /*&& rcIsTerrainArea( area )*/ )
#else // MODIFY_VOXEL_FLAG
if (sampleDist > 0)
#endif // MODIFY_VOXEL_FLAG
{
// Create sample locations in a grid.
dtCoordinates bmin, bmax;
rcVcopy(bmin, in[0]);
rcVcopy(bmax, in[0]);
for (int i = 1; i < nin; ++i)
{
rcVmin(bmin, in[i]);
rcVmax(bmax, in[i]);
}
int x0 = (int)floorf(bmin.X()/sampleDist);
int x1 = (int)ceilf(bmax.X()/sampleDist);
int z0 = (int)floorf(bmin.Z()/sampleDist);
int z1 = (int)ceilf(bmax.Z()/sampleDist);
samples.resize(0);
for (int z = z0; z < z1; ++z)
{
for (int x = x0; x < x1; ++x)
{
const dtCoordinates pt( x*sampleDist, (bmax.Y()+bmin.Y())*0.5f, z*sampleDist );
示例9: simplifyContour
static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
const float maxError, const int maxEdgeLen, const int buildFlags)
{
// Add initial points.
bool hasConnections = false;
for (int i = 0; i < points.size(); i += 4)
{
if ((points[i+3] & RC_CONTOUR_REG_MASK) != 0)
{
hasConnections = true;
break;
}
}
if (hasConnections)
{
// The contour has some portals to other regions.
// Add a new point to every location where the region changes.
for (int i = 0, ni = points.size()/4; i < ni; ++i)
{
int ii = (i+1) % ni;
const bool differentRegs = (points[i*4+3] & RC_CONTOUR_REG_MASK) != (points[ii*4+3] & RC_CONTOUR_REG_MASK);
const bool areaBorders = (points[i*4+3] & RC_AREA_BORDER) != (points[ii*4+3] & RC_AREA_BORDER);
if (differentRegs || areaBorders)
{
simplified.push(points[i*4+0]);
simplified.push(points[i*4+1]);
simplified.push(points[i*4+2]);
simplified.push(i);
}
}
}
if (simplified.size() == 0)
{
// If there is no connections at all,
// create some initial points for the simplification process.
// Find lower-left and upper-right vertices of the contour.
int llx = points[0];
int lly = points[1];
int llz = points[2];
int lli = 0;
int urx = points[0];
int ury = points[1];
int urz = points[2];
int uri = 0;
for (int i = 0; i < points.size(); i += 4)
{
int x = points[i+0];
int y = points[i+1];
int z = points[i+2];
if (x < llx || (x == llx && z < llz))
{
llx = x;
lly = y;
llz = z;
lli = i/4;
}
if (x > urx || (x == urx && z > urz))
{
urx = x;
ury = y;
urz = z;
uri = i/4;
}
}
simplified.push(llx);
simplified.push(lly);
simplified.push(llz);
simplified.push(lli);
simplified.push(urx);
simplified.push(ury);
simplified.push(urz);
simplified.push(uri);
}
// Add points until all raw points are within
// error tolerance to the simplified shape.
const int pn = points.size()/4;
for (int i = 0; i < simplified.size()/4; )
{
int ii = (i+1) % (simplified.size()/4);
int ax = simplified[i*4+0];
int az = simplified[i*4+2];
int ai = simplified[i*4+3];
int bx = simplified[ii*4+0];
int bz = simplified[ii*4+2];
int bi = simplified[ii*4+3];
// Find maximum deviation from the segment.
float maxd = 0;
int maxi = -1;
int ci, cinc, endi;
// Traverse the segment in lexilogical order so that the
// max deviation is calculated similarly when traversing
// opposite segments.
//.........这里部分代码省略.........
示例10: floodRegion
static bool floodRegion(int x, int y, int i,
unsigned short level, unsigned short minLevel, unsigned short r,
rcCompactHeightfield& chf,
unsigned short* src,
rcIntArray& stack)
{
const int w = chf.width;
// Flood fill mark region.
stack.resize(0);
stack.push((int)x);
stack.push((int)y);
stack.push((int)i);
src[i*2] = r;
src[i*2+1] = 0;
unsigned short lev = level >= minLevel+2 ? level-2 : minLevel;
int count = 0;
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
const rcCompactSpan& cs = chf.spans[ci];
// Check if any of the neighbours already have a valid region set.
unsigned short ar = 0;
for (int dir = 0; dir < 4; ++dir)
{
// 8 connected
if (rcGetCon(cs, dir) != 0xf)
{
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
unsigned short nr = src[ai*2];
if (nr != 0 && nr != r)
ar = nr;
const rcCompactSpan& as = chf.spans[ai];
const int dir2 = (dir+1) & 0x3;
if (rcGetCon(as, dir2) != 0xf)
{
const int ax2 = ax + rcGetDirOffsetX(dir2);
const int ay2 = ay + rcGetDirOffsetY(dir2);
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
unsigned short nr = src[ai2*2];
if (nr != 0 && nr != r)
ar = nr;
}
}
}
if (ar != 0)
{
src[ci*2] = 0;
continue;
}
count++;
// Expand neighbours.
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) != 0xf)
{
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
if (chf.spans[ai].dist >= lev)
{
if (src[ai*2] == 0)
{
src[ai*2] = r;
src[ai*2+1] = 0;
stack.push(ax);
stack.push(ay);
stack.push(ai);
}
}
}
}
}
return count > 0;
}
示例11: walkContour
static void walkContour(int x, int y, int i,
rcCompactHeightfield& chf,
unsigned char* flags, rcIntArray& points)
{
// Choose the first non-connected edge
unsigned char dir = 0;
while ((flags[i] & (1 << dir)) == 0)
dir++;
unsigned char startDir = dir;
int starti = i;
const navAreaMask area = chf.areaMasks[ i ];
int iter = 0;
while (++iter < 40000)
{
if (flags[i] & (1 << dir))
{
// Choose the edge corner
bool isBorderVertex = false;
bool isAreaBorder = false;
int px = x;
int py = getCornerHeight(x, y, i, dir, chf, isBorderVertex);
int pz = y;
switch(dir)
{
case 0: pz++; break;
case 1: px++; pz++; break;
case 2: px++; break;
}
int r = 0;
const rcCompactSpan& s = chf.spans[i];
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
{
const int ax = x + rcGetDirOffsetX(dir);
const int ay = y + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
r = (int)chf.spans[ai].regionID;
if (area != chf.areaMasks[ai])
isAreaBorder = true;
}
if (isBorderVertex)
r |= RC_BORDER_VERTEX;
if (isAreaBorder)
r |= RC_AREA_BORDER;
points.push(px);
points.push(py);
points.push(pz);
points.push(r);
flags[i] &= ~(1 << dir); // Remove visited edges
dir = (dir+1) & 0x3; // Rotate CW
}
else
{
int ni = -1;
const int nx = x + rcGetDirOffsetX(dir);
const int ny = y + rcGetDirOffsetY(dir);
const rcCompactSpan& s = chf.spans[i];
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
{
const rcCompactCell& nc = chf.cells[nx+ny*chf.width];
ni = (int)nc.index + rcGetCon(s, dir);
}
if (ni == -1)
{
// Should not happen.
return;
}
x = nx;
y = ny;
i = ni;
dir = (dir+3) & 0x3; // Rotate CCW
}
if (starti == i && startDir == dir)
{
break;
}
}
}
示例12: getHeightData
static void getHeightData(const rcCompactHeightfield& chf,
const unsigned short* poly, const int npoly,
const unsigned short* verts,
rcHeightPatch& hp, rcIntArray& stack)
{
// Floodfill the heightfield to get 2D height data,
// starting at vertex locations as seeds.
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
stack.resize(0);
// Use poly vertices as seed points for the flood fill.
for (int j = 0; j < npoly; ++j)
{
const int ax = (int)verts[poly[j]*3+0];
const int ay = (int)verts[poly[j]*3+1];
const int az = (int)verts[poly[j]*3+2];
if (ax < hp.xmin || ax >= hp.xmin+hp.width ||
az < hp.ymin || az >= hp.ymin+hp.height)
continue;
const rcCompactCell& c = chf.cells[ax+az*chf.width];
int dmin = 0xffff;
int ai = -1;
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
const rcCompactSpan& s = chf.spans[i];
int d = rcAbs(ay - (int)s.y);
if (d < dmin)
{
ai = i;
dmin = d;
}
}
if (ai != -1)
{
stack.push(ax);
stack.push(az);
stack.push(ai);
}
}
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
// Skip already visited locations.
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
if (hp.data[idx] != 0xffff)
continue;
const rcCompactSpan& cs = chf.spans[ci];
hp.data[idx] = cs.y;
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) == 0xf) continue;
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
if (ax < hp.xmin || ax >= (hp.xmin+hp.width) ||
ay < hp.ymin || ay >= (hp.ymin+hp.height))
continue;
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0xffff)
continue;
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir);
stack.push(ax);
stack.push(ay);
stack.push(ai);
}
}
}
示例13: buildPolyDetail
//.........这里部分代码省略.........
idx[m] = idx[m-1];
idx[k+1] = maxi;
nidx++;
}
else
{
++k;
}
}
// Add new vertices.
for (int k = 1; k < nidx-1; ++k)
{
vcopy(&verts[nverts*3], &edge[idx[k]*3]);
nverts++;
}
}
}
// Tesselate the base mesh.
edges.resize(0);
tris.resize(0);
idx.resize(0);
delaunay(nverts, verts, idx, tris, edges);
if (sampleDist > 0)
{
// Create sample locations in a grid.
float bmin[3], bmax[3];
vcopy(bmin, in);
vcopy(bmax, in);
for (int i = 1; i < nin; ++i)
{
vmin(bmin, &in[i*3]);
vmax(bmax, &in[i*3]);
}
int x0 = (int)floorf(bmin[0]/sampleDist);
int x1 = (int)ceilf(bmax[0]/sampleDist);
int z0 = (int)floorf(bmin[2]/sampleDist);
int z1 = (int)ceilf(bmax[2]/sampleDist);
samples.resize(0);
for (int z = z0; z < z1; ++z)
{
for (int x = x0; x < x1; ++x)
{
float pt[3];
pt[0] = x*sampleDist;
pt[2] = z*sampleDist;
// Make sure the samples are not too close to the edges.
if (distToPoly(nin,in,pt) > -sampleDist/2) continue;
samples.push(x);
samples.push(getHeight(pt, chf.bmin, ics, hp));
samples.push(z);
}
}
// Add the samples starting from the one that has the most
// error. The procedure stops when all samples are added
// or when the max error is within treshold.
const int nsamples = samples.size()/3;
for (int iter = 0; iter < nsamples; ++iter)
{
// Find sample with most error.
float bestpt[3];
float bestd = 0;
for (int i = 0; i < nsamples; ++i)
{
float pt[3];
pt[0] = samples[i*3+0]*sampleDist;
pt[1] = chf.bmin[1] + samples[i*3+1]*chf.ch;
pt[2] = samples[i*3+2]*sampleDist;
float d = distToTriMesh(pt, verts, nverts, &tris[0], tris.size()/4);
if (d < 0) continue; // did not hit the mesh.
if (d > bestd)
{
bestd = d;
vcopy(bestpt,pt);
}
}
// If the max error is within accepted threshold, stop tesselating.
if (bestd <= sampleMaxError)
break;
// Add the new sample point.
vcopy(&verts[nverts*3],bestpt);
nverts++;
// Create new triangulation.
// TODO: Incremental add instead of full rebuild.
edges.resize(0);
tris.resize(0);
idx.resize(0);
delaunay(nverts, verts, idx, tris, edges);
if (nverts >= MAX_VERTS)
break;
}
}
return true;
}
示例14: delaunay
// Based on Paul Bourke's triangulate.c
// http://astronomy.swin.edu.au/~pbourke/terrain/triangulate/triangulate.c
static void delaunay(const int nv, float *verts, rcIntArray& idx, rcIntArray& tris, rcIntArray& edges)
{
// Sort vertices
idx.resize(nv);
for (int i = 0; i < nv; ++i)
idx[i] = i;
#ifdef WIN32
qsort_s(&idx[0], idx.size(), sizeof(int), ptcmp, verts);
#else
qsort_r(&idx[0], idx.size(), sizeof(int), verts, ptcmp);
#endif
// Find the maximum and minimum vertex bounds.
// This is to allow calculation of the bounding triangle
float xmin = verts[0];
float ymin = verts[2];
float xmax = xmin;
float ymax = ymin;
for (int i = 1; i < nv; ++i)
{
xmin = rcMin(xmin, verts[i*3+0]);
xmax = rcMax(xmax, verts[i*3+0]);
ymin = rcMin(ymin, verts[i*3+2]);
ymax = rcMax(ymax, verts[i*3+2]);
}
float dx = xmax - xmin;
float dy = ymax - ymin;
float dmax = (dx > dy) ? dx : dy;
float xmid = (xmax + xmin) / 2.0f;
float ymid = (ymax + ymin) / 2.0f;
// Set up the supertriangle
// This is a triangle which encompasses all the sample points.
// The supertriangle coordinates are added to the end of the
// vertex list. The supertriangle is the first triangle in
// the triangle list.
float sv[3*3];
sv[0] = xmid - 20 * dmax;
sv[1] = 0;
sv[2] = ymid - dmax;
sv[3] = xmid;
sv[4] = 0;
sv[5] = ymid + 20 * dmax;
sv[6] = xmid + 20 * dmax;
sv[7] = 0;
sv[8] = ymid - dmax;
tris.push(-3);
tris.push(-2);
tris.push(-1);
tris.push(0); // not completed
for (int i = 0; i < nv; ++i)
{
const float xp = verts[idx[i]*3+0];
const float yp = verts[idx[i]*3+2];
edges.resize(0);
// Set up the edge buffer.
// If the point (xp,yp) lies inside the circumcircle then the
// three edges of that triangle are added to the edge buffer
// and that triangle is removed.
for (int j = 0; j < tris.size()/4; ++j)
{
int* t = &tris[j*4];
if (t[3]) // completed?
continue;
const float* v1 = t[0] < 0 ? &sv[(t[0]+3)*3] : &verts[idx[t[0]]*3];
const float* v2 = t[1] < 0 ? &sv[(t[1]+3)*3] : &verts[idx[t[1]]*3];
const float* v3 = t[2] < 0 ? &sv[(t[2]+3)*3] : &verts[idx[t[2]]*3];
float xc,yc,rsqr;
int inside = circumCircle(xp,yp, v1[0],v1[2], v2[0],v2[2], v3[0],v3[2], xc,yc,rsqr);
if (xc < xp && rcSqr(xp-xc) > rsqr)
t[3] = 1;
if (inside)
{
// Collect triangle edges.
edges.push(t[0]);
edges.push(t[1]);
edges.push(t[1]);
edges.push(t[2]);
edges.push(t[2]);
edges.push(t[0]);
// Remove triangle j.
t[0] = tris[tris.size()-4];
t[1] = tris[tris.size()-3];
t[2] = tris[tris.size()-2];
t[3] = tris[tris.size()-1];
tris.resize(tris.size()-4);
j--;
}
}
// Remove duplicate edges.
//.........这里部分代码省略.........
示例15: floodRegion
static bool floodRegion(int x, int y, int i,
unsigned short level, unsigned short r,
rcCompactHeightfield& chf,
unsigned short* srcReg, unsigned short* srcDist,
rcIntArray& stack)
{
const int w = chf.width;
const unsigned char area = chf.areas[i];
// Flood fill mark region.
stack.resize(0);
stack.push((int)x);
stack.push((int)y);
stack.push((int)i);
srcReg[i] = r;
srcDist[i] = 0;
unsigned short lev = level >= 2 ? level-2 : 0;
int count = 0;
while (stack.size() > 0)
{
int ci = stack.pop();
int cy = stack.pop();
int cx = stack.pop();
const rcCompactSpan& cs = chf.spans[ci];
// Check if any of the neighbours already have a valid region set.
unsigned short ar = 0;
for (int dir = 0; dir < 4; ++dir)
{
// 8 connected
if (rcGetCon(cs, dir) != RC_NOT_CONNECTED)
{
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
if (chf.areas[ai] != area)
continue;
unsigned short nr = srcReg[ai];
if (nr & RC_BORDER_REG) // Do not take borders into account.
continue;
if (nr != 0 && nr != r)
ar = nr;
const rcCompactSpan& as = chf.spans[ai];
const int dir2 = (dir+1) & 0x3;
if (rcGetCon(as, dir2) != RC_NOT_CONNECTED)
{
const int ax2 = ax + rcGetDirOffsetX(dir2);
const int ay2 = ay + rcGetDirOffsetY(dir2);
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
if (chf.areas[ai2] != area)
continue;
unsigned short nr2 = srcReg[ai2];
if (nr2 != 0 && nr2 != r)
ar = nr2;
}
}
}
if (ar != 0)
{
srcReg[ci] = 0;
continue;
}
count++;
// Expand neighbours.
for (int dir = 0; dir < 4; ++dir)
{
if (rcGetCon(cs, dir) != RC_NOT_CONNECTED)
{
const int ax = cx + rcGetDirOffsetX(dir);
const int ay = cy + rcGetDirOffsetY(dir);
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
if (chf.areas[ai] != area)
continue;
if (chf.dist[ai] >= lev && srcReg[ai] == 0)
{
srcReg[ai] = r;
srcDist[ai] = 0;
stack.push(ax);
stack.push(ay);
stack.push(ai);
}
}
}
}
return count > 0;
}