489 lines
18 KiB
C
489 lines
18 KiB
C
|
/****************************************************************************
|
|||
|
Copyright (c) 2010,RadonLabs GmbH
|
|||
|
Copyright (c) 2011-2013,WebJet Business Division,CYOU
|
|||
|
|
|||
|
http://www.genesis-3d.com.cn
|
|||
|
|
|||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
of this software and associated documentation files (the "Software"), to deal
|
|||
|
in the Software without restriction, including without limitation the rights
|
|||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
|
copies of the Software, and to permit persons to whom the Software is
|
|||
|
furnished to do so, subject to the following conditions:
|
|||
|
|
|||
|
The above copyright notice and this permission notice shall be included in
|
|||
|
all copies or substantial portions of the Software.
|
|||
|
|
|||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
|
THE SOFTWARE.
|
|||
|
****************************************************************************/
|
|||
|
#pragma once
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
@class Math::frustum
|
|||
|
|
|||
|
Defines a clipping frustum made of 6 planes.
|
|||
|
*/
|
|||
|
#include "math/plane.h"
|
|||
|
#include "math/matrix44.h"
|
|||
|
#include "math/bbox.h"
|
|||
|
#include "math/point.h"
|
|||
|
#include "math/clipstatus.h"
|
|||
|
#ifdef __OSX__
|
|||
|
#include "../rendersystem/config/RenderDeviceConfig.h"
|
|||
|
#else
|
|||
|
#include "rendersystem/config/RenderDeviceConfig.h"
|
|||
|
#endif
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
namespace Math
|
|||
|
{
|
|||
|
class frustum
|
|||
|
{
|
|||
|
public:
|
|||
|
/// plane indices
|
|||
|
enum PlaneIndex
|
|||
|
{
|
|||
|
Near = 0,
|
|||
|
Far,
|
|||
|
Left,
|
|||
|
Right,
|
|||
|
Top,
|
|||
|
Bottom,
|
|||
|
|
|||
|
NumPlanes
|
|||
|
};
|
|||
|
|
|||
|
/// default constructor
|
|||
|
frustum();
|
|||
|
///// construct from view and projection matrix
|
|||
|
//frustum(const matrix44& invViewProj);
|
|||
|
///// setup from view and proj matrix
|
|||
|
//void set(const matrix44& invViewProj);
|
|||
|
/// also view * proj
|
|||
|
void setmatrix(const matrix44& value);
|
|||
|
|
|||
|
/// setup from transformed bounding box
|
|||
|
void set(const bbox& box, const matrix44& boxTransform);
|
|||
|
/// test if point is inside frustum
|
|||
|
bool inside(const point& p) const;
|
|||
|
/// get clip bitmask of point (0 if inside, (1<<PlaneIndex) if outside)
|
|||
|
uint clipmask(const point& p) const;
|
|||
|
/// clip line against view frustum
|
|||
|
ClipStatus::Type clip(const line& l, line& clippedLine) const;
|
|||
|
/// get clip status of a local bounding box
|
|||
|
ClipStatus::Type clipstatus(const bbox& box) const;
|
|||
|
/// get clip status of a transformed bounding box
|
|||
|
ClipStatus::Type clipstatus(const bbox& box, const matrix44& boxTransform) const;
|
|||
|
/// convert to any type
|
|||
|
template<typename T> T as() const;
|
|||
|
|
|||
|
|
|||
|
static void ComputeFrustumFromProjection( float4* pOutFarPoints,float n,float f,const Math::matrix44& pProjection,bool isPersp = true );
|
|||
|
|
|||
|
static const int TopLeftFar = 0;
|
|||
|
static const int TopRightFar = 1;
|
|||
|
static const int BottomLeftFar = 2;
|
|||
|
static const int BottomRightFar = 3;
|
|||
|
static const int TopLeftNear = 4;
|
|||
|
static const int TopRightNear = 5;
|
|||
|
static const int BottomLeftNear = 6;
|
|||
|
static const int BottomRightNear = 7;
|
|||
|
|
|||
|
plane planes[NumPlanes]; //<2F><><EFBFBD>е<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><D7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>
|
|||
|
};
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
*/
|
|||
|
inline
|
|||
|
frustum::frustum()
|
|||
|
{
|
|||
|
// empty
|
|||
|
}
|
|||
|
|
|||
|
////------------------------------------------------------------------------------
|
|||
|
///**
|
|||
|
//*/
|
|||
|
//inline
|
|||
|
//frustum::frustum(const matrix44& invViewProj)
|
|||
|
//{
|
|||
|
// this->set(invViewProj);
|
|||
|
//}
|
|||
|
|
|||
|
////------------------------------------------------------------------------------
|
|||
|
///**
|
|||
|
// Setup frustum from invViewProj matrix (transform from projection space
|
|||
|
// into world space).
|
|||
|
//*/
|
|||
|
//inline void
|
|||
|
//frustum::set(const matrix44& invViewProj)
|
|||
|
//{
|
|||
|
// // frustum corners in projection space
|
|||
|
// point projPoints[8];
|
|||
|
// projPoints[TopLeftFar].set(-1.0f, 1.0f, 1.0f);
|
|||
|
// projPoints[TopRightFar].set(1.0f, 1.0f, 1.0f);
|
|||
|
// projPoints[BottomLeftFar].set(-1.0f, -1.0f, 1.0f);
|
|||
|
// projPoints[BottomRightFar].set(1.0f, -1.0f, 1.0f);
|
|||
|
//
|
|||
|
// projPoints[TopLeftNear].set(-1.0f, 1.0f, 0.0f);
|
|||
|
// projPoints[TopRightNear].set(1.0f, 1.0f, 0.0f);
|
|||
|
// projPoints[BottomLeftNear].set(-1.0f, -1.0f, 0.0f);
|
|||
|
// projPoints[BottomRightNear].set(1.0f, -1.0f, 0.0);
|
|||
|
//
|
|||
|
// // compute frustum corners in world space
|
|||
|
// point worldPoints[8];
|
|||
|
// IndexT i;
|
|||
|
// for (i = 0; i < 8; i++)
|
|||
|
// {
|
|||
|
// point& p = worldPoints[i];
|
|||
|
// p = matrix44::transform(invViewProj,projPoints[i]);
|
|||
|
// p *= 1.0f / p.w();
|
|||
|
// }
|
|||
|
//
|
|||
|
// // setup planes
|
|||
|
// this->planes[Near].setup_from_points(worldPoints[TopRightNear], worldPoints[TopLeftNear], worldPoints[BottomLeftNear]);
|
|||
|
// this->planes[Far].setup_from_points(worldPoints[TopLeftFar], worldPoints[TopRightFar], worldPoints[BottomRightFar]);
|
|||
|
// this->planes[Left].setup_from_points(worldPoints[BottomLeftFar], worldPoints[BottomLeftNear], worldPoints[TopLeftNear]);
|
|||
|
// this->planes[Right].setup_from_points(worldPoints[TopRightFar], worldPoints[TopRightNear], worldPoints[BottomRightNear]);
|
|||
|
// this->planes[Top].setup_from_points(worldPoints[TopLeftNear], worldPoints[TopRightNear], worldPoints[TopRightFar]);
|
|||
|
// this->planes[Bottom].setup_from_points(worldPoints[BottomLeftFar], worldPoints[BottomRightFar], worldPoints[BottomRightNear]);
|
|||
|
//}
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
*/
|
|||
|
inline void
|
|||
|
frustum::setmatrix(const matrix44& value)
|
|||
|
{
|
|||
|
planes[Left].vec.x = -value.mx[3][0] - value.mx[0][0];
|
|||
|
planes[Left].vec.y = -value.mx[3][1] - value.mx[0][1];
|
|||
|
planes[Left].vec.z = -value.mx[3][2] - value.mx[0][2];
|
|||
|
planes[Left].vec.w = -value.mx[3][3] - value.mx[0][3];
|
|||
|
|
|||
|
planes[Right].vec.x = - value.mx[3][0] + value.mx[0][0];
|
|||
|
planes[Right].vec.y = - value.mx[3][1] + value.mx[0][1];
|
|||
|
planes[Right].vec.z = - value.mx[3][2] + value.mx[0][2];
|
|||
|
planes[Right].vec.w = - value.mx[3][3] + value.mx[0][3];
|
|||
|
|
|||
|
planes[Top].vec.x = - value.mx[3][0] + value.mx[1][0];
|
|||
|
planes[Top].vec.y = - value.mx[3][1] + value.mx[1][1];
|
|||
|
planes[Top].vec.z = - value.mx[3][2] + value.mx[1][2];
|
|||
|
planes[Top].vec.w = - value.mx[3][3] + value.mx[1][3];
|
|||
|
|
|||
|
planes[Bottom].vec.x = - value.mx[3][0] - value.mx[1][0];
|
|||
|
planes[Bottom].vec.y = - value.mx[3][1] - value.mx[1][1];
|
|||
|
planes[Bottom].vec.z = - value.mx[3][2] - value.mx[1][2];
|
|||
|
planes[Bottom].vec.w = - value.mx[3][3] - value.mx[1][3];
|
|||
|
|
|||
|
planes[Near].vec.x = - value.mx[2][0];
|
|||
|
planes[Near].vec.y = - value.mx[2][1];
|
|||
|
planes[Near].vec.z = - value.mx[2][2];
|
|||
|
planes[Near].vec.w = - value.mx[2][3];
|
|||
|
|
|||
|
planes[Far].vec.x = - value.mx[3][0] + value.mx[2][0];
|
|||
|
planes[Far].vec.y = - value.mx[3][1] + value.mx[2][1];
|
|||
|
planes[Far].vec.z = - value.mx[3][2] + value.mx[2][2];
|
|||
|
planes[Far].vec.w = - value.mx[3][3] + value.mx[2][3];
|
|||
|
|
|||
|
for (int i = 0; i < 6; i++)
|
|||
|
{
|
|||
|
plane& pl = planes[i];
|
|||
|
float num2 = n_sqrt(pl.vec.x * pl.vec.x + pl.vec.y * pl.vec.y + pl.vec.z * pl.vec.z );//pl.Normal.Length();
|
|||
|
//pl.Normal = (Vector3) (pl.Normal / num2);
|
|||
|
pl.vec.x /= num2;
|
|||
|
pl.vec.y /= num2;
|
|||
|
pl.vec.z /= num2;
|
|||
|
pl.vec.w /= num2;
|
|||
|
|
|||
|
//pl.D /= num2;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
Setup from a transformed bounding box.
|
|||
|
*/
|
|||
|
inline void
|
|||
|
frustum::set(const bbox& box, const matrix44& boxTransform)
|
|||
|
{
|
|||
|
// compute frustum corners in world space
|
|||
|
point localPoint;
|
|||
|
point worldPoints[8];
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
// Top: pmax.y, Bottom: pmin.y, Left: pmin.x, Right: pmax.x, Far: pmax.z, Near: pmin.z
|
|||
|
switch (i)
|
|||
|
{
|
|||
|
// FIXME: replace with permute!
|
|||
|
case TopLeftFar: localPoint.set(box.pmin.x(), box.pmax.y(), box.pmax.z()); break;
|
|||
|
case TopRightFar: localPoint.set(box.pmax.x(), box.pmax.y(), box.pmax.z()); break;
|
|||
|
case BottomLeftFar: localPoint.set(box.pmin.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
case BottomRightFar: localPoint.set(box.pmax.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
case TopLeftNear: localPoint.set(box.pmin.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case TopRightNear: localPoint.set(box.pmax.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case BottomLeftNear: localPoint.set(box.pmin.x(), box.pmin.y(), box.pmin.z()); break;
|
|||
|
case BottomRightNear: localPoint.set(box.pmax.x(), box.pmin.y(), box.pmin.z()); break;
|
|||
|
}
|
|||
|
worldPoints[i] = matrix44::transform(boxTransform,localPoint);
|
|||
|
}
|
|||
|
|
|||
|
// setup planes from transformed world space coordinates
|
|||
|
this->planes[Near].setup_from_points(worldPoints[TopLeftNear], worldPoints[TopRightNear], worldPoints[BottomLeftNear]);
|
|||
|
this->planes[Far].setup_from_points(worldPoints[TopRightFar], worldPoints[TopLeftFar], worldPoints[BottomRightFar]);
|
|||
|
this->planes[Left].setup_from_points(worldPoints[BottomLeftNear], worldPoints[BottomLeftFar], worldPoints[TopLeftNear]);
|
|||
|
this->planes[Right].setup_from_points(worldPoints[BottomRightNear], worldPoints[TopRightNear], worldPoints[TopRightFar]);
|
|||
|
this->planes[Top].setup_from_points(worldPoints[TopRightNear], worldPoints[TopLeftNear], worldPoints[TopRightFar]);
|
|||
|
this->planes[Bottom].setup_from_points(worldPoints[BottomRightFar], worldPoints[BottomLeftFar], worldPoints[BottomRightNear]);
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
Test if point is inside frustum.
|
|||
|
*/
|
|||
|
inline bool
|
|||
|
frustum::inside(const point& p) const
|
|||
|
{
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < NumPlanes; i++)
|
|||
|
{
|
|||
|
if (this->planes[i].dot(p) > 0.0f)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
Get clipmask of point.
|
|||
|
*/
|
|||
|
inline uint
|
|||
|
frustum::clipmask(const point& p) const
|
|||
|
{
|
|||
|
uint clipMask = 0;
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < NumPlanes; i++)
|
|||
|
{
|
|||
|
if (this->planes[i].dot(p) > 0.0f)
|
|||
|
{
|
|||
|
clipMask |= 1<<i;
|
|||
|
}
|
|||
|
}
|
|||
|
return clipMask;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
*/
|
|||
|
inline ClipStatus::Type
|
|||
|
frustum::clip(const line& l, line& clippedLine) const
|
|||
|
{
|
|||
|
ClipStatus::Type clipStatus = ClipStatus::Inside;
|
|||
|
line l0(l);
|
|||
|
line l1;
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < NumPlanes; i++)
|
|||
|
{
|
|||
|
ClipStatus::Type planeClipStatus = this->planes[i].clip(l0, l1);
|
|||
|
if (ClipStatus::Outside == planeClipStatus)
|
|||
|
{
|
|||
|
return ClipStatus::Outside;
|
|||
|
}
|
|||
|
else if (ClipStatus::Clipped == planeClipStatus)
|
|||
|
{
|
|||
|
clipStatus = ClipStatus::Clipped;
|
|||
|
}
|
|||
|
l0 = l1;
|
|||
|
}
|
|||
|
clippedLine = l0;
|
|||
|
return clipStatus;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
*/
|
|||
|
inline ClipStatus::Type
|
|||
|
frustum::clipstatus(const bbox& box) const
|
|||
|
{
|
|||
|
uint andFlags = 0xffff;
|
|||
|
uint orFlags = 0;
|
|||
|
point p;
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
// get corner point of bounding box
|
|||
|
switch (i)
|
|||
|
{
|
|||
|
// FIXME: REPLACE WITH PERMUTE!
|
|||
|
case 0: p = box.pmin; break;
|
|||
|
case 1: p.set(box.pmin.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case 2: p.set(box.pmax.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case 3: p.set(box.pmax.x(), box.pmin.y(), box.pmin.z()); break;
|
|||
|
case 4: p = box.pmax; break;
|
|||
|
case 5: p.set(box.pmin.x(), box.pmax.y(), box.pmax.z()); break;
|
|||
|
case 6: p.set(box.pmin.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
case 7: p.set(box.pmax.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
}
|
|||
|
|
|||
|
// get clip mask of current box corner against frustum
|
|||
|
uint clipMask = this->clipmask(p);
|
|||
|
andFlags &= clipMask;
|
|||
|
orFlags |= clipMask;
|
|||
|
}
|
|||
|
if (0 == orFlags) return ClipStatus::Inside;
|
|||
|
else if (0 != andFlags) return ClipStatus::Outside;
|
|||
|
else return ClipStatus::Clipped;
|
|||
|
}
|
|||
|
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
Returns the clip status of a transformed bounding box.
|
|||
|
*/
|
|||
|
inline ClipStatus::Type
|
|||
|
frustum::clipstatus(const bbox& box, const matrix44& boxTransform) const
|
|||
|
{
|
|||
|
uint andFlags = 0xffff;
|
|||
|
uint orFlags = 0;
|
|||
|
point localPoint, transformedPoint;
|
|||
|
IndexT i;
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
// get corner point of bounding box
|
|||
|
switch (i)
|
|||
|
{
|
|||
|
// FIXME: REPLACE WITH PERMUTE!
|
|||
|
case 0: localPoint = box.pmin; break;
|
|||
|
case 1: localPoint.set(box.pmin.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case 2: localPoint.set(box.pmax.x(), box.pmax.y(), box.pmin.z()); break;
|
|||
|
case 3: localPoint.set(box.pmax.x(), box.pmin.y(), box.pmin.z()); break;
|
|||
|
case 4: localPoint = box.pmax; break;
|
|||
|
case 5: localPoint.set(box.pmin.x(), box.pmax.y(), box.pmax.z()); break;
|
|||
|
case 6: localPoint.set(box.pmin.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
case 7: localPoint.set(box.pmax.x(), box.pmin.y(), box.pmax.z()); break;
|
|||
|
}
|
|||
|
|
|||
|
// transform bounding box point
|
|||
|
transformedPoint = matrix44::transform(boxTransform,localPoint);
|
|||
|
|
|||
|
// get clip mask of current box corner against frustum
|
|||
|
uint clipMask = this->clipmask(transformedPoint);
|
|||
|
andFlags &= clipMask;
|
|||
|
orFlags |= clipMask;
|
|||
|
}
|
|||
|
if (0 == orFlags) return ClipStatus::Inside;
|
|||
|
else if (0 != andFlags) return ClipStatus::Outside;
|
|||
|
else return ClipStatus::Clipped;
|
|||
|
}
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Build a frustum from a persepective projection matrix. The matrix may only
|
|||
|
// contain a projection; any rotation, translation or scale will cause the
|
|||
|
// constructed frustum to be incorrect.
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
inline void
|
|||
|
frustum::ComputeFrustumFromProjection( float4* pOutFarPoints,float n,float f,const Math::matrix44& pProjection,bool isPersp )
|
|||
|
{
|
|||
|
|
|||
|
// Corners of the projection frustum in homogenous space.
|
|||
|
static float4 HomogenousPoints[8];
|
|||
|
HomogenousPoints[0].set(1.0f, 0.0f, 1.0f, 1.0f); // right (at far plane)
|
|||
|
HomogenousPoints[1].set(-1.0f, 0.0f, 1.0f, 1.0f); // left
|
|||
|
HomogenousPoints[2].set(0.0f, 1.0f, 1.0f, 1.0f);// top
|
|||
|
HomogenousPoints[3].set(0.0f, -1.0f, 1.0f, 1.0f); // bottom
|
|||
|
#if RENDERDEVICE_D3D9
|
|||
|
HomogenousPoints[4].set(0.0f, 0.0f, 0.0f, 1.0f); // near
|
|||
|
#endif
|
|||
|
#if RENDERDEVICE_OPENGL || RENDERDEVICE_OPENGLES
|
|||
|
HomogenousPoints[4].set(0.0f, 0.0f, -1.0f, 1.0f); // near
|
|||
|
#endif
|
|||
|
HomogenousPoints[5].set(0.0f, 0.0f, 1.0f, 1.0f); // far
|
|||
|
|
|||
|
matrix44 invProj = matrix44::inverse(pProjection);
|
|||
|
|
|||
|
float4 frustumPoints[6];
|
|||
|
// Compute the frustum corners to view space.
|
|||
|
for( int i = 0; i < 6; i++ )
|
|||
|
{
|
|||
|
// Transform point.
|
|||
|
frustumPoints[i] = matrix44::transform( invProj,HomogenousPoints[i] );
|
|||
|
}
|
|||
|
|
|||
|
if (isPersp)
|
|||
|
{
|
|||
|
// Compute the slopes.
|
|||
|
frustumPoints[0] = frustumPoints[0] * float4::reciprocal( frustumPoints[0] ).z();
|
|||
|
frustumPoints[1] = frustumPoints[1] * float4::reciprocal( frustumPoints[1] ).z();
|
|||
|
frustumPoints[2] = frustumPoints[2] * float4::reciprocal( frustumPoints[2] ).z();
|
|||
|
frustumPoints[3] = frustumPoints[3] * float4::reciprocal( frustumPoints[3] ).z();
|
|||
|
}
|
|||
|
float RightSlope,LeftSlope,TopSlope,BottomSlope,NearZ,FarZ;
|
|||
|
RightSlope = frustumPoints[0].x();
|
|||
|
LeftSlope = frustumPoints[1].x();
|
|||
|
TopSlope = frustumPoints[2].y();
|
|||
|
BottomSlope = frustumPoints[3].y();
|
|||
|
|
|||
|
// Compute near and far.
|
|||
|
frustumPoints[4] = frustumPoints[4] * float4::reciprocal( frustumPoints[4] ).w();
|
|||
|
frustumPoints[5] = frustumPoints[5] * float4::reciprocal( frustumPoints[5] ).w();
|
|||
|
|
|||
|
NearZ = frustumPoints[4].z();
|
|||
|
FarZ = frustumPoints[5].z();
|
|||
|
|
|||
|
NearZ = n < n_abs(NearZ) ? NearZ : -n;
|
|||
|
FarZ = -f;
|
|||
|
|
|||
|
if (isPersp)
|
|||
|
{
|
|||
|
|
|||
|
float4 vRightTop = float4(RightSlope,TopSlope,1.0f,1.0f);
|
|||
|
float4 vLeftBottom = float4(LeftSlope,BottomSlope,1.0f,1.0f);
|
|||
|
float4 vLeftTop = float4(LeftSlope,TopSlope,1.0f,1.0f);
|
|||
|
float4 vRightBottom = float4(RightSlope,BottomSlope,1.0f,1.0f);
|
|||
|
float4 vNear = float4(NearZ,NearZ,NearZ,1.0f);
|
|||
|
float4 vFar = float4(FarZ,FarZ,FarZ,1.0f);
|
|||
|
|
|||
|
float4 vRightTopNear = float4::multiply( vRightTop, vNear );
|
|||
|
float4 vRightTopFar = float4::multiply( vRightTop, vFar );
|
|||
|
float4 vLeftBottomNear = float4::multiply( vLeftBottom, vNear );
|
|||
|
float4 vLeftBottomFar = float4::multiply( vLeftBottom, vFar );
|
|||
|
|
|||
|
float4 vLeftTopNear = float4::multiply( vLeftTop, vNear );
|
|||
|
float4 vLeftTopFar = float4::multiply( vLeftTop, vFar );
|
|||
|
float4 vRightBottomNear = float4::multiply( vRightBottom, vNear );
|
|||
|
float4 vRightBottomFar = float4::multiply( vRightBottom, vFar );
|
|||
|
|
|||
|
pOutFarPoints[0] = vLeftTopFar; //TopLeftFar
|
|||
|
pOutFarPoints[1] = vRightTopFar; //TopRightFar
|
|||
|
pOutFarPoints[2] = vLeftBottomFar;//BottomLeftFar
|
|||
|
pOutFarPoints[3] = vRightBottomFar; //BottomRightFar
|
|||
|
pOutFarPoints[4] = vLeftTopNear; //TopLeftNear
|
|||
|
pOutFarPoints[5] = vRightTopNear; //TopRightNear
|
|||
|
pOutFarPoints[6] = vLeftBottomNear; //BottomLeftNear
|
|||
|
pOutFarPoints[7] = vRightBottomNear; //BottomRightNear
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
pOutFarPoints[0] = float4(LeftSlope,TopSlope,FarZ,1.f); //TopLeftFar
|
|||
|
pOutFarPoints[1] = float4(RightSlope,TopSlope,FarZ,1.f); //TopRightFar
|
|||
|
pOutFarPoints[2] = float4(LeftSlope,BottomSlope,FarZ,1.f);//BottomLeftFar
|
|||
|
pOutFarPoints[3] = float4(RightSlope,BottomSlope,FarZ,1.f); //BottomRightFar
|
|||
|
pOutFarPoints[4] = float4(LeftSlope,TopSlope,NearZ,1.f); //TopLeftNear
|
|||
|
pOutFarPoints[5] = float4(RightSlope,TopSlope,NearZ,1.f); //TopRightNear
|
|||
|
pOutFarPoints[6] = float4(LeftSlope,BottomSlope,NearZ,1.f); //BottomLeftNear
|
|||
|
pOutFarPoints[7] = float4(RightSlope,BottomSlope,NearZ,1.f); //BottomRightNear
|
|||
|
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
} // namespace Math
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
|