$search
00001 //CPP: 00002 // Title: class tgCamera 00003 // File: tgCamera.cpp 00004 // 00005 // Function: Viewing tgCamera for free movement in space 00006 // Forward, Backward, Strafe, Rotate 00007 // 00008 // Author: Thomas Mörwald 00009 // Date: 09.01.2007 00010 // ---------------------------------------------------------------------------- 00011 #include <blort/TomGine/tgCamera.h> 00012 00013 using namespace TomGine; 00014 00015 tgCamera::Parameter::Parameter(){ 00016 width = 640; 00017 height = 480; 00018 fx = 520.0f; 00019 fy = 520.0f; 00020 cx = 320.0f; 00021 cy = 240.0f; 00022 k1 = 0.0f; 00023 k2 = 0.0f; 00024 k3 = 0.0f; 00025 p1 = 0.0f; 00026 p2 = 0.0f; 00027 rot.fromRotVector(vec3(-2.0f,-1.0f,0.5f)); 00028 pos = vec3(0.6f, -0.2f, 0.5f); 00029 zNear = 0.01f; 00030 zFar = 4.0f; 00031 } 00032 00033 tgCamera::Parameter::Parameter(const sensor_msgs::CameraInfo& cam_info) 00034 { 00035 width = cam_info.width; 00036 height = cam_info.height; 00037 fx =cam_info.K.at(0); 00038 cx = cam_info.K.at(2); 00039 fy = cam_info.K.at(4); 00040 cy = cam_info.K.at(5); 00041 k1 = cam_info.D.at(0); 00042 k2 = cam_info.D.at(1); 00043 k3 = cam_info.D.at(4); 00044 p1 = cam_info.D.at(2); 00045 p2 = cam_info.D.at(3); 00046 zNear = 0.1f; 00047 zFar = 5.0f; 00048 rot.fromRotVector(vec3(-2.0f,-1.0f,0.5f)); 00049 pos = vec3(0.6f, -0.2f, 0.5f); 00050 } 00051 00052 void tgCamera::Parameter::setPose(const TomGine::tgPose& camPose) 00053 { 00054 // pos = camPose.t; 00055 // rot = camPose.q; 00056 } 00057 00058 tgCamera::tgCamera(){ 00059 f = tgVector3(0.0f,0.0f,-1.0f); 00060 s = tgVector3(1.0f,0.0f,0.0f); 00061 u = tgVector3(0.0f,1.0f,0.0f); 00062 } 00063 00064 void tgCamera::Load(tgCamera::Parameter camPars){ 00065 00066 // intrinsic parameters 00067 // transform the coordinate system of computer vision to OpenGL 00068 // Vision: origin is in the up left corner, x-axis pointing right, y-axis pointing down 00069 // OpenGL: origin is in the middle, x-axis pointing right, y-axis pointing up 00070 float fx = 2.0f*camPars.fx / camPars.width; // scale range from [0 ... 640] to [0 ... 2] 00071 float fy = 2.0f*camPars.fy / camPars.height; // scale range from [0 ... 480] to [0 ... 2] 00072 float cx = 1.0f-(2.0f*camPars.cx / camPars.width); // move coordinates from left to middle of image: [0 ... 2] -> [-1 ... 1] (not negative z value at w-division) 00073 float cy = (2.0f*camPars.cy / camPars.height)-1.0f; // flip and move coordinates from top to middle of image: [0 ... 2] -> [-1 ... 1] (not negative z value at w-division) 00074 float z1 = (camPars.zFar+camPars.zNear)/(camPars.zNear-camPars.zFar); // entries for clipping planes 00075 float z2 = 2.0f*camPars.zFar*camPars.zNear/(camPars.zNear-camPars.zFar); // look up for gluPerspective 00076 00077 // intrinsic matrix 00078 mat4 intrinsic; 00079 intrinsic[0]=fx; intrinsic[4]=0; intrinsic[8]=cx; intrinsic[12]=0; 00080 intrinsic[1]=0; intrinsic[5]=fy; intrinsic[9]=cy; intrinsic[13]=0; 00081 intrinsic[2]=0; intrinsic[6]=0; intrinsic[10]=z1; intrinsic[14]=z2; 00082 intrinsic[3]=0; intrinsic[7]=0; intrinsic[11]=-1; intrinsic[15]=0; // last row assigns w=-z which inverts cx and cy at w-division 00083 00084 // computer vision camera coordinates to OpenGL camera coordinates transform 00085 // rotate 180� about x-axis 00086 mat4 cv2gl; 00087 cv2gl[0]=1.0; cv2gl[4]=0.0; cv2gl[8]=0.0; cv2gl[12]=0.0; 00088 cv2gl[1]=0.0; cv2gl[5]=-1.0; cv2gl[9]=0.0; cv2gl[13]=0.0; 00089 cv2gl[2]=0.0; cv2gl[6]=0.0; cv2gl[10]=-1.0; cv2gl[14]=0.0; 00090 cv2gl[3]=0.0; cv2gl[7]=0.0; cv2gl[11]=0.0; cv2gl[15]=1.0; 00091 00092 // extrinsic parameters 00093 // look up comments in tools/hardware/video/src/slice/Video.ice 00094 // p = R^T*(w - t) = (R^T, -R^T*t) * (w,1) 00095 mat3 R = camPars.rot; 00096 vec3 t = camPars.pos; 00097 mat4 extrinsic; 00098 extrinsic[0]=R[0]; extrinsic[4]=R[3]; extrinsic[8]=R[6]; extrinsic[12]=0.0; 00099 extrinsic[1]=R[1]; extrinsic[5]=R[4]; extrinsic[9]=R[7]; extrinsic[13]=0.0; 00100 extrinsic[2]=R[2]; extrinsic[6]=R[5]; extrinsic[10]=R[8]; extrinsic[14]=0.0; 00101 extrinsic[3]=0.0; extrinsic[7]=0.0; extrinsic[11]=0.0; extrinsic[15]=1.0; 00102 // extrinsic = extrinsic.transpose(); // R^T 00103 vec4 tp = -(extrinsic * vec4(t.x, t.y, t.z, 1.0)); // -R^T*t 00104 extrinsic[12]=tp.x; extrinsic[13]=tp.y; extrinsic[14]=tp.z; 00105 extrinsic = cv2gl * extrinsic; 00106 00107 // set camera parameters 00108 SetViewport(camPars.width,camPars.height); 00109 SetZRange(camPars.zNear, camPars.zFar); 00110 SetIntrinsic(intrinsic); 00111 SetExtrinsic(extrinsic); 00112 SetPos(camPars.pos.x, camPars.pos.y, camPars.pos.z); 00113 } 00114 00115 void tgCamera::Set( float posx, float posy, float posz, 00116 float viewx, float viewy, float viewz, 00117 float upx, float upy, float upz, 00118 float fovy, unsigned width, unsigned height, 00119 float zNear, float zFar, 00120 unsigned short projection){ 00121 m_vPos = tgVector3(posx, posy, posz ); // set position 00122 m_vView = tgVector3(viewx, viewy, viewz); // set view point 00123 m_vUp = tgVector3(upx, upy, upz ); // set the up vector 00124 pvu2fsu(); 00125 00126 m_fovy = fovy; 00127 m_width = width; 00128 m_height = height; 00129 m_zNear = zNear; 00130 m_zFar = zFar; 00131 m_projection = projection; 00132 00133 fwh2intrinsic(); 00134 fsu2extrinsic(); 00135 } 00136 00137 void tgCamera::SetExtrinsic(float* M){ 00138 m_extrinsic = mat4(M); 00139 00140 extrinsic2fsu(); 00141 fsu2pvu(); 00142 00143 Activate(); 00144 } 00145 00146 void tgCamera::SetIntrinsic(float* M){ 00147 m_intrinsic = mat4(M); 00148 00149 Activate(); 00150 } 00151 00152 void tgCamera::SetIntrinsic( float fovy, unsigned width, unsigned height, 00153 float zNear, float zFar, 00154 unsigned short projection) 00155 { 00156 m_fovy = fovy; 00157 m_width = width; 00158 m_height = height; 00159 m_zNear = zNear; 00160 m_zFar = zFar; 00161 m_projection = projection; 00162 00163 float m[16]; 00164 glMatrixMode(GL_PROJECTION); 00165 glLoadIdentity(); 00166 00167 if(m_projection == GL_ORTHO){ 00168 glOrtho(0, m_width, 0, m_height, m_zNear, m_zFar); 00169 } 00170 else if(m_projection == GL_PERSPECTIVE){ 00171 gluPerspective( m_fovy, float(m_width)/float(m_height), m_zNear, m_zFar); 00172 } 00173 glGetFloatv(GL_PROJECTION_MATRIX, m); 00174 m_intrinsic = mat4(m); 00175 00176 Activate(); 00177 } 00178 00179 void tgCamera::SetViewport(unsigned w, unsigned h){ 00180 m_width = w; 00181 m_height = h; 00182 } 00183 00184 void tgCamera::SetZRange(float _near, float _far){ 00185 m_zNear = _near; 00186 m_zFar = _far; 00187 } 00188 00189 vec2 tgCamera::ToImageSpace(const vec3 &world_space){ 00190 vec2 ret; 00191 vec4 tmp = m_intrinsic * m_extrinsic * vec4(world_space.x,world_space.y,world_space.z,1.0f); 00192 00193 tmp.x = tmp.x / tmp.w; 00194 tmp.y = tmp.y / tmp.w; 00195 00196 ret.x = (tmp.x + 1.0f) * 0.5f * m_width; 00197 ret.y = (tmp.y + 1.0f) * 0.5f * m_height; 00198 00199 return ret; 00200 } 00201 00202 void tgCamera::Activate(){ 00203 // Apply intrinsic parameters 00204 glMatrixMode(GL_PROJECTION); 00205 glLoadMatrixf(m_intrinsic); 00206 00207 // Apply extrinsic parameters 00208 glMatrixMode(GL_MODELVIEW); 00209 glLoadMatrixf(m_extrinsic); 00210 00211 glViewport(0,0,m_width,m_height); 00212 glDepthRange(m_zNear,m_zFar); 00213 00214 // Extract frustum planes 00215 m_frustum.ExtractFrustum(); 00216 } 00217 00218 void tgCamera::Print(){ 00219 // float m[16]; 00220 // float p[16]; 00221 // 00222 // glGetFloatv(GL_MODELVIEW_MATRIX, m); 00223 // glGetFloatv(GL_PROJECTION_MATRIX, p); 00224 00225 mat4 m = m_extrinsic; 00226 mat4 p = m_intrinsic; 00227 00228 printf("Modelview matrix:\n"); 00229 printf("%f %f %f %f\n", m[0], m[4], m[8], m[12]); 00230 printf("%f %f %f %f\n", m[1], m[5], m[9], m[13]); 00231 printf("%f %f %f %f\n", m[2], m[6], m[10], m[14]); 00232 printf("%f %f %f %f\n", m[3], m[7], m[11], m[15]); 00233 printf("Projection matrix:\n"); 00234 printf("%f %f %f %f\n", p[0], p[4], p[8], p[12]); 00235 printf("%f %f %f %f\n", p[1], p[5], p[9], p[13]); 00236 printf("%f %f %f %f\n", p[2], p[6], p[10], p[14]); 00237 printf("%f %f %f %f\n", p[3], p[7], p[11], p[15]); 00238 } 00239 00240 void tgCamera::pvu2fsu(){ 00241 f = m_vView - m_vPos; f.normalize(); 00242 s = f.cross(m_vUp); s.normalize(); 00243 u = s.cross(f); u.normalize(); 00244 } 00245 00246 void tgCamera::fsu2pvu(){ 00247 m_vView = m_vPos + f; 00248 m_vUp = u; 00249 } 00250 00251 void tgCamera::fsu2extrinsic(){ 00252 float fR[16] = { s.x, u.x, -f.x, 0.0, 00253 s.y, u.y, -f.y, 0.0, 00254 s.z, u.z, -f.z, 0.0, 00255 0.0, 0.0, 0.0, 1.0}; 00256 00257 float ft[16] = { 1.0, 0.0, 0.0, 0.0, 00258 0.0, 1.0, 0.0, 0.0, 00259 0.0, 0.0, 1.0, 0.0, 00260 -m_vPos.x, -m_vPos.y, -m_vPos.z, 1.0}; 00261 mat4 R(fR); 00262 mat4 t(ft); 00263 00264 m_extrinsic = R * t; 00265 } 00266 00267 00268 void tgCamera::extrinsic2fsu(){ 00269 s.x=m_extrinsic[0]; u.x=m_extrinsic[1]; f.x=-m_extrinsic[2]; 00270 s.y=m_extrinsic[4]; u.y=m_extrinsic[5]; f.y=-m_extrinsic[6]; 00271 s.z=m_extrinsic[8]; u.z=m_extrinsic[9]; f.z=-m_extrinsic[10]; 00272 00273 float fR[16] = { s.x, u.x, -f.x, 0.0, 00274 s.y, u.y, -f.y, 0.0, 00275 s.z, u.z, -f.z, 0.0, 00276 0.0, 0.0, 0.0, 1.0}; 00277 mat4 R(fR); 00278 mat4 t; 00279 00280 t = R.inverse() * m_extrinsic; 00281 00282 m_vPos.x=-t[12]; m_vPos.x=-t[13]; m_vPos.x=-t[14]; 00283 } 00284 00285 void tgCamera::fwh2intrinsic(){ 00286 float m[16]; 00287 glMatrixMode(GL_PROJECTION); 00288 glLoadIdentity(); 00289 00290 if(m_projection == GL_ORTHO){ 00291 glOrtho(0, m_width, 0, m_height, m_zNear, m_zFar); 00292 } 00293 else if(m_projection == GL_PERSPECTIVE){ 00294 gluPerspective( m_fovy, float(m_width)/float(m_height), m_zNear, m_zFar); 00295 } 00296 glGetFloatv(GL_PROJECTION_MATRIX, m); 00297 m_intrinsic = mat4(m); 00298 } 00299 00300 tgPose tgCamera::GetPose(){ 00301 printf("[tgCamera::GetPose()] Not implemented yet\n"); 00302 return tgPose(); 00303 } 00304 //**************************************************************************** 00305 // Translations 00306 void tgCamera::Translate(tgVector3 v){ 00307 m_vPos = m_vPos + v; 00308 m_vView = m_vPos + f; 00309 } 00310 00311 void tgCamera::Translate(float x, float y, float z, float fWay){ 00312 tgVector3 v = tgVector3(x,y,z); 00313 v.normalize(); 00314 m_vPos = m_vPos + v * fWay; 00315 m_vView = m_vPos + f; 00316 } 00317 00318 void tgCamera::TranslateF(float fWay){ 00319 m_vPos = m_vPos + f * fWay; 00320 m_vView = m_vPos + f; 00321 } 00322 00323 void tgCamera::TranslateS(float fWay){ 00324 m_vPos = m_vPos + s * fWay; 00325 m_vView = m_vPos + f; 00326 } 00327 00328 void tgCamera::TranslateU(float fWay){ 00329 m_vPos = m_vPos + u * fWay; 00330 m_vView = m_vPos + f; 00331 } 00332 00333 //**************************************************************************** 00334 // Rotations 00335 void tgCamera::Rotate(float x, float y, float z, float fAngle){ 00336 tgVector3 v = tgVector3(x,y,z); 00337 f.rotate(fAngle, v); 00338 s.rotate(fAngle, v); 00339 u.rotate(fAngle, v); 00340 fsu2pvu(); 00341 } 00342 00343 void tgCamera::RotateF(float fAngle){ 00344 s.rotate(fAngle, f); 00345 u = s.cross(f); u.normalize(); 00346 fsu2pvu(); 00347 } 00348 00349 void tgCamera::RotateS(float fAngle){ 00350 f.rotate(fAngle, s); 00351 u = s.cross(f); u.normalize(); 00352 fsu2pvu(); 00353 } 00354 00355 void tgCamera::RotateU(float fAngle){ 00356 f.rotate(fAngle, u); 00357 s = f.cross(u); s.normalize(); 00358 fsu2pvu(); 00359 } 00360 00361 void tgCamera::RotateX(float fAngle){ 00362 printf("tgCamera.RotateX not implemented! \n"); 00363 } 00364 00365 void tgCamera::RotateY(float fAngle){ 00366 tgVector3 y = tgVector3(0.0f,1.0f,0.0f); 00367 f.rotate(fAngle, y); 00368 s = f.cross(y); s.normalize(); 00369 u = s.cross(f); u.normalize(); 00370 fsu2pvu(); 00371 } 00372 00373 void tgCamera::RotateZ(float fAngle){ 00374 printf("tgCamera.RotateZ not implemented! \n"); 00375 } 00376 00377 void tgCamera::Orbit(tgVector3 vPoint, tgVector3 vAxis, float fAngle){ 00378 tgVector3 d = m_vPos - vPoint; 00379 00380 d.rotate(fAngle, vAxis); 00381 m_vPos = vPoint + d; 00382 00383 f.rotate(fAngle, vAxis); 00384 s.rotate(fAngle, vAxis); 00385 u.rotate(fAngle, vAxis); 00386 } 00387 00388 //**************************************************************************** 00389 // Movement 00390 void tgCamera::ApplyTransform(){ 00391 fsu2extrinsic(); 00392 } 00393 00394 00395