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