00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00056 #ifndef __VCGLIB_SHOT
00057 #define __VCGLIB_SHOT
00058
00059 #include <vcg/space/point2.h>
00060 #include <vcg/space/point3.h>
00061 #include <vcg/math/similarity.h>
00062 #include <vcg/math/camera.h>
00063
00064 namespace vcg{
00065
00066 template <class S, class RotationType = Matrix44<S> >
00067 class Shot {
00068 public:
00069 typedef Camera<S> CameraType;
00070 typedef S ScalarType;
00071
00072 template <class ScalarType, class RotoType >
00073 class ReferenceFrame {
00074 friend class Shot<ScalarType, RotoType>;
00075 RotoType rot;
00076 Point3<S> tra;
00077 public:
00078 ReferenceFrame(){}
00079
00080 void SetIdentity(){ rot.SetIdentity(); tra = Point3<S>(0.0,0.0,0.0);}
00081 void SetTra(const Point3<S> & tr) {tra = tr;}
00082 void SetRot(const RotoType & rt) {rot = rt;}
00083 Point3<ScalarType> Tra() const { return tra;}
00084 RotoType Rot() const { return rot;}
00085 };
00086
00087 Camera<S> Intrinsics;
00088 ReferenceFrame<S,RotationType> Extrinsics;
00089 Shot(const Camera<S> &i, const ReferenceFrame<S,RotationType> &e)
00090 {
00091 Intrinsics = i;
00092 Extrinsics = e;
00093 }
00094
00095 Shot(const Camera<S> &c)
00096 {
00097 Intrinsics = c;
00098 Extrinsics.SetIdentity();
00099 }
00100
00101 Shot()
00102 {
00103 Extrinsics.SetIdentity();
00104 }
00105
00106 template <class Q>
00107 static inline Shot Construct( const Shot<Q> & b )
00108 {
00109 ReferenceFrame<S,RotationType> r;
00110 r.SetRot(Matrix44<S>::Construct(b.Extrinsics.Rot()));
00111 r.SetTra(Point3<S>::Construct(b.Extrinsics.Tra()));
00112 return Shot(Camera<S>::Construct(b.Intrinsics), r);
00113 }
00114
00115
00117 vcg::Point3<S> Axis(const int & i)const;
00118
00120 const vcg::Point3<S> GetViewDir()const;
00122 const vcg::Point3<S> GetViewPoint()const;
00124 void SetViewPoint(const vcg::Point3<S> & viewpoint);
00125
00127 float GetFovFromFocal();
00128
00130 void LookAt(const vcg::Point3<S> & point,const vcg::Point3<S> & up);
00131
00133 void LookAt(const S & eye_x,const S & eye_y,const S & eye_z,
00134 const S & at_x,const S & at_y,const S & at_z,
00135 const S & up_x,const S & up_y,const S & up_z);
00136
00138 void LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up);
00139
00140
00141
00142
00143
00144 void ConvertFocalToMM(S ccdwidth);
00145
00146
00147
00148
00149
00150 void RescalingWorld(S scalefactor, bool adjustIntrinsics);
00151
00153 void ApplyRigidTransformation(const Matrix44<S> & M);
00154
00156 void ApplySimilarity( Matrix44<S> M);
00157
00159 void ApplySimilarity(const Similarity<S> & Sim);
00160
00162 vcg::Point3<S> ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const;
00163
00165 vcg::Point3<S> ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const;
00166
00167
00168
00169
00170 vcg::Point3<S> ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const;
00171
00173 vcg::Point2<S> Project(const vcg::Point3<S> & p) const;
00174
00176 vcg::Point3<S> UnProject(const vcg::Point2<S> & p, const S & d) const;
00177
00178
00179
00180
00181 vcg::Point3<S> UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const;
00182
00184 S Depth(const vcg::Point3<S> & p)const;
00185
00186
00187
00188 public:
00189
00191 Matrix44<S> GetExtrinsicsToWorldMatrix() const
00192 {
00193 Matrix44<S> rotM;
00194 Extrinsics.rot.ToMatrix(rotM);
00195 return Matrix44<S>().SetTranslate(Extrinsics.tra) * rotM.transpose();
00196 }
00197
00199 Matrix44<S> GetWorldToExtrinsicsMatrix() const
00200 {
00201 Matrix44<S> rotM;
00202 Extrinsics.rot.ToMatrix(rotM);
00203 return rotM * Matrix44<S>().SetTranslate(-Extrinsics.tra) ;
00204 }
00205
00206
00207
00208
00209 void MultMatrix( vcg::Matrix44<S> m44)
00210 {
00211 Extrinsics.tra = m44 * Extrinsics.tra;
00212 m44[0][3] = m44[1][3] = m44[2][3] = 0.0;
00213 const S k = m44.GetRow3(0).Norm();
00214 Extrinsics.rot = Extrinsics.rot * m44.transpose() * (1/k);
00215 }
00216
00217
00218
00219
00220 void MultSimilarity( const Similarity<S> & s){ MultMatrix(s.Matrix());}
00221
00222 bool IsValid() const
00223 {
00224 return Intrinsics.PixelSizeMm[0]>0 && Intrinsics.PixelSizeMm[1]>0;
00225 }
00226
00227 };
00228
00229
00230
00231 template <class S, class RotationType>
00232 const vcg::Point3<S> Shot<S,RotationType>::GetViewDir() const
00233 {
00234 return Extrinsics.Rot().GetRow3(2);
00235 }
00236
00237
00238
00239
00241 template <class S, class RotationType>
00242 const vcg::Point3<S> Shot<S,RotationType>::GetViewPoint() const
00243 {
00244 return Extrinsics.tra;
00245 }
00247 template <class S, class RotationType>
00248 void Shot<S,RotationType>::SetViewPoint(const vcg::Point3<S> & viewpoint)
00249 {
00250 Extrinsics.SetTra( viewpoint );
00251 }
00252
00253
00255 template <class S, class RotationType>
00256 float Shot<S,RotationType>::GetFovFromFocal()
00257 {
00258 double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1];
00259 return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm))));
00260 }
00261
00262
00263
00265 template <class S, class RotationType>
00266 vcg::Point3<S> Shot<S,RotationType>::Axis(const int & i) const
00267 {
00268 vcg::Matrix44<S> m;
00269 Extrinsics.rot.ToMatrix(m);
00270 vcg::Point3<S> aa = m.GetRow3(i);
00271 return aa;
00272 }
00273
00275 template <class S, class RotationType>
00276 void Shot<S,RotationType>::LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
00277 {
00278 LookTowards(z_dir-GetViewPoint(),up);
00279 }
00280
00282 template <class S, class RotationType>
00283 void Shot<S,RotationType>::LookAt(const S & eye_x, const S & eye_y, const S & eye_z,
00284 const S & at_x, const S & at_y, const S & at_z,
00285 const S & up_x,const S & up_y,const S & up_z)
00286 {
00287 SetViewPoint(Point3<S>(eye_x,eye_y,eye_z));
00288 LookAt(Point3<S>(at_x,at_y,at_z),Point3<S>(up_x,up_y,up_z));
00289 }
00290
00292 template <class S, class RotationType>
00293 void Shot<S,RotationType>::LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
00294 {
00295 vcg::Point3<S> x_dir = up ^-z_dir;
00296 vcg::Point3<S> y_dir = -z_dir ^x_dir;
00297
00298 Matrix44<S> m;
00299 m.SetIdentity();
00300 *(vcg::Point3<S> *)&m[0][0] = x_dir/x_dir.Norm();
00301 *(vcg::Point3<S> *)&m[1][0] = y_dir/y_dir.Norm();
00302 *(vcg::Point3<S> *)&m[2][0] = -z_dir/z_dir.Norm();
00303
00304 Extrinsics.rot.FromMatrix(m);
00305 }
00306
00307
00308
00310 template <class S, class RotationType>
00311 vcg::Point3<S> Shot<S,RotationType>::ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const
00312 {
00313 Matrix44<S> rotM;
00314 Extrinsics.rot.ToMatrix(rotM);
00315 vcg::Point3<S> cp = rotM * (p - GetViewPoint() );
00316 cp[2]=-cp[2];
00317 return cp;
00318 }
00319
00321 template <class S, class RotationType>
00322 vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const
00323 {
00324 Matrix44<S> rotM;
00325 vcg::Point3<S> cp = p;
00326 cp[2]=-cp[2];
00327 Extrinsics.rot.ToMatrix(rotM);
00328 cp = rotM.transpose() * cp + GetViewPoint();
00329 return cp;
00330 }
00331
00333 template <class S, class RotationType>
00334 vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const
00335 {
00336 Matrix44<S> rotM;
00337 vcg::Point3<S> cp = p;
00338 cp[2]=-cp[2];
00339 Extrinsics.rot.ToMatrix(rotM);
00340 cp = Inverse(rotM) * cp + GetViewPoint();
00341 return cp;
00342 }
00343
00345 template <class S, class RotationType>
00346 vcg::Point2<S> Shot<S,RotationType>::Project(const vcg::Point3<S> & p) const
00347 {
00348 Point3<S> cp = ConvertWorldToCameraCoordinates(p);
00349 Point2<S> pp = Intrinsics.Project(cp);
00350 Point2<S> vp = Intrinsics.LocalToViewportPx(pp);
00351 return vp;
00352 }
00353
00355 template <class S, class RotationType>
00356 vcg::Point3<S> Shot<S,RotationType>::UnProject(const vcg::Point2<S> & p, const S & d) const
00357 {
00358 Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
00359 Point3<S> cp = Intrinsics.UnProject(lp,d);
00360 Point3<S> wp = ConvertCameraToWorldCoordinates(cp);
00361 return wp;
00362 }
00363
00364
00365
00366
00367 template <class S, class RotationType>
00368 vcg::Point3<S> Shot<S,RotationType>::UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const
00369 {
00370 Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
00371 Point3<S> cp = Intrinsics.UnProject(lp,d);
00372 Point3<S> wp = ConvertCameraToWorldCoordinates_Substitute(cp);
00373 return wp;
00374 }
00375
00377 template <class S, class RotationType>
00378 S Shot<S,RotationType>::Depth(const vcg::Point3<S> & p)const
00379 {
00380 return ConvertWorldToCameraCoordinates(p).Z();
00381 }
00382
00383
00384
00385
00386
00387 template <class S, class RotationType>
00388 void Shot<S, RotationType>::ConvertFocalToMM(S ccdwidth)
00389 {
00390 double ccd_width = ccdwidth;
00391 double ccd_height = (ccd_width * Intrinsics.ViewportPx[1]) / Intrinsics.ViewportPx[0];
00392 Intrinsics.PixelSizeMm[0] = (ccd_width / Intrinsics.ViewportPx[0]);
00393 Intrinsics.PixelSizeMm[1] = (ccd_height / Intrinsics.ViewportPx[1]);
00394 Intrinsics.FocalMm = (ccd_width * Intrinsics.FocalMm) / Intrinsics.ViewportPx[0];
00395 }
00396
00397
00398
00399
00400
00401 template <class S, class RotationType>
00402 void Shot<S, RotationType>::RescalingWorld(S scalefactor, bool adjustIntrinsics)
00403 {
00404
00405
00406 if (adjustIntrinsics)
00407 {
00408 Intrinsics.FocalMm = Intrinsics.FocalMm * scalefactor;
00409 double ccdwidth = static_cast<double>(Intrinsics.ViewportPx[0] * Intrinsics.PixelSizeMm[0]);
00410 double ccdheight = static_cast<double>(Intrinsics.ViewportPx[1] * Intrinsics.PixelSizeMm[1]);
00411
00412 Intrinsics.PixelSizeMm[0] = (ccdwidth * scalefactor) / Intrinsics.ViewportPx[0];
00413 Intrinsics.PixelSizeMm[1] = (ccdheight * scalefactor) / Intrinsics.ViewportPx[1];
00414 }
00415
00416
00417
00418
00419
00420
00421
00422 Extrinsics.tra *= scalefactor;
00423 }
00424
00426 template <class S, class RotationType>
00427 void Shot<S, RotationType>::ApplyRigidTransformation(const Matrix44<S> & M)
00428 {
00429 Matrix44<S> rotM;
00430 Extrinsics.rot.ToMatrix(rotM);
00431
00432 Extrinsics.tra = M * Extrinsics.tra;
00433 Matrix44<S> newRot = rotM * M.transpose();
00434 newRot[3][0] = newRot[3][1] = newRot[3][2] = 0.0;
00435
00436 Extrinsics.SetRot(newRot);
00437 }
00438
00440 template <class S, class RotationType>
00441 void Shot<S, RotationType>::ApplySimilarity( Matrix44<S> M)
00442 {
00443 Matrix44<S> rotM;
00444 Extrinsics.rot.ToMatrix(rotM);
00445
00446
00447 M = M * (1/M.ElementAt(3,3));
00448 M[3][3] = 1;
00449
00450
00451 ScalarType scalefactor = 1.0 / pow(ScalarType(M.Determinant()),1/ScalarType(3.0));
00452
00453
00454 Extrinsics.tra = M * Extrinsics.tra;
00455
00456 vcg::Matrix44<S> M2 = M;
00457
00458 M2 = M2 * scalefactor;
00459 M2[3][3] = 1.0;
00460 M2[0][3] = M2[1][3] = M2[2][3] = 0;
00461
00462 rotM = rotM * M2.transpose();
00463 Extrinsics.SetRot(rotM);
00464 }
00465
00467 template <class S, class RotationType>
00468 void Shot<S, RotationType>::ApplySimilarity(const Similarity<S> & Sm)
00469 {
00470 Matrix44<S> rotM;
00471 Extrinsics.rot.ToMatrix(rotM);
00472
00473
00474 vcg::Matrix44<S> R;
00475 Sm.rot.ToMatrix(R);
00476 vcg::Matrix44<S> T;
00477 T.SetIdentity();
00478 T.ElementAt(0,3) = Sm.tra[0];
00479 T.ElementAt(1,3) = Sm.tra[1];
00480 T.ElementAt(2,3) = Sm.tra[2];
00481 vcg::Matrix44d S44;
00482 S44.SetIdentity();
00483 S44 *= Sm.sca;
00484 S44.ElementAt(3,3) = 1.0;
00485
00486 vcg::Matrix44<S> M = T * R * S44;
00487
00488
00489 Extrinsics.tra = M * Extrinsics.tra;
00490
00491 vcg::Matrix44<S> M2 = M;
00492
00493 M2 = M2 * (1.0 / Sm.sca);
00494
00495 Extrinsics.rot = rotM * M2.transpose();
00496
00497 Extrinsics.rot.ElementAt(3,0) = 0;
00498 Extrinsics.rot.ElementAt(3,1) = 0;
00499 Extrinsics.rot.ElementAt(3,2) = 0;
00500 Extrinsics.rot.ElementAt(3,3) = 1;
00501
00502 }
00503
00504
00505
00506
00507
00508
00509 typedef Shot<float> Shotf;
00510 typedef Shot<double> Shotd;
00511
00512
00513 }
00514
00515 #endif
00516
00517
00518
00519