68
68
float* c, float& r)
70
70
static const float EPS = 1e-6f;
71
// Calculate the circle relative to p1, to avoid some precision issues.
72
const float v1[3] = {0,0,0};
72
const float cp = vcross2(p1, p2, p3);
77
const float cp = vcross2(v1, v2, v3);
73
78
if (fabsf(cp) > EPS)
75
const float p1Sq = vdot2(p1,p1);
76
const float p2Sq = vdot2(p2,p2);
77
const float p3Sq = vdot2(p3,p3);
78
c[0] = (p1Sq*(p2[2]-p3[2]) + p2Sq*(p3[2]-p1[2]) + p3Sq*(p1[2]-p2[2])) / (2*cp);
79
c[2] = (p1Sq*(p3[0]-p2[0]) + p2Sq*(p1[0]-p3[0]) + p3Sq*(p2[0]-p1[0])) / (2*cp);
80
const float v1Sq = vdot2(v1,v1);
81
const float v2Sq = vdot2(v2,v2);
82
const float v3Sq = vdot2(v3,v3);
83
c[0] = (v1Sq*(v2[2]-v3[2]) + v2Sq*(v3[2]-v1[2]) + v3Sq*(v1[2]-v2[2])) / (2*cp);
85
c[2] = (v1Sq*(v3[0]-v2[0]) + v2Sq*(v1[0]-v3[0]) + v3Sq*(v2[0]-v1[0])) / (2*cp);
201
207
int ix = (int)floorf(fx*ics + 0.01f);
202
208
int iz = (int)floorf(fz*ics + 0.01f);
203
ix = rcClamp(ix-hp.xmin, 0, hp.width);
204
iz = rcClamp(iz-hp.ymin, 0, hp.height);
209
ix = rcClamp(ix-hp.xmin, 0, hp.width - 1);
210
iz = rcClamp(iz-hp.ymin, 0, hp.height - 1);
205
211
unsigned short h = hp.data[ix+iz*hp.width];
206
212
if (h == RC_UNSET_HEIGHT)
216
222
if (nx < 0 || nz < 0 || nx >= hp.width || nz >= hp.height) continue;
217
223
const unsigned short nh = hp.data[nx+nz*hp.width];
218
224
if (nh == RC_UNSET_HEIGHT) continue;
220
226
const float d = fabsf(nh*ch - fy);
227
/* const float dx = (nx+0.5f)*cs - fx;
228
const float dz = (nz+0.5f)*cs - fz;
229
const float d = dx*dx+dz*dz;
260
257
if (nedges >= maxEdges)
262
259
ctx->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges);
266
// Add edge if not already in the triangulation.
263
// Add edge if not already in the triangulation.
267
264
int e = findEdge(edges, nedges, s, t);
270
267
int* edge = &edges[nedges*4];
283
280
static void updateLeftFace(int* e, int s, int t, int f)
285
if (e[0] == s && e[1] == t && e[2] == UNDEF)
282
if (e[0] == s && e[1] == t && e[2] == EV_UNDEF)
287
else if (e[1] == s && e[0] == t && e[3] == UNDEF)
284
else if (e[1] == s && e[0] == t && e[3] == EV_UNDEF)
291
288
static int overlapSegSeg2d(const float* a, const float* b, const float* c, const float* d)
320
317
static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e)
322
319
static const float EPS = 1e-5f;
324
321
int* edge = &edges[e*4];
326
323
// Cache s and t.
328
if (edge[2] == UNDEF)
325
if (edge[2] == EV_UNDEF)
333
else if (edge[3] == UNDEF)
330
else if (edge[3] == EV_UNDEF)
340
// Edge already completed.
337
// Edge already completed.
344
// Find best point on left of edge.
341
// Find best point on left of edge.
346
343
float c[3] = {0,0,0};
388
// Add new triangle or update edge info if s-t is on hull.
385
// Add new triangle or update edge info if s-t is on hull.
391
// Update face information of edge being completed.
388
// Update face information of edge being completed.
392
389
updateLeftFace(&edges[e*4], s, t, nfaces);
394
// Add new edge or update face info of old edge.
391
// Add new edge or update face info of old edge.
395
392
e = findEdge(edges, nedges, pt, s);
397
addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, UNDEF);
394
addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, EV_UNDEF);
399
396
updateLeftFace(&edges[e*4], pt, s, nfaces);
401
// Add new edge or update face info of old edge.
398
// Add new edge or update face info of old edge.
402
399
e = findEdge(edges, nedges, t, pt);
404
addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, UNDEF);
401
addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, EV_UNDEF);
406
403
updateLeftFace(&edges[e*4], t, pt, nfaces);
423
420
edges.resize(maxEdges*4);
425
422
for (int i = 0, j = nhull-1; i < nhull; j=i++)
426
addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], HULL, UNDEF);
423
addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], EV_HULL, EV_UNDEF);
428
425
int currentEdge = 0;
429
426
while (currentEdge < nedges)
431
if (edges[currentEdge*4+2] == UNDEF)
428
if (edges[currentEdge*4+2] == EV_UNDEF)
432
429
completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge);
433
if (edges[currentEdge*4+3] == UNDEF)
430
if (edges[currentEdge*4+3] == EV_UNDEF)
434
431
completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge);
439
436
tris.resize(nfaces*4);
440
437
for (int i = 0; i < nfaces*4; ++i)
489
// Calculate minimum extend of the polygon.
490
static float polyMinExtent(const float* verts, const int nverts)
492
float minDist = FLT_MAX;
493
for (int i = 0; i < nverts; i++)
495
const int ni = (i+1) % nverts;
496
const float* p1 = &verts[i*3];
497
const float* p2 = &verts[ni*3];
498
float maxEdgeDist = 0;
499
for (int j = 0; j < nverts; j++)
501
if (j == i || j == ni) continue;
502
float d = distancePtSeg2d(&verts[j*3], p1,p2);
503
maxEdgeDist = rcMax(maxEdgeDist, d);
505
minDist = rcMin(minDist, maxEdgeDist);
507
return rcSqrt(minDist);
510
// Last time I checked the if version got compiled using cmov, which was a lot faster than module (with idiv).
511
inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; }
512
inline int next(int i, int n) { return i+1 < n ? i+1 : 0; }
514
static void triangulateHull(const int nverts, const float* verts, const int nhull, const int* hull, rcIntArray& tris)
516
int start = 0, left = 1, right = nhull-1;
518
// Start from an ear with shortest perimeter.
519
// This tends to favor well formed triangles as starting point.
521
for (int i = 0; i < nhull; i++)
523
int pi = prev(i, nhull);
524
int ni = next(i, nhull);
525
const float* pv = &verts[hull[pi]*3];
526
const float* cv = &verts[hull[i]*3];
527
const float* nv = &verts[hull[ni]*3];
528
const float d = vdist2(pv,cv) + vdist2(cv,nv) + vdist2(nv,pv);
538
// Add first triangle
539
tris.push(hull[start]);
540
tris.push(hull[left]);
541
tris.push(hull[right]);
544
// Triangulate the polygon by moving left or right,
545
// depending on which triangle has shorter perimeter.
546
// This heuristic was chose emprically, since it seems
547
// handle tesselated straight edges well.
548
while (next(left, nhull) != right)
550
// Check to see if se should advance left or right.
551
int nleft = next(left, nhull);
552
int nright = prev(right, nhull);
554
const float* cvleft = &verts[hull[left]*3];
555
const float* nvleft = &verts[hull[nleft]*3];
556
const float* cvright = &verts[hull[right]*3];
557
const float* nvright = &verts[hull[nright]*3];
558
const float dleft = vdist2(cvleft, nvleft) + vdist2(nvleft, cvright);
559
const float dright = vdist2(cvright, nvright) + vdist2(cvleft, nvright);
563
tris.push(hull[left]);
564
tris.push(hull[nleft]);
565
tris.push(hull[right]);
571
tris.push(hull[left]);
572
tris.push(hull[nright]);
573
tris.push(hull[right]);
493
581
inline float getJitterX(const int i)
512
600
float edge[(MAX_VERTS_PER_EDGE+1)*3];
513
601
int hull[MAX_VERTS];
518
606
for (int i = 0; i < nin; ++i)
519
607
rcVcopy(&verts[i*3], &in[i*3]);
522
613
const float cs = chf.cs;
523
614
const float ics = 1.0f/cs;
616
// Calculate minimum extents of the polygon based on input data.
617
float minExtent = polyMinExtent(verts, nverts);
525
619
// Tessellate outlines.
526
620
// This is done in separate pass in order to ensure
527
621
// seamless height values across the ply boundaries.
725
// If the polygon minimum extent is small (sliver or small triangle), do not try to add internal points.
726
if (minExtent < sampleDist*2)
728
triangulateHull(nverts, verts, nhull, hull, tris);
632
732
// Tessellate the base mesh.
636
delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges);
733
// We're using the triangulateHull instead of delaunayHull as it tends to
734
// create a bit better triangulation for long thing triangles when there
735
// are no internal points.
736
triangulateHull(nverts, verts, nhull, hull, tris);
638
738
if (tris.size() == 0)
640
740
// Could not triangulate the poly, make sure there is some valid data there.
641
ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data.");
642
for (int i = 2; i < nverts; ++i)
741
ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon (%d verts).", nverts);
652
745
if (sampleDist > 0)
654
747
// Create sample locations in a grid.
730
823
delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges);
734
827
const int ntris = tris.size()/4;
735
828
if (ntris > MAX_TRIS)
737
830
tris.resize(MAX_TRIS*4);
738
831
ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Shrinking triangle count from %d to max %d.", ntris, MAX_TRIS);
744
static void getHeightData(const rcCompactHeightfield& chf,
745
const unsigned short* poly, const int npoly,
746
const unsigned short* verts, const int bs,
747
rcHeightPatch& hp, rcIntArray& stack)
838
static void getHeightDataSeedsFromVertices(const rcCompactHeightfield& chf,
839
const unsigned short* poly, const int npoly,
840
const unsigned short* verts, const int bs,
841
rcHeightPatch& hp, rcIntArray& stack)
749
843
// Floodfill the heightfield to get 2D height data,
750
844
// starting at vertex locations as seeds.
869
963
int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width;
870
964
const rcCompactSpan& cs = chf.spans[ci];
871
965
hp.data[idx] = cs.y;
967
// getHeightData seeds are given in coordinates with borders
976
static void getHeightData(const rcCompactHeightfield& chf,
977
const unsigned short* poly, const int npoly,
978
const unsigned short* verts, const int bs,
979
rcHeightPatch& hp, rcIntArray& stack,
982
// Note: Reads to the compact heightfield are offset by border size (bs)
983
// since border size offset is already removed from the polymesh vertices.
986
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
990
// Copy the height from the same region, and mark region borders
991
// as seed points to fill the rest.
992
for (int hy = 0; hy < hp.height; hy++)
994
int y = hp.ymin + hy + bs;
995
for (int hx = 0; hx < hp.width; hx++)
997
int x = hp.xmin + hx + bs;
998
const rcCompactCell& c = chf.cells[x+y*chf.width];
999
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
1001
const rcCompactSpan& s = chf.spans[i];
1002
if (s.reg == region)
1005
hp.data[hx + hy*hp.width] = s.y;
1008
// If any of the neighbours is not in same region,
1009
// add the current location as flood fill start
1010
bool border = false;
1011
for (int dir = 0; dir < 4; ++dir)
1013
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
1015
const int ax = x + rcGetDirOffsetX(dir);
1016
const int ay = y + rcGetDirOffsetY(dir);
1017
const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
1018
const rcCompactSpan& as = chf.spans[ai];
1019
if (as.reg != region)
1038
// if the polygon does not contian any points from the current region (rare, but happens)
1039
// then use the cells closest to the polygon vertices as seeds to fill the height field
1041
getHeightDataSeedsFromVertices(chf, poly, npoly, verts, bs, hp, stack);
874
1043
static const int RETRACT_SIZE = 256;
896
1065
const int ax = cx + rcGetDirOffsetX(dir);
897
1066
const int ay = cy + rcGetDirOffsetY(dir);
899
if (ax < hp.xmin || ax >= (hp.xmin+hp.width) ||
900
ay < hp.ymin || ay >= (hp.ymin+hp.height))
903
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT)
906
const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
1067
const int hx = ax - hp.xmin - bs;
1068
const int hy = ay - hp.ymin - bs;
1070
if (hx < 0 || hx >= hp.width || hy < 0 || hy >= hp.height)
1073
if (hp.data[hx + hy*hp.width] != RC_UNSET_HEIGHT)
1076
const int ai = (int)chf.cells[ax + ay*chf.width].index + rcGetCon(cs, dir);
908
1077
const rcCompactSpan& as = chf.spans[ai];
909
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
1079
hp.data[hx + hy*hp.width] = as.y;
920
1088
static unsigned char getEdgeFlags(const float* va, const float* vb,
924
1092
static const float thrSqr = rcSqr(0.001f);
925
1093
for (int i = 0, j = npoly-1; i < npoly; j=i++)
927
if (distancePtSeg2d(va, &vpoly[j*3], &vpoly[i*3]) < thrSqr &&
1095
if (distancePtSeg2d(va, &vpoly[j*3], &vpoly[i*3]) < thrSqr &&
928
1096
distancePtSeg2d(vb, &vpoly[j*3], &vpoly[i*3]) < thrSqr)
1072
1240
hp.ymin = bounds[i*4+2];
1073
1241
hp.width = bounds[i*4+1]-bounds[i*4+0];
1074
1242
hp.height = bounds[i*4+3]-bounds[i*4+2];
1075
getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack);
1243
getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack, mesh.regs[i]);
1077
1245
// Build detail mesh.
1078
1246
int nverts = 0;
1098
1266
poly[j*3+1] += orig[1];
1099
1267
poly[j*3+2] += orig[2];
1102
1270
// Store detail submesh.
1103
1271
const int ntris = tris.size()/4;
1105
1273
dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts;
1106
1274
dmesh.meshes[i*4+1] = (unsigned int)nverts;
1107
1275
dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris;
1108
dmesh.meshes[i*4+3] = (unsigned int)ntris;
1276
dmesh.meshes[i*4+3] = (unsigned int)ntris;
1110
1278
// Store vertices, allocate more memory if necessary.
1111
1279
if (dmesh.nverts+nverts > vcap)
1113
1281
while (dmesh.nverts+nverts > vcap)
1116
1284
float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM);