//-------------------------------------------------------------------------------------- // Update the particle VB using UpdateSubresource //-------------------------------------------------------------------------------------- void SoftParticles::QuickDepthSort(DWORD* indices, float* depths, int lo, int hi) { // lo is the lower index, hi is the upper index // of the region of array a that is to be sorted int i=lo, j=hi; float h; int index; float x=depths[(lo+hi)/2]; // partition do { while (depths[i] > x) i++; while (depths[j] < x) j--; if (i<=j) { h=depths[i]; depths[i]=depths[j]; depths[j]=h; index = indices[i]; indices[i] = indices[j]; indices[j] = index; i++; j--; } } while (i<=j); // recursion if (lo<j) QuickDepthSort(indices, depths, lo, j); if (i<hi) QuickDepthSort(indices, depths, i, hi); }
//-------------------------------------------------------------------------------------- void SortParticles( D3DXVECTOR3 vEye ) { for( UINT i = 0; i < g_NumUsedParticles; i++ ) { g_pParticleIndices[i] = i; D3DXVECTOR3 vDelta = vEye - g_pParticleArray[i].vPos; g_pParticleDepths[i] = D3DXVec3LengthSq( &vDelta ); } QuickDepthSort( g_pParticleIndices, g_pParticleDepths, 0, g_NumUsedParticles - 1 ); }
//-------------------------------------------------------------------------------------- // Sort the particle buffer //-------------------------------------------------------------------------------------- void SoftParticles::SortParticleBuffer( D3DXVECTOR3 vEye, D3DXVECTOR3 vDir ) { if( !g_pParticleDepthArray || !g_pCPUParticleIndices ) return; // assume vDir is normalized D3DXVECTOR3 vToParticle; //init indices and depths for( UINT i=0; i<MAX_PARTICLES; i++ ) { g_pCPUParticleIndices[i] = i; vToParticle = g_pCPUParticles[i].Pos - vEye; g_pParticleDepthArray[i] = D3DXVec3Dot( &vDir, &vToParticle ); } // Sort QuickDepthSort(g_pCPUParticleIndices, g_pParticleDepthArray, 0, MAX_PARTICLES-1); }
//-------------------------------------------------------------------------------------- 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; }