PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/3rdparty/ilmbase-1.0.2/ImathFrame.h
00001 
00002 //
00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
00004 // Digital Ltd. LLC
00005 // 
00006 // All rights reserved.
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are
00010 // met:
00011 // *       Redistributions of source code must retain the above copyright
00012 // notice, this list of conditions and the following disclaimer.
00013 // *       Redistributions in binary form must reproduce the above
00014 // copyright notice, this list of conditions and the following disclaimer
00015 // in the documentation and/or other materials provided with the
00016 // distribution.
00017 // *       Neither the name of Industrial Light & Magic nor the names of
00018 // its contributors may be used to endorse or promote products derived
00019 // from this software without specific prior written permission. 
00020 // 
00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 //
00034 
00035 
00036 
00037 #ifndef INCLUDED_IMATHFRAME_H
00038 #define INCLUDED_IMATHFRAME_H
00039 
00040 namespace Imath {
00041 
00042 template<class T> class Vec3;
00043 template<class T> class Matrix44;
00044 
00045 //
00046 //  These methods compute a set of reference frames, defined by their
00047 //  transformation matrix, along a curve. It is designed so that the 
00048 //  array of points and the array of matrices used to fetch these routines 
00049 //  don't need to be ordered as the curve.
00050 //  
00051 //  A typical usage would be :
00052 //
00053 //      m[0] = Imath::firstFrame( p[0], p[1], p[2] );
00054 //      for( int i = 1; i < n - 1; i++ )
00055 //      {
00056 //          m[i] = Imath::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] );
00057 //      }
00058 //      m[n-1] = Imath::lastFrame( m[n-2], p[n-2], p[n-1] );
00059 //
00060 //  See Graphics Gems I for the underlying algorithm.
00061 // 
00062 
00063 template<class T> Matrix44<T> firstFrame( const Vec3<T>&,    // First point
00064                                           const Vec3<T>&,    // Second point 
00065                                           const Vec3<T>& );  // Third point
00066 
00067 template<class T> Matrix44<T> nextFrame( const Matrix44<T>&, // Previous matrix
00068                                          const Vec3<T>&,     // Previous point
00069                                          const Vec3<T>&,     // Current point
00070                                          Vec3<T>&,           // Previous tangent
00071                                          Vec3<T>& );         // Current tangent
00072 
00073 template<class T> Matrix44<T> lastFrame( const Matrix44<T>&, // Previous matrix
00074                                          const Vec3<T>&,     // Previous point
00075                                          const Vec3<T>& );   // Last point
00076 
00077 //
00078 //  firstFrame - Compute the first reference frame along a curve.
00079 //
00080 //  This function returns the transformation matrix to the reference frame
00081 //  defined by the three points 'pi', 'pj' and 'pk'. Note that if the two
00082 //  vectors <pi,pj> and <pi,pk> are colinears, an arbitrary twist value will
00083 //  be choosen.
00084 //
00085 //  Throw 'NullVecExc' if 'pi' and 'pj' are equals.
00086 //
00087 
00088 template<class T> Matrix44<T> firstFrame
00089 ( 
00090     const Vec3<T>& pi,             // First point
00091     const Vec3<T>& pj,             // Second point
00092     const Vec3<T>& pk )            // Third point
00093 {
00094     Vec3<T> t = pj - pi; t.normalizeExc();
00095 
00096     Vec3<T> n = t.cross( pk - pi ); n.normalize();
00097     if( n.length() == 0.0f )
00098     {
00099         int i = fabs( t[0] ) < fabs( t[1] ) ? 0 : 1;
00100         if( fabs( t[2] ) < fabs( t[i] )) i = 2;
00101 
00102         Vec3<T> v( 0.0, 0.0, 0.0 ); v[i] = 1.0;
00103         n = t.cross( v ); n.normalize();
00104     }
00105 
00106     Vec3<T> b = t.cross( n );
00107 
00108     Matrix44<T> M;
00109 
00110     M[0][0] =  t[0]; M[0][1] =  t[1]; M[0][2] =  t[2]; M[0][3] = 0.0,
00111     M[1][0] =  n[0]; M[1][1] =  n[1]; M[1][2] =  n[2]; M[1][3] = 0.0,
00112     M[2][0] =  b[0]; M[2][1] =  b[1]; M[2][2] =  b[2]; M[2][3] = 0.0,
00113     M[3][0] = pi[0]; M[3][1] = pi[1]; M[3][2] = pi[2]; M[3][3] = 1.0;
00114 
00115     return M;
00116 }
00117 
00118 //
00119 //  nextFrame - Compute the next reference frame along a curve.
00120 //
00121 //  This function returns the transformation matrix to the next reference 
00122 //  frame defined by the previously computed transformation matrix and the
00123 //  new point and tangent vector along the curve.
00124 //
00125 
00126 template<class T> Matrix44<T> nextFrame
00127 ( 
00128     const Matrix44<T>&  Mi,             // Previous matrix
00129     const Vec3<T>&      pi,             // Previous point
00130     const Vec3<T>&      pj,             // Current point
00131     Vec3<T>&            ti,             // Previous tangent vector
00132     Vec3<T>&            tj )            // Current tangent vector
00133 {
00134     Vec3<T> a(0.0, 0.0, 0.0);           // Rotation axis.
00135     T r = 0.0;                          // Rotation angle.
00136 
00137     if( ti.length() != 0.0 && tj.length() != 0.0 )
00138     {
00139         ti.normalize(); tj.normalize();
00140         T dot = ti.dot( tj ); 
00141 
00142         //
00143         //  This is *really* necessary :
00144         //
00145 
00146         if( dot > 1.0 ) dot = 1.0; 
00147         else if( dot < -1.0 ) dot = -1.0;
00148 
00149         r = acosf( dot );
00150         a = ti.cross( tj );
00151     }
00152 
00153     if( a.length() != 0.0 && r != 0.0 )
00154     {
00155         Matrix44<T> R; R.setAxisAngle( a, r );
00156         Matrix44<T> Tj; Tj.translate(  pj );
00157         Matrix44<T> Ti; Ti.translate( -pi );
00158 
00159         return Mi * Ti * R * Tj;
00160     }
00161     else
00162     {
00163         Matrix44<T> Tr; Tr.translate( pj - pi );
00164 
00165         return Mi * Tr;
00166     }
00167 }
00168 
00169 //
00170 //  lastFrame - Compute the last reference frame along a curve.
00171 //
00172 //  This function returns the transformation matrix to the last reference 
00173 //  frame defined by the previously computed transformation matrix and the
00174 //  last point along the curve.
00175 //
00176 
00177 template<class T> Matrix44<T> lastFrame
00178 ( 
00179     const Matrix44<T>&  Mi,             // Previous matrix
00180     const Vec3<T>&      pi,             // Previous point
00181     const Vec3<T>&      pj )            // Last point
00182 {
00183     Matrix44<T> Tr; Tr.translate( pj - pi );
00184 
00185     return Mi * Tr;
00186 }
00187 
00188 } // namespace Imath
00189 
00190 #endif