00001 #ifndef AI_SDB_CAMERA_H
00002 #define AI_SDB_CAMERA_H
00003
00020
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
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
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
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
00418
00419 AI_Matrix44 invProjModelViewProj = this->GetInvProjection() * myTransform * otherViewProjection;
00420
00421
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;
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