~rebel/horde3d/trunk

« back to all changes in this revision

Viewing changes to trunk/Tools/Dependencies/RecastNavigation/RecastDemo/Source/Sample_TileMesh.cpp

  • Committer: felix
  • Date: 2015-07-07 12:57:07 UTC
  • Revision ID: svn-v4:5ce291ac-9df0-446f-9e4f-d57731c4dda7::1699
- Updated RecastNavigation to latest version and fixed multiple issues.
- Adapted GameDetourComponent, GameDetourCrowdComponent, DetourCrowdDemo and AAA accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
#endif
48
48
 
49
49
 
50
 
 
51
 
 
52
50
inline unsigned int nextPow2(unsigned int v)
53
51
{
54
52
        v--;
78
76
        Sample_TileMesh* m_sample;
79
77
        float m_hitPos[3];
80
78
        bool m_hitPosSet;
81
 
        float m_agentRadius;
82
79
        
83
80
public:
84
81
 
85
82
        NavMeshTileTool() :
86
83
                m_sample(0),
87
 
                m_hitPosSet(false),
88
 
                m_agentRadius(0)
 
84
                m_hitPosSet(false)
89
85
        {
90
86
                m_hitPos[0] = m_hitPos[1] = m_hitPos[2] = 0;
91
87
        }
291
287
        
292
288
        // Read header.
293
289
        NavMeshSetHeader header;
294
 
        fread(&header, sizeof(NavMeshSetHeader), 1, fp);
 
290
        size_t readLen = fread(&header, sizeof(NavMeshSetHeader), 1, fp);
 
291
        if (readLen != 1)
 
292
        {
 
293
                fclose(fp);
 
294
                return 0;
 
295
        }
295
296
        if (header.magic != NAVMESHSET_MAGIC)
296
297
        {
297
298
                fclose(fp);
320
321
        for (int i = 0; i < header.numTiles; ++i)
321
322
        {
322
323
                NavMeshTileHeader tileHeader;
323
 
                fread(&tileHeader, sizeof(tileHeader), 1, fp);
 
324
                readLen = fread(&tileHeader, sizeof(tileHeader), 1, fp);
 
325
                if (readLen != 1)
 
326
                        return 0;
 
327
 
324
328
                if (!tileHeader.tileRef || !tileHeader.dataSize)
325
329
                        break;
326
330
 
327
331
                unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
328
332
                if (!data) break;
329
333
                memset(data, 0, tileHeader.dataSize);
330
 
                fread(data, tileHeader.dataSize, 1, fp);
331
 
                
 
334
                readLen = fread(data, tileHeader.dataSize, 1, fp);
 
335
                if (readLen != 1)
 
336
                        return 0;
 
337
 
332
338
                mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0);
333
339
        }
334
340
        
350
356
        imguiLabel("Tiling");
351
357
        imguiSlider("TileSize", &m_tileSize, 16.0f, 1024.0f, 16.0f);
352
358
        
353
 
 
354
359
        if (m_geom)
355
360
        {
356
361
                const float* bmin = m_geom->getMeshBoundsMin();
394
399
 
395
400
        if (imguiButton("Load"))
396
401
        {
397
 
                setTool(new NavMeshTileTool);//crash if e.g. crowdtool selected
398
402
                dtFreeNavMesh(m_navMesh);
399
 
                
400
 
                
401
 
 
402
403
                m_navMesh = loadAll("all_tiles_navmesh.bin");
403
404
                m_navQuery->init(m_navMesh, 2048);
404
405
        }
465
466
        if (m_geom)
466
467
        {
467
468
                valid[DRAWMODE_NAVMESH] = m_navMesh != 0;
468
 
                valid[DRAWMODE_NAVMESH_TRANS] = m_navMesh != 0;
 
469
                valid[DRAWMODE_NAVMESH_TRANS] = true;
469
470
                valid[DRAWMODE_NAVMESH_BVTREE] = m_navMesh != 0;
470
471
                valid[DRAWMODE_NAVMESH_NODES] = m_navQuery != 0;
471
472
                valid[DRAWMODE_NAVMESH_PORTALS] = m_navMesh != 0;
490
491
        
491
492
        if (unavail == MAX_DRAWMODE)
492
493
                return;
493
 
 
 
494
        
494
495
        imguiLabel("Draw");
495
496
        if (imguiCheck("Input Mesh", m_drawMode == DRAWMODE_MESH, valid[DRAWMODE_MESH]))
496
497
                m_drawMode = DRAWMODE_MESH;
545
546
        DebugDrawGL dd;
546
547
 
547
548
        const float texScale = 1.0f / (m_cellSize * 10.0f);
548
 
        //m_drawMode = DRAWMODE_NAVMESH_BVTREE;
 
549
        
549
550
        // Draw mesh
550
551
        if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
551
552
        {
936
937
        m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
937
938
        m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
938
939
        
 
940
        // Expand the heighfield bounding box by border size to find the extents of geometry we need to build this tile.
 
941
        //
 
942
        // This is done in order to make sure that the navmesh tiles connect correctly at the borders,
 
943
        // and the obstacles close to the border work correctly with the dilation process.
 
944
        // No polygons (or contours) will be created on the border area.
 
945
        //
 
946
        // IMPORTANT!
 
947
        //
 
948
        //   :''''''''':
 
949
        //   : +-----+ :
 
950
        //   : |     | :
 
951
        //   : |     |<--- tile to build
 
952
        //   : |     | :  
 
953
        //   : +-----+ :<-- geometry needed
 
954
        //   :.........:
 
955
        //
 
956
        // You should use this bounding box to query your input geometry.
 
957
        //
 
958
        // For example if you build a navmesh for terrain, and want the navmesh tiles to match the terrain tile size
 
959
        // you will need to pass in data from neighbour terrain tiles too! In a simple case, just pass in all the 8 neighbours,
 
960
        // or use the bounding box below to only pass in a sliver of each of the 8 neighbours.
939
961
        rcVcopy(m_cfg.bmin, bmin);
940
962
        rcVcopy(m_cfg.bmax, bmax);
941
963
        m_cfg.bmin[0] -= m_cfg.borderSize*m_cfg.cs;
1049
1071
        for (int i  = 0; i < m_geom->getConvexVolumeCount(); ++i)
1050
1072
                rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
1051
1073
        
1052
 
        if (m_monotonePartitioning)
1053
 
        {
1054
 
                // Partition the walkable surface into simple regions without holes.
1055
 
                if (!rcBuildRegionsMonotone(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
1056
 
                {
1057
 
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
1058
 
                        return 0;
1059
 
                }
1060
 
        }
1061
 
        else
 
1074
        
 
1075
        // Partition the heightfield so that we can use simple algorithm later to triangulate the walkable areas.
 
1076
        // There are 3 martitioning methods, each with some pros and cons:
 
1077
        // 1) Watershed partitioning
 
1078
        //   - the classic Recast partitioning
 
1079
        //   - creates the nicest tessellation
 
1080
        //   - usually slowest
 
1081
        //   - partitions the heightfield into nice regions without holes or overlaps
 
1082
        //   - the are some corner cases where this method creates produces holes and overlaps
 
1083
        //      - holes may appear when a small obstacles is close to large open area (triangulation can handle this)
 
1084
        //      - overlaps may occur if you have narrow spiral corridors (i.e stairs), this make triangulation to fail
 
1085
        //   * generally the best choice if you precompute the nacmesh, use this if you have large open areas
 
1086
        // 2) Monotone partioning
 
1087
        //   - fastest
 
1088
        //   - partitions the heightfield into regions without holes and overlaps (guaranteed)
 
1089
        //   - creates long thin polygons, which sometimes causes paths with detours
 
1090
        //   * use this if you want fast navmesh generation
 
1091
        // 3) Layer partitoining
 
1092
        //   - quite fast
 
1093
        //   - partitions the heighfield into non-overlapping regions
 
1094
        //   - relies on the triangulation code to cope with holes (thus slower than monotone partitioning)
 
1095
        //   - produces better triangles than monotone partitioning
 
1096
        //   - does not have the corner cases of watershed partitioning
 
1097
        //   - can be slow and create a bit ugly tessellation (still better than monotone)
 
1098
        //     if you have large open areas with small obstacles (not a problem if you use tiles)
 
1099
        //   * good choice to use for tiled navmesh with medium and small sized tiles
 
1100
        
 
1101
        if (m_partitionType == SAMPLE_PARTITION_WATERSHED)
1062
1102
        {
1063
1103
                // Prepare for region partitioning, by calculating distance field along the walkable surface.
1064
1104
                if (!rcBuildDistanceField(m_ctx, *m_chf))
1065
1105
                {
1066
1106
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
1067
 
                        return 0;
 
1107
                        return false;
1068
1108
                }
1069
1109
                
1070
1110
                // Partition the walkable surface into simple regions without holes.
1071
1111
                if (!rcBuildRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
1072
1112
                {
1073
 
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
1074
 
                        return 0;
1075
 
                }
1076
 
        }
1077
 
        
 
1113
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build watershed regions.");
 
1114
                        return false;
 
1115
                }
 
1116
        }
 
1117
        else if (m_partitionType == SAMPLE_PARTITION_MONOTONE)
 
1118
        {
 
1119
                // Partition the walkable surface into simple regions without holes.
 
1120
                // Monotone partitioning does not need distancefield.
 
1121
                if (!rcBuildRegionsMonotone(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
 
1122
                {
 
1123
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build monotone regions.");
 
1124
                        return false;
 
1125
                }
 
1126
        }
 
1127
        else // SAMPLE_PARTITION_LAYERS
 
1128
        {
 
1129
                // Partition the walkable surface into simple regions without holes.
 
1130
                if (!rcBuildLayerRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea))
 
1131
                {
 
1132
                        m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build layer regions.");
 
1133
                        return false;
 
1134
                }
 
1135
        }
 
1136
                
1078
1137
        // Create contours.
1079
1138
        m_cset = rcAllocContourSet();
1080
1139
        if (!m_cset)