Fix navmesh creation w/ multiple objects
[blender-staging.git] / source / blender / editors / mesh / mesh_navmesh.c
index 0d9f6f2a0bebf5731c4f91a4e00d5deeff532fc4..740d18951dcb7cceb8497f7ba998404bf7be237c 100644 (file)
@@ -72,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;
@@ -84,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);
@@ -100,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");
@@ -215,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 ** */
@@ -244,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);
 
@@ -451,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);
                        }
                }
        }