From 36e27b07658440117f7bb3dbfee3d5812b6e0e83 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Fri, 9 Jul 2010 22:16:52 +0000 Subject: Added operator for generating navigation mesh for selected blender objects --- source/blender/editors/object/object_navmesh.cpp | 424 +++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 source/blender/editors/object/object_navmesh.cpp (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp new file mode 100644 index 00000000000..1e28164e30f --- /dev/null +++ b/source/blender/editors/object/object_navmesh.cpp @@ -0,0 +1,424 @@ +/** +* $Id:$ +* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* 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 +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL LICENSE BLOCK ***** +*/ +#include +#include "Recast.h" + +extern "C" +{ +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_ID.h" + +#include "BKE_depsgraph.h" +#include "BKE_context.h" +#include "BKE_mesh.h" +#include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" +#include "BLI_editVert.h" +#include "BLI_listbase.h" +#include "ED_object.h" +#include "BLI_math_vector.h" + +#include "ED_mesh.h" + +/*mesh/mesh_intern.h */ +extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct EditVert *example); +extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges); + +#include "WM_api.h" +#include "WM_types.h" + +static void createVertsTrisData(bContext *C, LinkNode* obs, int& nverts, float*& verts, int &ntris, int*& tris) +{ + MVert *mvert; + 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; + + nverts = 0; + ntris = 0; + //calculate number of verts and tris + for (oblink = obs; oblink; oblink = oblink->next) + { + ob = (Object*) oblink->link; + DerivedMesh *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; + + //resolve quad faces + mface = dm->getFaceArray(dm); + for (i=0; iv4) + ntris+=1; + } + } + + //create data + verts = (float*) MEM_mallocN(sizeof(float)*3*nverts, "verts"); + tris = (int*) MEM_mallocN(sizeof(int)*3*ntris, "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; + + curnverts = dm->getNumVerts(dm); + mvert = dm->getVertArray(dm); + //copy verts + for (i=0; ico); + 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]; + } + + //create tris + curnfaces = dm->getNumFaces(dm); + mface = dm->getFaceArray(dm); + for (i=0; iv1; 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; + tri += 3; + } + } + basenverts += curnverts; + } + + //release derived mesh + for (dmlink = dms; dmlink; dmlink = dmlink->next) + { + dm = (DerivedMesh*) dmlink->link; + dm->release(dm); + } + BLI_linklist_free(dms, NULL); +} + +static bool buildNavMesh(const RecastData& recastParams, int nverts, float* verts, int ntris, int* tris, + rcPolyMesh*& pmesh, rcPolyMeshDetail*& dmesh) +{ + float bmin[3], bmax[3]; + rcHeightfield* solid; + unsigned char *triflags; + rcCompactHeightfield* chf; + rcContourSet *cset; + + rcCalcBounds(verts, nverts, bmin, bmax); + + // + // Step 1. Initialize build config. + // + rcConfig cfg; + memset(&cfg, 0, sizeof(cfg)); + { +/* + 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; +*/ + 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; + + } + + // Set the area where the navigation will be build. + vcopy(cfg.bmin, bmin); + vcopy(cfg.bmax, bmax); + rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height); + + // + // Step 2. Rasterize input polygon soup. + // + // Allocate voxel heightfield where we rasterize our input data to. + solid = new rcHeightfield; + if (!solid) + return false; + + if (!rcCreateHeightfield(*solid, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch)) + return false; + + // Allocate array that can hold triangle flags. + triflags = (unsigned char*) MEM_mallocN(sizeof(unsigned char)*ntris, "triflags"); + if (!triflags) + return false; + // Find triangles which are walkable based on their slope and rasterize them. + memset(triflags, 0, ntris*sizeof(unsigned char)); + rcMarkWalkableTriangles(cfg.walkableSlopeAngle, verts, nverts, tris, ntris, triflags); + rcRasterizeTriangles(verts, nverts, tris, triflags, ntris, *solid); + MEM_freeN(triflags); + MEM_freeN(verts); + MEM_freeN(tris); + + // + // Step 3. Filter walkables surfaces. + // + rcFilterLedgeSpans(cfg.walkableHeight, cfg.walkableClimb, *solid); + rcFilterWalkableLowHeightSpans(cfg.walkableHeight, *solid); + + // + // Step 4. Partition walkable surface to simple regions. + // + + chf = new rcCompactHeightfield; + if (!chf) + return false; + if (!rcBuildCompactHeightfield(cfg.walkableHeight, cfg.walkableClimb, RC_WALKABLE, *solid, *chf)) + return false; + + delete solid; + + // Prepare for region partitioning, by calculating distance field along the walkable surface. + if (!rcBuildDistanceField(*chf)) + return false; + + // Partition the walkable surface into simple regions without holes. + if (!rcBuildRegions(*chf, cfg.walkableRadius, cfg.borderSize, cfg.minRegionSize, cfg.mergeRegionSize)) + return false; + + // + // Step 5. Trace and simplify region contours. + // + // Create contours. + cset = new rcContourSet; + if (!cset) + return false; + + if (!rcBuildContours(*chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset)) + return false; + + // + // Step 6. Build polygons mesh from contours. + // + pmesh = new rcPolyMesh; + if (!pmesh) + return false; + if (!rcBuildPolyMesh(*cset, cfg.maxVertsPerPoly, *pmesh)) + return false; + + + // + // Step 7. Create detail mesh which allows to access approximate height on each polygon. + // + + dmesh = new rcPolyMeshDetail; + if (!dmesh) + return false; + + if (!rcBuildPolyMeshDetail(*pmesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *dmesh)) + return false; + + delete chf; + delete cset; + + return true; +} + +static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshDetail*& dmesh) +{ + Object *obedit; + float co[3], rot[3]; + EditMesh *em; + int i,j, k, polyverts; + unsigned short* v; + int face[3]; + + zero_v3(co); + zero_v3(rot); + obedit = ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); + ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); + + em = BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + + //create verts for polygon mesh + for(i = 0; i < pmesh->nverts; i++) { + v = &pmesh->verts[3*i]; + co[0] = pmesh->bmin[0] + v[0]*pmesh->cs; + co[1] = pmesh->bmin[1] + v[1]*pmesh->ch; + co[2] = pmesh->bmin[2] + v[2]*pmesh->cs; + SWAP(float, co[1], co[2]); + addvertlist(em, co, NULL); + } + polyverts = pmesh->nverts; + + //create custom data layer to save polygon idx + CustomData_add_layer_named(&em->fdata, CD_PROP_INT, CD_CALLOC, NULL, 0, "recastData"); + + //create verts and faces for detailed mesh + for (i=0; inmeshes; i++) + { + int uniquevbase = em->totvert; + unsigned short vbase = dmesh->meshes[4*i+0]; + unsigned short ndv = dmesh->meshes[4*i+1]; + unsigned short tribase = dmesh->meshes[4*i+2]; + unsigned short trinum = dmesh->meshes[4*i+3]; + const unsigned short* p = &pmesh->polys[i*pmesh->nvp*2]; + int nv = 0; + for (j = 0; j < pmesh->nvp; ++j) + { + if (p[j] == 0xffff) break; + nv++; + } + //create unique verts + for (j=nv; jverts[vbase + j]); + SWAP(float, co[1], co[2]); + addvertlist(em, co, NULL); + } + + EM_init_index_arrays(em, 1, 0, 0); + + //create faces + for (j=0; jtris[4*(tribase+j)]; + EditFace* newFace; + for (k=0; k<3; k++) + { + if (tri[k]fdata, newFace->data, CD_PROP_INT); + *polygonIdx = i; + } + + EM_free_index_arrays(); + } + + delete pmesh; pmesh = NULL; + delete dmesh; dmesh = NULL; + + BKE_mesh_end_editmesh((Mesh*)obedit->data, em); + + DAG_id_flush_update((ID*)obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + + ED_object_exit_editmode(C, EM_FREEDATA); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); + return obedit; +} + +static int create_navmesh_exec(bContext *C, wmOperator *op) +{ + Scene* scene = CTX_data_scene(C); + int nverts, ntris; + float* verts; + int* tris; + rcPolyMesh* pmesh; + rcPolyMeshDetail* dmesh; + LinkNode* obs = NULL; + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) + { + 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); + createRepresentation(C, pmesh, dmesh); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_create_navmesh(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "NavMesh"; + ot->description= "Create navigation mesh for selected objects"; + ot->idname= "OBJECT_OT_create_navmesh"; + + /* api callbacks */ + ot->exec= create_navmesh_exec; +} +} -- cgit v1.2.3 From b17f90b22ce72e33769703bde7ed67bf5bce8709 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Wed, 14 Jul 2010 13:20:13 +0000 Subject: - fixed bugs with unique vertices of detailed mesh in generation and conversion of navigation mesh - set default physic type and name for navigation mesh object --- source/blender/editors/object/object_navmesh.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 1e28164e30f..14e0fc75498 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -38,6 +38,7 @@ extern "C" #include "DNA_meshdata_types.h" #include "DNA_ID.h" +#include "BKE_library.h" #include "BKE_depsgraph.h" #include "BKE_context.h" #include "BKE_mesh.h" @@ -345,7 +346,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD //create unique verts for (j=nv; jverts[vbase + j]); + copy_v3_v3(co, &dmesh->verts[3*(vbase + j)]); SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } @@ -386,6 +387,11 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD ED_object_exit_editmode(C, EM_FREEDATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); + + obedit->gameflag &= ~OB_COLLISION; + obedit->gameflag |= OB_NAVMESH; + obedit->body_type = OB_BODY_TYPE_NAVMESH; + rename_id((ID *)obedit, "Navmesh"); return obedit; } -- cgit v1.2.3 From 219e9022b9a2718abbe9bbd61514fcc1b8fa9b73 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Wed, 14 Jul 2010 20:09:04 +0000 Subject: - set default value for level height params - added flag OPTYPE_UNDO for navmesh operator to enable undo operation --- source/blender/editors/object/object_navmesh.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 14e0fc75498..c357581ee3d 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -426,5 +426,8 @@ void OBJECT_OT_create_navmesh(wmOperatorType *ot) /* api callbacks */ ot->exec= create_navmesh_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } } -- cgit v1.2.3 From b4b9e01f8d1d72a92df03c954063cb02b24d580e Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Tue, 20 Jul 2010 14:09:05 +0000 Subject: - set defaults to steering actuator parameters - fixed order of triangle indexes for navigation mesh representation --- source/blender/editors/object/object_navmesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index c357581ee3d..9b138365ac5 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -365,8 +365,8 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD else face[k] = uniquevbase+tri[k]-nv; //unique vertex } - newFace = addfacelist(em, EM_get_vert_for_index(face[0]), EM_get_vert_for_index(face[1]), - EM_get_vert_for_index(face[2]), NULL, NULL, NULL); + 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 int* polygonIdx = (int*)CustomData_em_get(&em->fdata, newFace->data, CD_PROP_INT); -- cgit v1.2.3 From b7819807b33ded7c20956c52bcaf1ee93bf428f7 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Wed, 21 Jul 2010 19:44:59 +0000 Subject: implemented navigation mesh visualization via modifier --- source/blender/editors/object/object_navmesh.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 9b138365ac5..a5ff74ae4fd 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -36,6 +36,7 @@ extern "C" #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_ID.h" #include "BKE_library.h" @@ -306,6 +307,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD int i,j, k, polyverts; unsigned short* v; int face[3]; + Scene *scene= CTX_data_scene(C); zero_v3(co); zero_v3(rot); @@ -392,6 +394,9 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD obedit->gameflag |= OB_NAVMESH; obedit->body_type = OB_BODY_TYPE_NAVMESH; rename_id((ID *)obedit, "Navmesh"); + + ED_object_modifier_add(NULL, scene, obedit, NULL, eModifierType_NavMesh); + //ModifierData *md= modifiers_findByType(ob, eModifierType_NavMesh); return obedit; } -- cgit v1.2.3 From af1ca0cfc17f9663908f23cafb322aa6e2b10782 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Tue, 27 Jul 2010 21:01:00 +0000 Subject: - added operators for manual assigning navigation polygon idx to mesh faces in edit mode - modified conversion process to take into account changes caused by mesh editing Note: conversion to dtStatNavMesh in KX_NavMeshObject hasn't worked correctly yet --- source/blender/editors/object/object_navmesh.cpp | 147 ++++++++++++++++++++++- 1 file changed, 145 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index a5ff74ae4fd..f7527e2d5d5 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -50,6 +50,8 @@ extern "C" #include "ED_object.h" #include "BLI_math_vector.h" +#include "RNA_access.h" + #include "ED_mesh.h" /*mesh/mesh_intern.h */ @@ -372,7 +374,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD //set navigation polygon idx to the custom layer int* polygonIdx = (int*)CustomData_em_get(&em->fdata, newFace->data, CD_PROP_INT); - *polygonIdx = i; + *polygonIdx = i+1; //add 1 to avoid zero idx } EM_free_index_arrays(); @@ -425,7 +427,7 @@ static int create_navmesh_exec(bContext *C, wmOperator *op) void OBJECT_OT_create_navmesh(wmOperatorType *ot) { /* identifiers */ - ot->name= "NavMesh"; + ot->name= "Create navigation mesh"; ot->description= "Create navigation mesh for selected objects"; ot->idname= "OBJECT_OT_create_navmesh"; @@ -435,4 +437,145 @@ void OBJECT_OT_create_navmesh(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } + +static int assign_navpolygon_poll(bContext *C) +{ + Object *ob= (Object *)CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + if (!ob || !ob->data) + return 0; + return (((Mesh*)ob->data)->edit_mesh != NULL); +} + +static int assign_navpolygon_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + //do work here + int targetPolyIdx = -1; + EditFace *ef, *efa; + efa = EM_get_actFace(em, 0); + if (efa) + { + if (CustomData_has_layer(&em->fdata, CD_PROP_INT)) + { + targetPolyIdx = *(int*)CustomData_em_get(&em->fdata, efa->data, CD_PROP_INT); + 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_PROP_INT); + *recastDataBlock = targetPolyIdx; + } + ef = ef->prev; + } + } + } + } + + DAG_id_flush_update((ID*)obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh((Mesh*)obedit->data, em); + return OPERATOR_FINISHED; +} + +void OBJECT_OT_assign_navpolygon(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Assign polygon index "; + ot->description= "Assign polygon index to face by active face"; + ot->idname= "OBJECT_OT_assign_navpolygon"; + + /* api callbacks */ + ot->poll = assign_navpolygon_poll; + ot->exec= assign_navpolygon_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int compare(const void * a, const void * b){ + return ( *(int*)a - *(int*)b ); +} +static int findFreeNavPolyIndex(EditMesh* em) +{ + //construct vector of indices + int numfaces = em->totface; + int* indices = new int[numfaces]; + EditFace* ef = (EditFace*)em->faces.last; + int idx = 0; + while(ef) + { + int polyIdx = *(int*)CustomData_em_get(&em->fdata, ef->data, CD_PROP_INT); + indices[idx] = polyIdx; + idx++; + ef = ef->prev; + } + qsort(indices, numfaces, sizeof(int), compare); + //search first free index + int freeIdx = 1; + int maxIdx = indices[numfaces-1]; + for (int i=0; ifreeIdx) + break; + } + delete indices; + return freeIdx; +} + +static int assign_new_navpolygon_exec(bContext *C, wmOperator *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_PROP_INT)) + { + 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_PROP_INT); + *recastDataBlock = targetPolyIdx; + } + ef = ef->prev; + } + } + } + + DAG_id_flush_update((ID*)obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh((Mesh*)obedit->data, em); + return OPERATOR_FINISHED; +} + +void OBJECT_OT_assign_new_navpolygon(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Assign new polygon index "; + ot->description= "Assign new polygon index to face"; + ot->idname= "OBJECT_OT_assign_new_navpolygon"; + + /* api callbacks */ + ot->poll = assign_navpolygon_poll; + ot->exec= assign_new_navpolygon_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} } -- cgit v1.2.3 From 870e0e37e52ec644ad1e2e728b8b9b422b1a6dc4 Mon Sep 17 00:00:00 2001 From: Nick Samarin Date: Thu, 29 Jul 2010 14:06:48 +0000 Subject: - fixed bug in steering actuator: calculate 2d distance to target for seeking and fleeing - added possibility to add navmesh modifier manually in order to transform manually created mesh to navigation mesh (with navigation polygons data layer) - added possibility to use existed navigation mesh object for navmesh generation (so new object won't be created, but existed object will be updated) --- source/blender/editors/object/object_navmesh.cpp | 66 +++++++++++++++++++----- 1 file changed, 52 insertions(+), 14 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index f7527e2d5d5..b8728e35a54 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -43,6 +43,8 @@ extern "C" #include "BKE_depsgraph.h" #include "BKE_context.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_scene.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" #include "BLI_editVert.h" @@ -57,6 +59,9 @@ extern "C" /*mesh/mesh_intern.h */ extern struct EditVert *addvertlist(EditMesh *em, float *vec, struct EditVert *example); extern struct EditFace *addfacelist(EditMesh *em, struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example, struct EditFace *exampleEdges); +extern void free_vertlist(EditMesh *em, ListBase *edve); +extern void free_edgelist(EditMesh *em, ListBase *lb); +extern void free_facelist(EditMesh *em, ListBase *lb); #include "WM_api.h" #include "WM_types.h" @@ -301,23 +306,43 @@ static bool buildNavMesh(const RecastData& recastParams, int nverts, float* vert return true; } -static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshDetail*& dmesh) +static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshDetail*& dmesh, Base* base) { - Object *obedit; float co[3], rot[3]; EditMesh *em; int i,j, k, polyverts; unsigned short* v; int face[3]; Scene *scene= CTX_data_scene(C); - + Object* obedit; + int createob = base==NULL; zero_v3(co); zero_v3(rot); - obedit = ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); - ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); + if (createob) + { + //create new object + obedit = ED_object_add_type(C, OB_MESH, co, rot, FALSE, 1); + } + 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)); + 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 for(i = 0; i < pmesh->nverts; i++) { v = &pmesh->verts[3*i]; @@ -392,13 +417,20 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD ED_object_exit_editmode(C, EM_FREEDATA); WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); - obedit->gameflag &= ~OB_COLLISION; - obedit->gameflag |= OB_NAVMESH; - obedit->body_type = OB_BODY_TYPE_NAVMESH; - rename_id((ID *)obedit, "Navmesh"); + if (createob) + { + obedit->gameflag &= ~OB_COLLISION; + obedit->gameflag |= OB_NAVMESH; + obedit->body_type = OB_BODY_TYPE_NAVMESH; + rename_id((ID *)obedit, "Navmesh"); + } + + ModifierData *md= modifiers_findByType(obedit, eModifierType_NavMesh); + if (!md) + { + ED_object_modifier_add(NULL, scene, obedit, NULL, eModifierType_NavMesh); + } - ED_object_modifier_add(NULL, scene, obedit, NULL, eModifierType_NavMesh); - //ModifierData *md= modifiers_findByType(ob, eModifierType_NavMesh); return obedit; } @@ -411,15 +443,22 @@ static int create_navmesh_exec(bContext *C, wmOperator *op) rcPolyMesh* pmesh; rcPolyMeshDetail* dmesh; LinkNode* obs = NULL; + Base* navmeshBase = NULL; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { - BLI_linklist_append(&obs, (void*)base->object); + 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); - createRepresentation(C, pmesh, dmesh); + createRepresentation(C, pmesh, dmesh, navmeshBase); return OPERATOR_FINISHED; } @@ -520,7 +559,6 @@ static int findFreeNavPolyIndex(EditMesh* em) qsort(indices, numfaces, sizeof(int), compare); //search first free index int freeIdx = 1; - int maxIdx = indices[numfaces-1]; for (int i=0; i Date: Fri, 30 Jul 2010 13:02:32 +0000 Subject: - moved navmesh conversion code to ED_Editors project (ED_navmesh_conversion.h and navmesh_conversion.cpp files) - added new custom data layer CD_Recast --- source/blender/editors/object/object_navmesh.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index b8728e35a54..dd947e02de6 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -355,7 +355,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD polyverts = pmesh->nverts; //create custom data layer to save polygon idx - CustomData_add_layer_named(&em->fdata, CD_PROP_INT, CD_CALLOC, NULL, 0, "recastData"); + CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "recastData"); //create verts and faces for detailed mesh for (i=0; inmeshes; i++) @@ -398,7 +398,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD EM_get_vert_for_index(face[1]), NULL, NULL, NULL); //set navigation polygon idx to the custom layer - int* polygonIdx = (int*)CustomData_em_get(&em->fdata, newFace->data, CD_PROP_INT); + int* polygonIdx = (int*)CustomData_em_get(&em->fdata, newFace->data, CD_RECAST); *polygonIdx = i+1; //add 1 to avoid zero idx } @@ -496,9 +496,9 @@ static int assign_navpolygon_exec(bContext *C, wmOperator *op) efa = EM_get_actFace(em, 0); if (efa) { - if (CustomData_has_layer(&em->fdata, CD_PROP_INT)) + if (CustomData_has_layer(&em->fdata, CD_RECAST)) { - targetPolyIdx = *(int*)CustomData_em_get(&em->fdata, efa->data, CD_PROP_INT); + targetPolyIdx = *(int*)CustomData_em_get(&em->fdata, efa->data, CD_RECAST); targetPolyIdx = targetPolyIdx>=0? targetPolyIdx : -targetPolyIdx; if (targetPolyIdx>0) { @@ -508,7 +508,7 @@ static int assign_navpolygon_exec(bContext *C, wmOperator *op) { if((ef->f & SELECT )&& ef!=efa) { - int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_PROP_INT); + int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); *recastDataBlock = targetPolyIdx; } ef = ef->prev; @@ -551,7 +551,7 @@ static int findFreeNavPolyIndex(EditMesh* em) int idx = 0; while(ef) { - int polyIdx = *(int*)CustomData_em_get(&em->fdata, ef->data, CD_PROP_INT); + int polyIdx = *(int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); indices[idx] = polyIdx; idx++; ef = ef->prev; @@ -576,7 +576,7 @@ static int assign_new_navpolygon_exec(bContext *C, wmOperator *op) EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); EditFace *ef; - if (CustomData_has_layer(&em->fdata, CD_PROP_INT)) + if (CustomData_has_layer(&em->fdata, CD_RECAST)) { int targetPolyIdx = findFreeNavPolyIndex(em); if (targetPolyIdx>0) @@ -587,7 +587,7 @@ static int assign_new_navpolygon_exec(bContext *C, wmOperator *op) { if(ef->f & SELECT ) { - int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_PROP_INT); + int* recastDataBlock = (int*)CustomData_em_get(&em->fdata, ef->data, CD_RECAST); *recastDataBlock = targetPolyIdx; } ef = ef->prev; -- cgit v1.2.3 From 0bca249298679334f842e5a982ffbcdba13aefc1 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 31 Aug 2010 22:08:01 +0000 Subject: Add CMake build system on Recast&Navigation branch --- source/blender/editors/object/object_navmesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 572edcff976..95738a05db4 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -1,5 +1,5 @@ /** -* $Id:$ +* $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From 8ed1c07a7b21d916f149dfa00649579165c45979 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sat, 10 Sep 2011 09:21:46 +0000 Subject: Navigation Mesh Modifier: * Fix scons define for operator append * Don't use abbreviations in the UI. --- source/blender/editors/object/object_navmesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 8ee63296c70..155ffd37627 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -537,7 +537,7 @@ static int assign_navpolygon_exec(bContext *C, wmOperator *op) void OBJECT_OT_assign_navpolygon(struct wmOperatorType *ot) { /* identifiers */ - ot->name= "Assign polygon index "; + ot->name= "Assign polygon index"; ot->description= "Assign polygon index to face by active face"; ot->idname= "OBJECT_OT_assign_navpolygon"; @@ -615,7 +615,7 @@ static int assign_new_navpolygon_exec(bContext *C, wmOperator *op) void OBJECT_OT_assign_new_navpolygon(struct wmOperatorType *ot) { /* identifiers */ - ot->name= "Assign new polygon index "; + ot->name= "Assign new polygon index"; ot->description= "Assign new polygon index to face"; ot->idname= "OBJECT_OT_assign_new_navpolygon"; -- cgit v1.2.3 From 357febc168cb13981f277b32f1ea2e3488b05b99 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Sep 2011 09:38:38 +0000 Subject: fix for building with collada and some other warnings --- source/blender/editors/object/object_navmesh.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source/blender/editors/object/object_navmesh.cpp') diff --git a/source/blender/editors/object/object_navmesh.cpp b/source/blender/editors/object/object_navmesh.cpp index 155ffd37627..d0768d30236 100644 --- a/source/blender/editors/object/object_navmesh.cpp +++ b/source/blender/editors/object/object_navmesh.cpp @@ -312,7 +312,7 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD { float co[3], rot[3]; EditMesh *em; - int i,j, k, polyverts; + int i,j, k; unsigned short* v; int face[3]; Main *bmain = CTX_data_main(C); @@ -355,7 +355,6 @@ static Object* createRepresentation(bContext *C, rcPolyMesh*& pmesh, rcPolyMeshD SWAP(float, co[1], co[2]); addvertlist(em, co, NULL); } - polyverts = pmesh->nverts; //create custom data layer to save polygon idx CustomData_add_layer_named(&em->fdata, CD_RECAST, CD_CALLOC, NULL, 0, "recastData"); -- cgit v1.2.3