projection.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "projection.h"
00019 #include "wall.h"
00020 #include <eq/base/log.h>
00021
00022 using namespace eq::base;
00023 using namespace std;
00024
00025 #define DEG2RAD( angle ) ((angle) * static_cast<float>(M_PI) / 180.f)
00026 #define RAD2DEG( angle ) ((angle) * 180.f / static_cast<float>(M_PI))
00027
00028 namespace eq
00029 {
00030 Projection::Projection()
00031 : origin( 0.f, 0.f, 0.f ),
00032 distance( 1.f ),
00033 fov( 77.3196f, 53.1301f ),
00034 hpr( 0.f, 0.f, 0.f )
00035 {}
00036
00037 void Projection::resizeHorizontal( const float ratio )
00038 {
00039 if( ratio == 1.f || ratio < 0.f )
00040 return;
00041
00042
00043
00044
00045 fov[0] = RAD2DEG( 2.f * atanf( ratio * tanf( DEG2RAD( .5f * fov[0] ))));
00046 }
00047
00048 void Projection::resizeVertical( const float ratio )
00049 {
00050 if( ratio == 1.f || ratio < 0.f )
00051 return;
00052
00053
00054 fov[1] = RAD2DEG( 2.f * atanf( ratio * tanf( DEG2RAD( .5f * fov[1] ))));
00055 }
00056
00057 Projection& Projection::operator = ( const Wall& wall )
00058 {
00059 Vector3f u = wall.bottomRight - wall.bottomLeft;
00060 Vector3f v = wall.topLeft - wall.bottomLeft;
00061 const float width = u.normalize();
00062 const float height = v.normalize();
00063
00064 Vector3f w;
00065 w.cross( u, v );
00066
00067 const Vector3f center((wall.bottomRight[0] + wall.topLeft[0]) * 0.5f,
00068 (wall.bottomRight[1] + wall.topLeft[1]) * 0.5f,
00069 (wall.bottomRight[2] + wall.topLeft[2]) * 0.5f);
00070
00071 if ( distance <= std::numeric_limits< float >::epsilon( ))
00072 distance = center.length();
00073
00074 Matrix3f mat;
00075 mat.array[0] = u[0];
00076 mat.array[1] = u[1];
00077 mat.array[2] = u[2];
00078
00079 mat.array[3] = v[0];
00080 mat.array[4] = v[1];
00081 mat.array[5] = v[2];
00082
00083 mat.array[6] = w[0];
00084 mat.array[7] = w[1];
00085 mat.array[8] = w[2];
00086
00087 fov[0] = RAD2DEG( atanf(0.5f * width / distance )) * 2.0f;
00088 fov[1] = RAD2DEG( atanf(0.5f * height / distance )) * 2.0f;
00089
00090 hpr[0] = -asinf( mat.array[2] );
00091 const float cosH = cosf(hpr[0]);
00092 hpr[0] = RAD2DEG(hpr[0]);
00093
00094 if( fabs( cosH ) > std::numeric_limits< float >::epsilon( ))
00095 {
00096 float tr_x = mat.array[8] / cosH;
00097 float tr_y = -mat.array[5] / cosH;
00098 hpr[1] = RAD2DEG( atan2f( tr_y, tr_x ));
00099
00100 tr_x = mat.array[0] / cosH;
00101 tr_y = -mat.array[1] / cosH;
00102 hpr[2] = RAD2DEG( atan2f( tr_y, tr_x ));
00103 }
00104 else
00105 {
00106 hpr[1] = 0.f;
00107
00108 const float tr_x = mat.array[4];
00109 const float tr_y = mat.array[3];
00110
00111 hpr[2] = RAD2DEG( atan2f( tr_y, tr_x ));
00112 }
00113
00114 origin = center - w * distance;
00115 return *this;
00116 }
00117
00118 bool Projection::operator == ( const Projection& rhs ) const
00119 {
00120 return( origin.equals( rhs.origin, 0.0001f ) &&
00121 (abs( distance - rhs.distance ) < 0.0001f ) &&
00122 fov.equals( rhs.fov, 0.0001f ) &&
00123 hpr.equals( rhs.hpr, 0.0001f ));
00124 }
00125
00126 bool Projection::operator != ( const Projection& rhs ) const
00127 {
00128 return ( !origin.equals( rhs.origin, 0.0001f ) ||
00129 (abs(distance - rhs.distance) >= 0.0001f ) ||
00130 !fov.equals( rhs.fov, 0.0001f ) ||
00131 !hpr.equals( rhs.hpr, 0.0001f ));
00132 }
00133
00134
00135 ostream& operator << ( ostream& os, const Projection& projection )
00136 {
00137 os << "projection" << endl;
00138 os << "{" << endl << indent;
00139 os << "origin " << projection.origin << endl;
00140 os << "distance " << projection.distance << endl;
00141 os << "fov " << projection.fov << endl;
00142 os << "hpr " << projection.hpr << endl;
00143 os << exdent << "}";
00144 return os;
00145 }
00146
00147 }