//----------------------------------------------------------------------- // Update using page local tile coordinates. void UpdateTile( int tileX, int tileZ ) { PagingLandScapeTile* tile = page_->getTile( tileX, tileZ ); if( tile != tile_ ) { tile_ = tile; bool tileLoaded = tile_ && tile_->isLoaded() && tile_->getRenderable(); renderLevel_.SetRenderLevel( (tileLoaded) ? tile_->getRenderable()->getRenderLevel() : 0 ); } }
//----------------------------------------------------------------------- PagingLandScapeTile* PagingLandScapePage::getTile(const Vector3& pos) const { const size_t x = static_cast<unsigned int>(pos.x / mPageMgr.getOptions()->scale.x / (mPageMgr.getOptions()->TileSize)); const size_t z = static_cast<unsigned int>(pos.z / mPageMgr.getOptions()->scale.z / (mPageMgr.getOptions()->TileSize)); PagingLandScapeTile* tile = getTile(x, z); if (tile && tile->isLoaded()) { return tile; } else { return 0; } }
//------------------------------------------------------------------------- void PagingLandScapePage::setRenderQueue(uint8 qid) { if (mPageState == STATE_LOADED && mVisible) { for (size_t i = 0; i < mTiles.size(); ++i) { for (size_t j = 0; j < mTiles[i].size(); ++j) { PagingLandScapeTile* t = mTiles[i][j]; if (t->isVisible()) { t->setRenderQueueGroup(qid); } } } } }
//------------------------------------------------------------------------- void PagingLandScapePage::updateLod() { if (mPageState == STATE_LOADED) { for (size_t i = 0; i < mTiles.size(); ++i) { for (size_t j = 0; j < mTiles[i].size(); ++j) { PagingLandScapeTile* t = mTiles[i][j]; if (t->isVisible()) { t->_updateLod(); } } } } }
//----------------------------------------------------------------------- void PagingLandScapeRenderableManager::clear() { if (!mTilesLoadRenderableQueue.empty()) { PagingLandScapeTile *t = mTilesLoadRenderableQueue.pop(); while (t) { t->uninit(); t = mTilesLoadRenderableQueue.pop(); } assert(mTilesLoadRenderableQueue.empty ()); } // As Renderables change too much over maps (+- lit, normals, etc...) mRenderablePool.deletePool(); }
//----------------------------------------------------------------------- void PagingLandScapePage::updateTerrain() { const unsigned int size = mPageMgr.getOptions()->TileSize - 1; for (size_t i = 0; i < mTiles.size(); ++i) { for (size_t j = 0; j < mTiles[i].size(); ++j) { PagingLandScapeTile* tile = mTiles[i][j]; // we need to adjust the deformation rectangle for the whole tile/renderable so to force a recalculation of the bounding box and the LOD calculation if (tile->getRenderable()) { tile->getRenderable()->adjustDeformationRectangle(0, 0); tile->getRenderable()->adjustDeformationRectangle(size, size); tile->updateTerrain(); } } } }
//----------------------------------------------------------------------- void PagingLandScapeRenderableManager::clear() { if (!mTilesLoadQueue.empty ()) { PagingLandScapeTile *t = mTilesLoadQueue.pop(); while (t) { t->uninit (); t = mTilesLoadQueue.pop (); } mTilesLoadQueue.clear (); } // If renderables change over maps (+- lit, normals, etc...) std::for_each(mRenderables.begin (), mRenderables.end (), delete_object()); mRenderables.clear(); mQueue.clear(); }
//----------------------------------------------------------------------- void PagingLandScapeTile::_linkRenderableNeighbor() { PLSM2_ASSERT (mLoaded && mRenderable); PagingLandScapeRenderable *n; PagingLandScapeTile *t = mNeighbors[SOUTH]; if (t && t->mLoaded) { n = t->getRenderable(); PLSM2_ASSERT (n); mRenderable->_setNeighbor (SOUTH, n); n->_setNeighbor (NORTH, mRenderable); } t = mNeighbors[NORTH]; if (t && t->mLoaded) { n = t->getRenderable(); PLSM2_ASSERT (n); mRenderable->_setNeighbor (NORTH, n); n->_setNeighbor (SOUTH, mRenderable); } t = mNeighbors[EAST]; if (t && t->mLoaded) { n = t->getRenderable(); PLSM2_ASSERT (n); mRenderable->_setNeighbor (EAST, n); n->_setNeighbor (WEST, mRenderable); } t = mNeighbors[WEST]; if (t && t->mLoaded) { n = t->getRenderable(); PLSM2_ASSERT (n); mRenderable->_setNeighbor (WEST, n); n->_setNeighbor (EAST, mRenderable); } }
//----------------------------------------------------------------------- bool PagingLandScapeRenderableManager::executeRenderableLoading(void) { if (mTilesLoadQueue.empty()) return true; else { const uint k = PagingLandScapeOptions::getSingleton ().num_renderables_loading; for (uint i = 0; i < k; i++ ) { PagingLandScapeTile* tile = mTilesLoadQueue.pop (); // no more in queues. if (tile == 0) return true; assert (tile->isLoaded ()); PagingLandScapeRenderable* rend = tile->getRenderable(); assert (!rend->isLoaded ()); SceneNode * tileSceneNode = tile->getTileNode (); assert (rend != 0 && tileSceneNode != 0); tileSceneNode->attachObject( rend ); // renderables need to be attached (BBox compute) if (rend->load()) { tile->_linkRenderableNeighbor (); } else { // renderable have been unloaded since. tile->unload (); } tileSceneNode->needUpdate(); } } return false; }
//----------------------------------------------------------------------- void PagingLandScapePage::setNeighbor(Neighbor n, PagingLandScapePage* p) { // set page neighbor mNeighbors[n] = p; // if neigther are loaded, nothing else to do const bool thisLoaded = isLoaded(); const bool neighLoaded = p && p->isLoaded(); if (!thisLoaded && !neighLoaded) { return; } assert (!thisLoaded || (thisLoaded && !mTiles.empty())); // tiles, 0 if not loaded PagingLandScapeTile* tileInCurrPage = 0; PagingLandScapeTile* tileInNeighborPage = 0; // indices for borders const unsigned int iNorthBorder = 0; const unsigned int iSouthBorder = mNumTiles - 1; const unsigned int iEastBorder = mNumTiles - 1; const unsigned int iWestBorder = 0; // walk the tiles in each border, and set roles accordingly switch (n) { case EAST: { for (unsigned int j = 0; j < mNumTiles; ++j) { if (thisLoaded) { // tiles of this page along east border tileInCurrPage = mTiles[iEastBorder][j]; } if (neighLoaded) { // tiles of neighbor page along west border tileInNeighborPage = p->getTile(iWestBorder, j); } // set neighbor tiles if (tileInCurrPage) { tileInCurrPage->_setNeighbor(EAST, tileInNeighborPage); } if (tileInNeighborPage) { tileInNeighborPage->_setNeighbor(WEST, tileInCurrPage); } } } break; case WEST: { for (unsigned int j = 0; j < mNumTiles; ++j) { if (thisLoaded) { // tiles of this page along west border tileInCurrPage = mTiles[iWestBorder][j]; } if (neighLoaded) { // tiles of neighbor page along east border tileInNeighborPage = p->getTile(iEastBorder, j); } // set neighbor tiles if (tileInCurrPage) { tileInCurrPage->_setNeighbor(WEST, tileInNeighborPage); } if (tileInNeighborPage) { tileInNeighborPage->_setNeighbor(EAST, tileInCurrPage); } } } break; case NORTH: { for (unsigned int i = 0; i < mNumTiles; ++i) { if (thisLoaded) { // tiles of this page along north border tileInCurrPage = mTiles[i][iNorthBorder]; } if (neighLoaded) { // tiles of neighbor page along south border tileInNeighborPage = p->getTile(i, iSouthBorder); } // set neighbor tiles if (tileInCurrPage) { tileInCurrPage->_setNeighbor(NORTH, tileInNeighborPage); } if (tileInNeighborPage) { tileInNeighborPage->_setNeighbor(SOUTH, tileInCurrPage); } } } break; case SOUTH: { for (unsigned int i = 0; i < mNumTiles; ++i) { if (thisLoaded) { // tiles of this page along south border tileInCurrPage = mTiles[i][iSouthBorder]; } if (neighLoaded) { // tiles of neighbor page along north border tileInNeighborPage = p->getTile(i, iNorthBorder); } // set neighbor tiles if (tileInCurrPage) { tileInCurrPage->_setNeighbor(SOUTH, tileInNeighborPage); } if (tileInNeighborPage) { tileInNeighborPage->_setNeighbor(NORTH, tileInCurrPage); } } } break; default: break; } }
//----------------------------------------------------------------------- void PagingLandScapePage::load() { touch(); if (isLoaded()) { S_LOG_WARNING("PagingLandScapePage at (" << mTableX << ", " << mTableZ << ") already loading/loaded, ignoring load() request"); return; } S_LOG_VERBOSE("Loading PagingLandScapePage at (" << mTableX << ", " << mTableZ << ")"); if (mPageState == STATE_INITED) { preloadInBackground(); // it takes a while to do it, so we don't bother trying to load and failing return; } if (mPageState == STATE_PRELOADED) { // load texture S_LOG_VERBOSE("Loading texture for PagingLandScapePage at (" << mTableX << ", " << mTableZ << ")"); mPageMgr.getSceneManager()->getTextureManager()->load(mTableX, mTableZ); // initialize tile containers mTiles.reserve(mNumTiles); mTiles.resize(mNumTiles); for (size_t i = 0; i < mNumTiles; ++i) { mTiles[i].reserve(mNumTiles); mTiles[i].resize(mNumTiles); } // initialize tiles PagingLandScapeTileManager* tileMgr = mPageMgr.getSceneManager()->getTileManager(); for (size_t i = 0; i < mTiles.size(); ++i) { for (size_t j = 0; j < mTiles[i].size(); ++j) { PagingLandScapeTile* tile = tileMgr->getTile(); assert (tile); mTiles[i][j] = tile; tile->init(mPageNode, mTableX, mTableZ, i, j); // set up tile neighbors within page if (j > 0) { PagingLandScapeTile* northTile = mTiles[i][j-1]; tile->_setNeighbor(NORTH, northTile); northTile->_setNeighbor(SOUTH, tile); } if (i > 0) { PagingLandScapeTile* westTile = mTiles[i-1][j]; tile->_setNeighbor(WEST, westTile); westTile->_setNeighbor(EAST, tile); } } } // set new state mPageState = STATE_LOADED; // set page neighbors setNeighbors(); // fire event fireEvent(EVENT_LOADED); } else if (mPageState == STATE_PRELOADING) { // wait... return; } else { S_LOG_WARNING("PagingLandScapePage at (" << mTableX << ", " << mTableZ << ") already loaded, proceeding to show it"); } show(true); }
//----------------------------------------------------------------------- void PagingLandScapeRenderableManager::processTileUnload() { if (mTilesLoadRenderableQueue.empty()) return; PagingLandScapeTile *tile; for (PagingLandScapeQueue<PagingLandScapeTile>::MsgQueType::iterator itq = mTilesLoadRenderableQueue.begin(); itq != mTilesLoadRenderableQueue.end();) { tile = *itq; assert (tile != 0); assert (tile->isLoading()); assert (tile->getRenderable ()); assert (tile->getRenderable ()->mQueued); assert (tile->isLoaded ()); assert (tile->getSceneNode()); assert (!tile->getRenderable ()->isLoaded ()); if (!tile->getRenderable ()->isInUse ()) { tile->setLoading (false); tile->getRenderable ()->mQueued = false; tile->unload (); itq = mTilesLoadRenderableQueue.erase (itq); } else { ++itq; } } }
//----------------------------------------------------------------------- bool PagingLandScapeData2D::setHeight( const uint x, const uint z, const uint Pos, const Real h ) { if (mHeightData[Pos] != h) { mHeightData[ Pos ] = h; uint tileposx = x; uint tileposz = z; // Make position local to tiles. // and return a Tile. PagingLandScapeTile *t = PagingLandScapePageManager::getSingleton().getTilePage(tileposx, tileposz, mPageX, mPageZ); if (t && t->isLoaded ()) { // tells what tile portion needs to be updated. PagingLandScapeRenderable * const r = t->getRenderable (); r->adjustDeformationRectangle (tileposx, tileposz); const uint tSize = PagingLandScapeOptions::getSingleton ().TileSize - 1; const uint NumTiles = PagingLandScapeOptions::getSingleton ().NumTiles; const PagingLandScapeTileInfo * const info = t->getInfo(); const uint tX = info->tileX; const uint tZ = info->tileZ; // If we're on a page edge, we must duplicate the change on the // neighbour tile (if it has one...) // could be a direct neighbour or a diagonal one (in a corner.) const bool left = (tileposx == 0 && tX != 0); const bool right = (tileposx == tSize && tX != NumTiles - 1); const bool down = (tileposz == 0 && tZ != 0); const bool up = (tileposz == tSize && tZ != NumTiles - 1); if (left) { PagingLandScapeRenderable * const rn = r->_getNeighbor(WEST); if (rn) { if (down) { PagingLandScapeRenderable * const rnUp = rn->_getNeighbor(NORTH); if (rnUp && rnUp->isLoaded ()) { rnUp->adjustDeformationRectangle (tSize, tSize); } } else if (up) { PagingLandScapeRenderable * const rnDown = rn->_getNeighbor(SOUTH); if (rnDown && rnDown->isLoaded ()) { rnDown->adjustDeformationRectangle (tSize, 0); } } if (rn->isLoaded ()) { rn->adjustDeformationRectangle (tSize, tileposz); } } } else if (right) { PagingLandScapeRenderable * const rn = r->_getNeighbor(EAST); if (rn) { if (down) { PagingLandScapeRenderable * const rnUp = rn->_getNeighbor(NORTH); if (rnUp && rnUp->isLoaded ()) { rnUp->adjustDeformationRectangle (0, tSize); } } else if (up) { PagingLandScapeRenderable * const rnDown = rn->_getNeighbor(SOUTH); if (rnDown && rnDown->isLoaded ()) { rnDown->adjustDeformationRectangle (0, 0); } } if (rn) { rn->adjustDeformationRectangle (0, tileposz); } } } if (down) { PagingLandScapeRenderable * const rn = r->_getNeighbor(NORTH); if (rn && rn->isLoaded ()) { rn->adjustDeformationRectangle (tileposx, tSize); } } else if (up) { PagingLandScapeRenderable * const rn = r->_getNeighbor(SOUTH); if (rn && rn->isLoaded ()) { rn->adjustDeformationRectangle (tileposx, 0); } } } adjustDeformationRectangle (x, z); return true; } return false; }