projection.cpp

00001 
00002 /* Copyright (c) 2007-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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     //const float newWidth_2 = ratio * distance * tanf(DEG2RAD( .5f * fov[1] ));
00043     //fov[1] = 2.f * atanf( newWidth_2 / distance );
00044     // -> distance can be removed:
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     // see resizeHorizontal
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 }
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8