00001 #include <stdlib.h>
00002 #include <math.h>
00003 #include <windows.h>
00004 #include "debug.h"
00005 
00006 #define TRUE_WIND_VELOCITY
00007 
00008 extern Debug* dbg;
00009 
00010 void init();
00011 void deInit();
00012 void InitParticles();
00013 void QuitApplication();
00014 float WindStormStrength(float fAltitude);
00015 void WindVelocity(float *pfLocation, float *pfVelocity);
00016 void UpdatePhysics();
00017 void PhysicsStep();
00018 
00019 class Particle
00020 {
00021         public:
00022                 Particle();
00023 
00024         public:
00025                 float m_pfPosition[3];  
00026                 float m_pfVelocity[3];  
00027                 float m_fMass;                  
00028                 float m_fHalfRhoSref;   
00029 };
00030 
00031 float g_fPhysicsTimeStep = 0.02f;                                       
00032 float g_fAccumulatedTimeStep = 0.0f;                            
00033 float g_fSimTime = 0.0f;                                                        
00034 float g_OneOverTwoPi = 1.0f/(8.0f * atanf(1.0f));       
00035 float g_pfStormCenter[] = {0.0f, 0.0f};                         
00036 float g_fFluidDensity = 1.225;                                          
00037 float g_fPI = 4.0f * atanf(1.0f);                                       
00038 float g_fGravitationalAccel = -9.8f;                            
00039 float g_fRandMax(float(RAND_MAX));                                      
00040 float g_fS0 = 0.5f;                                                                     
00041 float g_fS500 = 50.0f;                                                          
00042 LARGE_INTEGER g_liTimerFrequency;                                       
00043 LARGE_INTEGER g_liPreviousCounter;                                      
00044 
00045 const unsigned int g_uiGoalNumParticles = 400;      
00046 unsigned int g_uiNumParticles = 0;                                      
00047 Particle *g_pParticles = 0;                                                     
00048 
00049 void init()
00050 {
00051         if (FALSE == QueryPerformanceFrequency(&g_liTimerFrequency))
00052         {
00053             dbg->log("FALSE == QueryPerformanceFrequency(&g_liTimerFrequency)");
00054                 return;
00055         }
00056 
00057         InitParticles();
00058 
00059         if (FALSE == QueryPerformanceCounter(&g_liPreviousCounter))
00060         {
00061             dbg->log("FALSE == QueryPerformanceCounter(&g_liPreviousCounter)");
00062                 return;
00063         }
00064 }
00065 
00066 Particle::Particle() : m_pfPosition(), m_pfVelocity(),
00067         m_fMass(1.0f), m_fHalfRhoSref(1.0f)
00068 {
00069         m_pfPosition[0] = 0.0f;
00070         m_pfPosition[1] = 0.0f;
00071         m_pfPosition[2] = 0.0f;
00072 
00073         m_pfVelocity[0] = 0.0f;
00074         m_pfVelocity[1] = 0.0f;
00075         m_pfVelocity[2] = 0.0f;
00076 }
00077 
00078 void InitParticles()
00079 {
00080         g_pParticles = new Particle[g_uiGoalNumParticles];
00081         float fRadius, Sref;
00082         if (0 != g_pParticles)
00083         {
00084                 g_uiNumParticles = g_uiGoalNumParticles;
00085                 for (unsigned int i = 0; i < g_uiGoalNumParticles; i++)
00086                 {
00087                         g_pParticles[i].m_pfPosition[0] = -2.5f + 5.0f * float(rand()) / g_fRandMax;
00088                         g_pParticles[i].m_pfPosition[1] = -2.5f + 5.0f * float(rand()) / g_fRandMax;
00089                         g_pParticles[i].m_pfPosition[2] = 500.0f * float(rand()) / g_fRandMax;
00090 
00091                         g_pParticles[i].m_fMass = 0.05f + .05f * float(rand()) / g_fRandMax;
00092                         fRadius = 0.2f + 0.2f*float(rand()) / g_fRandMax;
00093                         Sref = g_fPI * fRadius * fRadius;
00094                         g_pParticles[i].m_fHalfRhoSref = 0.5 * Sref * g_fFluidDensity;
00095                 }
00096         }
00097 }
00098 
00099 void deInit()
00100 {
00101         delete [] g_pParticles;
00102 }
00103 
00104 
00105 float WindStormStrength(float fAltitude)
00106 {
00107         return(g_fS0 + ((g_fS500 - g_fS0) * fAltitude * fAltitude / 250000.0f));
00108 }
00109 
00110 
00111 
00112 void WindVelocity(float *pfLocation, float *pfVelocity)
00113 {
00114         if (0 == pfLocation || 0 == pfVelocity)
00115                 return;
00116 
00117         float fDX = pfLocation[0] - g_pfStormCenter[0];
00118         float fDY = pfLocation[1] - g_pfStormCenter[1];
00119 
00120         float fR = sqrtf(fDX * fDX + fDY * fDY);
00121         if (fR < 1.e-4)
00122                 fR = 1.0f;
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131         float fOneOverR = (1.0f / fR);
00132         if (fOneOverR < 1.0f)
00133         {
00134                 fOneOverR = 1.0f;
00135         }
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 #ifdef TRUE_WIND_VELOCITY
00148         float fCommonFactor = WindStormStrength(pfLocation[2]) * fOneOverR * g_OneOverTwoPi;
00149 
00150         pfVelocity[0] =  pfLocation[1] * fCommonFactor;
00151         pfVelocity[1] = -pfLocation[0] * fCommonFactor;
00152 #else
00153         float fTangentialVelocity = WindStormStrength(pfLocation[2]) * fOneOverR * g_OneOverTwoPi;
00154         float fDeltaAngle = fTangentialVelocity * g_fPhysicsTimeStep;
00155         float fAngle = atan2(fDY, fDX) + fDeltaAngle;
00156         float fNewX = fR * cos(fAngle);
00157         float fNewY = fR * sin(fAngle);
00158         pfVelocity[0] = (fNewX - pfLocation[0]) / g_fPhysicsTimeStep;
00159         pfVelocity[1] = (fNewY - pfLocation[1]) / g_fPhysicsTimeStep;
00160 #endif // TRUE_WIND_VELOCITY
00161 
00162 
00163 
00164         pfVelocity[2] = 0.0f;
00165 }
00166 
00167 
00168 
00169 void UpdatePhysics()
00170 {
00171         LARGE_INTEGER PC;
00172 
00173         if (FALSE == QueryPerformanceCounter(&PC))
00174         {
00175             dbg->log("FALSE == QueryPerformanceCounter(&PC)");
00176                 return;
00177         }
00178 
00179         LONGLONG DeltaCounter = PC.QuadPart - g_liPreviousCounter.QuadPart;
00180 
00181         g_liPreviousCounter = PC;
00182 
00183         float fDeltaTime = float(DeltaCounter) / float(g_liTimerFrequency.QuadPart);
00184 
00185         g_fAccumulatedTimeStep += fDeltaTime;
00186 
00187         while (g_fAccumulatedTimeStep > g_fPhysicsTimeStep)
00188         {
00189                 PhysicsStep();
00190                 g_fAccumulatedTimeStep -= g_fPhysicsTimeStep;
00191         }
00192 }
00193 
00194 
00195 
00196 void PhysicsStep()
00197 {
00198         float fVwind[3], fForce[3], fDragMagnitude, fVrelwind_squared, fSpeed;
00199         for (unsigned int i = 0; i < g_uiNumParticles; i++)
00200         {
00201                 WindVelocity(g_pParticles[i].m_pfPosition, fVwind);
00202 
00203 
00204 
00205 
00206 
00207 
00208 #ifndef MASSLESS_PARTICLES
00209                 
00210                 
00211                 fVwind[0] -= g_pParticles[i].m_pfVelocity[0];
00212                 fVwind[1] -= g_pParticles[i].m_pfVelocity[1];
00213                 fVwind[2] -= g_pParticles[i].m_pfVelocity[2];
00214                 fVrelwind_squared = fVwind[0] * fVwind[0] + fVwind[1] * fVwind[1] + fVwind[2] * fVwind[2];
00215                 fSpeed = sqrtf(fVrelwind_squared);
00216 
00217                 
00218                 
00219                 
00220                 const float fCD = 0.4;
00221 
00222                 fDragMagnitude = g_pParticles[i].m_fHalfRhoSref * fVrelwind_squared * fCD;
00223 
00224                 
00225                 fForce[0] = fDragMagnitude * fVwind[0] / fSpeed;
00226                 fForce[1] = fDragMagnitude * fVwind[1] / fSpeed;
00227                 fForce[2] = fDragMagnitude * fVwind[2] / fSpeed;
00228 
00229                 
00230 #ifdef INCLUDE_GRAVITY
00231                 fForce[2] += g_fGravitationalAccel * g_pParticles[i].m_fMass;
00232 #endif // INCLUDE_GRAVITY
00233 
00234                 
00235                 
00236                 
00237                 
00238                 g_pParticles[i].m_pfVelocity[0] += g_fPhysicsTimeStep * fForce[0] / g_pParticles[i].m_fMass;
00239                 g_pParticles[i].m_pfVelocity[1] += g_fPhysicsTimeStep * fForce[1] / g_pParticles[i].m_fMass;
00240                 g_pParticles[i].m_pfVelocity[2] += g_fPhysicsTimeStep * fForce[2] / g_pParticles[i].m_fMass;
00241 
00242 
00243 #else // massless particle option
00244                 g_pParticles[i].m_pfVelocity[0] = fVwind[0];
00245                 g_pParticles[i].m_pfVelocity[1] = fVwind[1];
00246                 g_pParticles[i].m_pfVelocity[2] = fVwind[2];
00247 #endif // DO_TEST
00248 
00249                 
00250                 
00251                 
00252                 
00253                 g_pParticles[i].m_pfPosition[0] += g_fPhysicsTimeStep * g_pParticles[i].m_pfVelocity[0];
00254                 g_pParticles[i].m_pfPosition[1] += g_fPhysicsTimeStep * g_pParticles[i].m_pfVelocity[1];
00255                 g_pParticles[i].m_pfPosition[2] += g_fPhysicsTimeStep * g_pParticles[i].m_pfVelocity[2];
00256 
00257                 
00258                 if (g_pParticles[i].m_pfPosition[2] <= 0.0f)
00259                 {
00260                         g_pParticles[i].m_pfPosition[0] = -2.5f + 5.0f * float(rand()) / g_fRandMax;
00261                         g_pParticles[i].m_pfPosition[1] = -2.5f + 5.0f * float(rand()) / g_fRandMax;
00262                         g_pParticles[i].m_pfPosition[2] = 500.0f * float(rand()) / g_fRandMax;
00263                 }
00264         }
00265 }