Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Atmosphere.cpp

Go to the documentation of this file.
00001 
00002 /*
00003     TEDDY - General graphics application library
00004     Copyright (C) 1999, 2000, 2001  Timo Suoranta
00005     tksuoran@cc.helsinki.fi
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021     $Id: Atmosphere.cpp,v 1.1 2002/01/08 20:47:04 tksuoran Exp $
00022 */
00023 
00024 
00025 #if defined(_MSC_VER)
00026 #pragma warning(disable:4244)  //  conversion from 'double' to 'float', possible loss of data
00027 #endif
00028 
00029 
00030 #include "Teddy/SpaceGame/Atmosphere.h"
00031 #include "Teddy/Maths/Matrix.h"
00032 #include "Teddy/Maths/Plane.h"
00033 #include "Teddy/Maths/Vector.h"
00034 #include <cmath>
00035 using namespace Teddy::Maths;
00036 
00037 
00038 namespace Teddy     {
00039 namespace SpaceGame {
00040 
00041 
00042 static void generateOrthonormalBasis( Vector &U, Vector &V, Vector &W );
00043 
00044 
00045 void PerspProjEllipsoid(
00046     const Ellipsoid &ellipsoid,
00047     const Vector    &eye,
00048     const Plane     &plane,
00049     Ellipse         &ellipse
00050 ){
00051     // compute matrix M
00052     Vector  AE   = ellipsoid.A * eye;
00053     float   EAE  = eye         | AE;
00054     float   BE   = ellipsoid.B | eye;
00055     float   tmp  = 4 * ( EAE + BE + ellipsoid.C );
00056     Vector  tmpv = ellipsoid.B + AE * 2;
00057     Matrix  mat;  // 3x3
00058 
00059     mat = Matrix::Identity;
00060 
00061     mat(0,0) = tmpv.v[0] * tmpv.v[0] - tmp * ellipsoid.A(0,0);
00062     mat(0,1) = tmpv.v[0] * tmpv.v[1] - tmp * ellipsoid.A(0,1);
00063     mat(0,2) = tmpv.v[0] * tmpv.v[2] - tmp * ellipsoid.A(0,2);
00064     mat(1,1) = tmpv.v[1] * tmpv.v[1] - tmp * ellipsoid.A(1,1);
00065     mat(1,2) = tmpv.v[1] * tmpv.v[2] - tmp * ellipsoid.A(1,2);
00066     mat(2,2) = tmpv.v[2] * tmpv.v[2] - tmp * ellipsoid.A(2,2);
00067     mat(1,0) = mat(0,1);
00068     mat(2,0) = mat(0,2);
00069     mat(2,1) = mat(1,2);
00070 
00071     // Normalize N and construct U and V so that {U,V,N} forms a
00072     // right-handed, orthonormal basis.
00073     Vector U;
00074     Vector V;
00075     Vector N = plane.getNormal();
00076     generateOrthonormalBasis( U, V, N );
00077 
00078     // compute coefficients for projected ellipse
00079     Vector MU       = mat * U;
00080     Vector MV       = mat * V;
00081     Vector MN       = mat * N;
00082     float  DmNE     = plane.getConstant() - ( N | eye );
00083 
00084     ellipse.A      = Matrix::Identity;  //  TIS
00085     ellipse.A(0,0) = U | MU;
00086     ellipse.A(0,1) = U | MV;
00087     ellipse.A(1,1) = V | MV;
00088     ellipse.A(1,0) = ellipse.A(0,1);
00089     ellipse.B.v[0]     =   2  * DmNE * ( U | MN );
00090     ellipse.B.v[1]     =   2  * DmNE * ( V | MN );
00091     ellipse.B.v[2]     =   1;                           //  TIS
00092     ellipse.C       = DmNE * DmNE * ( N | MN );
00093 }
00094 
00095 
00096 void ConvertEllipse(
00097     Ellipse &ellipse,
00098     Vector  &center,
00099     Vector  &axis0,
00100     Vector  &axis1,
00101     float   &halfLength0,
00102     float   &halfLength1
00103 ){
00104     // factor A = R^t D R
00105     double trace = ellipse.A(0,0) + ellipse.A(1,1);
00106     if( trace < 0 ){
00107         // Convert A from negative definite to positive definite
00108         // (multiply quadratic equation by -1).
00109         ellipse.A = -ellipse.A;
00110         ellipse.B = -ellipse.B;
00111         ellipse.C = -ellipse.C;
00112         trace     = -trace;
00113     }
00114 
00115     double tmp   = ellipse.A(0,0) - ellipse.A(1,1);
00116     double discr = sqrt( tmp*tmp + 4*ellipse.A(0,1) * ellipse.A(0,1) );
00117 
00118     //  Matrix D (eigenvalues of A)
00119     double D0    = 0.5 * (trace - discr);
00120     double D1    = 0.5 * (trace + discr);
00121     double invD0 = 1/D0;
00122     double invD1 = 1/D1;
00123 
00124     //  Matrix R (columns are eigenvectors of A)
00125     Matrix R;
00126     Vector beta;
00127 
00128     R = Matrix::Identity;  //  TIS
00129     if( ellipse.A(0,1) != 0 ){
00130         double invLength;
00131 
00132         R(0,0)    = ellipse.A(0,1);
00133         R(1,0)    = D0 - ellipse.A(0,0);
00134         invLength = 1 / sqrt( R(0,0) * R(0,0)  +  R(1,0) * R(1,0) );
00135         R(0,0)   *= invLength;
00136         R(1,0)   *= invLength;
00137 
00138         R(0,1)    = D1 - ellipse.A(1,1);
00139         R(1,1)    = ellipse.A(0,1);
00140         invLength = 1 / sqrt( R(0,1) * R(0,1)  +  R(1,1) * R(1,1) );
00141         R(0,1)   *= invLength;
00142         R(1,1)   *= invLength;
00143     }
00144 
00145     beta     =   R  * ellipse.B;        //  Compute the ellipse center
00146     center.v[0] = -0.5 * beta.v[0] * invD0;
00147     center.v[1] = -0.5 * beta.v[1] * invD1;
00148     center.v[2] =  0;  //  TIS
00149 
00150     axis0.v[0]  = R(0,0);  //  Compute the ellipse axes
00151     axis0.v[1]  = R(1,0);
00152     axis1.v[0]  = R(0,1);
00153     axis1.v[1]  = R(1,1);
00154 
00155     // compute the ellipse axis half lengths
00156     tmp           = D0 * center.v[0] * center.v[0]  +  D1 * center.v[1] * center.v[1]  -  ellipse.C;
00157     halfLength0 = sqrt(  fabs( tmp * invD0 )  );
00158     halfLength1 = sqrt(  fabs( tmp * invD1 )  );
00159 }
00160 
00161 
00162 
00163 static void generateOrthonormalBasis( Vector &U, Vector &V, Vector &W ){
00164     double inv_length;
00165 
00166     W.normalize();
00167 
00168     if( fabs(W.v[0]) >= fabs(W.v[1]) ){
00169         // W.v[0] or W.v[2] is the largest magnitude component, swap them
00170         inv_length = 1 / sqrt( W.v[0]*W.v[0]+W.v[2]*W.v[2] );
00171         U.v[0] = -W.v[2] * inv_length;
00172         U.v[1] = 0;
00173         U.v[2] = +W.v[0] * inv_length;
00174     }else{
00175         // W.v[1] or W.v[2] is the largest magnitude component, swap them
00176         inv_length = 1 / sqrt( W.v[1]*W.v[1]+W.v[2]*W.v[2] );
00177         U.v[0] = 0;
00178         U.v[1] = +W.v[2] * inv_length;
00179         U.v[2] = -W.v[1] * inv_length;
00180     }
00181 
00182     V = W ^ U;  //  Cross-product
00183 }
00184 
00185 
00186 };  //  namespace SpaceGame
00187 };  //  namespace Teddy
00188