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