📄 zfxd3d_skinman.cpp
字号:
}
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 + -