PBRT
|
00001 00002 // 00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 00036 00037 #ifndef INCLUDED_IMATHFRUSTUM_H 00038 #define INCLUDED_IMATHFRUSTUM_H 00039 00040 00041 #include "ImathVec.h" 00042 #include "ImathPlane.h" 00043 #include "ImathLine.h" 00044 #include "ImathMatrix.h" 00045 #include "ImathLimits.h" 00046 #include "ImathFun.h" 00047 #include "IexMathExc.h" 00048 00049 #if defined _WIN32 || defined _WIN64 00050 #ifdef near 00051 #define _redef_near 00052 #undef near 00053 #endif 00054 #ifdef far 00055 #define _redef_far 00056 #undef far 00057 #endif 00058 #endif 00059 00060 namespace Imath { 00061 00062 // 00063 // template class Frustum<T> 00064 // 00065 // The frustum is always located with the eye point at the 00066 // origin facing down -Z. This makes the Frustum class 00067 // compatable with OpenGL (or anything that assumes a camera 00068 // looks down -Z, hence with a right-handed coordinate system) 00069 // but not with RenderMan which assumes the camera looks down 00070 // +Z. Additional functions are provided for conversion from 00071 // and from various camera coordinate spaces. 00072 // 00073 00074 00075 template<class T> 00076 class Frustum 00077 { 00078 public: 00079 Frustum(); 00080 Frustum(const Frustum &); 00081 Frustum(T near, T far, T left, T right, T top, T bottom, bool ortho=false); 00082 Frustum(T near, T far, T fovx, T fovy, T aspect); 00083 virtual ~Frustum(); 00084 00085 //-------------------- 00086 // Assignment operator 00087 //-------------------- 00088 00089 const Frustum &operator = (const Frustum &); 00090 00091 //-------------------- 00092 // Operators: ==, != 00093 //-------------------- 00094 00095 bool operator == (const Frustum<T> &src) const; 00096 bool operator != (const Frustum<T> &src) const; 00097 00098 //-------------------------------------------------------- 00099 // Set functions change the entire state of the Frustum 00100 //-------------------------------------------------------- 00101 00102 void set(T near, T far, 00103 T left, T right, 00104 T top, T bottom, 00105 bool ortho=false); 00106 00107 void set(T near, T far, T fovx, T fovy, T aspect); 00108 00109 //------------------------------------------------------ 00110 // These functions modify an already valid frustum state 00111 //------------------------------------------------------ 00112 00113 void modifyNearAndFar(T near, T far); 00114 void setOrthographic(bool); 00115 00116 //-------------- 00117 // Access 00118 //-------------- 00119 00120 bool orthographic() const { return _orthographic; } 00121 T near() const { return _near; } 00122 T hither() const { return _near; } 00123 T far() const { return _far; } 00124 T yon() const { return _far; } 00125 T left() const { return _left; } 00126 T right() const { return _right; } 00127 T bottom() const { return _bottom; } 00128 T top() const { return _top; } 00129 00130 //----------------------------------------------------------------------- 00131 // Sets the planes in p to be the six bounding planes of the frustum, in 00132 // the following order: top, right, bottom, left, near, far. 00133 // Note that the planes have normals that point out of the frustum. 00134 // The version of this routine that takes a matrix applies that matrix 00135 // to transform the frustum before setting the planes. 00136 //----------------------------------------------------------------------- 00137 00138 void planes(Plane3<T> p[6]); 00139 void planes(Plane3<T> p[6], const Matrix44<T> &M); 00140 00141 //---------------------- 00142 // Derived Quantities 00143 //---------------------- 00144 00145 T fovx() const; 00146 T fovy() const; 00147 T aspect() const; 00148 Matrix44<T> projectionMatrix() const; 00149 00150 //----------------------------------------------------------------------- 00151 // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 00152 // and -1 <= bottom <= top <= 1) of this Frustum, and returns a new 00153 // Frustum whose near clipping-plane window is that rectangle in local 00154 // space. 00155 //----------------------------------------------------------------------- 00156 00157 Frustum<T> window(T left, T right, T top, T bottom) const; 00158 00159 //---------------------------------------------------------- 00160 // Projection is in screen space / Conversion from Z-Buffer 00161 //---------------------------------------------------------- 00162 00163 Line3<T> projectScreenToRay( const Vec2<T> & ) const; 00164 Vec2<T> projectPointToScreen( const Vec3<T> & ) const; 00165 00166 T ZToDepth(long zval, long min, long max) const; 00167 T normalizedZToDepth(T zval) const; 00168 long DepthToZ(T depth, long zmin, long zmax) const; 00169 00170 T worldRadius(const Vec3<T> &p, T radius) const; 00171 T screenRadius(const Vec3<T> &p, T radius) const; 00172 00173 00174 protected: 00175 00176 Vec2<T> screenToLocal( const Vec2<T> & ) const; 00177 Vec2<T> localToScreen( const Vec2<T> & ) const; 00178 00179 protected: 00180 T _near; 00181 T _far; 00182 T _left; 00183 T _right; 00184 T _top; 00185 T _bottom; 00186 bool _orthographic; 00187 }; 00188 00189 00190 template<class T> 00191 inline Frustum<T>::Frustum() 00192 { 00193 set(T (0.1), 00194 T (1000.0), 00195 T (-1.0), 00196 T (1.0), 00197 T (1.0), 00198 T (-1.0), 00199 false); 00200 } 00201 00202 template<class T> 00203 inline Frustum<T>::Frustum(const Frustum &f) 00204 { 00205 *this = f; 00206 } 00207 00208 template<class T> 00209 inline Frustum<T>::Frustum(T n, T f, T l, T r, T t, T b, bool o) 00210 { 00211 set(n,f,l,r,t,b,o); 00212 } 00213 00214 template<class T> 00215 inline Frustum<T>::Frustum(T near, T far, T fovx, T fovy, T aspect) 00216 { 00217 set(near,far,fovx,fovy,aspect); 00218 } 00219 00220 template<class T> 00221 Frustum<T>::~Frustum() 00222 { 00223 } 00224 00225 template<class T> 00226 const Frustum<T> & 00227 Frustum<T>::operator = (const Frustum &f) 00228 { 00229 _near = f._near; 00230 _far = f._far; 00231 _left = f._left; 00232 _right = f._right; 00233 _top = f._top; 00234 _bottom = f._bottom; 00235 _orthographic = f._orthographic; 00236 00237 return *this; 00238 } 00239 00240 template <class T> 00241 bool 00242 Frustum<T>::operator == (const Frustum<T> &src) const 00243 { 00244 return 00245 _near == src._near && 00246 _far == src._far && 00247 _left == src._left && 00248 _right == src._right && 00249 _top == src._top && 00250 _bottom == src._bottom && 00251 _orthographic == src._orthographic; 00252 } 00253 00254 template <class T> 00255 inline bool 00256 Frustum<T>::operator != (const Frustum<T> &src) const 00257 { 00258 return !operator== (src); 00259 } 00260 00261 template<class T> 00262 void Frustum<T>::set(T n, T f, T l, T r, T t, T b, bool o) 00263 { 00264 _near = n; 00265 _far = f; 00266 _left = l; 00267 _right = r; 00268 _bottom = b; 00269 _top = t; 00270 _orthographic = o; 00271 } 00272 00273 template<class T> 00274 void Frustum<T>::modifyNearAndFar(T n, T f) 00275 { 00276 if ( _orthographic ) 00277 { 00278 _near = n; 00279 } 00280 else 00281 { 00282 Line3<T> lowerLeft( Vec3<T>(0,0,0), Vec3<T>(_left,_bottom,-_near) ); 00283 Line3<T> upperRight( Vec3<T>(0,0,0), Vec3<T>(_right,_top,-_near) ); 00284 Plane3<T> nearPlane( Vec3<T>(0,0,-1), n ); 00285 00286 Vec3<T> ll,ur; 00287 nearPlane.intersect(lowerLeft,ll); 00288 nearPlane.intersect(upperRight,ur); 00289 00290 _left = ll.x; 00291 _right = ur.x; 00292 _top = ur.y; 00293 _bottom = ll.y; 00294 _near = n; 00295 _far = f; 00296 } 00297 00298 _far = f; 00299 } 00300 00301 template<class T> 00302 void Frustum<T>::setOrthographic(bool ortho) 00303 { 00304 _orthographic = ortho; 00305 } 00306 00307 template<class T> 00308 void Frustum<T>::set(T near, T far, T fovx, T fovy, T aspect) 00309 { 00310 if (fovx != 0 && fovy != 0) 00311 throw Iex::ArgExc ("fovx and fovy cannot both be non-zero."); 00312 00313 if (fovx != 0) 00314 { 00315 _right = near * Math<T>::tan (fovx / 2); 00316 _left = -_right; 00317 _top = ((_right - _left) / aspect) / 2; 00318 _bottom = -_top; 00319 } 00320 else 00321 { 00322 _top = near * Math<T>::tan (fovy / 2); 00323 _bottom = -_top; 00324 _right = (_top - _bottom) * aspect / 2; 00325 _left = -_right; 00326 } 00327 _near = near; 00328 _far = far; 00329 _orthographic = false; 00330 } 00331 00332 template<class T> 00333 T Frustum<T>::fovx() const 00334 { 00335 return Math<T>::atan2(_right,_near) - Math<T>::atan2(_left,_near); 00336 } 00337 00338 template<class T> 00339 T Frustum<T>::fovy() const 00340 { 00341 return Math<T>::atan2(_top,_near) - Math<T>::atan2(_bottom,_near); 00342 } 00343 00344 template<class T> 00345 T Frustum<T>::aspect() const 00346 { 00347 T rightMinusLeft = _right-_left; 00348 T topMinusBottom = _top-_bottom; 00349 00350 if (abs(topMinusBottom) < 1 && 00351 abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom)) 00352 { 00353 throw Iex::DivzeroExc ("Bad viewing frustum: " 00354 "aspect ratio cannot be computed."); 00355 } 00356 00357 return rightMinusLeft / topMinusBottom; 00358 } 00359 00360 template<class T> 00361 Matrix44<T> Frustum<T>::projectionMatrix() const 00362 { 00363 T rightPlusLeft = _right+_left; 00364 T rightMinusLeft = _right-_left; 00365 00366 T topPlusBottom = _top+_bottom; 00367 T topMinusBottom = _top-_bottom; 00368 00369 T farPlusNear = _far+_near; 00370 T farMinusNear = _far-_near; 00371 00372 if ((abs(rightMinusLeft) < 1 && 00373 abs(rightPlusLeft) > limits<T>::max() * abs(rightMinusLeft)) || 00374 (abs(topMinusBottom) < 1 && 00375 abs(topPlusBottom) > limits<T>::max() * abs(topMinusBottom)) || 00376 (abs(farMinusNear) < 1 && 00377 abs(farPlusNear) > limits<T>::max() * abs(farMinusNear))) 00378 { 00379 throw Iex::DivzeroExc ("Bad viewing frustum: " 00380 "projection matrix cannot be computed."); 00381 } 00382 00383 if ( _orthographic ) 00384 { 00385 T tx = -rightPlusLeft / rightMinusLeft; 00386 T ty = -topPlusBottom / topMinusBottom; 00387 T tz = -farPlusNear / farMinusNear; 00388 00389 if ((abs(rightMinusLeft) < 1 && 00390 2 > limits<T>::max() * abs(rightMinusLeft)) || 00391 (abs(topMinusBottom) < 1 && 00392 2 > limits<T>::max() * abs(topMinusBottom)) || 00393 (abs(farMinusNear) < 1 && 00394 2 > limits<T>::max() * abs(farMinusNear))) 00395 { 00396 throw Iex::DivzeroExc ("Bad viewing frustum: " 00397 "projection matrix cannot be computed."); 00398 } 00399 00400 T A = 2 / rightMinusLeft; 00401 T B = 2 / topMinusBottom; 00402 T C = -2 / farMinusNear; 00403 00404 return Matrix44<T>( A, 0, 0, 0, 00405 0, B, 0, 0, 00406 0, 0, C, 0, 00407 tx, ty, tz, 1.f ); 00408 } 00409 else 00410 { 00411 T A = rightPlusLeft / rightMinusLeft; 00412 T B = topPlusBottom / topMinusBottom; 00413 T C = -farPlusNear / farMinusNear; 00414 00415 T farTimesNear = -2 * _far * _near; 00416 if (abs(farMinusNear) < 1 && 00417 abs(farTimesNear) > limits<T>::max() * abs(farMinusNear)) 00418 { 00419 throw Iex::DivzeroExc ("Bad viewing frustum: " 00420 "projection matrix cannot be computed."); 00421 } 00422 00423 T D = farTimesNear / farMinusNear; 00424 00425 T twoTimesNear = 2 * _near; 00426 00427 if ((abs(rightMinusLeft) < 1 && 00428 abs(twoTimesNear) > limits<T>::max() * abs(rightMinusLeft)) || 00429 (abs(topMinusBottom) < 1 && 00430 abs(twoTimesNear) > limits<T>::max() * abs(topMinusBottom))) 00431 { 00432 throw Iex::DivzeroExc ("Bad viewing frustum: " 00433 "projection matrix cannot be computed."); 00434 } 00435 00436 T E = twoTimesNear / rightMinusLeft; 00437 T F = twoTimesNear / topMinusBottom; 00438 00439 return Matrix44<T>( E, 0, 0, 0, 00440 0, F, 0, 0, 00441 A, B, C, -1, 00442 0, 0, D, 0 ); 00443 } 00444 } 00445 00446 template<class T> 00447 Frustum<T> Frustum<T>::window(T l, T r, T t, T b) const 00448 { 00449 // move it to 0->1 space 00450 00451 Vec2<T> bl = screenToLocal( Vec2<T>(l,b) ); 00452 Vec2<T> tr = screenToLocal( Vec2<T>(r,t) ); 00453 00454 return Frustum<T>(_near, _far, bl.x, tr.x, tr.y, bl.y, _orthographic); 00455 } 00456 00457 00458 template<class T> 00459 Vec2<T> Frustum<T>::screenToLocal(const Vec2<T> &s) const 00460 { 00461 return Vec2<T>( _left + (_right-_left) * (1.f+s.x) / 2.f, 00462 _bottom + (_top-_bottom) * (1.f+s.y) / 2.f ); 00463 } 00464 00465 template<class T> 00466 Vec2<T> Frustum<T>::localToScreen(const Vec2<T> &p) const 00467 { 00468 T leftPlusRight = _left - 2 * p.x + _right; 00469 T leftMinusRight = _left-_right; 00470 T bottomPlusTop = _bottom - 2 * p.y + _top; 00471 T bottomMinusTop = _bottom-_top; 00472 00473 if ((abs(leftMinusRight) < 1 && 00474 abs(leftPlusRight) > limits<T>::max() * abs(leftMinusRight)) || 00475 (abs(bottomMinusTop) < 1 && 00476 abs(bottomPlusTop) > limits<T>::max() * abs(bottomMinusTop))) 00477 { 00478 throw Iex::DivzeroExc 00479 ("Bad viewing frustum: " 00480 "local-to-screen transformation cannot be computed"); 00481 } 00482 00483 return Vec2<T>( leftPlusRight / leftMinusRight, 00484 bottomPlusTop / bottomMinusTop ); 00485 } 00486 00487 template<class T> 00488 Line3<T> Frustum<T>::projectScreenToRay(const Vec2<T> &p) const 00489 { 00490 Vec2<T> point = screenToLocal(p); 00491 if (orthographic()) 00492 return Line3<T>( Vec3<T>(point.x,point.y, 0.0), 00493 Vec3<T>(point.x,point.y,-_near)); 00494 else 00495 return Line3<T>( Vec3<T>(0, 0, 0), Vec3<T>(point.x,point.y,-_near)); 00496 } 00497 00498 template<class T> 00499 Vec2<T> Frustum<T>::projectPointToScreen(const Vec3<T> &point) const 00500 { 00501 if (orthographic() || point.z == 0) 00502 return localToScreen( Vec2<T>( point.x, point.y ) ); 00503 else 00504 return localToScreen( Vec2<T>( point.x * _near / -point.z, 00505 point.y * _near / -point.z ) ); 00506 } 00507 00508 template<class T> 00509 T Frustum<T>::ZToDepth(long zval,long zmin,long zmax) const 00510 { 00511 int zdiff = zmax - zmin; 00512 00513 if (zdiff == 0) 00514 { 00515 throw Iex::DivzeroExc 00516 ("Bad call to Frustum::ZToDepth: zmax == zmin"); 00517 } 00518 00519 if ( zval > zmax+1 ) zval -= zdiff; 00520 00521 T fzval = (T(zval) - T(zmin)) / T(zdiff); 00522 return normalizedZToDepth(fzval); 00523 } 00524 00525 template<class T> 00526 T Frustum<T>::normalizedZToDepth(T zval) const 00527 { 00528 T Zp = zval * 2.0 - 1; 00529 00530 if ( _orthographic ) 00531 { 00532 return -(Zp*(_far-_near) + (_far+_near))/2; 00533 } 00534 else 00535 { 00536 T farTimesNear = 2 * _far * _near; 00537 T farMinusNear = Zp * (_far - _near) - _far - _near; 00538 00539 if (abs(farMinusNear) < 1 && 00540 abs(farTimesNear) > limits<T>::max() * abs(farMinusNear)) 00541 { 00542 throw Iex::DivzeroExc 00543 ("Frustum::normalizedZToDepth cannot be computed. The " 00544 "near and far clipping planes of the viewing frustum " 00545 "may be too close to each other"); 00546 } 00547 00548 return farTimesNear / farMinusNear; 00549 } 00550 } 00551 00552 template<class T> 00553 long Frustum<T>::DepthToZ(T depth,long zmin,long zmax) const 00554 { 00555 long zdiff = zmax - zmin; 00556 T farMinusNear = _far-_near; 00557 00558 if ( _orthographic ) 00559 { 00560 T farPlusNear = 2*depth + _far + _near; 00561 00562 if (abs(farMinusNear) < 1 && 00563 abs(farPlusNear) > limits<T>::max() * abs(farMinusNear)) 00564 { 00565 throw Iex::DivzeroExc 00566 ("Bad viewing frustum: near and far clipping planes " 00567 "are too close to each other"); 00568 } 00569 00570 T Zp = -farPlusNear/farMinusNear; 00571 return long(0.5*(Zp+1)*zdiff) + zmin; 00572 } 00573 else 00574 { 00575 // Perspective 00576 00577 T farTimesNear = 2*_far*_near; 00578 if (abs(depth) < 1 && 00579 abs(farTimesNear) > limits<T>::max() * abs(depth)) 00580 { 00581 throw Iex::DivzeroExc 00582 ("Bad call to DepthToZ function: value of `depth' " 00583 "is too small"); 00584 } 00585 00586 T farPlusNear = farTimesNear/depth + _far + _near; 00587 if (abs(farMinusNear) < 1 && 00588 abs(farPlusNear) > limits<T>::max() * abs(farMinusNear)) 00589 { 00590 throw Iex::DivzeroExc 00591 ("Bad viewing frustum: near and far clipping planes " 00592 "are too close to each other"); 00593 } 00594 00595 T Zp = farPlusNear/farMinusNear; 00596 return long(0.5*(Zp+1)*zdiff) + zmin; 00597 } 00598 } 00599 00600 template<class T> 00601 T Frustum<T>::screenRadius(const Vec3<T> &p, T radius) const 00602 { 00603 // Derivation: 00604 // Consider X-Z plane. 00605 // X coord of projection of p = xp = p.x * (-_near / p.z) 00606 // Let q be p + (radius, 0, 0). 00607 // X coord of projection of q = xq = (p.x - radius) * (-_near / p.z) 00608 // X coord of projection of segment from p to q = r = xp - xq 00609 // = radius * (-_near / p.z) 00610 // A similar analysis holds in the Y-Z plane. 00611 // So r is the quantity we want to return. 00612 00613 if (abs(p.z) > 1 || abs(-_near) < limits<T>::max() * abs(p.z)) 00614 { 00615 return radius * (-_near / p.z); 00616 } 00617 else 00618 { 00619 throw Iex::DivzeroExc 00620 ("Bad call to Frustum::screenRadius: the magnitude of `p' " 00621 "is too small"); 00622 } 00623 00624 return radius * (-_near / p.z); 00625 } 00626 00627 template<class T> 00628 T Frustum<T>::worldRadius(const Vec3<T> &p, T radius) const 00629 { 00630 if (abs(-_near) > 1 || abs(p.z) < limits<T>::max() * abs(-_near)) 00631 { 00632 return radius * (p.z / -_near); 00633 } 00634 else 00635 { 00636 throw Iex::DivzeroExc 00637 ("Bad viewing frustum: the near clipping plane is too " 00638 "close to zero"); 00639 } 00640 } 00641 00642 template<class T> 00643 void Frustum<T>::planes(Plane3<T> p[6]) 00644 { 00645 // 00646 // Plane order: Top, Right, Bottom, Left, Near, Far. 00647 // Normals point outwards. 00648 // 00649 00650 if (! _orthographic) 00651 { 00652 Vec3<T> a( _left, _bottom, -_near); 00653 Vec3<T> b( _left, _top, -_near); 00654 Vec3<T> c( _right, _top, -_near); 00655 Vec3<T> d( _right, _bottom, -_near); 00656 Vec3<T> o(0,0,0); 00657 00658 p[0].set( o, c, b ); 00659 p[1].set( o, d, c ); 00660 p[2].set( o, a, d ); 00661 p[3].set( o, b, a ); 00662 } 00663 else 00664 { 00665 p[0].set( Vec3<T>( 0, 1, 0), _top ); 00666 p[1].set( Vec3<T>( 1, 0, 0), _right ); 00667 p[2].set( Vec3<T>( 0,-1, 0),-_bottom ); 00668 p[3].set( Vec3<T>(-1, 0, 0),-_left ); 00669 } 00670 p[4].set( Vec3<T>(0, 0, 1), -_near ); 00671 p[5].set( Vec3<T>(0, 0,-1), _far ); 00672 } 00673 00674 00675 template<class T> 00676 void Frustum<T>::planes(Plane3<T> p[6], const Matrix44<T> &M) 00677 { 00678 // 00679 // Plane order: Top, Right, Bottom, Left, Near, Far. 00680 // Normals point outwards. 00681 // 00682 00683 Vec3<T> a = Vec3<T>( _left, _bottom, -_near) * M; 00684 Vec3<T> b = Vec3<T>( _left, _top, -_near) * M; 00685 Vec3<T> c = Vec3<T>( _right, _top, -_near) * M; 00686 Vec3<T> d = Vec3<T>( _right, _bottom, -_near) * M; 00687 if (! _orthographic) 00688 { 00689 double s = _far / double(_near); 00690 T farLeft = (T) (s * _left); 00691 T farRight = (T) (s * _right); 00692 T farTop = (T) (s * _top); 00693 T farBottom = (T) (s * _bottom); 00694 Vec3<T> e = Vec3<T>( farLeft, farBottom, -_far) * M; 00695 Vec3<T> f = Vec3<T>( farLeft, farTop, -_far) * M; 00696 Vec3<T> g = Vec3<T>( farRight, farTop, -_far) * M; 00697 Vec3<T> o = Vec3<T>(0,0,0) * M; 00698 p[0].set( o, c, b ); 00699 p[1].set( o, d, c ); 00700 p[2].set( o, a, d ); 00701 p[3].set( o, b, a ); 00702 p[4].set( a, d, c ); 00703 p[5].set( e, f, g ); 00704 } 00705 else 00706 { 00707 Vec3<T> e = Vec3<T>( _left, _bottom, -_far) * M; 00708 Vec3<T> f = Vec3<T>( _left, _top, -_far) * M; 00709 Vec3<T> g = Vec3<T>( _right, _top, -_far) * M; 00710 Vec3<T> h = Vec3<T>( _right, _bottom, -_far) * M; 00711 p[0].set( c, g, f ); 00712 p[1].set( d, h, g ); 00713 p[2].set( a, e, h ); 00714 p[3].set( b, f, e ); 00715 p[4].set( a, d, c ); 00716 p[5].set( e, f, g ); 00717 } 00718 } 00719 00720 typedef Frustum<float> Frustumf; 00721 typedef Frustum<double> Frustumd; 00722 00723 00724 } // namespace Imath 00725 00726 00727 #if defined _WIN32 || defined _WIN64 00728 #ifdef _redef_near 00729 #define near 00730 #endif 00731 #ifdef _redef_far 00732 #define far 00733 #endif 00734 #endif 00735 00736 #endif