fix some comments about the assumption made by the Shot

This commit is contained in:
Massimiliano Corsini 2011-05-19 08:46:38 +00:00
parent c35b1c84ff
commit 9349591548
1 changed files with 166 additions and 158 deletions

View File

@ -94,23 +94,31 @@ creation
****************************************************************************/ ****************************************************************************/
/** class Shot /** class Shot
The shot is made of two things:
* the Instrinsics paramaters, which are stored as a Camera type (check vcg/math/camera) and that Shot is made of two elements:
* the Instrinsics paramaters, which are stored as a Camera type (see vcg/math/camera) and that
determines how a point in the frame of the camera is projected in the 2D projection plane determines how a point in the frame of the camera is projected in the 2D projection plane
* the Extrinsics parameters, which are stored in the class Shot (che the type ReferenceFrame) * the Extrinsics parameters, which are stored in the class Shot (type ReferenceFrame)
and that tell viewpoint and view direction. and that describe viewpoint and view direction.
The Extrinsics parameters are kept as a rotation matrix "rot" and a translation vector "tra" Some important notes about the usage of this class:
NOTE: the translation matrix "tra" corresponds to -viewpoint while the rotation matrix
"rot" corresponds to the axis of the reference frame by row, i.e.
rot[0][0|1|2] == X axis
rot[1][0|1|2] == Y axis
rot[2][0|1|2] == Z axis
It follows that the matrix made with the upper left 3x3 equal to rot and the 4th colum equal to tra * The World coordinates system is assumed to be RIGHT-HANDED.
and (0,0,0,1) in the bottom row transform a point from world coordiantes to the reference frame * The Shot reference frame is assumed to be RIGHT-HANDED.
of the shot. * The associated Camera is assumed to point in the negative direction of the Z axis of the Shot coordinates system (reference frame).
As a consequence, the Camera coordinates system is LEFT-HANDED.
* The Extrinsics parameters are kept as a rotation matrix "rot" and a translation vector "tra"
The translation matrix "tra" corresponds to the viewpoint of the Shot while the rotation matrix
"rot" corresponds to the axis of the reference frame by row, i.e.
rot[0][0|1|2] == X axis
rot[1][0|1|2] == Y axis
rot[2][0|1|2] == Z axis
It follows that the matrix made with the upper left 3x3 equal to rot and the 4th colum equal to tra
and (0,0,0,1) in the bottom row transform a point from world coordiantes to the reference frame
of the shot.
@ -129,129 +137,129 @@ namespace vcg{
template <class S, class RotationType = Matrix44<S> > template <class S, class RotationType = Matrix44<S> >
class Shot { class Shot {
public: public:
typedef Camera<S> CameraType; typedef Camera<S> CameraType;
typedef S ScalarType; typedef S ScalarType;
template <class ScalarType, class RotoType > template <class ScalarType, class RotoType >
class ReferenceFrame { class ReferenceFrame {
friend class Shot<ScalarType, RotoType>; friend class Shot<ScalarType, RotoType>;
RotoType rot; // rotation RotoType rot; // rotation
Point3<S> tra; // viewpoint Point3<S> tra; // viewpoint
public: public:
void SetIdentity(){ rot.SetIdentity(); tra = Point3<S>(0.0,0.0,0.0);} void SetIdentity(){ rot.SetIdentity(); tra = Point3<S>(0.0,0.0,0.0);}
void SetTra(const Point3<S> & tr) {tra = tr;} void SetTra(const Point3<S> & tr) {tra = tr;}
void SetRot(const RotoType & rt) {rot = rt;} void SetRot(const RotoType & rt) {rot = rt;}
Point3<ScalarType> Tra() const { return tra;} Point3<ScalarType> Tra() const { return tra;}
RotoType Rot() const { return rot;} RotoType Rot() const { return rot;}
}; };
Camera<S> Intrinsics; // the camera that made the shot Camera<S> Intrinsics; // the camera that made the shot
ReferenceFrame<S,RotationType> Extrinsics; // the position and orientation of the camera ReferenceFrame<S,RotationType> Extrinsics; // the position and orientation of the camera
Shot(Camera<S> c) Shot(Camera<S> c)
{ {
Intrinsics = c; Intrinsics = c;
Extrinsics.SetIdentity(); Extrinsics.SetIdentity();
} }
Shot() Shot()
{ {
Extrinsics.SetIdentity(); Extrinsics.SetIdentity();
} }
/// GET the i-th axis of the coordinate system of the camera /// GET the i-th axis of the coordinate system of the camera
vcg::Point3<S> Axis(const int & i)const; vcg::Point3<S> Axis(const int & i)const;
/// GET the viewdir /// GET the viewdir
const vcg::Point3<S> GetViewDir()const; const vcg::Point3<S> GetViewDir()const;
/// GET the viewpoint /// GET the viewpoint
const vcg::Point3<S> GetViewPoint()const; const vcg::Point3<S> GetViewPoint()const;
/// SET the viewpoint /// SET the viewpoint
void SetViewPoint(const vcg::Point3<S> & viewpoint); void SetViewPoint(const vcg::Point3<S> & viewpoint);
/// GET fov from focal /// GET fov from focal
float GetFovFromFocal(); float GetFovFromFocal();
/// look at (point+up) /// look at (point+up)
void LookAt(const vcg::Point3<S> & point,const vcg::Point3<S> & up); void LookAt(const vcg::Point3<S> & point,const vcg::Point3<S> & up);
/// look at (opengl-like) /// look at (opengl-like)
void LookAt(const S & eye_x,const S & eye_y,const S & eye_z, void LookAt(const S & eye_x,const S & eye_y,const S & eye_z,
const S & at_x,const S & at_y,const S & at_z, const S & at_x,const S & at_y,const S & at_z,
const S & up_x,const S & up_y,const S & up_z); const S & up_x,const S & up_y,const S & up_z);
/// look towards (dir+up) /// look towards (dir+up)
void LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up); void LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up);
/// convert a 3d point from world to camera coordinates /// convert a 3d point from world to camera coordinates (do not confuse with the Shot reference frame)
vcg::Point3<S> ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const; vcg::Point3<S> ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const;
/// convert a 3d point from camera to world coordinates /// convert a 3d point from camera (do not confuse with the Shot reference frame) to world coordinates
vcg::Point3<S> ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const; vcg::Point3<S> ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const;
/// convert a 3d point from camera to world coordinates, uses inverse instead of trranspose /* convert a 3d point from camera (do not confuse with the Shot reference frame) to world coordinates
/// for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia) * it uses inverse instead of transpose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
vcg::Point3<S> ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const; */
vcg::Point3<S> ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const;
/// project a 3d point from world coordinates to 2d camera viewport (pixel) /// project a 3d point from world coordinates to 2d camera viewport (the value returned is in pixels)
vcg::Point2<S> Project(const vcg::Point3<S> & p) const; vcg::Point2<S> Project(const vcg::Point3<S> & p) const;
/// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates /// inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the projected point)
vcg::Point3<S> UnProject(const vcg::Point2<S> & p, const S & d) const; vcg::Point3<S> UnProject(const vcg::Point2<S> & p, const S & d) const;
/// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates, uses inverse instead of trranspose /* inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the projected point)
/// for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia) * uses inverse instead of trranspose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
vcg::Point3<S> UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const; */
vcg::Point3<S> UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const;
/// returns distance of point p from camera plane (z depth), used for unprojection /// returns the distance of point p from camera plane (z depth), required for unprojection operation
S Depth(const vcg::Point3<S> & p)const; S Depth(const vcg::Point3<S> & p)const;
// accessors // accessors
public: public:
/* Returns the matrix M such that /* Returns the matrix M such that
3dpoint_in_world_coordinates = M * 3dpoint_in_local_coordinates 3dpoint_in_world_coordinates = M * 3dpoint_in_local_coordinates
*/ */
Matrix44<S> GetExtrinsicsToWorldMatrix() const { Matrix44<S> GetExtrinsicsToWorldMatrix() const {
Matrix44<S> rotM ; Matrix44<S> rotM ;
Extrinsics.rot.ToMatrix(rotM); Extrinsics.rot.ToMatrix(rotM);
return Matrix44<S>().SetTranslate(Extrinsics.tra) * rotM.transpose(); return Matrix44<S>().SetTranslate(Extrinsics.tra) * rotM.transpose();
} }
/* Returns the matrix M such that /* Returns the matrix M such that
3dpoint_in_local_coordinates = M * 3dpoint_in_world_coordinates 3dpoint_in_local_coordinates = M * 3dpoint_in_world_coordinates
*/ */
Matrix44<S> GetWorldToExtrinsicsMatrix() const { Matrix44<S> GetWorldToExtrinsicsMatrix() const {
Matrix44<S> rotM ; Matrix44<S> rotM ;
Extrinsics.rot.ToMatrix(rotM); Extrinsics.rot.ToMatrix(rotM);
return rotM * Matrix44<S>().SetTranslate(-Extrinsics.tra) ; return rotM * Matrix44<S>().SetTranslate(-Extrinsics.tra) ;
} }
/* multiply the current reference frame for the matrix passed /* multiply the current reference frame for the matrix passed
note: it is up to the caller to check the the matrix passed is a pure rototraslation note: it is up to the caller to check the the matrix passed is a pure rototraslation
the matrix can have a scaling component, but is assumed uniform over the rows */
*/
void MultMatrix( vcg::Matrix44<S> m44) void MultMatrix( vcg::Matrix44<S> m44)
{ {
Extrinsics.tra = m44 * Extrinsics.tra; Extrinsics.tra = m44 * Extrinsics.tra;
m44[0][3] = m44[1][3] = m44[2][3] = 0.0; //set no translation m44[0][3] = m44[1][3] = m44[2][3] = 0.0; //set no translation
const S k = m44.GetRow3(0).Norm(); //compute scaling (assumed uniform) const S k = m44.GetRow3(0).Norm(); //compute scaling (assumed uniform)
Extrinsics.rot = Extrinsics.rot * m44.transpose() * (1/k); Extrinsics.rot = Extrinsics.rot * m44.transpose() * (1/k);
Extrinsics.rot.ElementAt(3,3)=S(1.0); //fix back after scaling
} }
/* multiply the current reference frame for the similarity passed /* multiply the current reference frame for the similarity passed
note: it is up to the caller to check the the matrix passed is a pure rototraslation note: it is up to the caller to check the the matrix passed is a pure rototraslation
*/ */
void MultSimilarity( const Similarity<S> & s){ MultMatrix(s.Matrix());} void MultSimilarity( const Similarity<S> & s){ MultMatrix(s.Matrix());}
bool IsValid() const bool IsValid() const
{ {
return Intrinsics.PixelSizeMm[0]>0 && Intrinsics.PixelSizeMm[1]>0; return Intrinsics.PixelSizeMm[0]>0 && Intrinsics.PixelSizeMm[1]>0;
} }
}; // end class definition }; // end class definition
@ -270,13 +278,13 @@ const vcg::Point3<S> Shot<S,RotationType>::GetViewDir() const
template <class S, class RotationType> template <class S, class RotationType>
const vcg::Point3<S> Shot<S,RotationType>::GetViewPoint() const const vcg::Point3<S> Shot<S,RotationType>::GetViewPoint() const
{ {
return Extrinsics.tra; return Extrinsics.tra;
} }
/// SET the viewpoint /// SET the viewpoint
template <class S, class RotationType> template <class S, class RotationType>
void Shot<S,RotationType>::SetViewPoint(const vcg::Point3<S> & viewpoint) void Shot<S,RotationType>::SetViewPoint(const vcg::Point3<S> & viewpoint)
{ {
Extrinsics.SetTra( viewpoint ); Extrinsics.SetTra( viewpoint );
} }
//--- //---
@ -284,8 +292,8 @@ void Shot<S,RotationType>::SetViewPoint(const vcg::Point3<S> & viewpoint)
template <class S, class RotationType> template <class S, class RotationType>
float Shot<S,RotationType>::GetFovFromFocal() float Shot<S,RotationType>::GetFovFromFocal()
{ {
double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1]; double viewportYMm= Intrinsics.PixelSizeMm[1]* Intrinsics.ViewportPx[1];
return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm)))); return 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*Intrinsics.FocalMm))));
} }
//--- //---
@ -294,119 +302,119 @@ float Shot<S,RotationType>::GetFovFromFocal()
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::Axis(const int & i) const vcg::Point3<S> Shot<S,RotationType>::Axis(const int & i) const
{ {
vcg::Matrix44<S> m; vcg::Matrix44<S> m;
Extrinsics.rot.ToMatrix(m); Extrinsics.rot.ToMatrix(m);
vcg::Point3<S> aa = m.GetRow3(i); vcg::Point3<S> aa = m.GetRow3(i);
return aa; return aa;
} }
/// look at (point+up) /// look at (point+up)
template <class S, class RotationType> template <class S, class RotationType>
void Shot<S,RotationType>::LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up) void Shot<S,RotationType>::LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
{ {
LookTowards(z_dir-GetViewPoint(),up); LookTowards(z_dir-GetViewPoint(),up);
} }
/// look at (opengl-like) /// look at (opengl-like)
template <class S, class RotationType> template <class S, class RotationType>
void Shot<S,RotationType>::LookAt(const S & eye_x, const S & eye_y, const S & eye_z, void Shot<S,RotationType>::LookAt(const S & eye_x, const S & eye_y, const S & eye_z,
const S & at_x, const S & at_y, const S & at_z, const S & at_x, const S & at_y, const S & at_z,
const S & up_x,const S & up_y,const S & up_z) const S & up_x,const S & up_y,const S & up_z)
{ {
SetViewPoint(Point3<S>(eye_x,eye_y,eye_z)); SetViewPoint(Point3<S>(eye_x,eye_y,eye_z));
LookAt(Point3<S>(at_x,at_y,at_z),Point3<S>(up_x,up_y,up_z)); LookAt(Point3<S>(at_x,at_y,at_z),Point3<S>(up_x,up_y,up_z));
} }
/// look towards /// look towards
template <class S, class RotationType> template <class S, class RotationType>
void Shot<S,RotationType>::LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up) void Shot<S,RotationType>::LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up)
{ {
vcg::Point3<S> x_dir = up ^-z_dir; vcg::Point3<S> x_dir = up ^-z_dir;
vcg::Point3<S> y_dir = -z_dir ^x_dir; vcg::Point3<S> y_dir = -z_dir ^x_dir;
Matrix44<S> m; Matrix44<S> m;
m.SetIdentity(); m.SetIdentity();
*(vcg::Point3<S> *)&m[0][0] = x_dir/x_dir.Norm(); *(vcg::Point3<S> *)&m[0][0] = x_dir/x_dir.Norm();
*(vcg::Point3<S> *)&m[1][0] = y_dir/y_dir.Norm(); *(vcg::Point3<S> *)&m[1][0] = y_dir/y_dir.Norm();
*(vcg::Point3<S> *)&m[2][0] = -z_dir/z_dir.Norm(); *(vcg::Point3<S> *)&m[2][0] = -z_dir/z_dir.Norm();
Extrinsics.rot.FromMatrix(m); Extrinsics.rot.FromMatrix(m);
} }
//--- Space transformation methods //--- Space transformation methods
/// convert a 3d point from world to camera coordinates /// convert a 3d point from world to camera coordinates (do not confuse with the Shot reference frame)
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const vcg::Point3<S> Shot<S,RotationType>::ConvertWorldToCameraCoordinates(const vcg::Point3<S> & p) const
{ {
Matrix44<S> rotM; Matrix44<S> rotM;
Extrinsics.rot.ToMatrix(rotM); Extrinsics.rot.ToMatrix(rotM);
vcg::Point3<S> cp = rotM * (p - GetViewPoint() ); vcg::Point3<S> cp = rotM * (p - GetViewPoint() );
cp[2]=-cp[2]; // note: camera reference system is right handed cp[2]=-cp[2];
return cp; return cp;
} }
/// convert a 3d point from camera to world coordinates /// convert a 3d point from camera coordinates (do not confuse with the Shot reference frame) to world coordinates
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates(const vcg::Point3<S> & p) const
{ {
Matrix44<S> rotM; Matrix44<S> rotM;
vcg::Point3<S> cp = p; vcg::Point3<S> cp = p;
cp[2]=-cp[2]; // note: World reference system is left handed cp[2]=-cp[2];
Extrinsics.rot.ToMatrix(rotM); Extrinsics.rot.ToMatrix(rotM);
cp = rotM.transpose() * cp + GetViewPoint(); cp = rotM.transpose() * cp + GetViewPoint();
return cp; return cp;
} }
/// convert a 3d point from camera to world coordinates, uses inverse instead of trranspose /// convert a 3d point from camera to world coordinates, uses inverse instead of trranspose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
/// for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const vcg::Point3<S> Shot<S,RotationType>::ConvertCameraToWorldCoordinates_Substitute(const vcg::Point3<S> & p) const
{ {
Matrix44<S> rotM; Matrix44<S> rotM;
vcg::Point3<S> cp = p; vcg::Point3<S> cp = p;
cp[2]=-cp[2]; // note: World reference system is left handed cp[2]=-cp[2];
Extrinsics.rot.ToMatrix(rotM); Extrinsics.rot.ToMatrix(rotM);
cp = Inverse(rotM) * cp + GetViewPoint(); // use invert istead of transpose to dela with non-rigid cases cp = Inverse(rotM) * cp + GetViewPoint();
return cp; return cp;
} }
/// project a 3d point from world coordinates to 2d camera viewport (pixel) /// project a 3d point from world coordinates to 2d camera viewport (the value returned is in pixel)
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point2<S> Shot<S,RotationType>::Project(const vcg::Point3<S> & p) const vcg::Point2<S> Shot<S,RotationType>::Project(const vcg::Point3<S> & p) const
{ {
Point3<S> cp = ConvertWorldToCameraCoordinates(p); Point3<S> cp = ConvertWorldToCameraCoordinates(p);
Point2<S> pp = Intrinsics.Project(cp); Point2<S> pp = Intrinsics.Project(cp);
Point2<S> vp = Intrinsics.LocalToViewportPx(pp); Point2<S> vp = Intrinsics.LocalToViewportPx(pp);
return vp; return vp;
} }
/// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates /// inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the point to unproject)
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::UnProject(const vcg::Point2<S> & p, const S & d) const vcg::Point3<S> Shot<S,RotationType>::UnProject(const vcg::Point2<S> & p, const S & d) const
{ {
Point2<S> lp = Intrinsics.ViewportPxToLocal(p); Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
Point3<S> cp = Intrinsics.UnProject(lp,d); Point3<S> cp = Intrinsics.UnProject(lp,d);
Point3<S> wp = ConvertCameraToWorldCoordinates(cp); Point3<S> wp = ConvertCameraToWorldCoordinates(cp);
return wp; return wp;
} }
/// inverse projection from 2d camera viewport (pixel) + Zdepth to 3d world coordinates, uses inverse instead of trranspose /* inverse projection from 2d camera viewport (in pixels) to 3d world coordinates (it requires the original depth of the projected point)
/// for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia) * uses inverse instead of trranspose for non-exactly-rigid rotation matrices (such as calculated by tsai and garcia)
*/
template <class S, class RotationType> template <class S, class RotationType>
vcg::Point3<S> Shot<S,RotationType>::UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const vcg::Point3<S> Shot<S,RotationType>::UnProject_Substitute(const vcg::Point2<S> & p, const S & d) const
{ {
Point2<S> lp = Intrinsics.ViewportPxToLocal(p); Point2<S> lp = Intrinsics.ViewportPxToLocal(p);
Point3<S> cp = Intrinsics.UnProject(lp,d); Point3<S> cp = Intrinsics.UnProject(lp,d);
Point3<S> wp = ConvertCameraToWorldCoordinates_Substitute(cp); Point3<S> wp = ConvertCameraToWorldCoordinates_Substitute(cp);
return wp; return wp;
} }
/// returns distance of point p from camera plane (z depth), used for unprojection /// returns the distance of point p from camera plane (z depth), required for unprojection operation
template <class S, class RotationType> template <class S, class RotationType>
S Shot<S,RotationType>::Depth(const vcg::Point3<S> & p)const S Shot<S,RotationType>::Depth(const vcg::Point3<S> & p)const
{ {
return ConvertWorldToCameraCoordinates(p).Z(); return ConvertWorldToCameraCoordinates(p).Z();
} }