Fix navmesh creation w/ multiple objects
[blender-staging.git] / source / blender / editors / mesh / mesh_navmesh.c
index 3d8718ef887e0f70143bc225dd5e2ae414e21b60..740d18951dcb7cceb8497f7ba998404bf7be237c 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/mesh/mesh_navmesh.c
+ *  \ingroup edmesh
+ */
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_scene_types.h"
@@ -68,7 +72,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
        LinkNode *oblink, *dmlink;
        DerivedMesh *dm;
        Scene *scene = CTX_data_scene(C);
-       LinkNode *dms = NULL;
+       LinkNodePair dms_pair = {NULL,NULL};
 
        int nverts, ntris, *tris;
        float *verts;
@@ -80,7 +84,8 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
        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);
+               DM_ensure_tessface(dm);
+               BLI_linklist_append(&dms_pair, dm);
 
                nverts += dm->getNumVerts(dm);
                nfaces = dm->getNumTessFaces(dm);
@@ -96,6 +101,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
 
                *r_lay |= ob->lay;
        }
+       LinkNode *dms = dms_pair.list;
 
        /* create data */
        verts = MEM_mallocN(sizeof(float) * 3 * nverts, "createVertsTrisData verts");
@@ -211,7 +217,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 
        /* Find triangles which are walkable based on their slope and rasterize them */
        recast_markWalkableTriangles(RAD2DEGF(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags);
-       recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid);
+       recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid, 1);
        MEM_freeN(triflags);
 
        /* ** Step 3: Filter walkables surfaces ** */
@@ -240,27 +246,48 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
                return false;
        }
 
-       /* Prepare for region partitioning, by calculating distance field along the walkable surface */
-       if (!recast_buildDistanceField(chf)) {
-               recast_destroyCompactHeightfield(chf);
+       if (recastParams->partitioning == RC_PARTITION_WATERSHED) {
+               /* Prepare for region partitioning, by calculating distance field along the walkable surface */
+               if (!recast_buildDistanceField(chf)) {
+                       recast_destroyCompactHeightfield(chf);
 
-               BKE_report(reports, RPT_ERROR, "Failed to build distance field");
-               return false;
-       }
+                       BKE_report(reports, RPT_ERROR, "Failed to build distance field");
+                       return false;
+               }
 
-       /* Partition the walkable surface into simple regions without holes */
-       if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
-               recast_destroyCompactHeightfield(chf);
+               /* Partition the walkable surface into simple regions without holes */
+               if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) {
+                       recast_destroyCompactHeightfield(chf);
 
-               BKE_report(reports, RPT_ERROR, "Failed to build regions");
-               return false;
+                       BKE_report(reports, RPT_ERROR, "Failed to build watershed regions");
+                       return false;
+               }
+       }
+       else if (recastParams->partitioning == RC_PARTITION_MONOTONE) {
+               /* Partition the walkable surface into simple regions without holes */
+               /* Monotone partitioning does not need distancefield. */
+               if (!recast_buildRegionsMonotone(chf, 0, minRegionArea, mergeRegionArea)) {
+                       recast_destroyCompactHeightfield(chf);
+
+                       BKE_report(reports, RPT_ERROR, "Failed to build monotone regions");
+                       return false;
+               }
+       }
+       else { /* RC_PARTITION_LAYERS */
+               /* Partition the walkable surface into simple regions without holes */
+               if (!recast_buildLayerRegions(chf, 0, minRegionArea)) {
+                       recast_destroyCompactHeightfield(chf);
+
+                       BKE_report(reports, RPT_ERROR, "Failed to build layer regions");
+                       return false;
+               }
        }
 
        /* ** 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_CONTOUR_TESS_WALL_EDGES)) {
                recast_destroyCompactHeightfield(chf);
                recast_destroyContourSet(cset);
 
@@ -321,7 +348,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
 
        if (createob) {
                /* create new object */
-               obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay);
+               obedit = ED_object_add_type(C, OB_MESH, "Navmesh", co, rot, false, lay);
        }
        else {
                obedit = base->object;
@@ -350,7 +377,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
                co[1] = bmin[1] + v[1] * ch;
                co[2] = bmin[2] + v[2] * cs;
                SWAP(float, co[1], co[2]);
-               BM_vert_create(em->bm, co, NULL, 0);
+               BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
        }
 
        /* create custom data layer to save polygon idx */
@@ -381,11 +408,11 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
                for (j = nv; j < ndv; j++) {
                        copy_v3_v3(co, &dverts[3 * (vbase + j)]);
                        SWAP(float, co[1], co[2]);
-                       BM_vert_create(em->bm, co, NULL, 0);
+                       BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP);
                }
 
                /* need to rebuild entirely because array size changes */
-               EDBM_index_arrays_init(em, BM_VERT);
+               BM_mesh_elem_table_init(em->bm, BM_VERT);
 
                /* create faces */
                for (j = 0; j < trinum; j++) {
@@ -400,10 +427,10 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
                                        face[k] = uniquevbase + tri[k] - nv;  /* unique vertex */
                        }
                        newFace = BM_face_create_quad_tri(em->bm,
-                                                         EDBM_vert_at_index(em, face[0]),
-                                                         EDBM_vert_at_index(em, face[2]),
-                                                         EDBM_vert_at_index(em, face[1]), NULL,
-                                                         NULL, false);
+                                                         BM_vert_at_index(em->bm, face[0]),
+                                                         BM_vert_at_index(em->bm, face[2]),
+                                                         BM_vert_at_index(em->bm, face[1]), NULL,
+                                                         NULL, BM_CREATE_NOP);
 
                        /* set navigation polygon idx to the custom layer */
                        polygonIdx = (int *)CustomData_bmesh_get(&em->bm->pdata, newFace->head.data, CD_RECAST);
@@ -425,7 +452,6 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
                obedit->gameflag &= ~OB_COLLISION;
                obedit->gameflag |= OB_NAVMESH;
                obedit->body_type = OB_BODY_TYPE_NAVMESH;
-               rename_id((ID *)obedit, "Navmesh");
        }
 
        BKE_mesh_ensure_navmesh(obedit->data);
@@ -448,7 +474,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
                                }
                        }
                        else {
-                               BLI_linklist_append(&obs, (void *)base->object);
+                               BLI_linklist_prepend(&obs, base->object);
                        }
                }
        }
@@ -461,7 +487,7 @@ static int navmesh_create_exec(bContext *C, wmOperator *op)
                unsigned int lay = 0;
 
                int nverts = 0, ntris = 0;
-               int *tris = 0;
+               int *tris = NULL;
                float *verts = NULL;
 
                createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris, &lay);