00001 /*
00002 File: Camera.cc
00003
00004 Function: See header file
00005
00006 Author(s): Andrew Willmott
00007
00008 Copyright: (c) 1995-2000, Andrew Willmott
00009 */
00010
00011 #include "gcl/Camera.h"
00012 #include "gcl/VecUtil.h"
00013 #include "gcl/Quaternion.h"
00014
00015 #ifdef VL_ROW_ORIENT
00016 #error not_implemented
00017 #endif
00018
00019 Camera::Camera() :
00020 model(2),
00021 position(0.0, 1.0, 4.0),
00022 orient(vl_w),
00023 scale(1.0),
00024 clipNear(0.1),
00025 clipFar(100.0),
00026 fov(30.0),
00027 aspect(1.0),
00028 lhand(false),
00029
00030 up(vl_y),
00031 viewDir(0.0, 0.0, -1.0),
00032 lookAt(0.0, 1.0, 0.0),
00033
00034 modelCentre(vl_0),
00035 trans(vl_0),
00036 rot(vl_0)
00037 {
00038 }
00039
00040 Void Camera::SetClipping(GCLReal nearPlane, GCLReal farPlane)
00041 {
00042 clipNear = nearPlane;
00043 clipFar = farPlane;
00044 }
00045
00046 Void Camera::SetFOV(GCLReal fieldOfView)
00047 {
00048 fov = fieldOfView;
00049 }
00050
00051 Void Camera::SetAspect(GCLReal aspectRatio)
00052 {
00053 aspect = aspectRatio;
00054 }
00055
00056 Void Camera::SetView(const Point &eyePoint, const Quaternion &q)
00057 {
00058 position = eyePoint;
00059 orient = q;
00060 }
00061
00062 Void Camera::SetLookAt(const Point &pos, const Point &at)
00063 {
00064 position = pos;
00065 viewDir = at - pos;
00066 SetupViewDir();
00067 }
00068
00069 Void Camera::SetViewDir(const Point &p, const Vector &dir)
00070 {
00071 position = p;
00072 viewDir = dir;
00073 SetupViewDir();
00074 }
00075
00076 Void Camera::SetViewUp(Vector vup)
00077 {
00078 up = norm(vup);
00079 SetupViewDir();
00080 }
00081
00082 Void Camera::SetModelCentric(const Coord &r, const Vector &t)
00083 {
00084 rot = r;
00085 trans = t;
00086 SetupModelCentric();
00087 }
00088
00089 Void Camera::SetScale(GCLReal newScale)
00090 {
00091 scale = newScale;
00092 }
00093
00094 const GCLReal kProjEpsilon = 0.01;
00095
00096 Void Camera::SetupViewDir()
00097 {
00098 Vector xAxis, yAxis, zAxis;
00099 VecTrans newOrient;
00100
00101 zAxis = -norm(viewDir);
00102
00103 xAxis = cross(up, zAxis);
00104 if (len(xAxis) < kProjEpsilon)
00105 xAxis = FindOrthoVector(zAxis);
00106
00107 xAxis.Normalise();
00108 yAxis = norm(cross(zAxis, xAxis));
00109
00110 newOrient[0] = xAxis;
00111 newOrient[1] = yAxis;
00112 newOrient[2] = zAxis;
00113
00114 orient = QuatInv(MakeQuat(newOrient));
00115 }
00116
00117 Void Camera::SetupLookAt()
00118 {
00119 viewDir = lookAt - position;
00120 SetupViewDir();
00121 }
00122
00123 Void Camera::SetupModelCentric()
00124 // we're looking at the base point; move it about with trans
00125 // rotating scene around it according to rotX and rotY
00126 // base point currently fixed at origin
00127 {
00128 Point lookAt = -trans;
00129 Point pos = -trans + vl_z;
00130 Transform rotn;
00131
00132 pos *= 4.0;
00133 lookAt *= 4.0;
00134
00135 rotn = Rotation(vl_y, -rot[1] * vl_pi) * Rotation(vl_x, -rot[0] * vl_pi);
00136
00137 pos = xform(rotn, pos);
00138 lookAt = xform(rotn, lookAt);
00139
00140 SetLookAt(pos, lookAt);
00141 }
00142
00143 Void Camera::GetViewDirParams()
00144 {
00145 VecTrans m;
00146
00147 m.MakeRot(QuatInv(norm(orient)));
00148 viewDir = -m[2];
00149 }
00150
00151 Void Camera::GetLookAtParams()
00152 {
00153 GetViewDirParams();
00154 lookAt = position + viewDir;
00155 }
00156
00157 Void Camera::GetModelCentricParams()
00158 {
00159 GetViewDirParams();
00160
00161 // work backwards from position & viewDir.
00162 rot[1] = -atan2(-viewDir[0], -viewDir[2]) / vl_pi;
00163 rot[0] = -asin(viewDir[1]) / vl_pi;
00164
00165 trans = xform(Rotation(vl_x, rot[0] * vl_pi) * Rotation(vl_y, rot[1] * vl_pi),
00166 position);
00167 trans = Vector(vl_z) - trans / 4.0;
00168
00169 }
00170
00171
00172 // --- Basic transform routines -----------------------------------------------
00173
00174 Transform Camera::ModelMatrix() const
00175 {
00176 return(Scalef(scale) * Rotation(QuatInv(norm(orient))) * Shift(-position));
00177 }
00178
00179 Transform Camera::ProjMatrix() const
00180 {
00181 Transform project(vl_I);
00182
00183 if (lhand)
00184 {
00185 project[3][3] = 0;
00186 project[2][2] = -(clipFar + clipNear) / (clipFar - clipNear);
00187 project[2][3] = - 2 * clipFar * clipNear / (clipFar - clipNear);
00188 project[3][2] = -1;
00189
00190 project[0][0] = 1.0 / tan(DegsToRads(fov));
00191 project[1][1] = aspect * project[0][0];
00192 }
00193 else
00194 {
00195 project[3][3] = 0;
00196 project[2][2] = -(clipFar + clipNear) / (clipFar - clipNear);
00197 project[2][3] = - 2 * clipFar * clipNear / (clipFar - clipNear);
00198 project[3][2] = -1;
00199
00200 project[0][0] = 1.0 / tan(DegsToRads(fov));
00201 project[1][1] = aspect * project[0][0];
00202 }
00203
00204 return(project);
00205 }
00206
00207
00208 // --- Avar stuff -------------------------------------------------------------
00209
00210 Void Camera::PrintAvars(Bool animFormat)
00211 {
00212 cout << "=== quaternion-based: " << endl;
00213 if (animFormat)
00214 {
00215 cout << "k cam_pos_v " << position[0] << ' ' << position[1] << ' ' << position[2] << endl;
00216 cout << "k cam_orient_q " << orient[0] << ' ' << orient[1] << ' ' << orient[2] << ' ' << orient[3] << endl;
00217 if (fov != 30.0)
00218 cout << "k cam_fov " << fov << endl;
00219 }
00220 else
00221 {
00222 cout << "cam_pos_v " << position[0] << ' ' << position[1] << ' ' << position[2];
00223 cout << " cam_orient_q " << orient[0] << ' ' << orient[1] << ' ' << orient[2] << ' ' << orient[3];
00224 if (fov != 30.0)
00225 cout << " cam_fov " << fov << endl;
00226 cout << endl;
00227 }
00228
00229 cout << "=== camera-based: " << endl;
00230 if (animFormat)
00231 {
00232 cout << "k cam_trans_v " << trans[0] << ' ' << trans[1] << ' ' << trans[2] << endl;
00233 cout << "k cam_rot_c " << rot[0] << ' ' << rot[1] << endl;
00234 if (fov != 30.0)
00235 cout << "k cam_fov " << fov << endl;
00236 }
00237 else
00238 {
00239 cout << "cam_trans_v " << trans[0] << ' ' << trans[1] << ' ' << trans[2];
00240 cout << " cam_rot_c " << rot[0] << ' ' << rot[1];
00241 if (fov != 30.0)
00242 cout << " cam_fov " << fov << endl;
00243 cout << endl;
00244 }
00245 }
00246
00247 Bool Camera::CheckAvar(StrConst avarName, GCLReal avarVal)
00248 {
00249 // XXX this is a hack for now: later camera params should be part of
00250 // actual avar mechanism
00251 if (avarName == "cam_orient_w")
00252 orient[3] = avarVal;
00253 else if (avarName.Prefix(-1) == "cam_orient_")
00254 {
00255 orient[avarName.Suffix(1)[0] - 'x'] = avarVal;
00256 model = 0;
00257 }
00258 else if (avarName.Prefix(-1) == "cam_pos_")
00259 position[avarName.Suffix(1)[0] - 'x'] = avarVal;
00260 else if (avarName == "cam_fov")
00261 fov = avarVal;
00262 else if (avarName == "cam_clip_near")
00263 clipNear = avarVal;
00264 else if (avarName == "cam_clip_far")
00265 clipFar = avarVal;
00266 else if (avarName == "cam_scale")
00267 scale = avarVal;
00268
00269 else if (avarName.Prefix(-1) == "cam_dir_")
00270 {
00271 viewDir[avarName.Suffix(1)[0] - 'x'] = avarVal;
00272 model = 1;
00273 }
00274 else if (avarName.Prefix(-1) == "cam_vup_")
00275 up[avarName.Suffix(1)[0] - 'x'] = avarVal;
00276 else if (avarName.Prefix(-1) == "cam_lookat_")
00277 {
00278 lookAt[avarName.Suffix(1)[0] - 'x'] = avarVal;
00279 model = 2;
00280 }
00281
00282 // for backwards-compatibility: deprecated
00283 else if (avarName.Prefix(-1) == "cam_trans_")
00284 {
00285 trans[avarName.Suffix(1)[0] - 'x'] = avarVal;
00286 model = 3;
00287 }
00288 else if (avarName.Prefix(-1) == "cam_rot_")
00289 {
00290 rot[avarName.Suffix(1)[0] - 'x'] = avarVal;
00291 model = 3;
00292 }
00293 else if (avarName == "zoom")
00294 fov = 30.0 / avarVal;
00295 else
00296 return(false);
00297
00298 return(true);
00299 }
00300
00301 Void Camera::SetupFromParams()
00302 {
00303 if (model == 0)
00304 ;
00305 else if (model == 1)
00306 SetupViewDir();
00307 else if (model == 2)
00308 SetupLookAt();
00309 else if (model == 3)
00310 SetupModelCentric();
00311 }
00312
00313
00314 // --- Camera utilities -------------------------------------------------------
00315
00316 Void FindWorldRay(
00317 const Coord &c,
00318 const Transform &inverseW2S,
00319 Point &from,
00320 Vector &dir
00321 )
00322 {
00323 HPoint eye(c[0], c[1], 0.0, 1.0);
00324 HPoint target(c[0], c[1], 1.0, 1.0);
00325
00326 eye = inverseW2S * eye;
00327 target = inverseW2S * target;
00328
00329 from = proj(eye);
00330 dir = proj(target);
00331 dir -= from;
00332 }
00333