AI_SDB_Camera.h

Go to the documentation of this file.
00001 #ifndef AI_SDB_CAMERA_H
00002 #define AI_SDB_CAMERA_H
00003 //------------------------------------------------------------------------------
00020 //#include "kernel/ntypes.h"
00021 #include "../math/AI_Matrix.h"
00022 #include "../math/AI_BBox.h"
00023 
00024 //------------------------------------------------------------------------------
00025 class AI_SDB_Camera
00026 {
00027 public:
00029     enum ClipStatus 
00030     {
00031         Outside,
00032         Inside,
00033         Clipped,
00034     };
00035 
00037     enum Type
00038     {
00039         Perspective,
00040         Orthogonal,
00041     };
00042 
00044     AI_SDB_Camera();
00046     AI_SDB_Camera(float aov, float aspect, float nearp, float farp);
00048     void SetPerspective(float aov, float aspect, float nearp, float farp);
00050     void SetOrthogonal(float w, float h, float nearp, float farp);
00052     void SetType(Type t);
00054     Type GetType() const;
00056     void SetWidth(float w);
00058     float GetWidth() const;
00060     void SetHeight(float h);
00062     float GetHeight() const;
00064     void SetAngleOfView(float a);
00066     float GetAngleOfView() const;
00068     void SetAspectRatio(float r);
00070     float GetAspectRatio() const;
00072     void SetNearPlane(float v);
00074     float GetNearPlane() const;
00076     void SetFarPlane(float v);
00078     float GetFarPlane() const;
00080     const AI_Matrix44& GetProjection();
00082     const AI_Matrix44& GetInvProjection();
00084     const AI_BBox& GetBox();
00085     // get the view volume
00086     void GetViewVolume(float & minx, float & maxx, float & miny, float & maxy, float & minz, float & maxz) const;
00088     ClipStatus GetClipStatus(const AI_Matrix44& myTransform, const AI_Matrix44& otherViewProjection);
00089 
00090 private:
00092     void UpdateProjInvProj();
00093 
00094     Type type;
00095     float width;
00096     float height;
00097     float angleOfView;
00098     float aspectRatio;
00099     float nearPlane;
00100     float farPlane;
00101     bool projDirty;
00102     bool boxDirty;
00103     AI_Matrix44 proj;
00104     AI_Matrix44 invProj;
00105     AI_BBox box;
00106 };
00107 
00108 //------------------------------------------------------------------------------
00111 inline
00112 AI_SDB_Camera::AI_SDB_Camera() :
00113     type(Perspective),
00114     width(0),
00115     height(0),
00116     angleOfView(ai_deg2rad(60.0f)),
00117     aspectRatio(4.0f / 3.0f),
00118     nearPlane(0.1f),
00119     farPlane(5000.0f),
00120     projDirty(true),
00121     boxDirty(true)
00122 {
00123     // empty
00124 }
00125 
00126 //------------------------------------------------------------------------------
00129 inline
00130 AI_SDB_Camera::AI_SDB_Camera(float aov, float aspect, float nearp, float farp) :
00131     type(Perspective),
00132     width(0),
00133     height(0),
00134     angleOfView(ai_deg2rad(aov)),
00135     aspectRatio(aspect),
00136     nearPlane(nearp),
00137     farPlane(farp),
00138     projDirty(true),
00139     boxDirty(true)
00140 {
00141     // empty
00142 }
00143 
00144 //------------------------------------------------------------------------------
00147 inline
00148 void
00149 AI_SDB_Camera::SetPerspective(float aov, float aspect, float nearp, float farp)
00150 {
00151     this->type = Perspective;
00152     this->angleOfView = ai_deg2rad(aov);
00153     this->aspectRatio = aspect;
00154     this->nearPlane = nearp;
00155     this->farPlane = farp;
00156     this->projDirty = true;
00157     this->boxDirty = true;
00158 }
00159 
00160 //------------------------------------------------------------------------------
00163 inline
00164 void
00165 AI_SDB_Camera::SetOrthogonal(float w, float h, float nearp, float farp)
00166 {
00167     this->type = Orthogonal;
00168     this->width = w;
00169     this->height = h;
00170     this->nearPlane = nearp;
00171     this->farPlane = farp;
00172     this->projDirty = true;
00173     this->boxDirty = true;
00174 }
00175 
00176 //------------------------------------------------------------------------------
00179 inline
00180 void
00181 AI_SDB_Camera::SetType(Type t)
00182 {
00183     this->type = t;
00184     this->projDirty = true;
00185     this->boxDirty  = true;
00186 }
00187 
00188 //------------------------------------------------------------------------------
00191 inline
00192 AI_SDB_Camera::Type
00193 AI_SDB_Camera::GetType() const
00194 {
00195     return this->type;
00196 }
00197 
00198 //------------------------------------------------------------------------------
00201 inline
00202 void
00203 AI_SDB_Camera::SetWidth(float w)
00204 {
00205     this->width = w;
00206     this->projDirty = true;
00207     this->boxDirty  = true;
00208 }
00209 
00210 //------------------------------------------------------------------------------
00213 inline
00214 float
00215 AI_SDB_Camera::GetWidth() const
00216 {
00217     return this->width;
00218 }
00219 
00220 //------------------------------------------------------------------------------
00223 inline
00224 void
00225 AI_SDB_Camera::SetHeight(float h)
00226 {
00227     this->height = h;
00228     this->projDirty = true;
00229     this->boxDirty  = true;
00230 }
00231 
00232 //------------------------------------------------------------------------------
00235 inline
00236 float
00237 AI_SDB_Camera::GetHeight() const
00238 {
00239     return this->height;
00240 }
00241 
00242 //------------------------------------------------------------------------------
00245 inline
00246 void
00247 AI_SDB_Camera::SetAngleOfView(float a)
00248 {
00249     this->angleOfView = ai_deg2rad(a);
00250     this->projDirty = true;
00251     this->boxDirty  = true;
00252 }
00253 
00254 //------------------------------------------------------------------------------
00257 inline
00258 float
00259 AI_SDB_Camera::GetAngleOfView() const
00260 {
00261     return ai_rad2deg(this->angleOfView);
00262 }
00263 
00264 //------------------------------------------------------------------------------
00267 inline
00268 void
00269 AI_SDB_Camera::SetAspectRatio(float r)
00270 {
00271     this->aspectRatio = r;
00272     this->projDirty = true;
00273     this->boxDirty = true;
00274 }
00275 
00276 //------------------------------------------------------------------------------
00279 inline
00280 float
00281 AI_SDB_Camera::GetAspectRatio() const
00282 {
00283     return this->aspectRatio;
00284 }
00285 
00286 //------------------------------------------------------------------------------
00289 inline
00290 void
00291 AI_SDB_Camera::SetNearPlane(float v)
00292 {
00293     this->nearPlane = v;
00294     this->projDirty = true;
00295     this->boxDirty = true;
00296 }
00297 
00298 //------------------------------------------------------------------------------
00301 inline
00302 float
00303 AI_SDB_Camera::GetNearPlane() const
00304 {
00305     return this->nearPlane;
00306 }
00307 
00308 //------------------------------------------------------------------------------
00311 inline
00312 void
00313 AI_SDB_Camera::SetFarPlane(float v)
00314 {
00315     this->farPlane = v;
00316     this->projDirty = true;
00317     this->boxDirty = true;
00318 }
00319 
00320 //------------------------------------------------------------------------------
00323 inline
00324 float
00325 AI_SDB_Camera::GetFarPlane() const
00326 {
00327     return this->farPlane;
00328 }
00329 
00330 //------------------------------------------------------------------------------
00341 inline
00342 void
00343 AI_SDB_Camera::GetViewVolume(float & minx, float & maxx, float & miny, float & maxy, float & minz, float & maxz) const
00344 {
00345     maxy = this->nearPlane * ai_tan(this->angleOfView * 0.5f);
00346     miny = -maxy;
00347     maxx = this->aspectRatio * maxy;
00348     minx = -maxx;
00349     minz = this->nearPlane;
00350     maxz = this->farPlane;
00351 }
00352 
00353 //------------------------------------------------------------------------------
00358 inline
00359 void
00360 AI_SDB_Camera::UpdateProjInvProj()
00361 {
00362     ai_assert(this->projDirty);
00363     this->projDirty = false;
00364     if (Perspective == this->type)
00365     {
00366         this->proj.perspFovRh(this->angleOfView, this->aspectRatio, this->nearPlane, this->farPlane);
00367     }
00368     else
00369     {
00370         this->proj.orthoRh(this->width, this->height, this->nearPlane, this->farPlane);
00371     }
00372     this->invProj = proj;
00373     this->invProj.invert();
00374 }
00375 
00376 //------------------------------------------------------------------------------
00383 inline
00384 const AI_Matrix44&
00385 AI_SDB_Camera::GetProjection()
00386 {
00387     if (this->projDirty)
00388     {
00389         this->UpdateProjInvProj();
00390     }
00391     return this->proj;
00392 }
00393 
00394 //------------------------------------------------------------------------------
00398 inline
00399 const AI_Matrix44&
00400 AI_SDB_Camera::GetInvProjection()
00401 {
00402     if (this->projDirty)
00403     {
00404         this->UpdateProjInvProj();
00405     }
00406     return this->invProj;
00407 }
00408 
00409 //------------------------------------------------------------------------------
00413 inline
00414 AI_SDB_Camera::ClipStatus 
00415 AI_SDB_Camera::GetClipStatus(const AI_Matrix44& myTransform, const AI_Matrix44& otherViewProjection)
00416 {
00417     // compute matrix which transforms my local hull into
00418     // projection space of the other camera
00419     AI_Matrix44 invProjModelViewProj = this->GetInvProjection() * myTransform * otherViewProjection;
00420 
00421     // compute clip code of hull
00422     int andFlags = 0xffff;
00423     int orFlags  = 0;
00424     int i;
00425     AI_Vector4 v0(0.0f, 0.0f, 0.0f, 1.0f);
00426     AI_Vector4 v1;
00427     for (i = 0; i < 8; i++)
00428     {
00429         if (i & 1) v0.x = -1.0f;
00430         else       v0.x = +1.0f;
00431         if (i & 2) v0.y = -1.0f;
00432         else       v0.y = +1.0f;
00433         if (i & 3) v0.z = 0.0f;
00434         else       v0.z = +1.0f;
00435 
00436         v1 = invProjModelViewProj * v0;
00437         int clip = 0;
00438         if (v1.x < -v1.w)       clip |= (1<<0);
00439         else if (v1.x > v1.w)   clip |= (1<<1);
00440         if (v1.y < -v1.w)       clip |= (1<<2);
00441         else if (v1.y > v1.w)   clip |= (1<<3);
00442         if (v1.z < -v1.w)       clip |= (1<<4);
00443         else if (v1.z > v1.w)   clip |= (1<<5);
00444         andFlags &= clip;
00445         orFlags  |= clip;
00446     }
00447     if (0 == orFlags)       return Inside;
00448     else if (0 != andFlags) return Outside;
00449     else                    return Clipped;
00450 }
00451 
00452 //------------------------------------------------------------------------------
00456 inline
00457 const AI_BBox&
00458 AI_SDB_Camera::GetBox()
00459 {
00460     if (this->boxDirty)
00461     {
00462         this->boxDirty = false;
00463         if (Perspective == this->type)
00464         {
00465             float tanAov = float(tan(this->angleOfView * 0.5f));
00466             this->box.vmin.z = this->nearPlane;
00467             this->box.vmax.z = this->farPlane;
00468             this->box.vmax.y = tanAov * this->farPlane;     // ??? -> tanAov * (this->farPlane - this->nearPlane);
00469             this->box.vmin.y = -this->box.vmax.y;
00470             this->box.vmax.x = this->box.vmax.y * this->aspectRatio;
00471             this->box.vmin.x = -this->box.vmax.x;
00472         }
00473         else
00474         {
00475             this->box.vmin.x = -this->width * 0.5f;
00476             this->box.vmin.y = -this->height * 0.5f;
00477             this->box.vmin.z = -1000000.0f;
00478             this->box.vmax.x = this->width * 0.5f;
00479             this->box.vmax.y = this->height * 0.5f;
00480             this->box.vmax.z = 1000000.0f;
00481         }
00482     }
00483     return this->box;
00484 }
00485 
00486 //------------------------------------------------------------------------------
00487 #endif