⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zfxd3d_skinman.cpp

📁 This is a book introduce some tech about Game Engine 3D
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      }

   if (bAlpha) fmt = D3DFMT_A8R8G8B8;
   else fmt = D3DFMT_R5G6B5;

   long  lWidth   = dibS.dsBmih.biWidth;
   long  lHeight  = dibS.dsBmih.biHeight;
   BYTE *pBMPBits = (BYTE*)dibS.dsBm.bmBits;

   // build d3d texture object
   hr = m_pDevice->CreateTexture(lWidth, lHeight, 1, 0,
                                 fmt, D3DPOOL_MANAGED,
                                 (LPDIRECT3DTEXTURE9*)(&(pTexture->pData)),
                                 NULL);
   if (FAILED(hr)) {
      if (hr==D3DERR_INVALIDCALL)
         Log("error: IDirect3DDevice::CreateTexture failed (D3DERR_INVALIDCALL)");
      else if (hr==D3DERR_OUTOFVIDEOMEMORY)
         Log("error: IDirect3DDevice::CreateTexture failed (D3DERR_OUTOFVIDEOMEMORY)");
      else if (hr==E_OUTOFMEMORY)
         Log("error: IDirect3DDevice::CreateTexture failed (E_OUTOFMEMORY)");
      else if (hr==D3DOK_NOAUTOGEN)
         Log("error: IDirect3DDevice::CreateTexture failed (D3DOK_NOAUTOGEN)");
      else
         Log("error: IDirect3DDevice::CreateTexture failed (unknown)");

      return ZFX_FAIL;
      }

   // get a dummy pointer
   LPDIRECT3DTEXTURE9 pTex = ((LPDIRECT3DTEXTURE9)pTexture->pData);

   if (FAILED(pTex->LockRect(0, &d3dRect, NULL, 0))) {
      Log("error: cannot lock texture to copy pixels \"%s\"", pTexture->chName);
      return ZFX_BUFFERLOCK;
      }

   if (bAlpha) {
      LineWidth = d3dRect.Pitch >> 2; // 32 bit = 4 byte
      pMemory = (DWORD*)d3dRect.pBits;
      }
   else {
      LineWidth = d3dRect.Pitch >> 1; // 16 bit = 2 Byte
      pMemory = (USHORT*)d3dRect.pBits;
      }

   // copy each pixel: the magic 3 in the formulars is given by the fact
   //                  that each pixel in the BMP is 3 byte (24 bit)
   for (int cy = 0; cy < lHeight; cy++) {
      for (int cx = 0; cx < lWidth; cx++) {

         if (bAlpha) {
            DWORD Color = 0xff000000;
            int   i = (cy*lWidth + cx)*3;
            memcpy(&Color, &pBMPBits[i], sizeof(BYTE)*3);
            ((DWORD*)pMemory)[cx + (cy*LineWidth)] = Color;
            } // 32 Bit
         else {
            // convert each 24 bit pixel value to 16 bit
            UCHAR B = (pBMPBits[(cy*lWidth + cx)*3 + 0]) >> 3,
                  G = (pBMPBits[(cy*lWidth + cx)*3 + 1]) >> 3,
                  R = (pBMPBits[(cy*lWidth + cx)*3 + 2]) >> 3;
            
            USHORT Color = RGB16BIT( (int)(((float) R / 255.0f) * 32.0f),
                                     (int)(((float) G / 255.0f) * 64.0f),
                                     (int)(((float) B / 255.0f) * 32.0f) );

            
            // put pixel as 16 Bit color
            ((USHORT*)pMemory)[cx + (cy*LineWidth)] = Color;
            } // 16 Bit

         } // for
      } // for

   pTex->UnlockRect(0);
   DeleteObject(hBMP);
   return ZFX_OK;
   } // CreateTexture
/*----------------------------------------------------------------*/


// encode vector data as RGBA color value for normal map
DWORD VectortoRGBA(ZFXVector *vc, float fHeight) {
   DWORD r = (DWORD)( 127.0f * vc->x + 128.0f );
   DWORD g = (DWORD)( 127.0f * vc->y + 128.0f );
   DWORD b = (DWORD)( 127.0f * vc->z + 128.0f );
   DWORD a = (DWORD)( 255.0f * fHeight );
   return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
   } // VectortoRGBA
/*----------------------------------------------------------------*/


/**
 * Suppose the texture is 32 Bit format heightmap and needs to be
 * converted to be a normal map instead.
 */
HRESULT ZFXD3DSkinManager::ConvertToNormalmap(ZFXTEXTURE *pTexture) {
   HRESULT hr=ZFX_OK;

   D3DLOCKED_RECT  d3dRect;
   D3DSURFACE_DESC desc;
   
   // get a dummy pointer
   LPDIRECT3DTEXTURE9 pTex = ((LPDIRECT3DTEXTURE9)pTexture->pData);

   pTex->GetLevelDesc(0, &desc);

   if (FAILED(pTex->LockRect(0, &d3dRect, NULL, 0))) {
      Log("error: cannot lock texture to copy pixels \"%s\"", pTexture->chName);
      return ZFX_BUFFERLOCK;
      }

   // get pointer to pixel data
   DWORD* pPixel = (DWORD*)d3dRect.pBits;
   
   // build normals at each pixel
   for (DWORD j=0; j<desc.Height; j++) {
      for (DWORD i=0; i<desc.Width; i++) {
         DWORD color00 = pPixel[0];
         DWORD color10 = pPixel[1];
         DWORD color01 = pPixel[d3dRect.Pitch/sizeof(DWORD)];
         
         float fHeight00 = (float)((color00&0x00ff0000)>>16)/255.0f;
         float fHeight10 = (float)((color10&0x00ff0000)>>16)/255.0f;
         float fHeight01 = (float)((color01&0x00ff0000)>>16)/255.0f;
         
         ZFXVector vcPoint00( i+0.0f, j+0.0f, fHeight00 );
         ZFXVector vcPoint10( i+1.0f, j+0.0f, fHeight10 );
         ZFXVector vcPoint01( i+0.0f, j+1.0f, fHeight01 );
         ZFXVector vc10 = vcPoint10 - vcPoint00;
         ZFXVector vc01 = vcPoint01 - vcPoint00;
         
         ZFXVector vcNormal;
         vcNormal.Cross(vc10, vc01);
         vcNormal.Normalize();
         
         // store normal as RGBA in normalmap
         *pPixel++ = VectortoRGBA( &vcNormal, fHeight00 );
         }
      }
   pTex->UnlockRect(0);
   
LPDIRECT3DSURFACE9 pSurface=NULL;
pTex->GetSurfaceLevel(0, &pSurface);
D3DXSaveSurfaceToFile("normal.bmp", D3DXIFF_BMP, pSurface, NULL, NULL);

   return ZFX_OK;
   } // ConvertToNormalmap
/*----------------------------------------------------------------*/


/**
 * Calculates a 32 bit ARGB value for use with d3d from given RGBA
 * color values ranging from 0-255.
 * -> IN: UCHAR - red value
 *        UCHAR - green value
 *        UCHAR - blue value
 *        UCHAR - alpha value
 */
DWORD ZFXD3DSkinManager::MakeD3DColor(UCHAR R, UCHAR G, UCHAR B, UCHAR A) {
   return (A << 24) | (R << 16) | (G << 8) | B;
   } // MakeD3DColor
/*----------------------------------------------------------------*/


/**
 * Sets the aplha channel of all pixels with given RGB value to the
 * amount of transparency specified. Make sure the corresponding
 * RGB values in the texture have alpha value set to 1.0f. So set
 * all alpha key prior to calling SetTransparency().
 * -> IN:  UCHAR              - red (0-255)
 *         UCHAR              - green (0-255)
 *         UCHAR              - blue (0-255)
 *         UCHAR              - alpha (0-255)
 * <- OUT: LPDIRECT3DTEXTURE9 - changed texture
 */
HRESULT ZFXD3DSkinManager::SetAlphaKey(LPDIRECT3DTEXTURE9 *ppTexture,
                                       UCHAR R, UCHAR G, 
                                       UCHAR B, UCHAR A) {
   D3DSURFACE_DESC  d3dDesc;
   D3DLOCKED_RECT   d3dRect;
   DWORD            dwKey, Color;

   // security check: must be ARGB format
   (*ppTexture)->GetLevelDesc(0, &d3dDesc);
   if (d3dDesc.Format != D3DFMT_A8R8G8B8)
      return ZFX_INVALIDPARAM;

   // calculate the key value
   dwKey = MakeD3DColor(R, G, B, 255);

   // calculate new color to set for key pixels
   if (A > 0) Color = MakeD3DColor(R, G, B, A);
   else Color = MakeD3DColor(0, 0, 0, A);

   if (FAILED((*ppTexture)->LockRect(0, &d3dRect, NULL, 0)))
      return ZFX_BUFFERLOCK;

   // overwrite all key pixels with new color value
   for (DWORD y=0; y<d3dDesc.Height; y++) {
      for (DWORD x=0; x<d3dDesc.Width; x++) {
         if ( ((DWORD*)d3dRect.pBits)[d3dDesc.Width*y+x] == dwKey )
            ((DWORD*)d3dRect.pBits)[d3dDesc.Width*y+x] = Color;
         }
      }
   (*ppTexture)->UnlockRect(0);

   return ZFX_OK;
   } // SetAlphaKey
/*----------------------------------------------------------------*/


/**
 * Sets all pixels in the texture to the amount of transparency.
 * <- OUT: LPDIRECT3DTEXTURE9 - changed texture
 * -> IN:  UCHAR              - alpha value (0-255)
 */
HRESULT ZFXD3DSkinManager::SetTransparency(LPDIRECT3DTEXTURE9 *ppTexture,
                                           UCHAR Alpha) {
   D3DSURFACE_DESC  d3dDesc;
   D3DLOCKED_RECT   d3dRect;
   DWORD            Color;
   UCHAR            A, R, G, B;

   // security check: must be ARGB format
   (*ppTexture)->GetLevelDesc(0, &d3dDesc);
   if (d3dDesc.Format != D3DFMT_A8R8G8B8)
      return ZFX_INVALIDPARAM;

   if (FAILED((*ppTexture)->LockRect(0, &d3dRect, NULL, 0)))
      return ZFX_BUFFERLOCK;

   // loop through all pixels
   for (DWORD y=0; y<d3dDesc.Height; y++) {
      for (DWORD x=0; x<d3dDesc.Width; x++) {
         // get color value from this pixel
         Color = ((DWORD*)d3dRect.pBits)[d3dDesc.Width*y+x];

         // calculate ARGB values from pixel color
         A = (UCHAR)( (Color & 0xff000000) >> 24);
         R = (UCHAR)( (Color & 0x00ff0000) >> 16);
         G = (UCHAR)( (Color & 0x0000ff00) >> 8);
         B = (UCHAR)( (Color & 0x000000ff) >> 0);
         
         // only set new alpha value if old value is greater
         if (A >= Alpha)
            A = Alpha;

         // put new color value for this pixel
         ((DWORD*)d3dRect.pBits)[d3dDesc.Width*y+x] = 
                        MakeD3DColor(R, G, B, A);
         }
      }
   (*ppTexture)->UnlockRect(0);

   return ZFX_OK;
   } // SetTransparency
/*----------------------------------------------------------------*/


/**
 * write outputstring to attribut outputstream if exists
 * -> IN: bool - flush immediately
 *        char - format string to output
 *        ...  - output values
 */
void ZFXD3DSkinManager::Log(char *chString, ...) {

   char ch[256];
   char *pArgs;

   pArgs = (char*) &chString + sizeof(chString);
   vsprintf(ch, chString, pArgs);
   fprintf(m_pLog, "[ZFXD3DSkinMn]: ");
   fprintf(m_pLog, ch);
   fprintf(m_pLog, "\n");
   
   if (g_bLF)
      fflush(m_pLog);
   } // Log
/*----------------------------------------------------------------*/


/**
 * Used to log values e.g. how many skins, testures, materials loaded.
 */
void ZFXD3DSkinManager::LogCurrentStatus(char *chLog, bool bDetailed) {
   FILE *pLog = fopen(chLog, "w");

   fprintf(pLog, "\n\nSKINMANAGER_SITREP: skins: %d, mats: %d, texrs: %d \n", 
           m_nNumSkins, m_nNumMaterials, m_nNumTextures);
   
   if (!bDetailed) return;

   fprintf(pLog, "SKINS { \n");
   for (UINT i=0; i<m_nNumSkins; i++) {
      fprintf(pLog, "   ID: %d { matrl: %d, ", i, m_pSkins[i].nMaterial);
      fprintf(pLog, "textr: [%d,%d,%d,%d,%d,%d,%d,%d] }\n", 
              m_pSkins[i].nTexture[0], m_pSkins[i].nTexture[1],
              m_pSkins[i].nTexture[2], m_pSkins[i].nTexture[3],
              m_pSkins[i].nTexture[4], m_pSkins[i].nTexture[5],
              m_pSkins[i].nTexture[6], m_pSkins[i].nTexture[7]);
      }
   fprintf(pLog, "   } \n");

   fprintf(pLog, "TEXTURES { \n");
   for (UINT j=0; j<m_nNumTextures; j++) {
      fprintf(pLog, "   ID: %d {\"%s\"} \n", j, m_pTextures[j].chName);
      }
   fprintf(pLog, "   } \n\n");

   fprintf(pLog, "MATERIALS { \n");
   for (UINT k=0; k<m_nNumMaterials; k++) {
      fprintf(pLog, "   ID: %d\n", k);
      fprintf(pLog, "   Diffuse (%f,%f,%f,%f)\n", m_pMaterials[k].cDiffuse.c[0],
         m_pMaterials[k].cDiffuse.c[1], m_pMaterials[k].cDiffuse.c[2], 
         m_pMaterials[k].cDiffuse.c[3]);
      fprintf(pLog, "   Ambient (%f,%f,%f,%f)\n", m_pMaterials[k].cAmbient.c[0],
         m_pMaterials[k].cAmbient.c[1], m_pMaterials[k].cAmbient.c[2], 
         m_pMaterials[k].cAmbient.c[3]);
      fprintf(pLog, "   Emissive (%f,%f,%f,%f)\n", m_pMaterials[k].cEmissive.c[0],
         m_pMaterials[k].cEmissive.c[1], m_pMaterials[k].cEmissive.c[2], 
         m_pMaterials[k].cEmissive.c[3]);
      fprintf(pLog, "   Specular (%f,%f,%f,%f) power: %f\n", m_pMaterials[k].cSpecular.c[0],
         m_pMaterials[k].cSpecular.c[1], m_pMaterials[k].cSpecular.c[2], 
         m_pMaterials[k].cSpecular.c[3], m_pMaterials[k].fPower);
      }
   fprintf(pLog, "   } \n\n");

   fclose(pLog);
   } // LogCurrentStatus
/*----------------------------------------------------------------*/


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -