⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imathfrustum.h

📁 image converter source code
💻 H
📖 第 1 页 / 共 2 页
字号:
    T topMinusBottom = _top-_bottom;    T farPlusNear    = _far+_near;    T farMinusNear   = _far-_near;    if ((abs(rightMinusLeft) < 1 &&	 abs(rightPlusLeft) > limits<T>::max() * abs(rightMinusLeft)) ||	(abs(topMinusBottom) < 1 &&	 abs(topPlusBottom) > limits<T>::max() * abs(topMinusBottom)) ||	(abs(farMinusNear) < 1 &&	 abs(farPlusNear) > limits<T>::max() * abs(farMinusNear)))    {	throw Iex::DivzeroExc ("Bad viewing frustum: "			       "projection matrix cannot be computed.");    }    if ( _orthographic )    {	T tx = -rightPlusLeft / rightMinusLeft;	T ty = -topPlusBottom / topMinusBottom;	T tz = -farPlusNear   / farMinusNear;	if ((abs(rightMinusLeft) < 1 &&	     2 > limits<T>::max() * abs(rightMinusLeft)) ||	    (abs(topMinusBottom) < 1 &&	     2 > limits<T>::max() * abs(topMinusBottom)) ||	    (abs(farMinusNear) < 1 &&	     2 > limits<T>::max() * abs(farMinusNear)))	{	    throw Iex::DivzeroExc ("Bad viewing frustum: "				   "projection matrix cannot be computed.");	}	T A  =  2 / rightMinusLeft;	T B  =  2 / topMinusBottom;	T C  = -2 / farMinusNear;	return Matrix44<T>( A,  0,  0,  0,			    0,  B,  0,  0,			    0,  0,  C,  0,			    tx, ty, tz, 1.f );    }    else    {	T A =  rightPlusLeft / rightMinusLeft;	T B =  topPlusBottom / topMinusBottom;	T C = -farPlusNear   / farMinusNear;	T farTimesNear = -2 * _far * _near;	if (abs(farMinusNear) < 1 &&	    abs(farTimesNear) > limits<T>::max() * abs(farMinusNear))	{	    throw Iex::DivzeroExc ("Bad viewing frustum: "				   "projection matrix cannot be computed.");	}	T D = farTimesNear / farMinusNear;	T twoTimesNear = 2 * _near;	if ((abs(rightMinusLeft) < 1 &&	     abs(twoTimesNear) > limits<T>::max() * abs(rightMinusLeft)) ||	    (abs(topMinusBottom) < 1 &&	     abs(twoTimesNear) > limits<T>::max() * abs(topMinusBottom)))	{	    throw Iex::DivzeroExc ("Bad viewing frustum: "				   "projection matrix cannot be computed.");	}	T E = twoTimesNear / rightMinusLeft;	T F = twoTimesNear / topMinusBottom;	return Matrix44<T>( E,  0,  0,  0,			    0,  F,  0,  0,			    A,  B,  C, -1,			    0,  0,  D,  0 );    }}template<class T>Frustum<T> Frustum<T>::window(T l, T r, T t, T b) const{    // move it to 0->1 space    Vec2<T> bl = screenToLocal( Vec2<T>(l,b) );    Vec2<T> tr = screenToLocal( Vec2<T>(r,t) );    return Frustum<T>(_near, _far, bl.x, tr.x, tr.y, bl.y, _orthographic);}template<class T>Vec2<T> Frustum<T>::screenToLocal(const Vec2<T> &s) const{    return Vec2<T>( _left + (_right-_left) * (1.f+s.x) / 2.f,		    _bottom + (_top-_bottom) * (1.f+s.y) / 2.f );}template<class T>Vec2<T> Frustum<T>::localToScreen(const Vec2<T> &p) const{    T leftPlusRight  = _left - 2 * p.x + _right;    T leftMinusRight = _left-_right;    T bottomPlusTop  = _bottom - 2 * p.y + _top;    T bottomMinusTop = _bottom-_top;    if ((abs(leftMinusRight) < 1 &&	 abs(leftPlusRight) > limits<T>::max() * abs(leftMinusRight)) ||	(abs(bottomMinusTop) < 1 &&	 abs(bottomPlusTop) > limits<T>::max() * abs(bottomMinusTop)))    {	throw Iex::DivzeroExc	    ("Bad viewing frustum: "	     "local-to-screen transformation cannot be computed");    }    return Vec2<T>( leftPlusRight / leftMinusRight,		    bottomPlusTop / bottomMinusTop );}template<class T>Line3<T> Frustum<T>::projectScreenToRay(const Vec2<T> &p) const{    Vec2<T> point = screenToLocal(p);    if (orthographic())	return Line3<T>( Vec3<T>(point.x,point.y, 0.0),			 Vec3<T>(point.x,point.y,-_near));    else	return Line3<T>( Vec3<T>(0, 0, 0), Vec3<T>(point.x,point.y,-_near));}template<class T>Vec2<T> Frustum<T>::projectPointToScreen(const Vec3<T> &point) const{    if (orthographic() || point.z == 0)	return localToScreen( Vec2<T>( point.x, point.y ) );    else	return localToScreen( Vec2<T>( point.x * _near / -point.z, 				       point.y * _near / -point.z ) );}template<class T>T Frustum<T>::ZToDepth(long zval,long zmin,long zmax) const{    int zdiff = zmax - zmin;    if (zdiff == 0)    {	throw Iex::DivzeroExc	    ("Bad call to Frustum::ZToDepth: zmax == zmin");    }    if ( zval > zmax+1 ) zval -= zdiff;    T fzval = (T(zval) - T(zmin)) / T(zdiff);    return normalizedZToDepth(fzval);}template<class T>T Frustum<T>::normalizedZToDepth(T zval) const{    T Zp = zval * 2.0 - 1;    if ( _orthographic )    {        return   -(Zp*(_far-_near) + (_far+_near))/2;    }    else     {	T farTimesNear = 2 * _far * _near;	T farMinusNear = Zp * (_far - _near) - _far - _near;	if (abs(farMinusNear) < 1 &&	    abs(farTimesNear) > limits<T>::max() * abs(farMinusNear))	{	    throw Iex::DivzeroExc		("Frustum::normalizedZToDepth cannot be computed.  The "		 "near and far clipping planes of the viewing frustum "		 "may be too close to each other");	}	return farTimesNear / farMinusNear;    }}template<class T>long Frustum<T>::DepthToZ(T depth,long zmin,long zmax) const{    long zdiff     = zmax - zmin;    T farMinusNear = _far-_near;    if ( _orthographic )    {	T farPlusNear = 2*depth + _far + _near;	if (abs(farMinusNear) < 1 &&	    abs(farPlusNear) > limits<T>::max() * abs(farMinusNear))	{	    throw Iex::DivzeroExc		("Bad viewing frustum: near and far clipping planes "		 "are too close to each other");	}	T Zp = -farPlusNear/farMinusNear;	return long(0.5*(Zp+1)*zdiff) + zmin;    }    else     { 	// Perspective	T farTimesNear = 2*_far*_near;	if (abs(depth) < 1 &&	    abs(farTimesNear) > limits<T>::max() * abs(depth))	{	    throw Iex::DivzeroExc		("Bad call to DepthToZ function: value of `depth' "		 "is too small");	}	T farPlusNear = farTimesNear/depth + _far + _near;	if (abs(farMinusNear) < 1 &&	    abs(farPlusNear) > limits<T>::max() * abs(farMinusNear))	{	    throw Iex::DivzeroExc		("Bad viewing frustum: near and far clipping planes "		 "are too close to each other");	}	T Zp = farPlusNear/farMinusNear;	return long(0.5*(Zp+1)*zdiff) + zmin;    }}template<class T>T Frustum<T>::screenRadius(const Vec3<T> &p, T radius) const{    // Derivation:    // Consider X-Z plane.    // X coord of projection of p = xp = p.x * (-_near / p.z)    // Let q be p + (radius, 0, 0).    // X coord of projection of q = xq = (p.x - radius)  * (-_near / p.z)    // X coord of projection of segment from p to q = r = xp - xq    //         = radius * (-_near / p.z)    // A similar analysis holds in the Y-Z plane.    // So r is the quantity we want to return.    if (abs(p.z) > 1 || abs(-_near) < limits<T>::max() * abs(p.z))    {	return radius * (-_near / p.z);    }    else    {	throw Iex::DivzeroExc	    ("Bad call to Frustum::screenRadius: the magnitude of `p' "	     "is too small");    }    return radius * (-_near / p.z);}template<class T>T Frustum<T>::worldRadius(const Vec3<T> &p, T radius) const{    if (abs(-_near) > 1 || abs(p.z) < limits<T>::max() * abs(-_near))    {	return radius * (p.z / -_near);    }    else    {	throw Iex::DivzeroExc	    ("Bad viewing frustum: the near clipping plane is too "	     "close to zero");    }}template<class T>void Frustum<T>::planes(Plane3<T> p[6]){    //    //	Plane order: Top, Right, Bottom, Left, Near, Far.    //  Normals point outwards.    //    if (! _orthographic)    {        Vec3<T> a( _left,  _bottom, -_near);        Vec3<T> b( _left,  _top,    -_near);        Vec3<T> c( _right, _top,    -_near);        Vec3<T> d( _right, _bottom, -_near);        Vec3<T> o(0,0,0);        p[0].set( o, c, b );        p[1].set( o, d, c );        p[2].set( o, a, d );        p[3].set( o, b, a );    }    else    {        p[0].set( Vec3<T>( 0, 1, 0), _top );        p[1].set( Vec3<T>( 1, 0, 0), _right );        p[2].set( Vec3<T>( 0,-1, 0),-_bottom );        p[3].set( Vec3<T>(-1, 0, 0),-_left );    }    p[4].set( Vec3<T>(0, 0, 1), -_near );    p[5].set( Vec3<T>(0, 0,-1), _far );}template<class T>void Frustum<T>::planes(Plane3<T> p[6], const Matrix44<T> &M){    //    //	Plane order: Top, Right, Bottom, Left, Near, Far.    //  Normals point outwards.    //    Vec3<T> a   = Vec3<T>( _left,  _bottom, -_near) * M;    Vec3<T> b   = Vec3<T>( _left,  _top,    -_near) * M;    Vec3<T> c   = Vec3<T>( _right, _top,    -_near) * M;    Vec3<T> d   = Vec3<T>( _right, _bottom, -_near) * M;    if (! _orthographic)    {        double s    = _far / double(_near);        T farLeft   = (T) (s * _left);        T farRight  = (T) (s * _right);        T farTop    = (T) (s * _top);        T farBottom = (T) (s * _bottom);        Vec3<T> e   = Vec3<T>( farLeft,  farBottom, -_far) * M;        Vec3<T> f   = Vec3<T>( farLeft,  farTop,    -_far) * M;        Vec3<T> g   = Vec3<T>( farRight, farTop,    -_far) * M;        Vec3<T> o   = Vec3<T>(0,0,0) * M;        p[0].set( o, c, b );        p[1].set( o, d, c );        p[2].set( o, a, d );        p[3].set( o, b, a );        p[4].set( a, d, c );        p[5].set( e, f, g );     }    else    {        Vec3<T> e   = Vec3<T>( _left,  _bottom, -_far) * M;        Vec3<T> f   = Vec3<T>( _left,  _top,    -_far) * M;        Vec3<T> g   = Vec3<T>( _right, _top,    -_far) * M;        Vec3<T> h   = Vec3<T>( _right, _bottom, -_far) * M;        p[0].set( c, g, f );        p[1].set( d, h, g );        p[2].set( a, e, h );        p[3].set( b, f, e );        p[4].set( a, d, c );        p[5].set( e, f, g );    }}typedef Frustum<float>	Frustumf;typedef Frustum<double> Frustumd;} // namespace Imath#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -