📄 imathfrustum.h
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas// Digital Ltd. LLC// // All rights reserved.// // Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// * Neither the name of Industrial Light & Magic nor the names of// its contributors may be used to endorse or promote products derived// from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE./////////////////////////////////////////////////////////////////////////////#ifndef INCLUDED_IMATHFRUSTUM_H#define INCLUDED_IMATHFRUSTUM_H#include "ImathVec.h"#include "ImathPlane.h"#include "ImathLine.h"#include "ImathMatrix.h"#include "ImathLimits.h"#include "ImathFun.h"#include "IexMathExc.h"#if defined _WIN32 || defined _WIN64 #ifdef near #undef near #endif #ifdef far #undef far #endif#endifnamespace Imath {//// template class Frustum<T>//// The frustum is always located with the eye point at the// origin facing down -Z. This makes the Frustum class // compatable with OpenGL (or anything that assumes a camera// looks down -Z, hence with a right-handed coordinate system) // but not with RenderMan which assumes the camera looks down// +Z. Additional functions are provided for conversion from// and from various camera coordinate spaces.//template<class T>class Frustum{ public: Frustum(); Frustum(const Frustum &); Frustum(T near, T far, T left, T right, T top, T bottom, bool ortho=false); Frustum(T near, T far, T fovx, T fovy, T aspect); virtual ~Frustum(); //-------------------- // Assignment operator //-------------------- const Frustum &operator = (const Frustum &); //-------------------- // Operators: ==, != //-------------------- bool operator == (const Frustum<T> &src) const; bool operator != (const Frustum<T> &src) const; //-------------------------------------------------------- // Set functions change the entire state of the Frustum //-------------------------------------------------------- void set(T near, T far, T left, T right, T top, T bottom, bool ortho=false); void set(T near, T far, T fovx, T fovy, T aspect); //------------------------------------------------------ // These functions modify an already valid frustum state //------------------------------------------------------ void modifyNearAndFar(T near, T far); void setOrthographic(bool); //-------------- // Access //-------------- bool orthographic() const { return _orthographic; } T near() const { return _near; } T far() const { return _far; } T left() const { return _left; } T right() const { return _right; } T bottom() const { return _bottom; } T top() const { return _top; } //----------------------------------------------------------------------- // Sets the planes in p to be the six bounding planes of the frustum, in // the following order: top, right, bottom, left, near, far. // Note that the planes have normals that point out of the frustum. // The version of this routine that takes a matrix applies that matrix // to transform the frustum before setting the planes. //----------------------------------------------------------------------- void planes(Plane3<T> p[6]); void planes(Plane3<T> p[6], const Matrix44<T> &M); //---------------------- // Derived Quantities //---------------------- T fovx() const; T fovy() const; T aspect() const; Matrix44<T> projectionMatrix() const; //----------------------------------------------------------------------- // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 // and -1 <= bottom <= top <= 1) of this Frustum, and returns a new // Frustum whose near clipping-plane window is that rectangle in local // space. //----------------------------------------------------------------------- Frustum<T> window(T left, T right, T top, T bottom) const; //---------------------------------------------------------- // Projection is in screen space / Conversion from Z-Buffer //---------------------------------------------------------- Line3<T> projectScreenToRay( const Vec2<T> & ) const; Vec2<T> projectPointToScreen( const Vec3<T> & ) const; T ZToDepth(long zval, long min, long max) const; T normalizedZToDepth(T zval) const; long DepthToZ(T depth, long zmin, long zmax) const; T worldRadius(const Vec3<T> &p, T radius) const; T screenRadius(const Vec3<T> &p, T radius) const; protected: Vec2<T> screenToLocal( const Vec2<T> & ) const; Vec2<T> localToScreen( const Vec2<T> & ) const; protected: T _near; T _far; T _left; T _right; T _top; T _bottom; bool _orthographic;};template<class T>inline Frustum<T>::Frustum(){ set(T (0.1), T (1000.0), T (-1.0), T (1.0), T (1.0), T (-1.0), false);}template<class T>inline Frustum<T>::Frustum(const Frustum &f){ *this = f;}template<class T>inline Frustum<T>::Frustum(T n, T f, T l, T r, T t, T b, bool o){ set(n,f,l,r,t,b,o);}template<class T>inline Frustum<T>::Frustum(T near, T far, T fovx, T fovy, T aspect){ set(near,far,fovx,fovy,aspect);}template<class T>Frustum<T>::~Frustum(){}template<class T>const Frustum<T> &Frustum<T>::operator = (const Frustum &f){ _near = f._near; _far = f._far; _left = f._left; _right = f._right; _top = f._top; _bottom = f._bottom; _orthographic = f._orthographic; return *this;}template <class T>boolFrustum<T>::operator == (const Frustum<T> &src) const{ return _near == src._near && _far == src._far && _left == src._left && _right == src._right && _top == src._top && _bottom == src._bottom && _orthographic == src._orthographic;}template <class T>inline boolFrustum<T>::operator != (const Frustum<T> &src) const{ return !operator== (src);}template<class T>void Frustum<T>::set(T n, T f, T l, T r, T t, T b, bool o){ _near = n; _far = f; _left = l; _right = r; _bottom = b; _top = t; _orthographic = o;}template<class T>void Frustum<T>::modifyNearAndFar(T n, T f){ if ( _orthographic ) { _near = n; } else { Line3<T> lowerLeft( Vec3<T>(0,0,0), Vec3<T>(_left,_bottom,-_near) ); Line3<T> upperRight( Vec3<T>(0,0,0), Vec3<T>(_right,_top,-_near) ); Plane3<T> nearPlane( Vec3<T>(0,0,-1), n ); Vec3<T> ll,ur; nearPlane.intersect(lowerLeft,ll); nearPlane.intersect(upperRight,ur); _left = ll.x; _right = ur.x; _top = ur.y; _bottom = ll.y; _near = n; _far = f; } _far = f;}template<class T>void Frustum<T>::setOrthographic(bool ortho){ _orthographic = ortho;}template<class T>void Frustum<T>::set(T near, T far, T fovx, T fovy, T aspect){ if (fovx != 0 && fovy != 0) throw Iex::ArgExc ("fovx and fovy cannot both be non-zero."); if (fovx != 0) { _right = near * Math<T>::tan(fovx/2.0); _left = -_right; _top = ((_right - _left)/aspect)/2.0; _bottom = -_top; } else { _top = near * Math<T>::tan(fovy/2.0); _bottom = -_top; _right = (_top - _bottom) * aspect / 2.0; _left = -_right; } _near = near; _far = far; _orthographic = false;}template<class T>T Frustum<T>::fovx() const{ return Math<T>::atan2(_right,_near) - Math<T>::atan2(_left,_near);}template<class T>T Frustum<T>::fovy() const{ return Math<T>::atan2(_top,_near) - Math<T>::atan2(_bottom,_near);}template<class T>T Frustum<T>::aspect() const{ T rightMinusLeft = _right-_left; T topMinusBottom = _top-_bottom; if (abs(topMinusBottom) < 1 && abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom)) { throw Iex::DivzeroExc ("Bad viewing frustum: " "aspect ratio cannot be computed."); } return rightMinusLeft / topMinusBottom;}template<class T>Matrix44<T> Frustum<T>::projectionMatrix() const{ T rightPlusLeft = _right+_left; T rightMinusLeft = _right-_left; T topPlusBottom = _top+_bottom;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -