//-------------------------------------------------------------------------------------- void CGroundBurstParticleSystem::Init() { UINT index = 0; UINT ParticlesPerStream = ( m_NumParticles / m_NumStreamers ) + 1; for( UINT s = 0; s < m_NumStreamers; s++ ) { D3DXVECTOR3 vStreamerDir = m_vDirection; vStreamerDir.x += RPercent() * m_vDirVariance.x; vStreamerDir.y += RPercent() * m_vDirVariance.y; vStreamerDir.z += RPercent() * m_vDirVariance.z; D3DXVec3Normalize( &vStreamerDir, &vStreamerDir ); D3DXVECTOR3 vStreamerPos; vStreamerPos.x = RPercent() * m_fSpread; vStreamerPos.y = RPercent() * m_fSpread; vStreamerPos.z = RPercent() * m_fSpread; for( UINT i = 0; i < ParticlesPerStream; i++ ) { if( index < m_NumParticles ) { m_pParticles[index].vPos = vStreamerPos; m_pParticles[index].vPos.x *= m_vPosMul.x; m_pParticles[index].vPos.y *= m_vPosMul.y; m_pParticles[index].vPos.z *= m_vPosMul.z; m_pParticles[index].vPos += m_vCenter; float fSpeed = m_fStartSpeed + RPercent() * m_fSpeedVariance; m_pParticles[index].vDir = vStreamerDir * fSpeed; m_pParticles[index].vDir.x *= m_vDirMul.x; m_pParticles[index].vDir.y *= m_vDirMul.y; m_pParticles[index].vDir.z *= m_vDirMul.z; float fRadiusLerp = ( fSpeed / ( m_fStartSpeed + m_fSpeedVariance ) ); m_pParticles[index].fRadius = m_fStartSize * fRadiusLerp + m_fEndSize * ( 1 - fRadiusLerp ); m_pParticles[index].fLife = m_fStartTime; m_pParticles[index].fFade = 0.0f; m_pParticles[index].fRot = RPercent() * 3.14159f * 2.0f; m_pParticles[index].fRotRate = RPercent() * 1.5f; float fLerp = RPercent(); D3DXVECTOR4 vColor = ( m_vColor0 * fLerp ) + ( m_vColor1 * ( 1.0f - fLerp ) ); m_pParticles[index].Color = ( DWORD )( vColor.w * 255.0f ) << 24; m_pParticles[index].Color |= ( ( DWORD )( vColor.z * 255.0f ) & 255 ) << 16; m_pParticles[index].Color |= ( ( DWORD )( vColor.y * 255.0f ) & 255 ) << 8; m_pParticles[index].Color |= ( ( DWORD )( vColor.x * 255.0f ) & 255 ); index++; } } } m_bStarted = false; m_fCurrentTime = m_fStartTime; }
//-------------------------------------------------------------------------------------- void CLandMineParticleSystem::Init() { for( UINT i = 0; i < m_NumParticles; i++ ) { D3DXVECTOR3 vDir = m_vDirection; vDir.x += RPercent() * m_vDirVariance.x; vDir.y += RPercent() * m_vDirVariance.y; vDir.z += RPercent() * m_vDirVariance.z; D3DXVec3Normalize( &vDir, &vDir ); m_pParticles[i].vPos.x = RPercent() * m_fSpread; m_pParticles[i].vPos.y = RPercent() * m_fSpread; m_pParticles[i].vPos.z = RPercent() * m_fSpread; m_pParticles[i].vPos.x *= m_vPosMul.x; m_pParticles[i].vPos.y *= m_vPosMul.y; m_pParticles[i].vPos.z *= m_vPosMul.z; float fDist = D3DXVec3Length( &m_pParticles[i].vPos ); fDist /= m_fSpread; m_pParticles[i].vPos += m_vCenter; float fSpeed = m_fStartSpeed + RPercent() * m_fSpeedVariance; float speedMod = 1.0f - fDist; m_pParticles[i].vDir = vDir * fSpeed * speedMod; m_pParticles[i].vDir.x *= m_vDirMul.x; m_pParticles[i].vDir.y *= m_vDirMul.y; m_pParticles[i].vDir.z *= m_vDirMul.z; float fRadiusLerp = ( fSpeed / ( m_fStartSpeed + m_fSpeedVariance ) ); m_pParticles[i].fRadius = m_fStartSize * fRadiusLerp + m_fEndSize * ( 1 - fRadiusLerp ); m_pParticles[i].fLife = m_fStartTime; m_pParticles[i].fFade = 0.0f; m_pParticles[i].fRot = RPercent() * 3.14159f * 2.0f; m_pParticles[i].fRotRate = RPercent() * 1.5f; float fLerp = RPercent(); D3DXVECTOR4 vColor = ( m_vColor0 * fLerp ) + ( m_vColor1 * ( 1.0f - fLerp ) ); m_pParticles[i].Color = ( DWORD )( vColor.w * 255.0f ) << 24; m_pParticles[i].Color |= ( ( DWORD )( vColor.z * 255.0f ) & 255 ) << 16; m_pParticles[i].Color |= ( ( DWORD )( vColor.y * 255.0f ) & 255 ) << 8; m_pParticles[i].Color |= ( ( DWORD )( vColor.x * 255.0f ) & 255 ); } m_bStarted = false; m_fCurrentTime = m_fStartTime; }
//-------------------------------------------------------------------------------------- void SoftParticles::EmitParticle( PARTICLE_VERTEX* pParticle ) { pParticle->Pos.x = 0.0f; pParticle->Pos.y = 0.7f; pParticle->Pos.z = 3.0f; pParticle->Vel.x = 1.0f; pParticle->Vel.y = 0.3f*RPercent(); pParticle->Vel.z = 0.3f*RPercent(); D3DXVec3Normalize( &pParticle->Vel, &pParticle->Vel ); pParticle->Vel *= g_ParticleVel; pParticle->Life = 0.0f; pParticle->Size = 0.0f; }
//-------------------------------------------------------------------------------------- HRESULT CTerrain::GenerateTile( TERRAIN_TILE* pTile, BOUNDING_BOX* pBBox ) { HRESULT hr = S_OK; // Alloc memory for the vertices pTile->NumVertices = ( m_NumSidesPerTile + 1 ) * ( m_NumSidesPerTile + 1 ); pTile->pRawVertices = new TERRAIN_VERTEX[ pTile->NumVertices ]; if( !pTile->pRawVertices ) return E_OUTOFMEMORY; pTile->BBox = *pBBox; pTile->Color.x = 0.60f + RPercent() * 0.40f; pTile->Color.y = 0.60f + RPercent() * 0.40f; pTile->Color.z = 0.60f + RPercent() * 0.40f; pTile->Color.w = 1.0f; UINT iVertex = 0; float zStart = pBBox->min.z; float xDelta = ( pBBox->max.x - pBBox->min.x ) / ( float )m_NumSidesPerTile; float zDelta = ( pBBox->max.z - pBBox->min.z ) / ( float )m_NumSidesPerTile; // Loop through terrain vertices and get height from the heightmap for( UINT z = 0; z < m_NumSidesPerTile + 1; z++ ) { float xStart = pBBox->min.x; for( UINT x = 0; x < m_NumSidesPerTile + 1; x++ ) { D3DXVECTOR3 pos( xStart,0,zStart ); D3DXVECTOR3 norm; pos.y = GetHeightOnMap( &pos ); pTile->pRawVertices[iVertex].pos = pos; //pTile->pRawVertices[iVertex].uv = GetUVForPosition( &pos ); //pTile->pRawVertices[iVertex].uv.y = 1.0f - pTile->pRawVertices[iVertex].uv.y; pTile->pRawVertices[iVertex].uv.x = ( float )x / ( ( float )m_NumSidesPerTile ); pTile->pRawVertices[iVertex].uv.y = 1.0f - ( float )z / ( ( float )m_NumSidesPerTile ); pTile->pRawVertices[iVertex].norm = GetNormalOnMap( &pos ); iVertex ++; xStart += xDelta; } zStart += zDelta; } return hr; }
//-------------------------------------------------------------------------------------- // Create and blur a noise volume texture //-------------------------------------------------------------------------------------- HRESULT SoftParticles::CreateNoiseVolume( ID3D11Device* pd3dDevice, UINT VolumeSize ) { HRESULT hr = S_OK; D3D11_SUBRESOURCE_DATA InitData; InitData.pSysMem = new CHAR4[ VolumeSize*VolumeSize*VolumeSize ]; InitData.SysMemPitch = VolumeSize*sizeof(CHAR4); InitData.SysMemSlicePitch = VolumeSize*VolumeSize*sizeof(CHAR4); // Gen a bunch of random values CHAR4* pData = (CHAR4*)InitData.pSysMem; for( UINT i=0; i<VolumeSize*VolumeSize*VolumeSize; i++ ) { pData[i].w = (char)(RPercent() * 128.0f); } // Generate normals from the density gradient float heightAdjust = 0.5f; D3DXVECTOR3 Normal; D3DXVECTOR3 DensityGradient; for( UINT z=0; z<VolumeSize; z++ ) { for( UINT y=0; y<VolumeSize; y++ ) { for( UINT x=0; x<VolumeSize; x++ ) { DensityGradient.x = GetDensity( x+1, y, z, pData, VolumeSize ) - GetDensity( x-1, y, z, pData, VolumeSize )/heightAdjust; DensityGradient.y = GetDensity( x, y+1, z, pData, VolumeSize ) - GetDensity( x, y-1, z, pData, VolumeSize )/heightAdjust; DensityGradient.z = GetDensity( x, y, z+1, pData, VolumeSize ) - GetDensity( x, y, z-1, pData, VolumeSize )/heightAdjust; D3DXVec3Normalize( &Normal, &DensityGradient ); SetNormal( Normal, x,y,z, pData, VolumeSize ); } } } D3D11_TEXTURE3D_DESC desc; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.Depth = desc.Height = desc.Width = VolumeSize; desc.Format = DXGI_FORMAT_R8G8B8A8_SNORM; desc.MipLevels = 1; desc.MiscFlags = 0; desc.Usage = D3D11_USAGE_IMMUTABLE; V_RETURN( pd3dDevice->CreateTexture3D( &desc, &InitData, &g_pNoiseVolume ) ); D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; ZeroMemory( &SRVDesc, sizeof(SRVDesc) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; SRVDesc.Texture3D.MipLevels = desc.MipLevels; SRVDesc.Texture3D.MostDetailedMip = 0; V_RETURN(pd3dDevice->CreateShaderResourceView( g_pNoiseVolume, &SRVDesc, &g_pNoiseVolumeRV )); delete InitData.pSysMem; return hr; }
//-------------------------------------------------------------------------------------- void CStalkParticleSystem::Init() { for( UINT i = 0; i < m_NumParticles; i++ ) { m_pParticles[i].vPos.x = RPercent() * m_fSpread; m_pParticles[i].vPos.y = RPercent() * m_fSpread; m_pParticles[i].vPos.z = RPercent() * m_fSpread; m_pParticles[i].vPos.x *= m_vPosMul.x; m_pParticles[i].vPos.y *= m_vPosMul.y; m_pParticles[i].vPos.z *= m_vPosMul.z; m_pParticles[i].vPos += m_vCenter; m_pParticles[i].vDir.x = RPercent(); m_pParticles[i].vDir.y = fabs( RPercent() ); m_pParticles[i].vDir.z = RPercent(); m_pParticles[i].vDir.x *= m_vDirMul.x; m_pParticles[i].vDir.y *= m_vDirMul.y; m_pParticles[i].vDir.z *= m_vDirMul.z; D3DXVec3Normalize( &m_pParticles[i].vDir, &m_pParticles[i].vDir ); m_pParticles[i].fRadius = m_fStartSize; m_pParticles[i].fLife = m_fStartTime; m_pParticles[i].fFade = 0.0f; m_pParticles[i].fRot = RPercent() * 3.14159f * 2.0f; float fLerp = RPercent(); D3DXVECTOR4 vColor = m_vColor0 * fLerp + m_vColor1 * ( 1.0f - fLerp ); m_pParticles[i].Color = ( DWORD )( vColor.w * 255.0f ) << 24; m_pParticles[i].Color |= ( ( DWORD )( vColor.z * 255.0f ) & 255 ) << 16; m_pParticles[i].Color |= ( ( DWORD )( vColor.y * 255.0f ) & 255 ) << 8; m_pParticles[i].Color |= ( ( DWORD )( vColor.x * 255.0f ) & 255 ); } m_bStarted = false; m_fCurrentTime = m_fStartTime; }
//-------------------------------------------------------------------------------------- HRESULT CTerrain::CreateGrass() { HRESULT hr = S_OK; float fTileSize = m_fWorldScale / ( float )m_SqrtNumTiles; fTileSize /= 2.0f; float fGrassWidth = m_fGrassWidth / 2.0f; float fGrassHeight = m_fGrassHeight; D3DXVECTOR3* pGrassCenters = new D3DXVECTOR3[ m_NumGrassBlades ]; if( !pGrassCenters ) return E_OUTOFMEMORY; for( UINT i = 0; i < m_NumGrassBlades; i++ ) { pGrassCenters[i].x = RPercent() * fTileSize; pGrassCenters[i].y = 0.0f; pGrassCenters[i].z = RPercent() * fTileSize; } GRASS_VERTEX* pVertices = NULL; D3D10_BUFFER_DESC BufferDesc; if( m_pDev10 ) { BufferDesc.ByteWidth = m_NumGrassBlades * 4 * sizeof( GRASS_VERTEX ); BufferDesc.Usage = D3D10_USAGE_IMMUTABLE; BufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER; BufferDesc.CPUAccessFlags = 0; BufferDesc.MiscFlags = 0; pVertices = new GRASS_VERTEX[ m_NumGrassBlades * 4 ]; if( !pVertices ) return E_OUTOFMEMORY; } else { V_RETURN( m_pDev->CreateVertexBuffer( m_NumGrassBlades * 4 * sizeof( GRASS_VERTEX ), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pGrassVB, NULL ) ); V_RETURN( m_pGrassVB->Lock( 0, 0, ( void** )&pVertices, 0 ) ); } UINT vIndex = 0; for( UINT i = 0; i < m_NumGrassBlades; i++ ) { D3DXVECTOR3 vRandRight( RPercent(), 0, RPercent() ); D3DXVec3Normalize( &vRandRight, &vRandRight ); pVertices[vIndex ].pos = pGrassCenters[i] - vRandRight * fGrassWidth; pVertices[vIndex ].uv = D3DXVECTOR2( 0, 1 ); pVertices[vIndex + 1].pos = pGrassCenters[i] + vRandRight * fGrassWidth; pVertices[vIndex + 1].uv = D3DXVECTOR2( 1, 1 ); pVertices[vIndex + 2].pos = pVertices[vIndex + 1].pos + D3DXVECTOR3( 0, fGrassHeight, 0 ); pVertices[vIndex + 2].uv = D3DXVECTOR2( 1, 0 ); pVertices[vIndex + 3].pos = pVertices[vIndex ].pos + D3DXVECTOR3( 0, fGrassHeight, 0 ); pVertices[vIndex + 3].uv = D3DXVECTOR2( 0, 0 ); vIndex += 4; } if( m_pDev10 ) { D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = pVertices; V_RETURN( m_pDev10->CreateBuffer( &BufferDesc, &InitData, &m_pGrassVB10 ) ); SAFE_DELETE_ARRAY( pVertices ); } else { m_pGrassVB->Unlock(); } // Alloc indices and distances SHORT* pGrassIndices = new SHORT[ m_NumGrassBlades ]; if( !pGrassIndices ) return E_OUTOFMEMORY; float* pGrassDistances = new float[ m_NumGrassBlades ]; if( !pGrassDistances ) return E_OUTOFMEMORY; m_NumDirections = 16; if( m_pDev10 ) { m_ppGrassIB10 = new ID3D10Buffer*[ m_NumDirections ]; if( !m_ppGrassIB10 ) return E_OUTOFMEMORY; } else { m_ppGrassIB = new LPDIRECT3DINDEXBUFFER9[ m_NumDirections ]; if( !m_ppGrassIB ) return E_OUTOFMEMORY; } m_pDirections = new D3DXVECTOR3[ m_NumDirections ]; if( !m_pDirections ) return E_OUTOFMEMORY; D3DXVECTOR3 vStartDir( -1,0,0 ); float fAngleDelta = ( D3DX_PI * 2.0f ) / ( float )( m_NumDirections ); for( UINT i = 0; i < m_NumDirections; i++ ) { D3DXMATRIX mRot; D3DXMatrixRotationY( &mRot, i * fAngleDelta ); D3DXVec3TransformNormal( &m_pDirections[i], &vStartDir, &mRot ); // init indices and distances for( UINT g = 0; g < m_NumGrassBlades; g++ ) { pGrassIndices[g] = ( SHORT )g; pGrassDistances[g] = -D3DXVec3Dot( &m_pDirections[i], &pGrassCenters[g] ); } // sort indices QuickDepthSort( pGrassIndices, pGrassDistances, 0, m_NumGrassBlades - 1 ); SHORT* pIndices = NULL; if( m_pDev10 ) { BufferDesc.ByteWidth = m_NumGrassBlades * 6 * sizeof( SHORT ); BufferDesc.Usage = D3D10_USAGE_IMMUTABLE; BufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; BufferDesc.CPUAccessFlags = 0; BufferDesc.MiscFlags = 0; pIndices = new SHORT[ m_NumGrassBlades * 6 ]; if( !pIndices ) return E_OUTOFMEMORY; } else { V_RETURN( m_pDev->CreateIndexBuffer( m_NumGrassBlades * 6 * sizeof( SHORT ), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_ppGrassIB[i], NULL ) ); V_RETURN( m_ppGrassIB[i]->Lock( 0, 0, ( void** )&pIndices, 0 ) ); } UINT iIndex = 0; for( UINT g = 0; g < m_NumGrassBlades; g++ ) { //Starting vert SHORT GrassIndex = pGrassIndices[g] * 4; //Tri1 pIndices[iIndex ] = GrassIndex; pIndices[iIndex + 1] = GrassIndex + 3; pIndices[iIndex + 2] = GrassIndex + 1; //Tri2 pIndices[iIndex + 3] = GrassIndex + 1; pIndices[iIndex + 4] = GrassIndex + 3; pIndices[iIndex + 5] = GrassIndex + 2; iIndex += 6; } if( m_pDev10 ) { D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = pIndices; V_RETURN( m_pDev10->CreateBuffer( &BufferDesc, &InitData, &m_ppGrassIB10[i] ) ); SAFE_DELETE_ARRAY( pIndices ); } else { m_ppGrassIB[i]->Unlock(); } } SAFE_DELETE_ARRAY( pGrassIndices ); SAFE_DELETE_ARRAY( pGrassDistances ); SAFE_DELETE_ARRAY( pGrassCenters ); return hr; }