frustum.cpp
Engine/source/math/util/frustum.cpp
Public Variables
sGFXProjRotMatrix (EulerF((M_PI_F/2.0f), 0.0f, 0.0f))
Detailed Description
Public Variables
const MatrixF sGFXProjRotMatrix (EulerF((M_PI_F/2.0f), 0.0f, 0.0f))
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "math/util/frustum.h" 26 27#include "math/mMathFn.h" 28#include "math/mathUtils.h" 29#include "math/mSphere.h" 30#include "platform/profiler.h" 31 32static const MatrixF sGFXProjRotMatrix( EulerF( (M_PI_F / 2.0f), 0.0f, 0.0f ) ); 33 34 35//TODO: For OBB/frustum intersections and ortho frustums, we can resort to a much quicker AABB/OBB test 36 37 38// Must be CW ordered for face[0] of each edge! Keep in mind that normals 39// are pointing *inwards* and thus what appears CCW outside is CW inside. 40FrustumData::EdgeListType FrustumData::smEdges 41( 42 PolyhedronData::Edge( PlaneNear, PlaneTop, NearTopRight, NearTopLeft ), 43 PolyhedronData::Edge( PlaneNear, PlaneBottom, NearBottomLeft, NearBottomRight ), 44 PolyhedronData::Edge( PlaneNear, PlaneLeft, NearTopLeft, NearBottomLeft ), 45 PolyhedronData::Edge( PlaneNear, PlaneRight, NearTopRight, NearBottomRight ), 46 PolyhedronData::Edge( PlaneFar, PlaneTop, FarTopLeft, FarTopRight ), 47 PolyhedronData::Edge( PlaneFar, PlaneBottom, FarBottomRight, FarBottomLeft ), 48 PolyhedronData::Edge( PlaneFar, PlaneLeft, FarBottomLeft, FarTopLeft ), 49 PolyhedronData::Edge( PlaneFar, PlaneRight, FarTopRight, FarBottomRight ), 50 PolyhedronData::Edge( PlaneTop, PlaneLeft, FarTopLeft, NearTopLeft ), 51 PolyhedronData::Edge( PlaneTop, PlaneRight, NearTopRight, FarTopRight ), 52 PolyhedronData::Edge( PlaneBottom, PlaneLeft, NearBottomLeft, FarBottomLeft ), 53 PolyhedronData::Edge( PlaneBottom, PlaneRight, FarBottomRight, NearBottomRight ) 54); 55 56 57//----------------------------------------------------------------------------- 58 59Frustum::Frustum( bool isOrtho, 60 F32 nearLeft, 61 F32 nearRight, 62 F32 nearTop, 63 F32 nearBottom, 64 F32 nearDist, 65 F32 farDist, 66 const MatrixF &transform ) 67{ 68 mTransform = transform; 69 mPosition = transform.getPosition(); 70 71 mNearLeft = nearLeft; 72 mNearRight = nearRight; 73 mNearTop = nearTop; 74 mNearBottom = nearBottom; 75 mNearDist = nearDist; 76 mFarDist = farDist; 77 mIsOrtho = isOrtho; 78 79 mNumTiles = 1; 80 mCurrTile.set(0,0); 81 mTileOverlap.set(0.0f, 0.0f); 82 83 mProjectionOffset.zero(); 84 mProjectionOffsetMatrix.identity(); 85} 86 87//----------------------------------------------------------------------------- 88 89void Frustum::set( bool isOrtho, 90 F32 fovYInRadians, 91 F32 aspectRatio, 92 F32 nearDist, 93 F32 farDist, 94 const MatrixF &transform ) 95{ 96 F32 left, right, top, bottom; 97 MathUtils::makeFrustum( &left, &right, &top, &bottom, fovYInRadians, aspectRatio, nearDist ); 98 99 tile( &left, &right, &top, &bottom, mNumTiles, mCurrTile, mTileOverlap ); 100 set( isOrtho, left, right, top, bottom, nearDist, farDist, transform ); 101} 102 103//----------------------------------------------------------------------------- 104 105void Frustum::set( bool isOrtho, 106 F32 nearLeft, 107 F32 nearRight, 108 F32 nearTop, 109 F32 nearBottom, 110 F32 nearDist, 111 F32 farDist, 112 const MatrixF &transform ) 113{ 114 mTransform = transform; 115 mPosition = mTransform.getPosition(); 116 117 mNearLeft = nearLeft; 118 mNearRight = nearRight; 119 mNearTop = nearTop; 120 mNearBottom = nearBottom; 121 mNearDist = nearDist; 122 mFarDist = farDist; 123 mIsOrtho = isOrtho; 124 125 mDirty = true; 126} 127 128//----------------------------------------------------------------------------- 129 130#if 0 131void MatrixF &projMat, bool normalize ) 132{ 133 // From "Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix" 134 // by Gil Gribb and Klaus Hartmann. 135 // 136 // http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf 137 138 // Right clipping plane. 139 PlaneRight ].set( projMat[3] - projMat[0], 140 projMat[7] - projMat[4], 141 projMat[11] - projMat[8], 142 projMat[15] - projMat[12] ); 143 144 // Left clipping plane. 145 PlaneLeft ].set( projMat[3] + projMat[0], 146 projMat[7] + projMat[4], 147 projMat[11] + projMat[8], 148 projMat[15] + projMat[12] ); 149 150 // Bottom clipping plane. 151 PlaneBottom ].set( projMat[3] + projMat[1], 152 projMat[7] + projMat[5], 153 projMat[11] + projMat[9], 154 projMat[15] + projMat[13] ); 155 156 // Top clipping plane. 157 PlaneTop ].set( projMat[3] - projMat[1], 158 projMat[7] - projMat[5], 159 projMat[11] - projMat[9], 160 projMat[15] - projMat[13] ); 161 162 // Near clipping plane 163 PlaneNear ].set( projMat[3] + projMat[2], 164 projMat[7] + projMat[6], 165 projMat[11] + projMat[10], 166 projMat[15] + projMat[14] ); 167 168 // Far clipping plane. 169 PlaneFar ].set( projMat[3] - projMat[2], 170 projMat[7] - projMat[6], 171 projMat[11] - projMat[10], 172 projMat[15] - projMat[14] ); 173 174 if( normalize ) 175 { 176 for( i ) 177 i ].normalize(); 178 } 179 180 /*// Create the corner points via plane intersections. 181 mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneLeft ], &mPoints[ NearTopLeft ] ); 182 mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneRight ], &mPoints[ NearTopRight ] ); 183 mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneLeft ], &mPoints[ NearBottomLeft ] ); 184 mPlanes[ PlaneNear ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneRight ], &mPoints[ NearBottomRight ] ); 185 mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneLeft ], &mPoints[ FarTopLeft ] ); 186 mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneTop ], mPlanes[ PlaneRight ], &mPoints[ FarTopRight ] ); 187 mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneLeft ], &mPoints[ FarBottomLeft ] ); 188 mPlanes[ PlaneFar ].intersect( mPlanes[ PlaneBottom ], mPlanes[ PlaneRight ], &mPoints[ FarBottomRight ] ); 189 */ 190 191 // Update the axis aligned bounding box. 192 _updateBounds(); 193} 194#endif 195 196//----------------------------------------------------------------------------- 197 198void Frustum::setNearDist( F32 nearDist ) 199{ 200 setNearFarDist( nearDist, mFarDist ); 201} 202 203//----------------------------------------------------------------------------- 204 205void Frustum::setFarDist( F32 farDist ) 206{ 207 setNearFarDist( mNearDist, farDist ); 208} 209 210//----------------------------------------------------------------------------- 211 212void Frustum::setNearFarDist( F32 nearDist, F32 farDist ) 213{ 214 if( mNearDist == nearDist && mFarDist == farDist ) 215 return; 216 217 // Recalculate the frustum. 218 MatrixF xfm( mTransform ); 219 220 const F32 CENTER_EPSILON = 0.001f; 221 F32 centerX = mNearLeft + (mNearRight - mNearLeft) * 0.5; 222 F32 centerY = mNearBottom + (mNearTop - mNearBottom) * 0.5; 223 if ((centerX > CENTER_EPSILON || centerX < -CENTER_EPSILON) || (centerY > CENTER_EPSILON || centerY < -CENTER_EPSILON) ) 224 { 225 // Off-center projection, so re-calc use the new distances 226 FovPort expectedFovPort; 227 expectedFovPort.leftTan = -(mNearLeft / mNearDist); 228 expectedFovPort.rightTan = (mNearRight / mNearDist); 229 expectedFovPort.upTan = (mNearTop / mNearDist); 230 expectedFovPort.downTan = -(mNearBottom / mNearDist); 231 MathUtils::makeFovPortFrustum(this, mIsOrtho, nearDist, farDist, expectedFovPort); 232 } 233 else 234 { 235 // Projection is not off-center, use the normal code 236 set(mIsOrtho, getFov(), getAspectRatio(), nearDist, farDist, xfm); 237 } 238} 239 240//----------------------------------------------------------------------------- 241 242void Frustum::cropNearFar(F32 newNearDist, F32 newFarDist) 243{ 244 const F32 newOverOld = newNearDist / mNearDist; 245 246 set( mIsOrtho, mNearLeft * newOverOld, mNearRight * newOverOld, mNearTop * newOverOld, mNearBottom * newOverOld, 247 newNearDist, newFarDist, mTransform); 248} 249 250//----------------------------------------------------------------------------- 251 252bool Frustum::bakeProjectionOffset() 253{ 254 // Nothing to bake if ortho 255 if( mIsOrtho ) 256 return false; 257 258 // Nothing to bake if no offset 259 if( mProjectionOffset.isZero() ) 260 return false; 261 262 // Near plane points in camera space 263 Point3F np[4]; 264 np[0].set( mNearLeft, mNearDist, mNearTop ); // NearTopLeft 265 np[1].set( mNearRight, mNearDist, mNearTop ); // NearTopRight 266 np[2].set( mNearLeft, mNearDist, mNearBottom ); // NearBottomLeft 267 np[3].set( mNearRight, mNearDist, mNearBottom ); // NearBottomRight 268 269 // Generate the near plane 270 PlaneF nearPlane( np[0], np[1], np[3] ); 271 272 // Far plane points in camera space 273 const F32 farOverNear = mFarDist / mNearDist; 274 Point3F fp0( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopLeft 275 Point3F fp1( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear ); // FarTopRight 276 Point3F fp2( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomLeft 277 Point3F fp3( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); // FarBottomRight 278 279 // Generate the far plane 280 PlaneF farPlane( fp0, fp1, fp3 ); 281 282 // The offset camera point 283 Point3F offsetCamera( mProjectionOffset.x, 0.0f, mProjectionOffset.y ); 284 285 // The near plane point we'll be using for our calculations below 286 U32 nIndex = 0; 287 if( mProjectionOffset.x < 0.0 ) 288 { 289 // Offset to the left so we'll need to use the near plane point on the right 290 nIndex = 1; 291 } 292 if( mProjectionOffset.y > 0.0 ) 293 { 294 // Offset to the top so we'll need to use the near plane point at the bottom 295 nIndex += 2; 296 } 297 298 // Begin by calculating the offset point on the far plane as it goes 299 // from the offset camera to the edge of the near plane. 300 Point3F farPoint; 301 Point3F fdir = np[nIndex] - offsetCamera; 302 fdir.normalize(); 303 if( farPlane.intersect(offsetCamera, fdir, &farPoint) ) 304 { 305 // Calculate the new near plane edge from the non-offset camera position 306 // to the far plane point from above. 307 Point3F nearPoint; 308 Point3F ndir = farPoint; 309 ndir.normalize(); 310 if( nearPlane.intersect( Point3F::Zero, ndir, &nearPoint) ) 311 { 312 // Handle a x offset 313 if( mProjectionOffset.x < 0.0 ) 314 { 315 // The new near plane right side 316 mNearRight = nearPoint.x; 317 } 318 else if( mProjectionOffset.x > 0.0 ) 319 { 320 // The new near plane left side 321 mNearLeft = nearPoint.x; 322 } 323 324 // Handle a y offset 325 if( mProjectionOffset.y < 0.0 ) 326 { 327 // The new near plane top side 328 mNearTop = nearPoint.y; 329 } 330 else if( mProjectionOffset.y > 0.0 ) 331 { 332 // The new near plane bottom side 333 mNearBottom = nearPoint.y; 334 } 335 } 336 } 337 338 mDirty = true; 339 340 // Indicate that we've modified the frustum 341 return true; 342} 343 344//----------------------------------------------------------------------------- 345 346void FrustumData::_update() const 347{ 348 if( !mDirty ) 349 return; 350 351 PROFILE_SCOPE( Frustum_update ); 352 353 const Point3F& cameraPos = mPosition; 354 355 // Build the frustum points in camera space first. 356 357 if( mIsOrtho ) 358 { 359 mPoints[ NearTopLeft ].set( mNearLeft, mNearDist, mNearTop ); 360 mPoints[ NearTopRight ].set( mNearRight, mNearDist, mNearTop ); 361 mPoints[ NearBottomLeft ].set( mNearLeft, mNearDist, mNearBottom ); 362 mPoints[ NearBottomRight ].set( mNearRight, mNearDist, mNearBottom ); 363 mPoints[ FarTopLeft ].set( mNearLeft, mFarDist, mNearTop ); 364 mPoints[ FarTopRight ].set( mNearRight, mFarDist, mNearTop ); 365 mPoints[ FarBottomLeft ].set( mNearLeft, mFarDist, mNearBottom ); 366 mPoints[ FarBottomRight ].set( mNearRight, mFarDist, mNearBottom ); 367 } 368 else 369 { 370 const F32 farOverNear = mFarDist / mNearDist; 371 372 mPoints[ NearTopLeft ].set( mNearLeft, mNearDist, mNearTop ); 373 mPoints[ NearTopRight ].set( mNearRight, mNearDist, mNearTop ); 374 mPoints[ NearBottomLeft ].set( mNearLeft, mNearDist, mNearBottom ); 375 mPoints[ NearBottomRight ].set( mNearRight, mNearDist, mNearBottom ); 376 mPoints[ FarTopLeft ].set( mNearLeft * farOverNear, mFarDist, mNearTop * farOverNear ); 377 mPoints[ FarTopRight ].set( mNearRight * farOverNear, mFarDist, mNearTop * farOverNear ); 378 mPoints[ FarBottomLeft ].set( mNearLeft * farOverNear, mFarDist, mNearBottom * farOverNear ); 379 mPoints[ FarBottomRight ].set( mNearRight * farOverNear, mFarDist, mNearBottom * farOverNear ); 380 } 381 382 // Transform the points into the desired culling space. 383 384 for( U32 i = 0; i < mPoints.size(); ++ i ) 385 mTransform.mulP( mPoints[ i ] ); 386 387 // Update the axis aligned bounding box from 388 // the newly transformed points. 389 390 mBounds = Box3F::aroundPoints( mPoints.address(), mPoints.size() ); 391 392 // Finally build the planes. 393 394 if( mIsOrtho ) 395 { 396 mPlanes[ PlaneLeft ].set( mPoints[ NearBottomLeft ], 397 mPoints[ FarTopLeft ], 398 mPoints[ FarBottomLeft ] ); 399 400 mPlanes[ PlaneRight ].set( mPoints[ NearTopRight ], 401 mPoints[ FarBottomRight ], 402 mPoints[ FarTopRight ] ); 403 404 mPlanes[ PlaneTop ].set( mPoints[ FarTopRight ], 405 mPoints[ NearTopLeft ], 406 mPoints[ NearTopRight ] ); 407 408 mPlanes[ PlaneBottom ].set( mPoints[ NearBottomRight ], 409 mPoints[ FarBottomLeft ], 410 mPoints[ FarBottomRight ] ); 411 412 mPlanes[ PlaneNear ].set( mPoints[ NearTopLeft ], 413 mPoints[ NearBottomLeft ], 414 mPoints[ NearTopRight ] ); 415 416 mPlanes[ PlaneFar ].set( mPoints[ FarTopLeft ], 417 mPoints[ FarTopRight ], 418 mPoints[ FarBottomLeft ] ); 419 } 420 else 421 { 422 mPlanes[ PlaneLeft ].set( cameraPos, 423 mPoints[ NearTopLeft ], 424 mPoints[ NearBottomLeft ] ); 425 426 mPlanes[ PlaneRight ].set( cameraPos, 427 mPoints[ NearBottomRight ], 428 mPoints[ NearTopRight ] ); 429 430 mPlanes[ PlaneTop ].set( cameraPos, 431 mPoints[ NearTopRight ], 432 mPoints[ NearTopLeft ] ); 433 434 mPlanes[ PlaneBottom ].set( cameraPos, 435 mPoints[ NearBottomLeft ], 436 mPoints[ NearBottomRight ] ); 437 438 mPlanes[ PlaneNear ].set( mPoints[ NearTopLeft ], 439 mPoints[ NearBottomLeft ], 440 mPoints[ NearTopRight ] ); 441 442 mPlanes[ PlaneFar ].set( mPoints[ FarTopLeft ], 443 mPoints[ FarTopRight ], 444 mPoints[ FarBottomLeft ] ); 445 } 446 447 // If the frustum plane orientation doesn't match mIsInverted 448 // now, invert all the plane normals. 449 // 450 // Note that if we have a transform matrix with a negative scale, 451 // then the initial planes we have computed will always be inverted. 452 453 const bool inverted = mPlanes[ PlaneNear ].whichSide( cameraPos ) == PlaneF::Front; 454 if( inverted != mIsInverted ) 455 { 456 for( U32 i = 0; i < mPlanes.size(); ++ i ) 457 mPlanes[ i ].invert(); 458 } 459 460 AssertFatal( mPlanes[ PlaneNear ].whichSide( cameraPos ) != PlaneF::Front, 461 "Frustum::_update - Viewpoint lies on front side of near plane!" ); 462 463 // And now the center points which are mostly just used in debug rendering. 464 465 mPlaneCenters[ PlaneLeftCenter ] = ( mPoints[ NearTopLeft ] + 466 mPoints[ NearBottomLeft ] + 467 mPoints[ FarTopLeft ] + 468 mPoints[ FarBottomLeft ] ) / 4.0f; 469 470 mPlaneCenters[ PlaneRightCenter ] = ( mPoints[ NearTopRight ] + 471 mPoints[ NearBottomRight ] + 472 mPoints[ FarTopRight ] + 473 mPoints[ FarBottomRight ] ) / 4.0f; 474 475 mPlaneCenters[ PlaneTopCenter ] = ( mPoints[ NearTopLeft ] + 476 mPoints[ NearTopRight ] + 477 mPoints[ FarTopLeft ] + 478 mPoints[ FarTopRight ] ) / 4.0f; 479 480 mPlaneCenters[ PlaneBottomCenter ] = ( mPoints[ NearBottomLeft ] + 481 mPoints[ NearBottomRight ] + 482 mPoints[ FarBottomLeft ] + 483 mPoints[ FarBottomRight ] ) / 4.0f; 484 485 mPlaneCenters[ PlaneNearCenter ] = ( mPoints[ NearTopLeft ] + 486 mPoints[ NearTopRight ] + 487 mPoints[ NearBottomLeft ] + 488 mPoints[ NearBottomRight ] ) / 4.0f; 489 490 mPlaneCenters[ PlaneFarCenter ] = ( mPoints[ FarTopLeft ] + 491 mPoints[ FarTopRight ] + 492 mPoints[ FarBottomLeft ] + 493 mPoints[ FarBottomRight ] ) / 4.0f; 494 495 // Done. 496 497 mDirty = false; 498} 499 500//----------------------------------------------------------------------------- 501 502void Frustum::invert() 503{ 504 mIsInverted = !mIsInverted; 505 _update(); 506} 507 508//----------------------------------------------------------------------------- 509 510void Frustum::setTransform( const MatrixF &mat ) 511{ 512 mTransform = mat; 513 mPosition = mTransform.getPosition(); 514 mDirty = true; 515} 516 517//----------------------------------------------------------------------------- 518 519void Frustum::scaleFromCenter( F32 scale ) 520{ 521 // Extract the fov and aspect ratio. 522 F32 fovInRadians = mAtan2( (mNearTop - mNearBottom)*mNumTiles/2.0f, mNearDist ) * 2.0f; 523 F32 aspectRatio = (mNearRight - mNearLeft)/(mNearTop - mNearBottom); 524 525 // Now move the near and far planes out. 526 F32 halfDist = ( mFarDist - mNearDist ) / 2.0f; 527 mNearDist -= halfDist * ( scale - 1.0f ); 528 mFarDist += halfDist * ( scale - 1.0f ); 529 530 // Setup the new scaled frustum. 531 set( mIsOrtho, fovInRadians, aspectRatio, mNearDist, mFarDist, mTransform ); 532} 533 534//----------------------------------------------------------------------------- 535 536void Frustum::mul( const MatrixF& mat ) 537{ 538 mTransform.mul( mat ); 539 mDirty = true; 540} 541 542//----------------------------------------------------------------------------- 543 544void Frustum::mulL( const MatrixF& mat ) 545{ 546 MatrixF last( mTransform ); 547 mTransform.mul( mat, last ); 548 549 mDirty = true; 550} 551 552//----------------------------------------------------------------------------- 553 554void Frustum::setProjectionOffset(const Point2F& offsetMat) 555{ 556 mProjectionOffset = offsetMat; 557 mProjectionOffsetMatrix.identity(); 558 mProjectionOffsetMatrix.setPosition(Point3F(mProjectionOffset.x, mProjectionOffset.y, 0.0f)); 559} 560 561//----------------------------------------------------------------------------- 562 563void Frustum::getProjectionMatrix( MatrixF *proj, bool gfxRotate ) const 564{ 565 if (mIsOrtho) 566 { 567 MathUtils::makeOrthoProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate); 568 proj->mulL(mProjectionOffsetMatrix); 569 } 570 else 571 { 572 MathUtils::makeProjection(proj, mNearLeft, mNearRight, mNearTop, mNearBottom, mNearDist, mFarDist, gfxRotate); 573 proj->mulL(mProjectionOffsetMatrix); 574 } 575} 576 577//----------------------------------------------------------------------------- 578 579void Frustum::tileFrustum(U32 numTiles, const Point2I& curTile, Point2F overlap) 580{ 581 //These will be stored to re-tile the frustum if needed 582 mNumTiles = numTiles; 583 mCurrTile = curTile; 584 mTileOverlap = overlap; 585 586 tile(&mNearLeft, &mNearRight, &mNearTop, &mNearBottom, mNumTiles, mCurrTile, mTileOverlap); 587} 588 589//----------------------------------------------------------------------------- 590 591void Frustum::tile( F32 *left, F32 *right, F32 *top, F32 *bottom, U32 numTiles, const Point2I& curTile, Point2F overlap ) 592{ 593 if (numTiles == 1) 594 return; 595 596 Point2F tileSize( ( *right - *left ) / (F32)numTiles, 597 ( *top - *bottom ) / (F32)numTiles ); 598 599 F32 leftOffset = tileSize.x*overlap.x; 600 F32 rightOffset = tileSize.x*overlap.x*2; 601 F32 bottomOffset = tileSize.y*overlap.y; 602 F32 topOffset = tileSize.y*overlap.y*2; 603 604 *left += tileSize.x * curTile.x - leftOffset; 605 *right = *left + tileSize.x + rightOffset; 606 *bottom += tileSize.y * curTile.y - bottomOffset; 607 *top = *bottom + tileSize.y + topOffset; 608} 609