00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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;
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
00072
00073 Vector U;
00074 Vector V;
00075 Vector N = plane.getNormal();
00076 generateOrthonormalBasis( U, V, N );
00077
00078
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;
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;
00092 ellipse.C = DmNE * DmNE * ( N | MN );
00093 }
00094
00095
00096 void ConvertEllipse(
00097 Ellipse &ellipse,
00098 Vector ¢er,
00099 Vector &axis0,
00100 Vector &axis1,
00101 float &halfLength0,
00102 float &halfLength1
00103 ){
00104
00105 double trace = ellipse.A(0,0) + ellipse.A(1,1);
00106 if( trace < 0 ){
00107
00108
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
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
00125 Matrix R;
00126 Vector beta;
00127
00128 R = Matrix::Identity;
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;
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;
00149
00150 axis0.v[0] = R(0,0);
00151 axis0.v[1] = R(1,0);
00152 axis1.v[0] = R(0,1);
00153 axis1.v[1] = R(1,1);
00154
00155
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
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
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;
00183 }
00184
00185
00186 };
00187 };
00188