00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "frustum.h"
00011
00012
00013 Frustum::Frustum(float fov, float aspectRatio, float n) :
00014 infinite(true)
00015 {
00016 init(fov, aspectRatio, n, n);
00017 }
00018
00019
00020 Frustum::Frustum(float fov, float aspectRatio, float n, float f) :
00021 infinite(false)
00022 {
00023 init(fov, aspectRatio, n, f);
00024 }
00025
00026
00027 void Frustum::init(float fov, float aspectRatio, float n, float f)
00028 {
00029 float h = (float) tan(fov / 2.0f);
00030 float w = h * aspectRatio;
00031
00032 Vec3f normals[4];
00033 normals[Bottom] = Vec3f(0, 1, -h);
00034 normals[Top] = Vec3f(0, -1, -h);
00035 normals[Left] = Vec3f(1, 0, -w);
00036 normals[Right] = Vec3f(-1, 0, -w);
00037 for (int i = 0; i < 4; i++)
00038 {
00039 normals[i].normalize();
00040 planes[i] = Planef(normals[i], Point3f(0, 0, 0));
00041 }
00042
00043 planes[Near] = Planef(Vec3f(0, 0, -1), -n);
00044 planes[Far] = Planef(Vec3f(0, 0, 1), f);
00045 }
00046
00047
00048 Frustum::Aspect Frustum::test(const Point3f& p) const
00049 {
00050 return testSphere(p, 0);
00051 }
00052
00053
00054 Frustum::Aspect Frustum::testSphere(const Point3f& center, float radius) const
00055 {
00056 int nPlanes = infinite ? 5 : 6;
00057 int intersections = 0;
00058
00059 for (int i = 0; i < nPlanes; i++)
00060 {
00061 float distanceToPlane = planes[i].distanceTo(center);
00062 if (distanceToPlane < -radius)
00063 return Outside;
00064 else if (distanceToPlane <= radius)
00065 intersections |= (1 << i);
00066 }
00067
00068 return (intersections == 0) ? Inside : Intersect;
00069 }
00070
00071
00072 Frustum::Aspect Frustum::testSphere(const Point3d& center, double radius) const
00073 {
00074 int nPlanes = infinite ? 5 : 6;
00075 int intersections = 0;
00076
00077 for (int i = 0; i < nPlanes; i++)
00078 {
00079
00080 Vec3f plNormal = planes[i].normal;
00081 Vec3d plNormalDbl(plNormal.x, plNormal.y, plNormal.z);
00082
00083 double distanceToPlane = plNormalDbl.x * center.x + plNormalDbl.y * center.y + plNormalDbl.z * center.z + planes[i].d;
00084 if (distanceToPlane < -radius)
00085 return Outside;
00086 else if (distanceToPlane <= radius)
00087 intersections |= (1 << i);
00088 }
00089
00090 return (intersections == 0) ? Inside : Intersect;
00091 }
00092
00093 #if 0
00094
00095
00096
00097 Frustum::Aspect Frustum::testHalfSpace(const Planef& plane)
00098 {
00099 return Intersect;
00100 }
00101 #endif
00102
00103
00104 void Frustum::transform(const Mat3f&)
00105 {
00106 }
00107
00108
00109 void Frustum::transform(const Mat4f& m)
00110 {
00111 int nPlanes = infinite ? 5 : 6;
00112 Mat4f invTranspose = m.inverse().transpose();
00113
00114 for (int i = 0; i < nPlanes; i++)
00115 {
00116 planes[i] = planes[i] * invTranspose;
00117 float s = 1.0f / planes[i].normal.length();
00118 planes[i].normal = planes[i].normal * s;
00119 planes[i].d *= s;
00120 }
00121 }