Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Camera.cc

Go to the documentation of this file.
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 

Generated at Sat Aug 5 00:16:57 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000