00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "frustum.h"
00022 #include "matrix.h"
00023
00024 #include <cstdio>
00025
00026 using namespace salt;
00027
00028 void Frustum::Dump() const
00029 {
00030 printf("Frustum %p:\n", this);
00031 for(int i=0; i<6; ++i)
00032 {
00033 printf(" %d: %f %f %f %f\n", i, mPlanes[i].normal.x(), mPlanes[i].normal.y(), mPlanes[i].normal.z(), mPlanes[i].d);
00034 }
00035 }
00036 void Frustum::Set(const Matrix& worldTransform, float fov, float zNear, float zFar, float aspect)
00037 {
00038 Matrix viewTransform = worldTransform;
00039 viewTransform.InvertRotationMatrix();
00040
00041 float halfWorldWidth = zNear * (float)tan(gDegToRad(fov*0.5f));
00042 float halfWorldHeight = halfWorldWidth * (aspect);
00043
00044 Matrix projectionTransform;
00045
00046 projectionTransform.Identity();
00047 projectionTransform(0,0) = zNear/halfWorldWidth;
00048 projectionTransform(1,1) = zNear/halfWorldHeight;
00049 projectionTransform(2,2) = -(zFar+zNear)/(zFar-zNear);
00050 projectionTransform(2,3) = -(2.0f*zFar*zNear)/(zFar-zNear);
00051 projectionTransform(3,2) = -1;
00052 projectionTransform(3,3) = 0;
00053
00054
00055 Matrix frustumMatrix = projectionTransform * viewTransform;
00056
00057
00058 float *m= frustumMatrix.m;
00059
00060 Plane *p = &mPlanes[Frustum::PI_RIGHT];
00061 p->normal.Set(m[3]-m[0], m[7]-m[4], m[11]-m[8]);
00062 p->d = m[15]-m[12];
00063
00064 p = &mPlanes[Frustum::PI_LEFT];
00065 p->normal.Set(m[3]+m[0], m[7]+m[4], m[11]+m[8]);
00066 p->d = m[15]+m[12];
00067
00068 p = &mPlanes[Frustum::PI_BOTTOM];
00069 p->normal.Set(m[3]+m[1], m[7]+m[5], m[11]+m[9]);
00070 p->d = m[15]+m[13];
00071
00072 p = &mPlanes[Frustum::PI_TOP];
00073 p->normal.Set(m[3]-m[1], m[7]-m[5], m[11]-m[9]);
00074 p->d = m[15]-m[13];
00075
00076 p = &mPlanes[Frustum::PI_NEAR];
00077 p->normal.Set(m[3]-m[2], m[7]-m[6], m[11]-m[10]);
00078 p->d = m[15]-m[14];
00079
00080 p = &mPlanes[Frustum::PI_FAR];
00081 p->normal.Set(m[3]+m[2], m[7]+m[6], m[11]+m[10]);
00082 p->d = m[15]+m[14];
00083
00084
00085 for(int i=0;i<6;++i)
00086 {
00087 mPlanes[i].Normalize();
00088 }
00089 }
00090
00091 Frustum::eFrustumSide Frustum::Intersects(const AABB3& bb) const
00092 {
00093 bool split = false;
00094
00095 for(int i=0; i<6; ++i)
00096 {
00097 EPlaneSide result = mPlanes[i].ClassifyBox(bb);
00098 if(result == PLANESIDE_SPLIT) split = true;
00099
00100 if(result == PLANESIDE_BACK) return FS_OUTSIDE;
00101 }
00102
00103 if(split)
00104 return FS_SPLIT;
00105 else
00106 return FS_INSIDE;
00107 }
00108