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); }
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); }
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"); }
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; } }
// 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; }
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); } } }
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; }
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); } }