//----------------------------------------------------------------------------- // Name: CParticleSystem() // Desc: //----------------------------------------------------------------------------- CParticleSystem::CParticleSystem() { m_dwVBOffset = 0; // Gives the offset of the vertex buffer chunk that's currently being filled m_dwFlush = 512; // Number of point sprites to load before sending them to hardware(512 = 2048 divided into 4 chunks) m_dwDiscard = 2048; // Max number of point sprites the vertex buffer can load until we are forced to discard and start over m_pActiveList = NULL; // Head node of point sprites that are active m_pFreeList = NULL; // Head node of point sprites that are inactive and waiting to be recycled. m_pPlanes = NULL; m_dwActiveCount = 0; m_fCurrentTime = 0.0f; m_fLastUpdate = 0.0f; m_pVB = NULL; // The vertex buffer where point sprites are to be stored m_chTexFile = NULL; m_ptexParticle = NULL; m_dwMaxParticles = 1; m_dwNumToRelease = 1; m_fReleaseInterval = 1.0f; m_fLifeCycle = 1.0f; m_fSize = 1.0f; m_clrColor = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f); m_vPosition = ArnVec3(0.0f,0.0f,0.0f); m_vVelocity = ArnVec3(0.0f,0.0f,0.0f); m_vGravity = ArnVec3(0.0f,0.0f,0.0f); m_vWind = ArnVec3(0.0f,0.0f,0.0f); m_bAirResistence = true; m_fVelocityVar = 1.0f; SetTexture("particle.bmp"); }
void Renderer::update_hero_pos() { ArnMesh *m = reinterpret_cast<ArnMesh *>(scene_graph->getSceneRoot()->findFirstNodeOfType(NDT_RT_MESH)); if (m) { const Car &car = Car::getSingleton(); m->setLocalXform_Trans(ArnVec3(car.get_pos()[0], car.get_pos()[1], car.get_pos()[2])); m->recalcLocalXform(); } }
//----------------------------------------------------------------------------- // Name: Update() // Desc: //----------------------------------------------------------------------------- HRESULT CParticleSystem::Update( FLOAT fElpasedTime ) { Particle *pParticle = 0; Particle **ppParticle = 0; Plane *pPlane = 0; Plane **ppPlane = 0; ArnVec3 vOldPosition; m_fCurrentTime += fElpasedTime; // Update our particle system timer... ppParticle = &m_pActiveList; // Start at the head of the active list while( *ppParticle ) { pParticle = *ppParticle; // Set a pointer to the head // Calculate new position float fTimePassed = m_fCurrentTime - pParticle->m_fInitTime; if( fTimePassed >= m_fLifeCycle ) { // Time is up, put the particle back on the free list... *ppParticle = pParticle->m_pNext; pParticle->m_pNext = m_pFreeList; m_pFreeList = pParticle; --m_dwActiveCount; } else { // Update particle position and velocity // Update velocity with respect to Gravity (Constant Acceleration) pParticle->m_vCurVel += m_vGravity * fElpasedTime; // Update velocity with respect to Wind (Acceleration based on // difference of vectors) if( m_bAirResistence == true ) pParticle->m_vCurVel += (m_vWind - pParticle->m_vCurVel) * fElpasedTime; // Finally, update position with respect to velocity vOldPosition = pParticle->m_vCurPos; pParticle->m_vCurPos += pParticle->m_vCurVel * fElpasedTime; //----------------------------------------------------------------- // BEGIN Checking the particle against each plane that was set up ppPlane = &m_pPlanes; // Set a pointer to the head while( *ppPlane ) { pPlane = *ppPlane; int result = classifyPoint( &pParticle->m_vCurPos, pPlane ); if( result == CP_BACK /*|| result == CP_ONPLANE */ ) { if( pPlane->m_nCollisionResult == CR_BOUNCE ) { pParticle->m_vCurPos = vOldPosition; //----------------------------------------------------------------- // // The new velocity vector of a particle that is bouncing off // a plane is computed as follows: // // Vn = (N.V) * N // Vt = V - Vn // Vp = Vt - Kr * Vn // // Where: // // . = Dot product operation // N = The normal of the plane from which we bounced // V = Velocity vector prior to bounce // Vn = Normal force // Kr = The coefficient of restitution ( Ex. 1 = Full Bounce, // 0 = Particle Sticks ) // Vp = New velocity vector after bounce // //----------------------------------------------------------------- float Kr = pPlane->m_fBounceFactor; ArnVec3 Vn = pPlane->m_vNormal * ArnVec3Dot( &pPlane->m_vNormal, &pParticle->m_vCurVel ); ArnVec3 Vt = pParticle->m_vCurVel - Vn; ArnVec3 Vp = Vt - (Vn * Kr); pParticle->m_vCurVel = Vp; } else if( pPlane->m_nCollisionResult == CR_RECYCLE ) { pParticle->m_fInitTime -= m_fLifeCycle; } else if( pPlane->m_nCollisionResult == CR_STICK ) { pParticle->m_vCurPos = vOldPosition; pParticle->m_vCurVel = ArnVec3(0.0f,0.0f,0.0f); } } ppPlane = &pPlane->m_pNext; } // END Plane Checking //----------------------------------------------------------------- ppParticle = &pParticle->m_pNext; } } //------------------------------------------------------------------------- // Emit new particles in accordance to the flow rate... // // NOTE: The system operates with a finite number of particles. // New particles will be created until the max amount has // been reached, after that, only old particles that have // been recycled can be reintialized and used again. //------------------------------------------------------------------------- if( m_fCurrentTime - m_fLastUpdate > m_fReleaseInterval ) { // Reset update timing... m_fLastUpdate = m_fCurrentTime; // Emit new particles at specified flow rate... for( DWORD i = 0; i < m_dwNumToRelease; ++i ) { // Do we have any free particles to put back to work? if( m_pFreeList ) { // If so, hand over the first free one to be reused. pParticle = m_pFreeList; // Then make the next free particle in the list next to go! m_pFreeList = pParticle->m_pNext; } else { // There are no free particles to recycle... // We'll have to create a new one from scratch! if( m_dwActiveCount < m_dwMaxParticles ) { if( NULL == ( pParticle = new Particle ) ) return E_OUTOFMEMORY; } } if( m_dwActiveCount < m_dwMaxParticles ) { pParticle->m_pNext = m_pActiveList; // Make it the new head... m_pActiveList = pParticle; // Set the attributes for our new particle... pParticle->m_vCurVel = m_vVelocity; if( m_fVelocityVar != 0.0f ) { ArnVec3 vRandomVec = getRandomVector(); pParticle->m_vCurVel += vRandomVec * m_fVelocityVar; } pParticle->m_fInitTime = m_fCurrentTime; pParticle->m_vCurPos = m_vPosition; ++m_dwActiveCount; } } } return S_OK; }