forked from bartvdbraak/blender
navmesh: code clean-up, should be no functional changes.
This commit is contained in:
parent
dcccf3fc1f
commit
b66f219687
@ -17,12 +17,13 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2004 by Blender Foundation
|
||||
* The Original Code is Copyright (C) 2011 by Blender Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
* Contributor(s): Benoit Bolsee,
|
||||
* Nick Samarin
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
@ -67,89 +68,95 @@
|
||||
static void createVertsTrisData(bContext *C, LinkNode* obs, int *nverts_r, float **verts_r, int *ntris_r, int **tris_r)
|
||||
{
|
||||
MVert *mvert;
|
||||
int nfaces = 0, *tri, i, curnverts, basenverts, curnfaces;
|
||||
int nfaces= 0, *tri, i, curnverts, basenverts, curnfaces;
|
||||
MFace *mface;
|
||||
float co[3], wco[3];
|
||||
Object *ob;
|
||||
LinkNode *oblink, *dmlink;
|
||||
DerivedMesh *dm;
|
||||
Scene* scene = CTX_data_scene(C);
|
||||
LinkNode* dms = NULL;
|
||||
Scene* scene= CTX_data_scene(C);
|
||||
LinkNode* dms= NULL;
|
||||
|
||||
int nverts, ntris, *tris;
|
||||
float *verts;
|
||||
|
||||
nverts = 0;
|
||||
ntris = 0;
|
||||
//calculate number of verts and tris
|
||||
for (oblink = obs; oblink; oblink = oblink->next)
|
||||
{
|
||||
ob = (Object*) oblink->link;
|
||||
dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
|
||||
nverts= 0;
|
||||
ntris= 0;
|
||||
|
||||
/* calculate number of verts and tris */
|
||||
for(oblink= obs; oblink; oblink= oblink->next) {
|
||||
ob= (Object*) oblink->link;
|
||||
dm= mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
|
||||
BLI_linklist_append(&dms, (void*)dm);
|
||||
|
||||
nverts += dm->getNumVerts(dm);
|
||||
nfaces = dm->getNumFaces(dm);
|
||||
ntris += nfaces;
|
||||
nverts+= dm->getNumVerts(dm);
|
||||
nfaces= dm->getNumFaces(dm);
|
||||
ntris+= nfaces;
|
||||
|
||||
//resolve quad faces
|
||||
mface = dm->getFaceArray(dm);
|
||||
for (i=0; i<nfaces; i++)
|
||||
{
|
||||
MFace* mf = &mface[i];
|
||||
if (mf->v4)
|
||||
/* resolve quad faces */
|
||||
mface= dm->getFaceArray(dm);
|
||||
for(i= 0; i<nfaces; i++) {
|
||||
MFace* mf= &mface[i];
|
||||
if(mf->v4)
|
||||
ntris+=1;
|
||||
}
|
||||
}
|
||||
|
||||
//create data
|
||||
verts = MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts");
|
||||
tris = MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces");
|
||||
/* create data */
|
||||
verts= MEM_mallocN(sizeof(float)*3*nverts, "createVertsTrisData verts");
|
||||
tris= MEM_mallocN(sizeof(int)*3*ntris, "createVertsTrisData faces");
|
||||
|
||||
basenverts = 0;
|
||||
tri = tris;
|
||||
for (oblink = obs, dmlink = dms; oblink && dmlink;
|
||||
oblink = oblink->next, dmlink = dmlink->next)
|
||||
{
|
||||
ob = (Object*) oblink->link;
|
||||
dm = (DerivedMesh*) dmlink->link;
|
||||
basenverts= 0;
|
||||
tri= tris;
|
||||
for(oblink= obs, dmlink= dms; oblink && dmlink;
|
||||
oblink= oblink->next, dmlink= dmlink->next) {
|
||||
ob= (Object*) oblink->link;
|
||||
dm= (DerivedMesh*) dmlink->link;
|
||||
|
||||
curnverts= dm->getNumVerts(dm);
|
||||
mvert= dm->getVertArray(dm);
|
||||
|
||||
/* copy verts */
|
||||
for(i= 0; i<curnverts; i++) {
|
||||
MVert *v= &mvert[i];
|
||||
|
||||
curnverts = dm->getNumVerts(dm);
|
||||
mvert = dm->getVertArray(dm);
|
||||
//copy verts
|
||||
for (i=0; i<curnverts; i++)
|
||||
{
|
||||
MVert *v = &mvert[i];
|
||||
copy_v3_v3(co, v->co);
|
||||
mul_v3_m4v3(wco, ob->obmat, co);
|
||||
verts[3*(basenverts+i)+0] = wco[0];
|
||||
verts[3*(basenverts+i)+1] = wco[2];
|
||||
verts[3*(basenverts+i)+2] = wco[1];
|
||||
|
||||
verts[3*(basenverts+i)+0]= wco[0];
|
||||
verts[3*(basenverts+i)+1]= wco[2];
|
||||
verts[3*(basenverts+i)+2]= wco[1];
|
||||
}
|
||||
|
||||
//create tris
|
||||
curnfaces = dm->getNumFaces(dm);
|
||||
mface = dm->getFaceArray(dm);
|
||||
for (i=0; i<curnfaces; i++)
|
||||
{
|
||||
MFace* mf = &mface[i];
|
||||
tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v3; tri[2]= basenverts + mf->v2;
|
||||
/* create tris */
|
||||
curnfaces= dm->getNumFaces(dm);
|
||||
mface= dm->getFaceArray(dm);
|
||||
|
||||
for(i= 0; i<curnfaces; i++) {
|
||||
MFace* mf= &mface[i];
|
||||
|
||||
tri[0]= basenverts + mf->v1;
|
||||
tri[1]= basenverts + mf->v3;
|
||||
tri[2]= basenverts + mf->v2;
|
||||
tri += 3;
|
||||
if (mf->v4)
|
||||
{
|
||||
tri[0]= basenverts + mf->v1; tri[1]= basenverts + mf->v4; tri[2]= basenverts + mf->v3;
|
||||
|
||||
if(mf->v4) {
|
||||
tri[0]= basenverts + mf->v1;
|
||||
tri[1]= basenverts + mf->v4;
|
||||
tri[2]= basenverts + mf->v3;
|
||||
tri += 3;
|
||||
}
|
||||
}
|
||||
basenverts += curnverts;
|
||||
|
||||
basenverts+= curnverts;
|
||||
}
|
||||
|
||||
//release derived mesh
|
||||
for (dmlink = dms; dmlink; dmlink = dmlink->next)
|
||||
{
|
||||
dm = (DerivedMesh*) dmlink->link;
|
||||
/* release derived mesh */
|
||||
for(dmlink= dms; dmlink; dmlink= dmlink->next) {
|
||||
dm= (DerivedMesh*) dmlink->link;
|
||||
dm->release(dm);
|
||||
}
|
||||
|
||||
BLI_linklist_free(dms, NULL);
|
||||
|
||||
*nverts_r= nverts;
|
||||
@ -172,101 +179,46 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
|
||||
recast_calcBounds(verts, nverts, bmin, bmax);
|
||||
|
||||
//
|
||||
// Step 1. Initialize build config.
|
||||
//
|
||||
{
|
||||
/*
|
||||
float cellsize = 0.3f;
|
||||
float cellheight = 0.2f;
|
||||
float agentmaxslope = M_PI/4;
|
||||
float agentmaxclimb = 0.9f;
|
||||
float agentheight = 2.0f;
|
||||
float agentradius = 0.6f;
|
||||
float edgemaxlen = 12.0f;
|
||||
float edgemaxerror = 1.3f;
|
||||
float regionminsize = 50.f;
|
||||
float regionmergesize = 20.f;
|
||||
int vertsperpoly = 6;
|
||||
float detailsampledist = 6.0f;
|
||||
float detailsamplemaxerror = 1.0f;
|
||||
cfg.cs = cellsize;
|
||||
cfg.ch = cellheight;
|
||||
cfg.walkableSlopeAngle = agentmaxslope/M_PI*180.f;
|
||||
cfg.walkableHeight = (int)ceilf(agentheight/ cfg.ch);
|
||||
cfg.walkableClimb = (int)floorf(agentmaxclimb / cfg.ch);
|
||||
cfg.walkableRadius = (int)ceilf(agentradius / cfg.cs);
|
||||
cfg.maxEdgeLen = (int)(edgemaxlen/cellsize);
|
||||
cfg.maxSimplificationError = edgemaxerror;
|
||||
cfg.minRegionSize = (int)rcSqr(regionminsize);
|
||||
cfg.mergeRegionSize = (int)rcSqr(regionmergesize);
|
||||
cfg.maxVertsPerPoly = vertsperpoly;
|
||||
cfg.detailSampleDist = detailsampledist< 0.9f ? 0 : cellsize * detailsampledist;
|
||||
cfg.detailSampleMaxError = cellheight * detailsamplemaxerror;
|
||||
*/
|
||||
#if 0
|
||||
cfg.cs = recastParams.cellsize;
|
||||
cfg.ch = recastParams.cellheight;
|
||||
cfg.walkableSlopeAngle = recastParams.agentmaxslope/((float)M_PI)*180.f;
|
||||
cfg.walkableHeight = (int)ceilf(recastParams.agentheight/ cfg.ch);
|
||||
cfg.walkableClimb = (int)floorf(recastParams.agentmaxclimb / cfg.ch);
|
||||
cfg.walkableRadius = (int)ceilf(recastParams.agentradius / cfg.cs);
|
||||
cfg.maxEdgeLen = (int)(recastParams.edgemaxlen/recastParams.cellsize);
|
||||
cfg.maxSimplificationError = recastParams.edgemaxerror;
|
||||
cfg.minRegionSize = (int)rcSqr(recastParams.regionminsize);
|
||||
cfg.mergeRegionSize = (int)rcSqr(recastParams.regionmergesize);
|
||||
cfg.maxVertsPerPoly = recastParams.vertsperpoly;
|
||||
cfg.detailSampleDist = recastParams.detailsampledist< 0.9f ? 0 :
|
||||
recastParams.cellsize * recastParams.detailsampledist;
|
||||
cfg.detailSampleMaxError = recastParams.cellheight * recastParams.detailsamplemaxerror;
|
||||
#endif
|
||||
}
|
||||
|
||||
walkableHeight = (int)ceilf(recastParams->agentheight/ recastParams->cellheight);
|
||||
walkableClimb = (int)floorf(recastParams->agentmaxclimb / recastParams->cellheight);
|
||||
walkableRadius = (int)ceilf(recastParams->agentradius / recastParams->cellsize);
|
||||
minRegionSize = (int)(recastParams->regionminsize * recastParams->regionminsize);
|
||||
mergeRegionSize = (int)(recastParams->regionmergesize * recastParams->regionmergesize);
|
||||
maxEdgeLen = (int)(recastParams->edgemaxlen/recastParams->cellsize);
|
||||
detailSampleDist = recastParams->detailsampledist< 0.9f ? 0 :
|
||||
/* ** Step 1. Initialize build config ** */
|
||||
walkableHeight= (int)ceilf(recastParams->agentheight/ recastParams->cellheight);
|
||||
walkableClimb= (int)floorf(recastParams->agentmaxclimb / recastParams->cellheight);
|
||||
walkableRadius= (int)ceilf(recastParams->agentradius / recastParams->cellsize);
|
||||
minRegionSize= (int)(recastParams->regionminsize * recastParams->regionminsize);
|
||||
mergeRegionSize= (int)(recastParams->regionmergesize * recastParams->regionmergesize);
|
||||
maxEdgeLen= (int)(recastParams->edgemaxlen/recastParams->cellsize);
|
||||
detailSampleDist= recastParams->detailsampledist< 0.9f ? 0 :
|
||||
recastParams->cellsize * recastParams->detailsampledist;
|
||||
detailSampleMaxError = recastParams->cellheight * recastParams->detailsamplemaxerror;
|
||||
detailSampleMaxError= recastParams->cellheight * recastParams->detailsamplemaxerror;
|
||||
|
||||
// Set the area where the navigation will be build.
|
||||
/* Set the area where the navigation will be build. */
|
||||
recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height);
|
||||
|
||||
//
|
||||
// Step 2. Rasterize input polygon soup.
|
||||
//
|
||||
// Allocate voxel heightfield where we rasterize our input data to.
|
||||
solid = recast_newHeightfield();
|
||||
/* ** Step 2: Rasterize input polygon soup ** */
|
||||
/* Allocate voxel heightfield where we rasterize our input data to */
|
||||
solid= recast_newHeightfield();
|
||||
|
||||
if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
|
||||
if(!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) {
|
||||
recast_destroyHeightfield(solid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate array that can hold triangle flags.
|
||||
triflags = MEM_callocN(sizeof(unsigned char)*ntris, "buildNavMesh triflags");
|
||||
/* Allocate array that can hold triangle flags */
|
||||
triflags= MEM_callocN(sizeof(unsigned char)*ntris, "buildNavMesh triflags");
|
||||
|
||||
// Find triangles which are walkable based on their slope and rasterize them.
|
||||
/* Find triangles which are walkable based on their slope and rasterize them */
|
||||
recast_markWalkableTriangles(RAD2DEG(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags);
|
||||
recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid);
|
||||
MEM_freeN(triflags);
|
||||
|
||||
//
|
||||
// Step 3. Filter walkables surfaces.
|
||||
//
|
||||
/* ** Step 3: Filter walkables surfaces ** */
|
||||
recast_filterLedgeSpans(walkableHeight, walkableClimb, solid);
|
||||
recast_filterWalkableLowHeightSpans(walkableHeight, solid);
|
||||
|
||||
//
|
||||
// Step 4. Partition walkable surface to simple regions.
|
||||
//
|
||||
/* ** Step 4: Partition walkable surface to simple regions ** */
|
||||
|
||||
chf = recast_newCompactHeightfield();
|
||||
if (!recast_buildCompactHeightfield(walkableHeight, walkableClimb, RECAST_WALKABLE, solid, chf)) {
|
||||
chf= recast_newCompactHeightfield();
|
||||
if(!recast_buildCompactHeightfield(walkableHeight, walkableClimb, RECAST_WALKABLE, solid, chf)) {
|
||||
recast_destroyHeightfield(solid);
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
@ -275,38 +227,34 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
|
||||
recast_destroyHeightfield(solid);
|
||||
|
||||
// Prepare for region partitioning, by calculating distance field along the walkable surface.
|
||||
if (!recast_buildDistanceField(chf)) {
|
||||
/* Prepare for region partitioning, by calculating distance field along the walkable surface */
|
||||
if(!recast_buildDistanceField(chf)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Partition the walkable surface into simple regions without holes.
|
||||
if (!recast_buildRegions(chf, walkableRadius, 0, minRegionSize, mergeRegionSize)) {
|
||||
/* Partition the walkable surface into simple regions without holes */
|
||||
if(!recast_buildRegions(chf, walkableRadius, 0, minRegionSize, mergeRegionSize)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 5. Trace and simplify region contours.
|
||||
//
|
||||
// Create contours.
|
||||
cset = recast_newContourSet();
|
||||
/* ** Step 5: Trace and simplify region contours ** */
|
||||
/* Create contours */
|
||||
cset= recast_newContourSet();
|
||||
|
||||
if (!recast_buildContours(chf, recastParams->edgemaxerror, maxEdgeLen, cset)) {
|
||||
if(!recast_buildContours(chf, recastParams->edgemaxerror, maxEdgeLen, cset)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
recast_destroyContourSet(cset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 6. Build polygons mesh from contours.
|
||||
//
|
||||
*pmesh = recast_newPolyMesh();
|
||||
if (!recast_buildPolyMesh(cset, recastParams->vertsperpoly, *pmesh)) {
|
||||
/* ** Step 6: Build polygons mesh from contours ** */
|
||||
*pmesh= recast_newPolyMesh();
|
||||
if(!recast_buildPolyMesh(cset, recastParams->vertsperpoly, *pmesh)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
recast_destroyContourSet(cset);
|
||||
recast_destroyPolyMesh(*pmesh);
|
||||
@ -315,12 +263,10 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Step 7. Create detail mesh which allows to access approximate height on each polygon.
|
||||
//
|
||||
/* ** Step 7: Create detail mesh which allows to access approximate height on each polygon ** */
|
||||
|
||||
*dmesh = recast_newPolyMeshDetail();
|
||||
if (!recast_buildPolyMeshDetail(*pmesh, chf, detailSampleDist, detailSampleMaxError, *dmesh)) {
|
||||
*dmesh= recast_newPolyMeshDetail();
|
||||
if(!recast_buildPolyMeshDetail(*pmesh, chf, detailSampleDist, detailSampleMaxError, *dmesh)) {
|
||||
recast_destroyCompactHeightfield(chf);
|
||||
recast_destroyContourSet(cset);
|
||||
recast_destroyPolyMesh(*pmesh);
|
||||
@ -342,10 +288,10 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
int i,j, k;
|
||||
unsigned short* v;
|
||||
int face[3];
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Main *bmain= CTX_data_main(C);
|
||||
Scene *scene= CTX_data_scene(C);
|
||||
Object* obedit;
|
||||
int createob = base==NULL;
|
||||
int createob= base==NULL;
|
||||
int nverts, nmeshes, nvp;
|
||||
unsigned short *verts, *meshes, *polys;
|
||||
float bmin[3], cs, ch, *dverts;
|
||||
@ -355,71 +301,67 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
zero_v3(co);
|
||||
zero_v3(rot);
|
||||
|
||||
if (createob)
|
||||
{
|
||||
//create new object
|
||||
obedit = ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1);
|
||||
if(createob) {
|
||||
/* create new object */
|
||||
obedit= ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
obedit = base->object;
|
||||
else {
|
||||
obedit= base->object;
|
||||
scene_select_base(scene, base);
|
||||
copy_v3_v3(obedit->loc, co);
|
||||
copy_v3_v3(obedit->rot, rot);
|
||||
}
|
||||
|
||||
ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER);
|
||||
em = BKE_mesh_get_editmesh(((Mesh *)obedit->data));
|
||||
em= BKE_mesh_get_editmesh(((Mesh *)obedit->data));
|
||||
|
||||
if (!createob)
|
||||
{
|
||||
//clear
|
||||
if(!createob) {
|
||||
/* clear */
|
||||
if(em->verts.first) free_vertlist(em, &em->verts);
|
||||
if(em->edges.first) free_edgelist(em, &em->edges);
|
||||
if(em->faces.first) free_facelist(em, &em->faces);
|
||||
if(em->selected.first) BLI_freelistN(&(em->selected));
|
||||
}
|
||||
|
||||
//create verts for polygon mesh
|
||||
verts = recast_polyMeshGetVerts(pmesh, &nverts);
|
||||
/* create verts for polygon mesh */
|
||||
verts= recast_polyMeshGetVerts(pmesh, &nverts);
|
||||
recast_polyMeshGetBoundbox(pmesh, bmin, NULL);
|
||||
recast_polyMeshGetCell(pmesh, &cs, &ch);
|
||||
|
||||
for(i = 0; i < nverts; i++) {
|
||||
v = &verts[3*i];
|
||||
co[0] = bmin[0] + v[0]*cs;
|
||||
co[1] = bmin[1] + v[1]*ch;
|
||||
co[2] = bmin[2] + v[2]*cs;
|
||||
for(i= 0; i<nverts; i++) {
|
||||
v= &verts[3*i];
|
||||
co[0]= bmin[0] + v[0]*cs;
|
||||
co[1]= bmin[1] + v[1]*ch;
|
||||
co[2]= bmin[2] + v[2]*cs;
|
||||
SWAP(float, co[1], co[2]);
|
||||
addvertlist(em, co, NULL);
|
||||
}
|
||||
|
||||
//create custom data layer to save polygon idx
|
||||
CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "recastData");
|
||||
/* create custom data layer to save polygon idx */
|
||||
CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData");
|
||||
|
||||
//create verts and faces for detailed mesh
|
||||
meshes = recast_polyMeshDetailGetMeshes(dmesh, &nmeshes);
|
||||
polys = recast_polyMeshGetPolys(pmesh, NULL, &nvp);
|
||||
dverts = recast_polyMeshDetailGetVerts(dmesh, NULL);
|
||||
tris = recast_polyMeshDetailGetTris(dmesh, NULL);
|
||||
/* create verts and faces for detailed mesh */
|
||||
meshes= recast_polyMeshDetailGetMeshes(dmesh, &nmeshes);
|
||||
polys= recast_polyMeshGetPolys(pmesh, NULL, &nvp);
|
||||
dverts= recast_polyMeshDetailGetVerts(dmesh, NULL);
|
||||
tris= recast_polyMeshDetailGetTris(dmesh, NULL);
|
||||
|
||||
for (i=0; i<nmeshes; i++)
|
||||
{
|
||||
int uniquevbase = em->totvert;
|
||||
unsigned short vbase = meshes[4*i+0];
|
||||
unsigned short ndv = meshes[4*i+1];
|
||||
unsigned short tribase = meshes[4*i+2];
|
||||
unsigned short trinum = meshes[4*i+3];
|
||||
const unsigned short* p = &polys[i*nvp*2];
|
||||
int nv = 0;
|
||||
for (j = 0; j < nvp; ++j)
|
||||
{
|
||||
if (p[j] == 0xffff) break;
|
||||
for(i= 0; i<nmeshes; i++) {
|
||||
int uniquevbase= em->totvert;
|
||||
unsigned short vbase= meshes[4*i+0];
|
||||
unsigned short ndv= meshes[4*i+1];
|
||||
unsigned short tribase= meshes[4*i+2];
|
||||
unsigned short trinum= meshes[4*i+3];
|
||||
const unsigned short* p= &polys[i*nvp*2];
|
||||
int nv= 0;
|
||||
|
||||
for(j= 0; j < nvp; ++j) {
|
||||
if(p[j]==0xffff) break;
|
||||
nv++;
|
||||
}
|
||||
//create unique verts
|
||||
for (j=nv; j<ndv; j++)
|
||||
{
|
||||
|
||||
/* create unique verts */
|
||||
for(j= nv; j<ndv; j++) {
|
||||
copy_v3_v3(co, &dverts[3*(vbase + j)]);
|
||||
SWAP(float, co[1], co[2]);
|
||||
addvertlist(em, co, NULL);
|
||||
@ -427,26 +369,24 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
|
||||
EM_init_index_arrays(em, 1, 0, 0);
|
||||
|
||||
//create faces
|
||||
for (j=0; j<trinum; j++)
|
||||
{
|
||||
unsigned char* tri = &tris[4*(tribase+j)];
|
||||
/* create faces */
|
||||
for(j= 0; j<trinum; j++) {
|
||||
unsigned char* tri= &tris[4*(tribase+j)];
|
||||
EditFace* newFace;
|
||||
int* polygonIdx;
|
||||
|
||||
for (k=0; k<3; k++)
|
||||
{
|
||||
if (tri[k]<nv)
|
||||
face[k] = p[tri[k]]; //shared vertex
|
||||
for(k= 0; k<3; k++) {
|
||||
if(tri[k]<nv)
|
||||
face[k]= p[tri[k]]; /* shared vertex */
|
||||
else
|
||||
face[k] = uniquevbase+tri[k]-nv; //unique vertex
|
||||
face[k]= uniquevbase+tri[k]-nv; /* unique vertex */
|
||||
}
|
||||
newFace = addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[2]),
|
||||
newFace= addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[2]),
|
||||
EM_get_vert_for_index(face[1]), NULL, NULL, NULL);
|
||||
|
||||
//set navigation polygon idx to the custom layer
|
||||
polygonIdx = (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST);
|
||||
*polygonIdx = i+1; //add 1 to avoid zero idx
|
||||
/* set navigation polygon idx to the custom layer */
|
||||
polygonIdx= (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST);
|
||||
*polygonIdx= i+1; /* add 1 to avoid zero idx */
|
||||
}
|
||||
|
||||
EM_free_index_arrays();
|
||||
@ -464,17 +404,15 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
ED_object_exit_editmode(C, EM_FREEDATA);
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
|
||||
|
||||
if (createob)
|
||||
{
|
||||
obedit->gameflag &= ~OB_COLLISION;
|
||||
obedit->gameflag |= OB_NAVMESH;
|
||||
obedit->body_type = OB_BODY_TYPE_NAVMESH;
|
||||
if(createob) {
|
||||
obedit->gameflag&= ~OB_COLLISION;
|
||||
obedit->gameflag|= OB_NAVMESH;
|
||||
obedit->body_type= OB_BODY_TYPE_NAVMESH;
|
||||
rename_id((ID *)obedit, "Navmesh");
|
||||
}
|
||||
|
||||
md= modifiers_findByType(obedit, eModifierType_NavMesh);
|
||||
if (!md)
|
||||
{
|
||||
if(!md) {
|
||||
ED_object_modifier_add(NULL, bmain, scene, obedit, NULL, eModifierType_NavMesh);
|
||||
}
|
||||
|
||||
@ -483,33 +421,25 @@ static Object* createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
|
||||
|
||||
static int create_navmesh_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Scene* scene = CTX_data_scene(C);
|
||||
Scene* scene= CTX_data_scene(C);
|
||||
int nverts, ntris;
|
||||
float* verts;
|
||||
int* tris;
|
||||
struct recast_polyMesh *pmesh;
|
||||
struct recast_polyMeshDetail *dmesh;
|
||||
LinkNode* obs = NULL;
|
||||
Base* navmeshBase = NULL;
|
||||
LinkNode* obs= NULL;
|
||||
Base* navmeshBase= NULL;
|
||||
|
||||
//CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) //expand macros to avoid error in convertion from void*
|
||||
{
|
||||
ListBase ctx_data_list;
|
||||
CollectionPointerLink *ctx_link;
|
||||
CTX_data_selected_editable_bases(C, &ctx_data_list);
|
||||
for(ctx_link = (CollectionPointerLink *)ctx_data_list.first;
|
||||
ctx_link; ctx_link = (CollectionPointerLink *)ctx_link->next) {
|
||||
Base* base= (Base*)ctx_link->ptr.data;
|
||||
{
|
||||
if (base->object->body_type==OB_BODY_TYPE_NAVMESH)
|
||||
{
|
||||
if (!navmeshBase || base==CTX_data_active_base(C))
|
||||
navmeshBase = base;
|
||||
CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
|
||||
if(base->object->body_type==OB_BODY_TYPE_NAVMESH) {
|
||||
if(!navmeshBase || base==CTX_data_active_base(C))
|
||||
navmeshBase= base;
|
||||
}
|
||||
else
|
||||
BLI_linklist_append(&obs, (void*)base->object);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris);
|
||||
BLI_linklist_free(obs, NULL);
|
||||
buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh);
|
||||
@ -540,28 +470,25 @@ static int assign_navpolygon_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
||||
|
||||
//do work here
|
||||
int targetPolyIdx = -1;
|
||||
/* do work here */
|
||||
int targetPolyIdx= -1;
|
||||
EditFace *ef, *efa;
|
||||
efa = EM_get_actFace(em, 0);
|
||||
if (efa)
|
||||
{
|
||||
if (CustomData_has_layer(&em->fdata, CD_RECAST))
|
||||
{
|
||||
targetPolyIdx = *(int*)CustomData_em_get(&em->fdata, efa->data, CD_RECAST);
|
||||
targetPolyIdx = targetPolyIdx>=0? targetPolyIdx : -targetPolyIdx;
|
||||
if (targetPolyIdx>0)
|
||||
{
|
||||
//set target poly idx to other selected faces
|
||||
ef = (EditFace*)em->faces.last;
|
||||
while(ef)
|
||||
{
|
||||
if((ef->f & SELECT )&& ef!=efa)
|
||||
{
|
||||
int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
*recastDataBlock = targetPolyIdx;
|
||||
efa= EM_get_actFace(em, 0);
|
||||
|
||||
if(efa) {
|
||||
if(CustomData_has_layer(&em->fdata, CD_RECAST)) {
|
||||
targetPolyIdx= *(int*)CustomData_em_get(&em->fdata, efa->data, CD_RECAST);
|
||||
targetPolyIdx= targetPolyIdx>=0? targetPolyIdx : -targetPolyIdx;
|
||||
|
||||
if(targetPolyIdx>0) {
|
||||
/* set target poly idx to other selected faces */
|
||||
ef= (EditFace*)em->faces.last;
|
||||
while(ef) {
|
||||
if((ef->f & SELECT )&& ef!=efa) {
|
||||
int* recastDataBlock= (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
*recastDataBlock= targetPolyIdx;
|
||||
}
|
||||
ef = ef->prev;
|
||||
ef= ef->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -571,6 +498,7 @@ static int assign_navpolygon_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
|
||||
|
||||
BKE_mesh_end_editmesh((Mesh*)obedit->data, em);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
@ -595,29 +523,27 @@ static int compare(const void * a, const void * b){
|
||||
|
||||
static int findFreeNavPolyIndex(EditMesh* em)
|
||||
{
|
||||
//construct vector of indices
|
||||
int numfaces = em->totface;
|
||||
int* indices = MEM_callocN(sizeof(int)*numfaces, "findFreeNavPolyIndex(indices)");
|
||||
EditFace* ef = (EditFace*)em->faces.last;
|
||||
int i, idx = 0, freeIdx = 1;
|
||||
/* construct vector of indices */
|
||||
int numfaces= em->totface;
|
||||
int* indices= MEM_callocN(sizeof(int)*numfaces, "findFreeNavPolyIndex(indices)");
|
||||
EditFace* ef= (EditFace*)em->faces.last;
|
||||
int i, idx= 0, freeIdx= 1;
|
||||
|
||||
while(ef)
|
||||
{
|
||||
int polyIdx = *(int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
indices[idx] = polyIdx;
|
||||
while(ef) {
|
||||
int polyIdx= *(int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
indices[idx]= polyIdx;
|
||||
idx++;
|
||||
ef = ef->prev;
|
||||
ef= ef->prev;
|
||||
}
|
||||
|
||||
qsort(indices, numfaces, sizeof(int), compare);
|
||||
|
||||
//search first free index
|
||||
freeIdx = 1;
|
||||
for (i=0; i<numfaces; i++)
|
||||
{
|
||||
if (indices[i]==freeIdx)
|
||||
/* search first free index */
|
||||
freeIdx= 1;
|
||||
for(i= 0; i<numfaces; i++) {
|
||||
if(indices[i]==freeIdx)
|
||||
freeIdx++;
|
||||
else if (indices[i]>freeIdx)
|
||||
else if(indices[i]>freeIdx)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -630,23 +556,20 @@ static int assign_new_navpolygon_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
|
||||
|
||||
EditFace *ef;
|
||||
if (CustomData_has_layer(&em->fdata, CD_RECAST))
|
||||
{
|
||||
int targetPolyIdx = findFreeNavPolyIndex(em);
|
||||
if (targetPolyIdx>0)
|
||||
{
|
||||
//set target poly idx to selected faces
|
||||
ef = (EditFace*)em->faces.last;
|
||||
while(ef)
|
||||
{
|
||||
if(ef->f & SELECT )
|
||||
{
|
||||
int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
*recastDataBlock = targetPolyIdx;
|
||||
|
||||
if(CustomData_has_layer(&em->fdata, CD_RECAST)) {
|
||||
int targetPolyIdx= findFreeNavPolyIndex(em);
|
||||
|
||||
if(targetPolyIdx>0) {
|
||||
/* set target poly idx to selected faces */
|
||||
ef= (EditFace*)em->faces.last;
|
||||
while(ef) {
|
||||
if(ef->f & SELECT) {
|
||||
int *recastDataBlock= (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST);
|
||||
*recastDataBlock= targetPolyIdx;
|
||||
}
|
||||
ef = ef->prev;
|
||||
ef= ef->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user