1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreGrid3DPageStrategy.h" 29 30 #include "OgreStreamSerialiser.h" 31 #include "OgreException.h" 32 #include "OgreCamera.h" 33 #include "OgrePagedWorldSection.h" 34 #include "OgrePage.h" 35 #include "OgreSceneNode.h" 36 #include "OgreSceneManager.h" 37 #include "OgreMaterialManager.h" 38 #include "OgreManualObject.h" 39 #include "OgrePageManager.h" 40 41 namespace Ogre 42 { 43 //--------------------------------------------------------------------- 44 const uint32 Grid3DPageStrategyData::CHUNK_ID = StreamSerialiser::makeIdentifier("G3DD"); 45 const uint16 Grid3DPageStrategyData::CHUNK_VERSION = 1; 46 //--------------------------------------------------------------------- Grid3DPageStrategyData()47 Grid3DPageStrategyData::Grid3DPageStrategyData() 48 : PageStrategyData() 49 , mWorldOrigin(Vector3::ZERO) 50 , mOrigin(Vector3::ZERO) 51 , mCellSize(1000,1000,1000) 52 , mLoadRadius(2000) 53 , mHoldRadius(3000) 54 , mMinCellX(-512) 55 , mMinCellY(-512) 56 , mMinCellZ(-512) 57 , mMaxCellX(511) 58 , mMaxCellY(511) 59 , mMaxCellZ(511) 60 { 61 } 62 //--------------------------------------------------------------------- setCellRange(int32 minX,int32 minY,int32 minZ,int32 maxX,int32 maxY,int32 maxZ)63 void Grid3DPageStrategyData::setCellRange(int32 minX, int32 minY, int32 minZ, int32 maxX, int32 maxY, int32 maxZ) 64 { 65 mMinCellX = minX; 66 mMinCellY = minY; 67 mMinCellZ = minZ; 68 mMaxCellX = maxX; 69 mMaxCellY = maxY; 70 mMaxCellZ = maxZ; 71 } 72 //--------------------------------------------------------------------- setCellRangeMinX(int32 minX)73 void Grid3DPageStrategyData::setCellRangeMinX(int32 minX) 74 { 75 mMinCellX = minX; 76 } 77 //--------------------------------------------------------------------- setCellRangeMinY(int32 minY)78 void Grid3DPageStrategyData::setCellRangeMinY(int32 minY) 79 { 80 mMinCellY = minY; 81 } 82 //--------------------------------------------------------------------- setCellRangeMinZ(int32 minZ)83 void Grid3DPageStrategyData::setCellRangeMinZ(int32 minZ) 84 { 85 mMinCellZ = minZ; 86 } 87 //--------------------------------------------------------------------- setCellRangeMaxX(int32 maxX)88 void Grid3DPageStrategyData::setCellRangeMaxX(int32 maxX) 89 { 90 mMaxCellX = maxX; 91 } 92 //--------------------------------------------------------------------- setCellRangeMaxY(int32 maxY)93 void Grid3DPageStrategyData::setCellRangeMaxY(int32 maxY) 94 { 95 mMaxCellY = maxY; 96 } 97 //--------------------------------------------------------------------- setCellRangeMaxZ(int32 maxZ)98 void Grid3DPageStrategyData::setCellRangeMaxZ(int32 maxZ) 99 { 100 mMaxCellZ = maxZ; 101 } 102 //--------------------------------------------------------------------- ~Grid3DPageStrategyData()103 Grid3DPageStrategyData::~Grid3DPageStrategyData() 104 { 105 } 106 //--------------------------------------------------------------------- setOrigin(const Vector3 & origin)107 void Grid3DPageStrategyData::setOrigin(const Vector3& origin) 108 { 109 mWorldOrigin = origin; 110 } 111 //--------------------------------------------------------------------- determineGridLocation(const Vector3 & pos,int32 * x,int32 * y,int32 * z)112 void Grid3DPageStrategyData::determineGridLocation(const Vector3& pos, int32 *x, int32 *y, int32 *z) 113 { 114 Vector3 relPos = pos - mOrigin + mCellSize * 0.5f; 115 116 *x = static_cast<int32>(floor(relPos.x / mCellSize.x)); 117 *y = static_cast<int32>(floor(relPos.y / mCellSize.y)); 118 *z = static_cast<int32>(floor(relPos.z / mCellSize.z)); 119 } 120 //--------------------------------------------------------------------- getBottomLeftGridSpace(int32 x,int32 y,int32 z,Vector3 & bl)121 void Grid3DPageStrategyData::getBottomLeftGridSpace(int32 x, int32 y, int32 z, Vector3& bl) 122 { 123 bl.x = mOrigin.x + (x-0.5f) * mCellSize.x; 124 bl.y = mOrigin.y + (y-0.5f) * mCellSize.y; 125 bl.z = mOrigin.z + (z-0.5f) * mCellSize.z; 126 } 127 //--------------------------------------------------------------------- getMidPointGridSpace(int32 x,int32 y,int32 z,Vector3 & mid)128 void Grid3DPageStrategyData::getMidPointGridSpace(int32 x, int32 y, int32 z, Vector3& mid) 129 { 130 mid.x = mOrigin.x + float(x) * mCellSize.x; 131 mid.y = mOrigin.y + float(y) * mCellSize.y; 132 mid.z = mOrigin.z + float(z) * mCellSize.z; 133 } 134 //--------------------------------------------------------------------- getCornersGridSpace(int32 x,int32 y,int32 z,Vector3 * pEightPoints)135 void Grid3DPageStrategyData::getCornersGridSpace(int32 x, int32 y, int32 z, Vector3* pEightPoints) 136 { 137 getBottomLeftGridSpace(x, y, z, pEightPoints[0]); 138 pEightPoints[1] = pEightPoints[0] + Vector3(mCellSize.x, 0, 0); 139 pEightPoints[2] = pEightPoints[0] + Vector3(mCellSize.x, mCellSize.y, 0); 140 pEightPoints[3] = pEightPoints[0] + Vector3(0, mCellSize.y, 0); 141 pEightPoints[4] = pEightPoints[0] + Vector3(0, 0, mCellSize.z); 142 pEightPoints[5] = pEightPoints[1] + Vector3(0, 0, mCellSize.z); 143 pEightPoints[6] = pEightPoints[2] + Vector3(0, 0, mCellSize.z); 144 pEightPoints[7] = pEightPoints[3] + Vector3(0, 0, mCellSize.z); 145 } 146 //--------------------------------------------------------------------- setCellSize(const Vector3 & sz)147 void Grid3DPageStrategyData::setCellSize(const Vector3& sz) 148 { 149 mCellSize = sz; 150 } 151 //--------------------------------------------------------------------- 152 //--------------------------------------------------------------------- setLoadRadius(Real sz)153 void Grid3DPageStrategyData::setLoadRadius(Real sz) 154 { 155 mLoadRadius = sz; 156 } 157 //--------------------------------------------------------------------- setHoldRadius(Real sz)158 void Grid3DPageStrategyData::setHoldRadius(Real sz) 159 { 160 mHoldRadius = sz; 161 } 162 //--------------------------------------------------------------------- calculatePageID(int32 x,int32 y,int32 z)163 PageID Grid3DPageStrategyData::calculatePageID(int32 x, int32 y, int32 z) 164 { 165 // Go into positive range (simpler on decode) 166 x -= mMinCellX; 167 y -= mMinCellY; 168 z -= mMinCellZ; 169 // Push index bits into place 170 uint32 key = z & 1023; 171 key = (key<<10) | (y&1023); 172 key = (key<<10) | (x&1023); 173 return (PageID)key; 174 } 175 //--------------------------------------------------------------------- calculateCell(PageID inPageID,int32 * x,int32 * y,int32 * z)176 void Grid3DPageStrategyData::calculateCell(PageID inPageID, int32 *x, int32 *y, int32* z) 177 { 178 // Pop bits from page index: 179 int32 ox = inPageID & 1023; inPageID >>= 10; 180 int32 oy = inPageID & 1023; inPageID >>= 10; 181 int32 oz = inPageID & 1023; 182 //// Hand made sign extension from 10bits to 32: 183 //NOT NEEDED ANYMORE because this is crafted positive... 184 //if( ox > 511 ) ox = 1024 - ox; 185 //if( oy > 511 ) oy = 1024 - oy; 186 //if( oz > 511 ) oz = 1024 - oz; 187 // Back in the [min..max] range: 188 *x = ox + mMinCellX; 189 *y = oy + mMinCellY; 190 *z = oz + mMinCellZ; 191 } 192 //--------------------------------------------------------------------- load(StreamSerialiser & ser)193 bool Grid3DPageStrategyData::load(StreamSerialiser& ser) 194 { 195 if (!ser.readChunkBegin(CHUNK_ID, CHUNK_VERSION, "Grid3DPageStrategyData")) 196 return false; 197 198 ser.read(&mOrigin); 199 ser.read(&mCellSize); 200 ser.read(&mLoadRadius); 201 ser.read(&mHoldRadius); 202 ser.read(&mMinCellX); 203 ser.read(&mMaxCellX); 204 ser.read(&mMinCellY); 205 ser.read(&mMaxCellY); 206 ser.read(&mMinCellZ); 207 ser.read(&mMaxCellZ); 208 209 ser.readChunkEnd(CHUNK_ID); 210 211 return true; 212 } 213 //--------------------------------------------------------------------- save(StreamSerialiser & ser)214 void Grid3DPageStrategyData::save(StreamSerialiser& ser) 215 { 216 ser.writeChunkBegin(CHUNK_ID, CHUNK_VERSION); 217 218 ser.write(&mWorldOrigin); 219 ser.write(&mCellSize); 220 ser.write(&mLoadRadius); 221 ser.write(&mHoldRadius); 222 ser.write(&mMinCellX); 223 ser.write(&mMaxCellX); 224 ser.write(&mMinCellY); 225 ser.write(&mMaxCellY); 226 ser.write(&mMinCellZ); 227 ser.write(&mMaxCellZ); 228 229 ser.writeChunkEnd(CHUNK_ID); 230 } 231 //--------------------------------------------------------------------- 232 //--------------------------------------------------------------------- Grid3DPageStrategy(PageManager * manager)233 Grid3DPageStrategy::Grid3DPageStrategy(PageManager* manager) 234 : PageStrategy("Grid3D", manager) 235 { 236 237 } 238 //--------------------------------------------------------------------- ~Grid3DPageStrategy()239 Grid3DPageStrategy::~Grid3DPageStrategy() 240 { 241 242 } 243 //--------------------------------------------------------------------- notifyCamera(Camera * cam,PagedWorldSection * section)244 void Grid3DPageStrategy::notifyCamera(Camera* cam, PagedWorldSection* section) 245 { 246 Grid3DPageStrategyData* stratData = static_cast<Grid3DPageStrategyData*>(section->getStrategyData()); 247 248 const Vector3& pos = cam->getDerivedPosition(); 249 int32 x, y, z; 250 stratData->determineGridLocation(pos, &x, &y, &z); 251 252 Real loadRadius = stratData->getLoadRadius(); 253 Real holdRadius = stratData->getHoldRadius(); 254 // scan the whole Hold range 255 Real fxmin = (Real)x - holdRadius/stratData->getCellSize().x; 256 Real fxmax = (Real)x + holdRadius/stratData->getCellSize().x; 257 Real fymin = (Real)y - holdRadius/stratData->getCellSize().y; 258 Real fymax = (Real)y + holdRadius/stratData->getCellSize().y; 259 Real fzmin = (Real)z - holdRadius/stratData->getCellSize().z; 260 Real fzmax = (Real)z + holdRadius/stratData->getCellSize().z; 261 262 int32 xmin = stratData->getCellRangeMinX(); 263 int32 xmax = stratData->getCellRangeMaxX(); 264 int32 ymin = stratData->getCellRangeMinY(); 265 int32 ymax = stratData->getCellRangeMaxY(); 266 int32 zmin = stratData->getCellRangeMinZ(); 267 int32 zmax = stratData->getCellRangeMaxZ(); 268 269 // Round UP max, round DOWN min 270 xmin = fxmin < xmin ? xmin : (int32)floor(fxmin); 271 xmax = fxmax > xmax ? xmax : (int32)ceil(fxmax); 272 ymin = fymin < ymin ? ymin : (int32)floor(fymin); 273 ymax = fymax > ymax ? ymax : (int32)ceil(fymax); 274 zmin = fzmin < zmin ? zmin : (int32)floor(fzmin); 275 zmax = fzmax > zmax ? zmax : (int32)ceil(fzmax); 276 // the inner, active load range 277 fxmin = (Real)x - loadRadius/stratData->getCellSize().x; 278 fxmax = (Real)x + loadRadius/stratData->getCellSize().x; 279 fymin = (Real)y - loadRadius/stratData->getCellSize().y; 280 fymax = (Real)y + loadRadius/stratData->getCellSize().y; 281 fzmin = (Real)z - loadRadius/stratData->getCellSize().z; 282 fzmax = (Real)z + loadRadius/stratData->getCellSize().z; 283 // Round UP max, round DOWN min 284 int32 loadxmin = fxmin < xmin ? xmin : (int32)floor(fxmin); 285 int32 loadxmax = fxmax > xmax ? xmax : (int32)ceil(fxmax); 286 int32 loadymin = fymin < ymin ? ymin : (int32)floor(fymin); 287 int32 loadymax = fymax > ymax ? ymax : (int32)ceil(fymax); 288 int32 loadzmin = fzmin < zmin ? zmin : (int32)floor(fzmin); 289 int32 loadzmax = fzmax > zmax ? zmax : (int32)ceil(fzmax); 290 291 for (int32 cz = zmin; cz <= zmax; ++cz) 292 { 293 for (int32 cy = ymin; cy <= ymax; ++cy) 294 { 295 for (int32 cx = xmin; cx <= xmax; ++cx) 296 { 297 PageID pageID = stratData->calculatePageID(cx, cy, cz); 298 299 if (cx >= loadxmin && cx <= loadxmax 300 && cy >= loadymin && cy <= loadymax 301 && cz >= loadzmin && cz <= loadzmax ) 302 { 303 Vector3 bl; 304 stratData->getBottomLeftGridSpace(cx, cy, cz, bl); 305 Ogre::AxisAlignedBox bbox(bl, bl+stratData->getCellSize()); 306 307 if( cam->isVisible(bbox) ) 308 section->loadPage(pageID); 309 else 310 section->holdPage(pageID); 311 } 312 else 313 { 314 // in the outer 'hold' range, keep it but don't actively load 315 section->holdPage(pageID); 316 } 317 // other pages will by inference be marked for unloading 318 } 319 } 320 } 321 } 322 //--------------------------------------------------------------------- createData()323 PageStrategyData* Grid3DPageStrategy::createData() 324 { 325 return OGRE_NEW Grid3DPageStrategyData(); 326 } 327 //--------------------------------------------------------------------- destroyData(PageStrategyData * d)328 void Grid3DPageStrategy::destroyData(PageStrategyData* d) 329 { 330 OGRE_DELETE d; 331 } 332 //--------------------------------------------------------------------- updateDebugDisplay(Page * p,SceneNode * sn)333 void Grid3DPageStrategy::updateDebugDisplay(Page* p, SceneNode* sn) 334 { 335 uint8 dbglvl = mManager->getDebugDisplayLevel(); 336 if (dbglvl) 337 { 338 // we could try to avoid updating the geometry every time here, but this 339 // wouldn't easily deal with paging parameter changes. There shouldn't 340 // be that many pages anyway, and this is debug after all, so update every time 341 int32 x, y, z; 342 Grid3DPageStrategyData* stratData = static_cast<Grid3DPageStrategyData*>( 343 p->getParentSection()->getStrategyData()); 344 stratData->calculateCell(p->getID(), &x, &y, &z); 345 346 Grid3DPageStrategyData* data = static_cast<Grid3DPageStrategyData*>(p->getParentSection()->getStrategyData()); 347 348 // Determine our centre point, we'll anchor here 349 Vector3 midPoint; 350 data->getMidPointGridSpace(x, y, z, midPoint); 351 sn->setPosition(midPoint); 352 353 //--- Get coordinates, relative to midPoint : 354 Vector3 corners[8]; 355 Vector3 hSize = 0.500f * stratData->getCellSize(); 356 for (int i = 0; i < 8; ++i) 357 { 358 corners[i].x = i&1 ? hSize.x : -hSize.x; 359 corners[i].z = i&2 ? hSize.y : -hSize.y; 360 corners[i].y = i&4 ? hSize.z : -hSize.z; 361 } 362 363 //--- Get a material 364 String matName = "Ogre/G3D/Debug"; 365 MaterialPtr mat = MaterialManager::getSingleton().getByName(matName); 366 if (mat.isNull()) 367 { 368 mat = MaterialManager::getSingleton().create(matName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); 369 Pass* pass = mat->getTechnique(0)->getPass(0); 370 pass->setLightingEnabled(false); 371 pass->setVertexColourTracking(TVC_AMBIENT); 372 pass->setDepthWriteEnabled(false); 373 mat->load(); 374 } 375 376 ManualObject* mo = 0; 377 bool update = sn->numAttachedObjects() > 0; 378 if( update ) 379 { 380 mo = static_cast<ManualObject*>(sn->getAttachedObject(0)); 381 mo->beginUpdate(0); 382 } 383 else 384 { 385 mo = p->getParentSection()->getSceneManager()->createManualObject(); 386 mo->begin(matName, RenderOperation::OT_LINE_STRIP); 387 } 388 389 ColourValue vcol = ColourValue::Green; 390 mo->position(corners[0]); mo->colour(vcol); // First Square... 391 mo->position(corners[1]); mo->colour(vcol); 392 mo->position(corners[3]); mo->colour(vcol); 393 mo->position(corners[2]); mo->colour(vcol); 394 mo->position(corners[0]); mo->colour(vcol); 395 mo->position(corners[4]); mo->colour(vcol); // 0-4 link + second square and 396 mo->position(corners[5]); mo->colour(vcol); 397 mo->position(corners[7]); mo->colour(vcol); 398 mo->position(corners[6]); mo->colour(vcol); 399 mo->position(corners[4]); mo->colour(vcol); 400 mo->position(corners[5]); mo->colour(vcol); // 5-1 link 401 mo->position(corners[1]); mo->colour(vcol); 402 mo->position(corners[3]); mo->colour(vcol); // 3-7 link 403 mo->position(corners[7]); mo->colour(vcol); 404 mo->position(corners[6]); mo->colour(vcol); // 6-2 link 405 mo->position(corners[2]); mo->colour(vcol); 406 mo->end(); 407 408 if(!update) 409 sn->attachObject(mo); 410 } 411 } 412 413 //--------------------------------------------------------------------- getPageID(const Vector3 & pos,PagedWorldSection * section)414 PageID Grid3DPageStrategy::getPageID(const Vector3& pos, PagedWorldSection* section) 415 { 416 Grid3DPageStrategyData* stratData = static_cast<Grid3DPageStrategyData*>(section->getStrategyData()); 417 418 int32 x, y, z; 419 stratData->determineGridLocation(pos, &x, &y, &z); 420 return stratData->calculatePageID(x, y, z); 421 } 422 } 423