예제 #1
0
    void MapBuilder::buildMap(uint32 mapID)
    {
#ifndef __APPLE__
        //printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID);
#endif

        std::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->empty())
        {
            // build navMesh
            dtNavMesh* navMesh = NULL;
            buildNavMesh(mapID, navMesh);
            if (!navMesh)
            {
                printf("[Map %04i] Failed creating navmesh!\n", mapID);
                return;
            }

            // now start building mmtiles for each tile
            printf("[Map %04i] We have %u tiles.                          \n", mapID, (unsigned int)tiles->size());
            for (std::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("[Map %04u] Complete!\n", mapID);
    }
예제 #2
0
    void MapBuilder::buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY)
    {
        dtNavMesh* navMesh = NULL;
        buildNavMesh(mapID, navMesh);
        if (!navMesh)
        {
            printf("Failed creating navmesh!              \n");
            return;
        }

        buildTile(mapID, tileX, tileY, navMesh);
        dtFreeNavMesh(navMesh);
    }
예제 #3
0
    void MapBuilder::buildMap(int mapID)
    {
        printf("Building map %03u:\n", mapID);

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

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

            // add all tiles within bounds to tile list.
            for (int i = minX; i <= maxX; ++i)
                for (int 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<int>::iterator it = tiles->begin(); it != tiles->end(); ++it)
        {
            int 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");
    }
예제 #4
0
    void MapBuilder::buildSingleTile(int mapID, int tileX, int tileY)
    {
        dtNavMesh* navMesh = NULL;
        dtNavMeshParams* meshParams = NULL;
        buildNavMesh(mapID, navMesh, meshParams);
        if (!navMesh)
        {
            printf("Failed creating navmesh!              \n");
            return;
        }

        buildTile(mapID, tileX, tileY, navMesh);
        dtFreeNavMesh(navMesh);
        if (meshParams)
          { delete meshParams; }
    }
예제 #5
0
// TODO I need to redraw the changed tiles!!
int OgreDetourTileCache::addConvexShapeObstacle(ConvexVolume *obstacle)
{
    // Add convex shape to input geometry
    int result = m_geom->addConvexVolume(obstacle);
    if (result == -1)
        return result;

// TODO use these vars for deferring addConvexShape actions
//    mChangedConvexVolumes[mChangedConvexVolumesCount] = obstacle;
//    mChangedConvexVolumesCount++;

    // Determine which navmesh tiles have to be updated
         // Borrowed from detourTileCache::update()
            // Find touched tiles using obstacle bounds.
    int ntouched = 0;
    dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
    m_tileCache->queryTiles(obstacle->bmin, obstacle->bmax, touched, &ntouched, DT_MAX_TOUCHED_TILES);

    // Rebuild affected tiles
// TODO maybe defer this and timeslice it, like happend in dtTileCache with tempObstacle updates
    for (int i = 0; i < ntouched; ++i)
    {
// TODO when you do deffered commands, make sure you issue a rebuild for a tile only once per update, so remove doubles from the request queue (this is what contains() is for in dtTileCache)
        // Retrieve coordinates of tile that has to be rebuilt
        const dtCompressedTile* tile = m_tileCache->getTileByRef(touched[i]);

        // If it is null, tile is already rebuilt (and has a new ref ID)
        if(tile) {
            int tx = tile->header->tx;
            int ty = tile->header->ty;
            tile = NULL;

// TODO we actually want a buildTile method with a tileRef as input param. As this method does a bounding box intersection with tiles again, which might result in multiple tiles being rebuilt (which will lead to nothing because only one tile is removed..), and we determined which tiles to bebuild already, anyway (using queryTiles)
            buildTile(tx, ty, m_geom);  // Might rebuild multiple tiles
        }

    }


    return result;
}
예제 #6
0
void OgreDetourTileCache::buildTiles(InputGeom *inputGeom, const Ogre::AxisAlignedBox *areaToUpdate)
{
    // Use bounding box from inputgeom if no area was explicitly specified
    Ogre::AxisAlignedBox updateArea;
    if(!areaToUpdate)
        updateArea = inputGeom->getBoundingBox();
    else
        updateArea = *areaToUpdate;

    // Reduce bounding area a little with one cell in size, to be sure that if it was already tile-aligned, we don't select an extra tile
    updateArea.setMinimum( updateArea.getMinimum() + Ogre::Vector3(m_cellSize, 0, m_cellSize) );
    updateArea.setMaximum( updateArea.getMaximum() - Ogre::Vector3(m_cellSize, 0, m_cellSize) );

    // Select tiles to build or rebuild (builds a tile-aligned BB)
    TileSelection selection = getTileSelection(updateArea);


    // Debug drawing of bounding area that is updated
    // Remove previous debug drawn bounding box of rebuilt area
    if(mDebugRebuiltBB) {
        mDebugRebuiltBB->detachFromParent();
        m_recast->m_pSceneMgr->destroyManualObject(mDebugRebuiltBB);
        mDebugRebuiltBB = NULL;
    }
    if(DEBUG_DRAW_REBUILT_BB)
        mDebugRebuiltBB = InputGeom::drawBoundingBox(selection.bounds, m_recast->m_pSceneMgr);


    int tilesToBuildX = (selection.maxTx - selection.minTx)+1;  // Tile ranges are inclusive
    int tilesToBuildY = (selection.maxTy - selection.minTy)+1;
    if(tilesToBuildX * tilesToBuildY > 5)
        Ogre::LogManager::getSingletonPtr()->logMessage("Building "+Ogre::StringConverter::toString(tilesToBuildX)+" x "+Ogre::StringConverter::toString(tilesToBuildY)+" navmesh tiles.");

    // Build tiles
    for (int ty = selection.minTy; ty <= selection.maxTy; ty++) {
        for (int tx = selection.minTx; tx <= selection.maxTx; tx++) {
            buildTile(tx, ty, inputGeom);
        }
    }
}
예제 #7
0
bool OgreDetourTileCache::removeConvexShapeObstacleById(int obstacleIndex, ConvexVolume** removedVolume)
{
    ConvexVolume* obstacle;
    if(! m_geom->deleteConvexVolume(obstacleIndex, &obstacle))
        return false;

    if(removedVolume != NULL)
        *removedVolume = obstacle;

// TODO use these vars for deferring addConvexShape actions
    //mChangedConvexVolumes[mChangedConvexVolumesCount] = obstacle;
    //mChangedConvexVolumesCount++;

//TODO For removing a convex volume again, store a reference to the impacted tiles in the convex volume so they can be found quickly
    int ntouched = 0;
    dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
    m_tileCache->queryTiles(obstacle->bmin, obstacle->bmax, touched, &ntouched, DT_MAX_TOUCHED_TILES);

    // Rebuild affected tiles
// TODO maybe defer this and timeslice it, like happens in dtTileCache with tempObstacle updates
    for (int i = 0; i < ntouched; ++i)
    {
// TODO when you do deffered commands, make sure you issue a rebuild for a tile only once per update, so remove doubles from the request queue (this is what contains() is for in dtTileCache)
        // Retrieve coordinates of tile that has to be rebuilt
        const dtCompressedTile* tile = m_tileCache->getTileByRef(touched[i]);

        // If it is null, tile is already rebuilt (and has a new ref ID)
        if(tile) {
            int tx = tile->header->tx;
            int ty = tile->header->ty;
            tile = NULL;

            // Issue full rebuild from inputGeom, with the specified convex shape removed, for this tile
            buildTile(tx, ty, m_geom);
        }
    }

    return true;
}
예제 #8
0
    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); }
    }