lambdacube-engine-0.1.1: Graphics/LambdaCube/Frustum.hs
module Graphics.LambdaCube.Frustum where
import Graphics.LambdaCube.Types
{-
class Plane
{
public:
Vec3 normal,point;
float d;
void set3Points( Vec3 &v1, Vec3 &v2, Vec3 &v3);
float distance(Vec3 &p);
};
void Plane::set3Points( Vec3 &v1, Vec3 &v2, Vec3 &v3) {
Vec3 aux1, aux2;
aux1 = v1 - v2;
aux2 = v3 - v2;
normal = aux2 * aux1;
normal.normalize();
point.copy(v2);
d = -(normal.innerProduct(point));
}
float Plane::distance(Vec3 &p) {
return (d + normal.innerProduct(p));
}
class FrustumG
{
private:
enum {
TOP = 0,
BOTTOM,
LEFT,
RIGHT,
NEARP,
FARP
};
public:
static enum {OUTSIDE, INTERSECT, INSIDE};
Plane pl[6];
Vec3 ntl,ntr,nbl,nbr,ftl,ftr,fbl,fbr;
float nearD, farD, ratio, angle,tang;
float nw,nh,fw,fh;
void FrustumG::setCamInternals(float angle, float ratio, float nearD, float farD);
void FrustumG::setCamDef(Vec3 &p, Vec3 &l, Vec3 &u);
int FrustumG::pointInFrustum(Vec3 &p);
int FrustumG::sphereInFrustum(Vec3 &p, float raio);
int FrustumG::boxInFrustum(AABox &b);
};
#define ANG2RAD 3.14159265358979323846/180.0
void FrustumG::setCamInternals(float angle, float ratio, float nearD, float farD) {
this->ratio = ratio;
this->angle = angle;
this->nearD = nearD;
this->farD = farD;
tang = (float)tan(angle* ANG2RAD * 0.5) ;
nh = nearD * tang;
nw = nh * ratio;
fh = farD * tang;
fw = fh * ratio;
}
void FrustumG::setCamDef(Vec3 &p, Vec3 &l, Vec3 &u) {
Vec3 dir,nc,fc,X,Y,Z;
Z = p - l;
Z.normalize();
X = u * Z;
X.normalize();
Y = Z * X;
nc = p - Z * nearD;
fc = p - Z * farD;
ntl = nc + Y * nh - X * nw;
ntr = nc + Y * nh + X * nw;
nbl = nc - Y * nh - X * nw;
nbr = nc - Y * nh + X * nw;
ftl = fc + Y * fh - X * fw;
ftr = fc + Y * fh + X * fw;
fbl = fc - Y * fh - X * fw;
fbr = fc - Y * fh + X * fw;
pl[TOP].set3Points(ntr,ntl,ftl);
pl[BOTTOM].set3Points(nbl,nbr,fbr);
pl[LEFT].set3Points(ntl,nbl,fbl);
pl[RIGHT].set3Points(nbr,ntr,fbr);
pl[NEARP].set3Points(ntl,ntr,nbr);
pl[FARP].set3Points(ftr,ftl,fbl);
}
int FrustumG::pointInFrustum(Vec3 &p) {
int result = INSIDE;
for(int i=0; i < 6; i++) {
if (pl[i].distance(p) < 0)
return OUTSIDE;
}
return(result);
}
int FrustumG::sphereInFrustum(Vec3 &p, float raio) {
int result = INSIDE;
float distance;
for(int i=0; i < 6; i++) {
distance = pl[i].distance(p);
if (distance < -raio)
return OUTSIDE;
else if (distance < raio)
result = INTERSECT;
}
return(result);
}
int FrustumG::boxInFrustum(AABox &b) {
int result = INSIDE;
for(int i=0; i < 6; i++) {
if (pl[i].distance(b.getVertexP(pl[i].normal)) < 0)
return OUTSIDE;
else if (pl[i].distance(b.getVertexN(pl[i].normal)) < 0)
result = INTERSECT;
}
return(result);
}
-}