37
37
#include "DNA_meshdata_types.h"
39
#include "BLI_utildefines.h"
39
42
#include "BKE_navmesh_conversion.h"
40
43
#include "BKE_cdderivedmesh.h"
42
#include "BLI_utildefines.h"
45
45
#include "recast-capi.h"
47
BLI_INLINE float area2(const float* a, const float* b, const float* c)
47
BLI_INLINE float area2(const float *a, const float *b, const float *c)
49
49
return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]);
52
BLI_INLINE int left(const float* a, const float* b, const float* c)
52
BLI_INLINE int left(const float *a, const float *b, const float *c)
54
54
return area2(a, b, c) < 0;
57
int polyNumVerts(const unsigned short* p, const int vertsPerPoly)
57
int polyNumVerts(const unsigned short *p, const int vertsPerPoly)
60
for (i=0; i<vertsPerPoly; i++)
60
for (i = 0; i < vertsPerPoly; i++) {
69
int polyIsConvex(const unsigned short* p, const int vertsPerPoly, const float* verts)
68
int polyIsConvex(const unsigned short *p, const int vertsPerPoly, const float *verts)
71
70
int j, nv = polyNumVerts(p, vertsPerPoly);
76
const float* v = &verts[3*p[j]];
77
const float* v_next = &verts[3*p[(j+1)%nv]];
78
const float* v_prev = &verts[3*p[(nv+j-1)%nv]];
73
for (j = 0; j < nv; j++) {
74
const float *v = &verts[3 * p[j]];
75
const float *v_next = &verts[3 * p[(j + 1) % nv]];
76
const float *v_prev = &verts[3 * p[(nv + j - 1) % nv]];
79
77
if (!left(v_prev, v, v_next))
86
float distPointToSegmentSq(const float* point, const float* a, const float* b)
84
/* XXX, could replace with #dist_to_line_segment_v3(), or add a squared version */
85
float distPointToSegmentSq(const float point[3], const float a[3], const float b[3])
88
87
float abx[3], dx[3];
91
sub_v3_v3v3(abx, b,a);
92
sub_v3_v3v3(dx, point,a);
94
d = abx[0]*abx[0]+abx[2]*abx[2];
95
t = abx[0]*dx[0]+abx[2]*dx[2];
90
sub_v3_v3v3(abx, b, a);
91
sub_v3_v3v3(dx, point, a);
93
d = abx[0] * abx[0] + abx[2] * abx[2];
94
t = abx[0] * dx[0] + abx[2] * dx[2];
103
dx[0] = a[0] + t*abx[0] - point[0];
104
dx[2] = a[2] + t*abx[2] - point[2];
102
dx[0] = a[0] + t * abx[0] - point[0];
103
dx[2] = a[2] + t * abx[2] - point[2];
106
return dx[0]*dx[0] + dx[2]*dx[2];
105
return dx[0] * dx[0] + dx[2] * dx[2];
109
int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r,
110
int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r,
108
int buildRawVertIndicesData(DerivedMesh *dm, int *nverts_r, float **verts_r,
109
int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r,
113
112
int vi, fi, triIdx;
114
113
int nverts, ntris;
121
120
nverts = dm->getNumVerts(dm);
121
if (nverts >= 0xffff) {
124
122
printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff);
127
verts = MEM_callocN(sizeof(float)*3*nverts, "buildRawVertIndicesData verts");
125
verts = MEM_callocN(sizeof(float) * 3 * nverts, "buildRawVertIndicesData verts");
128
126
dm->getVertCos(dm, (float(*)[3])verts);
131
for (vi=0; vi<nverts; vi++)
133
SWAP(float, verts[3*vi+1], verts[3*vi+2]);
128
/* flip coordinates */
129
for (vi = 0; vi < nverts; vi++) {
130
SWAP(float, verts[3 * vi + 1], verts[3 * vi + 2]);
136
//calculate number of tris
133
/* calculate number of tris */
137
134
nfaces = dm->getNumTessFaces(dm);
138
135
faces = dm->getTessFaceArray(dm);
140
for (fi=0; fi<nfaces; fi++)
142
MFace* face = &faces[fi];
137
for (fi = 0; fi < nfaces; fi++) {
138
MFace *face = &faces[fi];
147
//copy and transform to triangles (reorder on the run)
148
trisToFacesMap = MEM_callocN(sizeof(int)*ntris, "buildRawVertIndicesData trisToFacesMap");
149
tris = MEM_callocN(sizeof(unsigned short)*3*ntris, "buildRawVertIndicesData tris");
143
/* copy and transform to triangles (reorder on the run) */
144
trisToFacesMap = MEM_callocN(sizeof(int) * ntris, "buildRawVertIndicesData trisToFacesMap");
145
tris = MEM_callocN(sizeof(unsigned short) * 3 * ntris, "buildRawVertIndicesData tris");
152
for (fi=0; fi<nfaces; fi++)
154
MFace* face = &faces[fi];
155
tri[3*triIdx+0] = (unsigned short) face->v1;
156
tri[3*triIdx+1] = (unsigned short) face->v3;
157
tri[3*triIdx+2] = (unsigned short) face->v2;
158
trisToFacesMap[triIdx++]=fi;
161
tri[3*triIdx+0] = (unsigned short) face->v1;
162
tri[3*triIdx+1] = (unsigned short) face->v4;
163
tri[3*triIdx+2] = (unsigned short) face->v3;
164
trisToFacesMap[triIdx++]=fi;
148
for (fi = 0; fi < nfaces; fi++) {
149
MFace *face = &faces[fi];
150
tri[3 * triIdx + 0] = (unsigned short) face->v1;
151
tri[3 * triIdx + 1] = (unsigned short) face->v3;
152
tri[3 * triIdx + 2] = (unsigned short) face->v2;
153
trisToFacesMap[triIdx++] = fi;
155
tri[3 * triIdx + 0] = (unsigned short) face->v1;
156
tri[3 * triIdx + 1] = (unsigned short) face->v4;
157
tri[3 * triIdx + 2] = (unsigned short) face->v3;
158
trisToFacesMap[triIdx++] = fi;
168
//carefully, recast data is just reference to data in derived mesh
169
*recastData = (int*)CustomData_get_layer(&dm->polyData, CD_RECAST);
162
/* carefully, recast data is just reference to data in derived mesh */
163
*recastData = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST);
171
165
*nverts_r = nverts;
172
166
*verts_r = verts;
180
int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys,
181
unsigned short* polys, const unsigned short* dmeshes,
182
const float* verts, const unsigned short* dtris,
183
const int* dtrisToPolysMap)
174
int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys,
175
unsigned short *polys, const unsigned short *dmeshes,
176
const float *verts, const unsigned short *dtris,
177
const int *dtrisToPolysMap)
186
180
int capacity = vertsPerPoly;
187
unsigned short* newPoly = MEM_callocN(sizeof(unsigned short)*capacity, "buildPolygonsByDetailedMeshes newPoly");
188
memset(newPoly, 0xff, sizeof(unsigned short)*capacity);
181
unsigned short *newPoly = MEM_callocN(sizeof(unsigned short) * capacity, "buildPolygonsByDetailedMeshes newPoly");
182
memset(newPoly, 0xff, sizeof(unsigned short) * capacity);
190
for (polyidx=0; polyidx<npolys; polyidx++)
184
for (polyidx = 0; polyidx < npolys; polyidx++) {
196
189
int tri, btri = -1;
197
190
int edge, bedge = -1;
198
int dtrisNum = dmeshes[polyidx*4+3];
199
int dtrisBase = dmeshes[polyidx*4+2];
200
unsigned char *traversedTris = MEM_callocN(sizeof(unsigned char)*dtrisNum, "buildPolygonsByDetailedMeshes traversedTris");
201
unsigned short* adjustedPoly;
191
int dtrisNum = dmeshes[polyidx * 4 + 3];
192
int dtrisBase = dmeshes[polyidx * 4 + 2];
193
unsigned char *traversedTris = MEM_callocN(sizeof(unsigned char) * dtrisNum, "buildPolygonsByDetailedMeshes traversedTris");
194
unsigned short *adjustedPoly;
203
196
int allBorderTraversed;
205
for (j=0; j<dtrisNum && btri==-1;j++)
207
int curpolytri = dtrisBase+j;
210
unsigned short neighbortri = dtris[curpolytri*3*2+3+k];
211
if ( neighbortri==0xffff || dtrisToPolysMap[neighbortri]!=polyidx+1)
198
for (j = 0; j < dtrisNum && btri == -1; j++) {
199
int curpolytri = dtrisBase + j;
200
for (k = 0; k < 3; k++) {
201
unsigned short neighbortri = dtris[curpolytri * 3 * 2 + 3 + k];
202
if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) {
213
203
btri = curpolytri;
219
if (btri==-1 || bedge==-1)
221
//can't find triangle with border edge
209
if (btri == -1 || bedge == -1) {
210
/* can't find triangle with border edge */
222
211
MEM_freeN(traversedTris);
223
212
MEM_freeN(newPoly);
228
newPoly[nv++] = dtris[btri*3*2+bedge];
217
newPoly[nv++] = dtris[btri * 3 * 2 + bedge];
231
traversedTris[tri-dtrisBase] = 1;
232
while (tri!=btri || edge!=bedge)
234
int neighbortri = dtris[tri*3*2+3+edge];
235
if (neighbortri==0xffff || dtrisToPolysMap[neighbortri]!=polyidx+1)
239
unsigned short* newPolyBig;
219
edge = (bedge + 1) % 3;
220
traversedTris[tri - dtrisBase] = 1;
221
while (tri != btri || edge != bedge) {
222
int neighbortri = dtris[tri * 3 * 2 + 3 + edge];
223
if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) {
224
if (nv == capacity) {
225
unsigned short *newPolyBig;
240
226
capacity += vertsPerPoly;
241
newPolyBig = MEM_callocN(sizeof(unsigned short)*capacity, "buildPolygonsByDetailedMeshes newPolyBig");
242
memset(newPolyBig, 0xff, sizeof(unsigned short)*capacity);
243
memcpy(newPolyBig, newPoly, sizeof(unsigned short)*nv);
227
newPolyBig = MEM_callocN(sizeof(unsigned short) * capacity, "buildPolygonsByDetailedMeshes newPolyBig");
228
memset(newPolyBig, 0xff, sizeof(unsigned short) * capacity);
229
memcpy(newPolyBig, newPoly, sizeof(unsigned short) * nv);
244
230
MEM_freeN(newPoly);
245
newPoly = newPolyBig;
231
newPoly = newPolyBig;
247
newPoly[nv++] = dtris[tri*3*2+edge];
233
newPoly[nv++] = dtris[tri * 3 * 2 + edge];
234
/* move to next edge */
235
edge = (edge + 1) % 3;
238
/* move to next tri */
253
239
int twinedge = -1;
256
if (dtris[neighbortri*3*2+3+k] == tri)
240
for (k = 0; k < 3; k++) {
241
if (dtris[neighbortri * 3 * 2 + 3 + k] == tri) {
246
if (twinedge == -1) {
264
247
printf("Converting navmesh: Error! Can't find neighbor edge - invalid adjacency info\n");
265
248
MEM_freeN(traversedTris);
266
249
goto returnLabel;
268
251
tri = neighbortri;
269
edge = (twinedge+1)%3;
270
traversedTris[tri-dtrisBase] = 1;
252
edge = (twinedge + 1) % 3;
253
traversedTris[tri - dtrisBase] = 1;
274
adjustedPoly = MEM_callocN(sizeof(unsigned short)*nv, "buildPolygonsByDetailedMeshes adjustedPoly");
257
adjustedPoly = MEM_callocN(sizeof(unsigned short) * nv, "buildPolygonsByDetailedMeshes adjustedPoly");
278
unsigned short prev = newPoly[(nv+i-1)%nv];
259
for (i = 0; i < nv; i++) {
260
unsigned short prev = newPoly[(nv + i - 1) % nv];
279
261
unsigned short cur = newPoly[i];
280
unsigned short next = newPoly[(i+1)%nv];
281
float distSq = distPointToSegmentSq(&verts[3*cur], &verts[3*prev], &verts[3*next]);
262
unsigned short next = newPoly[(i + 1) % nv];
263
float distSq = distPointToSegmentSq(&verts[3 * cur], &verts[3 * prev], &verts[3 * next]);
282
264
static const float tolerance = 0.001f;
283
if (distSq>tolerance)
265
if (distSq > tolerance)
284
266
adjustedPoly[adjustedNv++] = cur;
286
memcpy(newPoly, adjustedPoly, adjustedNv*sizeof(unsigned short));
268
memcpy(newPoly, adjustedPoly, adjustedNv * sizeof(unsigned short));
287
269
MEM_freeN(adjustedPoly);
290
272
allBorderTraversed = 1;
291
for (i=0; i<dtrisNum; i++)
293
if (traversedTris[i]==0)
295
//check whether it has border edges
296
int curpolytri = dtrisBase+i;
299
unsigned short neighbortri = dtris[curpolytri*3*2+3+k];
300
if ( neighbortri==0xffff || dtrisToPolysMap[neighbortri]!=polyidx+1)
273
for (i = 0; i < dtrisNum; i++) {
274
if (traversedTris[i] == 0) {
275
/* check whether it has border edges */
276
int curpolytri = dtrisBase + i;
277
for (k = 0; k < 3; k++) {
278
unsigned short neighbortri = dtris[curpolytri * 3 * 2 + 3 + k];
279
if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) {
302
280
allBorderTraversed = 0;
309
if (nv<=vertsPerPoly && allBorderTraversed)
313
polys[polyidx*vertsPerPoly*2+i] = newPoly[i];
287
if (nv <= vertsPerPoly && allBorderTraversed) {
288
for (i = 0; i < nv; i++) {
289
polys[polyidx * vertsPerPoly * 2 + i] = newPoly[i];
328
const int* recastData;
329
const int* trisToFacesMap;
303
const int *recastData;
304
const int *trisToFacesMap;
332
static int compareByData(void *ctx, const void * a, const void * b)
307
static int compareByData(void *ctx, const void *a, const void *b)
334
return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)a]] -
335
((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] );
309
return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)a]] -
310
((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)b]]);
338
int buildNavMeshData(const int nverts, const float* verts,
339
const int ntris, const unsigned short *tris,
340
const int* recastData, const int* trisToFacesMap,
341
int *ndtris_r, unsigned short **dtris_r,
342
int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r,
343
int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r)
313
int buildNavMeshData(const int nverts, const float *verts,
314
const int ntris, const unsigned short *tris,
315
const int *recastData, const int *trisToFacesMap,
316
int *ndtris_r, unsigned short **dtris_r,
317
int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r,
318
int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r)
346
321
int *trisMapping;
353
328
unsigned short *dtris, *dmeshes, *polys;
354
329
int *dtrisToPolysMap, *dtrisToTrisMap;
358
332
printf("Converting navmesh: Error! Can't find recast custom data\n");
362
trisMapping = MEM_callocN(sizeof(int)*ntris, "buildNavMeshData trisMapping");
336
trisMapping = MEM_callocN(sizeof(int) * ntris, "buildNavMeshData trisMapping");
364
//sort the triangles by polygon idx
365
for (i=0; i<ntris; i++)
338
/* sort the triangles by polygon idx */
339
for (i = 0; i < ntris; i++)
367
341
context.recastData = recastData;
368
342
context.trisToFacesMap = trisToFacesMap;
369
343
recast_qsort(trisMapping, ntris, sizeof(int), &context, compareByData);
371
//search first valid triangle - triangle of convex polygon
345
/* search first valid triangle - triangle of convex polygon */
372
346
validTriStart = -1;
373
for (i=0; i< ntris; i++)
375
if (recastData[trisToFacesMap[trisMapping[i]]]>0)
347
for (i = 0; i < ntris; i++) {
348
if (recastData[trisToFacesMap[trisMapping[i]]] > 0) {
377
349
validTriStart = i;
354
if (validTriStart < 0) {
384
355
printf("Converting navmesh: Error! No valid polygons in mesh\n");
385
356
MEM_freeN(trisMapping);
389
ndtris = ntris-validTriStart;
390
//fill dtris to faces mapping
391
dtrisToTrisMap = MEM_callocN(sizeof(int)*ndtris, "buildNavMeshData dtrisToTrisMap");
392
memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris*sizeof(int));
360
ndtris = ntris - validTriStart;
361
/* fill dtris to faces mapping */
362
dtrisToTrisMap = MEM_callocN(sizeof(int) * ndtris, "buildNavMeshData dtrisToTrisMap");
363
memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris * sizeof(int));
393
364
MEM_freeN(trisMapping);
395
//create detailed mesh triangles - copy only valid triangles
396
//and reserve memory for adjacency info
397
dtris = MEM_callocN(sizeof(unsigned short)*3*2*ndtris, "buildNavMeshData dtris");
398
memset(dtris, 0xffff, sizeof(unsigned short)*3*2*ndtris);
399
for (i=0; i<ndtris; i++)
401
memcpy(dtris+3*2*i, tris+3*dtrisToTrisMap[i], sizeof(unsigned short)*3);
366
/* create detailed mesh triangles - copy only valid triangles
367
* and reserve memory for adjacency info */
368
dtris = MEM_callocN(sizeof(unsigned short) * 3 * 2 * ndtris, "buildNavMeshData dtris");
369
memset(dtris, 0xffff, sizeof(unsigned short) * 3 * 2 * ndtris);
370
for (i = 0; i < ndtris; i++) {
371
memcpy(dtris + 3 * 2 * i, tris + 3 * dtrisToTrisMap[i], sizeof(unsigned short) * 3);
404
//create new recast data corresponded to dtris and renumber for continuous indices
374
/* create new recast data corresponded to dtris and renumber for continuous indices */
405
375
prevPolyIdx = -1;
407
dtrisToPolysMap = MEM_callocN(sizeof(int)*ndtris, "buildNavMeshData dtrisToPolysMap");
408
for (i=0; i<ndtris; i++)
377
dtrisToPolysMap = MEM_callocN(sizeof(int) * ndtris, "buildNavMeshData dtrisToPolysMap");
378
for (i = 0; i < ndtris; i++) {
410
379
curPolyIdx = recastData[trisToFacesMap[dtrisToTrisMap[i]]];
411
if (curPolyIdx!=prevPolyIdx)
380
if (curPolyIdx != prevPolyIdx) {
414
prevPolyIdx=curPolyIdx;
382
prevPolyIdx = curPolyIdx;
416
384
dtrisToPolysMap[i] = newPolyIdx;
420
//build adjacency info for detailed mesh triangles
388
/* build adjacency info for detailed mesh triangles */
421
389
recast_buildMeshAdjacency(dtris, ndtris, nverts, 3);
423
//create detailed mesh description for each navigation polygon
424
npolys = dtrisToPolysMap[ndtris-1];
425
dmeshes = MEM_callocN(sizeof(unsigned short)*npolys*4, "buildNavMeshData dmeshes");
426
memset(dmeshes, 0, npolys*4*sizeof(unsigned short));
391
/* create detailed mesh description for each navigation polygon */
392
npolys = dtrisToPolysMap[ndtris - 1];
393
dmeshes = MEM_callocN(sizeof(unsigned short) * npolys * 4, "buildNavMeshData dmeshes");
394
memset(dmeshes, 0, npolys * 4 * sizeof(unsigned short));
429
for (i=0; i<ndtris; i++)
397
for (i = 0; i < ndtris; i++) {
431
398
int curpolyidx = dtrisToPolysMap[i];
432
if (curpolyidx!=prevpolyidx)
434
if (curpolyidx!=prevpolyidx+1)
399
if (curpolyidx != prevpolyidx) {
400
if (curpolyidx != prevpolyidx + 1) {
436
401
printf("Converting navmesh: Error! Wrong order of detailed mesh faces\n");
439
dmesh = dmesh==NULL ? dmeshes : dmesh+4;
440
dmesh[2] = (unsigned short)i; //tbase
404
dmesh = dmesh == NULL ? dmeshes : dmesh + 4;
405
dmesh[2] = (unsigned short)i; /* tbase */
406
dmesh[3] = 0; /* tnum */
442
407
prevpolyidx = curpolyidx;
447
//create navigation polygons
412
/* create navigation polygons */
448
413
vertsPerPoly = 6;
449
polys = MEM_callocN(sizeof(unsigned short)*npolys*vertsPerPoly*2, "buildNavMeshData polys");
450
memset(polys, 0xff, sizeof(unsigned short)*vertsPerPoly*2*npolys);
414
polys = MEM_callocN(sizeof(unsigned short) * npolys * vertsPerPoly * 2, "buildNavMeshData polys");
415
memset(polys, 0xff, sizeof(unsigned short) * vertsPerPoly * 2 * npolys);
452
417
buildPolygonsByDetailedMeshes(vertsPerPoly, npolys, polys, dmeshes, verts, dtris, dtrisToPolysMap);
467
int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly,
468
int *nverts, float **verts,
469
int *ndtris, unsigned short **dtris,
470
int *npolys, unsigned short **dmeshes,
471
unsigned short **polys, int **dtrisToPolysMap,
472
int **dtrisToTrisMap, int **trisToFacesMap)
432
int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly,
433
int *nverts, float **verts,
434
int *ndtris, unsigned short **dtris,
435
int *npolys, unsigned short **dmeshes,
436
unsigned short **polys, int **dtrisToPolysMap,
437
int **dtrisToTrisMap, int **trisToFacesMap)
475
int ntris = 0, *recastData=NULL;
476
unsigned short *tris=NULL;
440
int ntris = 0, *recastData = NULL;
441
unsigned short *tris = NULL;
478
443
res = buildRawVertIndicesData(dm, nverts, verts, &ntris, &tris, trisToFacesMap, &recastData);
481
445
printf("Converting navmesh: Error! Can't get vertices and indices from mesh\n");
485
449
res = buildNavMeshData(*nverts, *verts, ntris, tris, recastData, *trisToFacesMap,
486
ndtris, dtris, npolys, dmeshes,polys, vertsPerPoly,
487
dtrisToPolysMap, dtrisToTrisMap);
450
ndtris, dtris, npolys, dmeshes, polys, vertsPerPoly,
451
dtrisToPolysMap, dtrisToTrisMap);
490
453
printf("Converting navmesh: Error! Can't get vertices and indices from mesh\n");