Beispiel #1
0
    void MapBuilder::buildMap(uint32 mapID)
    {
        printf("Building map %03u:\n", mapID);

        set<uint32>* tiles = getTileList(mapID);

        // make sure we process maps which don't have tiles
        if (!tiles->size())
        {
            // convert coord bounds to grid bounds
            uint32 minX, minY, maxX, maxY;
            getGridBounds(mapID, minX, minY, maxX, maxY);

            // add all tiles within bounds to tile list.
            for (uint32 i = minX; i <= maxX; ++i)
                for (uint32 j = minY; j <= maxY; ++j)
                    tiles->insert(StaticMapTree::packTileID(i, j));
        }

        if (!tiles->size())
            return;

        // build navMesh
        dtNavMesh* navMesh = NULL;
        buildNavMesh(mapID, navMesh);
        if (!navMesh)
        {
            printf("Failed creating navmesh!              \n");
            return;
        }

        // now start building mmtiles for each tile
        printf("We have %u tiles.                          \n", (unsigned int)tiles->size());
        for (set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
        {
            uint32 tileX, tileY;

            // unpack tile coords
            StaticMapTree::unpackTileID((*it), tileX, tileY);

            if (shouldSkipTile(mapID, tileX, tileY))
                continue;

            buildTile(mapID, tileX, tileY, navMesh);
        }

        dtFreeNavMesh(navMesh);

        printf("Complete!                               \n\n");
    }
    void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh)
    {
        std::set<uint32>* tiles = getTileList(mapID);

        // old code for non-statically assigned bitmask sizes:
        ///*** calculate number of bits needed to store tiles & polys ***/
        //int tileBits = dtIlog2(dtNextPow2(tiles->size()));
        //if (tileBits < 1) tileBits = 1;                                     // need at least one bit!
        //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits;

        int polyBits = STATIC_POLY_BITS;

        int maxTiles = tiles->size();
        int maxPolysPerTile = 1 << polyBits;

        /***          calculate bounds of map         ***/

        uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY;
        for (std::set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
        {
            StaticMapTree::unpackTileID(*it, tileX, tileY);

            if (tileX > tileXMax)
                tileXMax = tileX;
            else if (tileX < tileXMin)
                tileXMin = tileX;

            if (tileY > tileYMax)
                tileYMax = tileY;
            else if (tileY < tileYMin)
                tileYMin = tileY;
        }

        // use Max because '32 - tileX' is negative for values over 32
        float bmin[3], bmax[3];
        getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax);

        /***       now create the navmesh       ***/

        // navmesh creation params
        dtNavMeshParams navMeshParams;
        memset(&navMeshParams, 0, sizeof(dtNavMeshParams));
        navMeshParams.tileWidth = GRID_SIZE;
        navMeshParams.tileHeight = GRID_SIZE;
        rcVcopy(navMeshParams.orig, bmin);
        navMeshParams.maxTiles = maxTiles;
        navMeshParams.maxPolys = maxPolysPerTile;

        navMesh = dtAllocNavMesh();
        printf("[Map %04u] Creating navMesh...\n", mapID);
        if (!navMesh->init(&navMeshParams))
        {
            printf("[Map %04u] Failed creating navmesh!                \n", mapID);
            return;
        }

        char fileName[25];
        sprintf(fileName, "mmaps/%04u.mmap", mapID);

        FILE* file = fopen(fileName, "wb");
        if (!file)
        {
            dtFreeNavMesh(navMesh);
            char message[1024];
            sprintf(message, "[Map %04u] Failed to open %s for writing!\n", mapID, fileName);
            perror(message);
            return;
        }

        // now that we know navMesh params are valid, we can write them to file
        fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file);
        fclose(file);
    }
    void MapBuilder::buildNavMesh(int mapID, dtNavMesh*& navMesh, dtNavMeshParams*& navMeshParams)
    {
        bool isFirstNavMesh = navMeshParams ? false : true;

        if (isFirstNavMesh)
        {
            set<uint32>* tiles = getTileList(mapID);
            int polyBits = DT_POLY_BITS;
            int maxTiles = tiles->size();
            int maxPolysPerTile = 1 << polyBits;

            /***          calculate bounds of map         ***/
            uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY;
            for (set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
            {
                StaticMapTree::unpackTileID((*it), tileX, tileY);

                if (tileX > tileXMax)
                    { tileXMax = tileX; }
                else if (tileX < tileXMin)
                    { tileXMin = tileX; }

                if (tileY > tileYMax)
                    { tileYMax = tileY; }
                else if (tileY < tileYMin)
                    { tileYMin = tileY; }
            }

            // use Max because '32 - tileX' is negative for values over 32
            float bmin[3], bmax[3];
            getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax);

            /***       now create the navmesh       ***/
            // navmesh creation params
            navMeshParams = new dtNavMeshParams();
            memset(navMeshParams, 0, sizeof(dtNavMeshParams));
            navMeshParams->tileWidth = GRID_SIZE;
            navMeshParams->tileHeight = GRID_SIZE;
            rcVcopy(navMeshParams->orig, bmin);
            navMeshParams->maxTiles = maxTiles;
            navMeshParams->maxPolys = maxPolysPerTile;
        }

        navMesh = dtAllocNavMesh();
        if (!navMesh->init(navMeshParams))
        {
            printf("Failed creating navmesh!                \n");
            return;
        }

        if (isFirstNavMesh)
        {
            char fileName[25];
            sprintf(fileName, "mmaps/%03u.mmap", mapID);

            FILE* file = fopen(fileName, "wb");
            if (!file)
            {
                dtFreeNavMesh(navMesh);
                char message[1024];
                sprintf(message, "Failed to open %s for writing!\n", fileName);
                perror(message);
                return;
            }
            // now that we know navMesh params are valid, we can write them to file
            fwrite(navMeshParams, sizeof(dtNavMeshParams), 1, file);
            fclose(file);
        }
    }
    void MapBuilder::buildMap(int mapID, bool standAlone)
    {
        set<uint32>* tiles = getTileList(mapID);

        // make sure we process maps which don't have tiles
        if (!tiles->size())
        {
            // convert coord bounds to grid bounds
            uint32 minX, minY, maxX, maxY;
            getGridBounds(mapID, minX, minY, maxX, maxY);

            // add all tiles within bounds to tile list.
            for (uint32 i = minX; i <= maxX; ++i)
                for (uint32 j = minY; j <= maxY; ++j)
                    { tiles->insert(StaticMapTree::packTileID(i, j)); }
        }

        if (!tiles->size())
            { return; }

        // build navMesh
        dtNavMesh* navMesh = NULL;
        dtNavMeshParams* meshParams = NULL;
        buildNavMesh(mapID, navMesh, meshParams);
        if (!navMesh)
        {
            printf("Failed creating navmesh for map %03u!              \n", mapID);
            if (meshParams)
                { delete meshParams; }
            return;
        }

        if (activated())
          { dtFreeNavMesh(navMesh); }  // each tile will get it's own pointer to navMesh 

        // now start building/scheduling mmtiles for each tile
        printf(" %s map %03u [%u tiles]\n", activated() ? "Scheduling" : "Building", mapID, (unsigned int)tiles->size());
        for (set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
        {
            uint32 tileX, tileY;

            // unpack tile coords
            StaticMapTree::unpackTileID((*it), tileX, tileY);

            if (shouldSkipTile(mapID, tileX, tileY))
                { continue; }

            if (!activated())
            {
                buildTile(mapID, tileX, tileY, navMesh);
            }
            else
            {
                dtNavMesh *mesh = NULL;
                buildNavMesh(mapID, mesh, meshParams); //meshParams is not null, so we get a new pointer to dtNavMesh
                if (mesh)
                {
                    TileBuilder* tb = new TileBuilder(this, mapID, tileX, tileY, mesh);
                    Tile_Message_Block *mb = new Tile_Message_Block(tb);
                    if (m_threadPool->putq(mb) == -1)
                      { break; }
                }
            }
        }
        if (activated() && standAlone)
        {
            Tile_Message_Block *finish_mb = new Tile_Message_Block(NULL);
            finish_mb->msg_type(ACE_Message_Block::MB_HANGUP);
            m_threadPool->putq(finish_mb);
            m_threadPool->wait();
        }

        if (!activated())
          { dtFreeNavMesh(navMesh); }

        if (meshParams)
            { delete meshParams; }

        if (!activated())
          { printf(" Map %03u complete!\n\n", mapID); }
    }