www.pudn.com > snow.rar > D3DHelperFuncs.cpp


 
#include "D3DHelperFuncs.h" 
 
char *SurfFormatToString(D3DFORMAT srcformat) 
{ 
  switch(srcformat) { 
    case D3DFMT_UNKNOWN:      return("D3DFMT_UNKNOWN");       
                              
    case D3DFMT_R8G8B8:       return("D3DFMT_R8G8B8");        
    case D3DFMT_A8R8G8B8:     return("D3DFMT_A8R8G8B8");      
    case D3DFMT_X8R8G8B8:     return("D3DFMT_X8R8G8B8");      
    case D3DFMT_R5G6B5:       return("D3DFMT_R5G6B5");        
    case D3DFMT_X1R5G5B5:     return("D3DFMT_X1R5G5B5");      
    case D3DFMT_A1R5G5B5:     return("D3DFMT_A1R5G5B5");      
    case D3DFMT_A4R4G4B4:     return("D3DFMT_A4R4G4B4");      
    case D3DFMT_R3G3B2:       return("D3DFMT_R3G3B2");        
    case D3DFMT_A8:           return("D3DFMT_A8");            
    case D3DFMT_A8R3G3B2:     return("D3DFMT_A8R3G3B2");      
    case D3DFMT_X4R4G4B4:     return("D3DFMT_X4R4G4B4");      
                              
    case D3DFMT_A8P8:         return("D3DFMT_A8P8");          
    case D3DFMT_P8:           return("D3DFMT_P8");            
                              
    case D3DFMT_L8:           return("D3DFMT_L8");            
    case D3DFMT_A8L8:         return("D3DFMT_A8L8");          
    case D3DFMT_A4L4:         return("D3DFMT_A4L4");          
                              
    case D3DFMT_V8U8:         return("D3DFMT_V8U8");          
    case D3DFMT_L6V5U5:       return("D3DFMT_L6V5U5");        
    case D3DFMT_X8L8V8U8:     return("D3DFMT_X8L8V8U8");      
    case D3DFMT_Q8W8V8U8:     return("D3DFMT_Q8W8V8U8");      
    case D3DFMT_V16U16:       return("D3DFMT_V16U16");        
   // case D3DFMT_W11V11U10:    return("D3DFMT_W11V11U10");     
                                                                  
    case D3DFMT_UYVY:         return("D3DFMT_UYVY");          
    case D3DFMT_YUY2:         return("D3DFMT_YUY2");          
    case D3DFMT_DXT1:         return("D3DFMT_DXT1");          
    case D3DFMT_DXT2:         return("D3DFMT_DXT2");          
    case D3DFMT_DXT3:         return("D3DFMT_DXT3");          
    case D3DFMT_DXT4:         return("D3DFMT_DXT4");          
    case D3DFMT_DXT5:         return("D3DFMT_DXT5");          
 
    case D3DFMT_D16_LOCKABLE: return("D3DFMT_D16_LOCKABLE");  
    case D3DFMT_D32:          return("D3DFMT_D32");           
    case D3DFMT_D15S1:        return("D3DFMT_D15S1");         
    case D3DFMT_D24S8:        return("D3DFMT_D24S8");         
    case D3DFMT_D16:          return("D3DFMT_D16");           
    case D3DFMT_D24X8:        return("D3DFMT_D24X8");         
    case D3DFMT_D24X4S4:      return("D3DFMT_D24X4S4");       
 
    case D3DFMT_VERTEXDATA:   return("D3DFMT_VERTEXDATA");  
    case D3DFMT_INDEX16:      return("D3DFMT_INDEX16");  
    case D3DFMT_INDEX32:      return("D3DFMT_INDEX32");  
    default:                  return("**UNKNOWN**");  
  }; 
  return(""); 
} 
 
HRESULT CreateQuad(LPDIRECT3DVERTEXBUFFER9 *pVB, D3DPOOL pool, float fSize,  
                   DWORD dwColor, LPDIRECT3DDEVICE9 pDev, 
                   float fTexTileX, float fTexTileY) 
{ 
  HRESULT hr; 
 
  if(FAILED(hr = pDev->CreateVertexBuffer(6*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), 
                  0, D3DFVF_XYZ_DIFFUSE_TEX1, pool, pVB,NULL))) 
    return hr; 
 
  VERTEX_XYZ_DIFFUSE_TEX1 *pVertices; 
  float fSizeDiv2 = fSize/2; 
 
  if( FAILED( hr = (*pVB)->Lock( 0, 6*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), (VOID**)&pVertices, 0 ) ) ) 
      return hr; 
 
  // first triangle 
  pVertices[0].position = D3DXVECTOR3(-fSizeDiv2, fSizeDiv2, 0.0f); 
  pVertices[0].color    = dwColor; 
  pVertices[0].tu       = 0.0f; 
  pVertices[0].tv       = 0.0f; 
 
  pVertices[1].position = D3DXVECTOR3(fSizeDiv2, fSizeDiv2, 0.0f); 
  pVertices[1].color    = dwColor; 
  pVertices[1].tu       = fTexTileX; 
  pVertices[1].tv       = 0.0f; 
 
  pVertices[2].position = D3DXVECTOR3(fSizeDiv2, -fSizeDiv2, 0.0f); 
  pVertices[2].color    = dwColor; 
  pVertices[2].tu       = fTexTileX; 
  pVertices[2].tv       = fTexTileY; 
 
  // second triangle 
  pVertices[3].position = D3DXVECTOR3(-fSizeDiv2, fSizeDiv2, 0.0f); 
  pVertices[3].color    = dwColor; 
  pVertices[3].tu       = 0.0f; 
  pVertices[3].tv       = 0.0f; 
 
  pVertices[4].position = D3DXVECTOR3(fSizeDiv2, -fSizeDiv2, 0.0f); 
  pVertices[4].color    = dwColor; 
  pVertices[4].tu       = fTexTileX; 
  pVertices[4].tv       = fTexTileY; 
 
  pVertices[5].position = D3DXVECTOR3(-fSizeDiv2, -fSizeDiv2, 0.0f); 
  pVertices[5].color    = dwColor; 
  pVertices[5].tu       = 0.0f; 
  pVertices[5].tv       = fTexTileY; 
 
  if( FAILED( hr = (*pVB)->Unlock() ) ) return hr; 
  return(S_OK); 
} 
 
HRESULT CreateVertexGrid(LPDIRECT3DVERTEXBUFFER9 *pVB, LPDIRECT3DINDEXBUFFER9 *pIB, 
                         D3DPOOL pool, float fTotalSize, DWORD dwColor,  
                         int iNumVerticesX, int iNumVerticesY, LPDIRECT3DDEVICE9 pDev) 
{ 
  HRESULT hr; 
 
  // create and fill vertex buffer 
  { 
    if(FAILED(hr = pDev->CreateVertexBuffer(iNumVerticesX*iNumVerticesY*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), 
                    0, D3DFVF_XYZ_DIFFUSE_TEX1, pool, pVB,NULL))) 
      return hr; 
 
    VERTEX_XYZ_DIFFUSE_TEX1 *pVertices; 
    float fSizeDiv2 = fTotalSize/2; 
 
    if( FAILED( hr = (*pVB)->Lock( 0, iNumVerticesX*iNumVerticesY*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), (VOID**)&pVertices, 0 ) ) ) 
        return hr; 
 
    for (int x=0; x < iNumVerticesX; x++) { 
      for (int y=0; y < iNumVerticesY; y++) { 
        pVertices[(y*iNumVerticesX)+x].position = D3DXVECTOR3( 
          (iNumVerticesX > 1) ? (((float)x/(float)(iNumVerticesX-1))*fTotalSize)-fSizeDiv2 : 0,  
          (iNumVerticesY > 1) ? (((float)(iNumVerticesY-1-y)/(float)(iNumVerticesY-1))*fTotalSize)-fSizeDiv2 : 0,  
          0.0f); 
 
        pVertices[(y*iNumVerticesX)+x].color    = dwColor; 
        pVertices[(y*iNumVerticesX)+x].tu       = (float)x/(float)(iNumVerticesX-1); 
        pVertices[(y*iNumVerticesX)+x].tv       = (float)y/(float)(iNumVerticesY-1); 
      } 
    } 
  } 
 
  // create index buffer 
  { 
    if(FAILED(hr = pDev->CreateIndexBuffer( 
        iNumVerticesX*iNumVerticesY*2*3*2, // *2 (tris) *3 (indicies per tri) * 2 (bytes per index) 
        D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, 
        D3DPOOL_MANAGED, pIB,NULL))) 
      return hr; 
 
    // lock and fill index buffer 
 
    WORD *pIndices; 
    if(FAILED(hr = (*pIB)->Lock(0, iNumVerticesX*iNumVerticesY*2*3*2, (VOID**)&pIndices,  
      0))) 
      return hr; 
   
    WORD *pIndex = pIndices; 
    for (int x=0; x < iNumVerticesX-1; x++) { 
      for (int y=0; y < iNumVerticesY-1; y++) { 
        // first triangle 
        *(pIndex++) = ((y)*iNumVerticesX)+x; 
        *(pIndex++) = ((y)*iNumVerticesX)+x+1; 
        *(pIndex++) = ((y+1)*iNumVerticesX)+x+1; 
 
        // second triangle 
        *(pIndex++) = ((y)*iNumVerticesX)+x; 
        *(pIndex++) = ((y+1)*iNumVerticesX)+x+1; 
        *(pIndex++) = ((y+1)*iNumVerticesX)+x; 
      } 
    } 
 
    if(FAILED(hr = (*pIB)->Unlock())) return hr; 
    if(FAILED(hr = (*pVB)->Unlock())) return hr; 
  } 
  return(S_OK); 
 
} 
 
HRESULT CreateVertexFrame(LPDIRECT3DVERTEXBUFFER9 *pVB, LPDIRECT3DINDEXBUFFER9 *pIB, 
                         D3DPOOL pool, float fTotalSize, DWORD dwColor,  
                         int iNumVerticesX, int iNumVerticesY, LPDIRECT3DDEVICE9 pDev) 
{ 
  HRESULT hr; 
 
  // create and fill vertex buffer 
  { 
    if(FAILED(hr = pDev->CreateVertexBuffer((((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2)+2)*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), 
      0, D3DFVF_XYZ_DIFFUSE_TEX1, pool, pVB,NULL))) 
      return hr; 
 
    VERTEX_XYZ_DIFFUSE_TEX1 *pVertices; 
    float fSizeDiv2 = fTotalSize/2; 
 
    if( FAILED( hr = (*pVB)->Lock( 0, (((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2)+1)*sizeof(VERTEX_XYZ_DIFFUSE_TEX1), (VOID**)&pVertices, 0 ) ) ) 
        return hr; 
 
    // top row 
    for (int x=0; x < iNumVerticesX; x++) { 
      pVertices->position = D3DXVECTOR3( 
        (((float)x/(float)(iNumVerticesX-1))*fTotalSize)-fSizeDiv2,  
        fSizeDiv2,  
        0.0f); 
 
      pVertices->color    = dwColor; 
      pVertices->tu       = (float)x/(float)(iNumVerticesX-1); 
      pVertices->tv       = 0.0f; 
      pVertices++; 
    } 
     
    // right row 
    for (int y=1; y < iNumVerticesY; y++) { 
      pVertices->position = D3DXVECTOR3( 
        fSizeDiv2,  
        (((float)(iNumVerticesY-1-y)/(float)(iNumVerticesY-1))*fTotalSize)-fSizeDiv2,  
        0.0f); 
 
      pVertices->color    = dwColor; 
      pVertices->tu       = 1.0f; 
      pVertices->tv       = (float)y/(float)(iNumVerticesY-1); 
      pVertices++; 
    } 
 
    // bottom row 
    for (x=iNumVerticesX-1; x >= 1; x--) { 
      pVertices->position = D3DXVECTOR3( 
        (((float)x/(float)(iNumVerticesX-1))*fTotalSize)-fSizeDiv2,  
        -fSizeDiv2,  
        0.0f); 
 
      pVertices->color    = dwColor; 
      pVertices->tu       = (float)x/(float)(iNumVerticesX-1); 
      pVertices->tv       = 1.0f; 
      pVertices++; 
    } 
     
    // left row 
    for (y=iNumVerticesY-1; y >= 1; y--) { 
      pVertices->position = D3DXVECTOR3( 
        -fSizeDiv2,  
        (((float)(iNumVerticesY-1-y)/(float)(iNumVerticesY-1))*fTotalSize)-fSizeDiv2,  
        0.0f); 
 
      pVertices->color    = dwColor; 
      pVertices->tu       = 0.0f; 
      pVertices->tv       = (float)y/(float)(iNumVerticesY-1); 
      pVertices++; 
    } 
 
     
    // last point in exact center 
    pVertices->position = D3DXVECTOR3(0.0f,0.0f, 0.0f); 
    pVertices->color    = dwColor; 
    pVertices->tu       = 0.5f; 
    pVertices->tv       = 0.5f; 
     
  } 
 
  // create index buffer 
  { 
    if(FAILED(hr = pDev->CreateIndexBuffer( 
        (((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2))*3*2, // *3 (indicies per tri) * 2 (bytes per index) 
        D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, 
        D3DPOOL_MANAGED, pIB,NULL))) 
      return hr; 
 
    // lock and fill index buffer 
 
    WORD *pIndices; 
    if(FAILED(hr = (*pIB)->Lock(0, (((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2))*3*2, (VOID**)&pIndices,  
      0))) 
      return hr; 
   
    // the triangles are arranged in a fan pattern...  
    // probably could have used tri fans here but GeForce class cards like tri lists better 
    WORD *pIndex = pIndices; 
    for (int q=0; q < (((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2)); q++) { 
      // first triangle 
      *(pIndex++) = q; 
      *(pIndex++) = ((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2); 
      *(pIndex++) = ((q+1 == ((iNumVerticesX-1)*2)+((iNumVerticesY-1)*2)) ? 0 : q+1); 
    } 
 
    if(FAILED(hr = (*pIB)->Unlock())) return hr; 
    if(FAILED(hr = (*pVB)->Unlock())) return hr; 
  } 
  return(S_OK); 
 
} 
 
 
HRESULT RenderCopy(LPDIRECT3DTEXTURE9 ptexSource, LPDIRECT3DTEXTURE9 ptexDest, 
                   int iDestWidth, int iDestHeight, LPDIRECT3DDEVICE9 pDev, 
                   LPDIRECT3DVERTEXBUFFER9 pvbQuad) 
{ 
  HRESULT hr; 
  // get the current depth buffer (we have to pass this into SetRenderTarget 
  // so we don't inadvertently drop our depth buffer.) 
  LPDIRECT3DSURFACE9 pDepthSurf; 
  pDev->GetDepthStencilSurface(&pDepthSurf); 
 
  // get the current rendering target (we'll set it back later) 
  LPDIRECT3DSURFACE9 pOldRenderTarget; 
  pDev->GetRenderTarget(0, &pOldRenderTarget); 
 
  // get surface interfaces 
  LPDIRECT3DSURFACE9 psurfDest; 
  ptexDest->GetSurfaceLevel(0, &psurfDest); 
 
  // set new rendering target & clear 
  pDev->SetRenderTarget(0,psurfDest); 
  pDev->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000, 1.0f, 0L ); 
   
  // turn off z buffering 
  pDev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 
   
  // set up texture stages for simple texture stage copy 
	pDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1); 
	pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); 
	pDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); 
	pDev->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);  
	pDev->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1); 
 
  SetupOrthoProjForRenderCopy(pDev, iDestWidth, iDestHeight); 
 
  // set the source texture active 
  pDev->SetTexture(0, ptexSource); 
 
  // begin rendering the scene 
  if (FAILED(hr = pDev->BeginScene())) return hr; 
  pDev->SetStreamSource( 0, pvbQuad,0, sizeof(VERTEX_XYZ_DIFFUSE_TEX1)); 
  //pDev->SetVertexShader( D3DFVF_XYZ_DIFFUSE_TEX1 ); 
 
  // this "blits" the texture 
  pDev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ); 
 
  // end scene 
  pDev->EndScene(); 
   
  // release the dest surface  
  psurfDest->Release(); 
 
  // set the rendering target back to the old target. 
  pDev->SetRenderTarget(0, pDepthSurf); 
  pDev->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 
  pOldRenderTarget->Release(); 
 
  // release the depth surface interface. 
  pDepthSurf->Release(); 
  return S_OK; 
} 
 
HRESULT SmoothRenderCopy(LPDIRECT3DTEXTURE9 ptexSource, LPDIRECT3DTEXTURE9 ptexDest,  
                         int iDestWidth, int iDestHeight, LPDIRECT3DDEVICE9 pDev,  
                         LPDIRECT3DVERTEXBUFFER9 pvbQuad) 
{ 
  // no alpha blending or lighting 
  pDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 
	pDev->SetRenderState(D3DRS_LIGHTING, FALSE); 
 
  // turn on bilinear filtering (this is what "smooths the noise") 
 // pDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); 
  //pDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); 
  //pDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); 
   
  // render-copy the texture 
  return(RenderCopy(ptexSource, ptexDest, iDestWidth, iDestHeight, pDev, pvbQuad)); 
} 
 
HRESULT SetupOrthoProjForRenderCopy(LPDIRECT3DDEVICE9 pDev, int iWidth, int iHeight) 
{ 
  // set up orthogonal projection matrix, so that one texel = one pixel in the final 
  // image, with no perspective correction. 
  D3DXMATRIX projmat; 
  D3DXMatrixOrthoLH(&projmat, (float)iWidth, (float)iHeight, 0.0, 100.0); 
  pDev->SetTransform( D3DTS_PROJECTION, &projmat ); 
 
  // set up world matrix so that it rotates the quad slightly. 
  D3DXMATRIX worldmattemp, worldmat, transmat; 
  D3DXMatrixScaling(&worldmattemp, (float)iWidth/2.0f, (float)iHeight/2.0f, 1.0); 
 
  // move the quad left and up 0.5 units, so that the texels are perfectly 
  // centered on the screen pixels. 
  D3DXMatrixMultiply(&worldmat, &worldmattemp, D3DXMatrixTranslation(&transmat, -0.5f, -0.5f, 0)); 
 
  pDev->SetTransform( D3DTS_WORLD, &worldmat ); 
 
  // set up view matrix 
  D3DXMATRIX viewmat; 
  D3DXMatrixIdentity(&viewmat); 
  pDev->SetTransform( D3DTS_VIEW, &viewmat ); 
  return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: DoesRayIntersectTriangle() 
// Desc: Given a ray origin (orig) and direction (dir), and three vertices of 
//       of a triangle, this function returns TRUE and the interpolated texture 
//       coordinates if the ray intersects the triangle 
//----------------------------------------------------------------------------- 
bool DoesRayIntersectTriangle( const D3DXVECTOR3& orig, 
                               const D3DXVECTOR3& dir, D3DXVECTOR3& v0, 
                               D3DXVECTOR3& v1, D3DXVECTOR3& v2, 
                               FLOAT* t, FLOAT* u, FLOAT* v ) 
{ 
    // Find vectors for two edges sharing vert0 
    D3DXVECTOR3 edge1 = v1 - v0; 
    D3DXVECTOR3 edge2 = v2 - v0; 
 
    // Begin calculating determinant - also used to calculate U parameter 
    D3DXVECTOR3 pvec; 
    D3DXVec3Cross( &pvec, &dir, &edge2 ); 
 
    // If determinant is near zero, ray lies in plane of triangle 
    FLOAT det = D3DXVec3Dot( &edge1, &pvec ); 
    if( det < 0.0001f ) 
        return false; 
 
    // Calculate distance from vert0 to ray origin 
    D3DXVECTOR3 tvec = orig - v0; 
 
    // Calculate U parameter and test bounds 
    *u = D3DXVec3Dot( &tvec, &pvec ); 
    if( *u < 0.0f || *u > det ) 
        return false; 
 
    // Prepare to test V parameter 
    D3DXVECTOR3 qvec; 
    D3DXVec3Cross( &qvec, &tvec, &edge1 ); 
 
    // Calculate V parameter and test bounds 
    *v = D3DXVec3Dot( &dir, &qvec ); 
    if( *v < 0.0f || *u + *v > det ) 
        return false; 
 
    // Calculate t, scale parameters, ray intersects triangle 
    *t = D3DXVec3Dot( &edge2, &qvec ); 
    FLOAT fInvDet = 1.0f / det; 
    *t *= fInvDet; 
    *u *= fInvDet; 
    *v *= fInvDet; 
 
    return true; 
} 
 
HRESULT CreateShader(LPDIRECT3DDEVICE9 pDev, const char *strFilename,  
                     DWORD *pDecl, DWORD &dwID) 
{/* 
  HRESULT hr; 
  LPD3DXBUFFER pCode; 
  D3DXMACRO*pDefines; 
  // Assemble the shader from the file 
  if( FAILED( hr =D3DXAssembleShaderFromFile( strFilename, pDefines, 
                                                 &pCode, 0,NULL, NULL ) ) ) 
    return hr; 
 
  // if PDecl is not null, we know this is a vertex shader. 
  if (pDecl) { 
    hr = pDev->CreateVertexShader( pDecl,  
      (DWORD*)pCode->GetBufferPointer(), &dwID, 0 ); 
  } 
  else { 
    // it's a pixel shader! 
    hr = pDev->CreatePixelShader((DWORD *)pCode->GetBufferPointer(), &dwID); 
  } 
   
  pCode->Release(); 
  if( FAILED(hr) ) return hr;*/ 
  return(S_OK); 
}