vcglib/vcg/math/shot.h

260 lines
8.5 KiB
C++

/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.18 2005/12/12 16:53:43 callieri
corrected UnProject, it's necessary also a ZDepth value to perform inverse projection
Revision 1.17 2005/12/07 10:57:52 callieri
added commodity function ProjectWorldtoViewport() to obtain directly pixel indices without calling two separate function of two different objects
Revision 1.16 2005/12/02 16:14:35 callieri
in Shot<S>::Axis changed Row3 to GetRow3 . row3 was the old method name of Matrix44
Revision 1.15 2005/12/01 01:03:37 cignoni
Removed excess ';' from end of template functions, for gcc compiling
Revision 1.14 2005/11/23 14:18:35 ganovelli
added access to similarity (just for symmetry with Camera() )
Revision 1.13 2005/11/23 11:58:52 ganovelli
Empty constructor added, untemplated class Shotf and Shotd added
usage: Shotf myShot;
corrected member access rights
Revision 1.12 2005/07/11 13:12:35 cignoni
small gcc-related compiling issues (typenames,ending cr, initialization order)
Revision 1.11 2005/01/22 11:20:20 ponchio
<...Point3.h> -> <...point3.h>
Revision 1.10 2005/01/05 13:26:15 ganovelli
corretto cambiamento di sistema di rif.
Revision 1.9 2004/12/15 18:45:50 tommyfranken
*** empty log message ***
Revision 1.4 2004/10/07 14:41:31 fasano
Little fix on ViewPoint() method
Revision 1.3 2004/10/07 14:24:53 ganovelli
added LookAt,LookToward
Revision 1.2 2004/10/05 19:04:25 ganovelli
version 5-10-2004 in progress
Revision 1.1 2004/09/15 22:58:05 ganovelli
re-creation
Revision 1.2 2004/09/06 21:41:30 ganovelli
*** empty log message ***
Revision 1.1 2004/09/03 13:01:51 ganovelli
creation
****************************************************************************/
#ifndef __VCGLIB_SHOT
#define __VCGLIB_SHOT
// #include <vector>
// #include <vcg/Matrix44.h>
// #include <vcg/Box3.h>
#include <vcg/space/point2.h>
#include <vcg/space/point3.h>
#include <vcg/math/similarity.h>
#include <vcg/math/camera.h>
namespace vcg{
template <class S>
class Shot {
public:
typedef Camera<S> CameraType;
typedef S ScalarType;
protected:
enum {
NOTVALID_BIT = 0x1,
CREATED_EMPTY= 0x2
};
char flags;
Camera<S> & camera; // the camera that shot
vcg::Similarity<S,vcg::Matrix44<S> > similarity; // the position from where it did it
public:
Shot( Camera<S> & c):camera(c){similarity.SetIdentity();flags=0;}
Shot():camera(*new vcg::Camera<S>()){similarity.SetIdentity();flags|=CREATED_EMPTY;}
~Shot(){if(flags&CREATED_EMPTY) delete &camera;}
bool IsValid(){ return (flags& NOTVALID_BIT)==0;}
void SetValid(bool v){ if(!v) flags|=NOTVALID_BIT; else flags&=~NOTVALID_BIT;}
Camera<S> & Camera(){return camera;};
/// access to similarity
vcg::Similarity<S,vcg::Matrix44<S> > & Similarity(){return similarity;}
/// take the i-th axis of the coordinate system of the camera
vcg::Point3<S> Axis(const int & i)const;
/// take the viewpoint
const vcg::Point3<S> ViewPoint()const;
/// set the viewpoint
void SetViewPoint(const vcg::Point3<S> & viewpoint);
/// look at
void LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up);
/// look at (same as opengl)
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 & up_x,const S & up_y,const S & up_z);
/// look towards
void LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up);
/// convert a 3d point in camera coordinates
vcg::Point3<S> ConvertToCameraCoordinates(const vcg::Point3<S> & p) const;
/// convert a 3d point in camera coordinates
vcg::Point3<S> ConvertToWorldCoordinates(const vcg::Point3<S> & p) const;
/// project onto the camera plane
vcg::Point2<S> Project(const vcg::Point3<S> & p) const;
/// inverse projection from camera plane + Zdepth to original 3D
vcg::Point3<S> UnProject(const vcg::Point2<S> & p, const S & d) const;
/// take the distance from the point p and the plane parallel to the camera plane and passing through the view
/// point. The would be z depth
S Depth(const vcg::Point3<S> & p)const;
/// project a 3d point from 3D WORLD to 2D VIEWPORT
vcg::Point2<S> ProjectWorldtoViewport(const vcg::Point3<S> & p) const;
}; // end class definition
template <class S>
const vcg::Point3<S> Shot<S>::ViewPoint() const {
//Matrix44<S> m = similarity.Matrix();
//return Point3<S>(m[0][3],m[1][3],m[2][3]);
return -similarity.tra;
}
template <class S>
vcg::Point3<S> Shot<S>::Axis(const int & i) const {
vcg::Matrix44<S> m;
similarity.rot.ToMatrix(m);
vcg::Point3<S> aa = m.GetRow3(i);
return aa;
}
template <class S>
void Shot<S>::SetViewPoint(const vcg::Point3<S> & viewpoint){
similarity.tra = -viewpoint;
}
template <class S>
void Shot<S>::LookAt(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up){
LookTowards(z_dir-ViewPoint(),up);
}
template <class S>
void Shot<S>::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 & up_x,const S & up_y,const S & up_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));
}
template <class S>
void Shot<S>::LookTowards(const vcg::Point3<S> & z_dir,const vcg::Point3<S> & up){
vcg::Point3<S> x_dir = up ^-z_dir ;
vcg::Point3<S> y_dir = -z_dir ^x_dir ;
Matrix44<S> m;
m.SetIdentity();
*(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[2][0] = -z_dir/z_dir.Norm();
similarity.rot.FromMatrix(m);
}
template <class S>
vcg::Point3<S> Shot<S>::ConvertToCameraCoordinates(const vcg::Point3<S> & p) const{
Matrix44<S> rotM;
similarity.rot.ToMatrix(rotM);
vcg::Point3<S> cp = rotM * (p+similarity.tra);
// note: the camera reference system is right handed
cp[2]=-cp[2];
return cp;
}
template <class S>
vcg::Point3<S> Shot<S>::ConvertToWorldCoordinates(const vcg::Point3<S> & p) const{
Matrix44<S> rotM;
vcg::Point3<S> cp = p;
// note: the World reference system is left handed
cp[2]=-cp[2];
similarity.rot.ToMatrix(rotM);
cp = Inverse(rotM) * cp-similarity.tra;
return cp;
}
template <class S>
vcg::Point2<S> Shot<S>::Project(const vcg::Point3<S> & p) const{
return camera.Project(ConvertToCameraCoordinates(p));
}
template <class S>
vcg::Point3<S> Shot<S>::UnProject(const vcg::Point2<S> & p, const S & d) const{
Point2<S> tp = camera.ViewportToLocal(p);
vcg::Point3<S> q = camera.UnProject(tp, d);
return ConvertToWorldCoordinates(q);
}
template <class S>
S Shot<S>::Depth(const vcg::Point3<S> & p)const {
return ConvertToCameraCoordinates(p).Z();
}
template <class S>
vcg::Point2<S> Shot<S>::ProjectWorldtoViewport(const vcg::Point3<S> & p)const
{
return camera.LocalToViewport( camera.Project( ConvertToCameraCoordinates(p) ) );
}
class Shotf: public Shot<float>{};
class Shotd: public Shot<double>{};
} // end name space
#endif