| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975 |
- //-------------------------------------------------------------------------------
- /**
- * This program is distributed under the terms of the GNU Lesser General
- * Public License (LGPL).
- *
- * ASSIMP Viewer Utility
- *
- */
- //-------------------------------------------------------------------------------
- #include "stdafx.h"
- #include "assimp_view.h"
- namespace AssimpView {
- //
- // Specifies the number of different shaders generated for
- // the current asset. This number is incremented by CreateMaterial()
- // each time a shader isn't found in cache and needs to be created
- //
- unsigned int g_iShaderCount = 0 ;
- //-------------------------------------------------------------------------------
- // Compiler idependent stricmp() function.
- //
- // Used for case insensitive string comparison
- //-------------------------------------------------------------------------------
- inline int ASSIMP_stricmp(const char *s1, const char *s2)
- {
- const char *a1, *a2;
- a1 = s1;
- a2 = s2;
- while (true)
- {
- char c1 = (char)tolower(*a1);
- char c2 = (char)tolower(*a2);
- if ((0 == c1) && (0 == c2)) return 0;
- if (c1 < c2) return-1;
- if (c1 > c2) return 1;
- ++a1;
- ++a2;
- }
- }
- //-------------------------------------------------------------------------------
- // D3DX callback function to fill a texture with a checkers pattern
- //
- // This pattern is used to mark textures which could not be loaded
- //-------------------------------------------------------------------------------
- VOID WINAPI FillFunc(D3DXVECTOR4* pOut,
- CONST D3DXVECTOR2* pTexCoord,
- CONST D3DXVECTOR2* pTexelSize,
- LPVOID pData)
- {
- UNREFERENCED_PARAMETER(pData);
- UNREFERENCED_PARAMETER(pTexelSize);
- // generate a nice checker pattern (yellow/black)
- // size of a square: 32 * 32 px
- unsigned int iX = (unsigned int)(pTexCoord->x * 256.0f);
- unsigned int iY = (unsigned int)(pTexCoord->y * 256.0f);
- bool bBlack = false;
- if ((iX / 32) % 2 == 0)
- {
- if ((iY / 32) % 2 == 0)bBlack = true;
- }
- else
- {
- if ((iY / 32) % 2 != 0)bBlack = true;
- }
- pOut->w = 1.0f;
- if (bBlack)
- {
- pOut->x = pOut->y = pOut->z = 0.0f;
- }
- else
- {
- pOut->x = pOut->y = 1.0f;
- pOut->z = 0.0f;
- }
- return;
- }
- //-------------------------------------------------------------------------------
- // Setup the default texture for a texture channel
- //
- // Generates a default checker pattern for a texture
- //-------------------------------------------------------------------------------
- int SetDefaultTexture(IDirect3DTexture9** p_ppiOut)
- {
- if(FAILED(g_piDevice->CreateTexture(
- 256,
- 256,
- 0,
- 0,
- D3DFMT_A8R8G8B8,
- D3DPOOL_MANAGED,
- p_ppiOut,
- NULL)))
- {
- CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture",
- D3DCOLOR_ARGB(0xFF,0xFF,0,0));
- }
- D3DXFillTexture(*p_ppiOut,&FillFunc,NULL);
- return 1;
- }
- //-------------------------------------------------------------------------------
- // find a valid path to a texture file
- //
- // Handle 8.3 syntax correctly, search the environment of the
- // executable and the asset for a texture with a name very similar to a given one
- //-------------------------------------------------------------------------------
- bool TryLongerPath(char* szTemp,aiString* p_szString)
- {
- char szTempB[MAX_PATH];
- strcpy(szTempB,szTemp);
- // go to the beginning of the file name
- char* szFile = strrchr(szTempB,'\\');
- if (!szFile)szFile = strrchr(szTempB,'/');
-
- char* szFile2 = szTemp + (szFile - szTempB)+1;
- szFile++;
- char* szExt = strrchr(szFile,'.')+1;
- *szFile = 0;
- strcat(szTempB,"*.*");
- const unsigned int iSize = (const unsigned int) ( szExt - 1 - szFile );
- HANDLE h;
- WIN32_FIND_DATA info;
- // build a list of files
- h = FindFirstFile(szTempB, &info);
- if (h != INVALID_HANDLE_VALUE)
- {
- do
- {
- if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0))
- {
- char* szExtFound = strrchr(info.cFileName, '.')+1;
- if ((char*)0x1 != szExtFound)
- {
- if (0 == ASSIMP_stricmp(szExtFound,szExt))
- {
- const unsigned int iSizeFound = (const unsigned int) (
- szExtFound - 1 - info.cFileName);
- for (unsigned int i = 0; i < iSizeFound;++i)
- info.cFileName[i] = (CHAR)tolower(info.cFileName[i]);
- if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize)))
- {
- // we have it. Build the full path ...
- char* sz = strrchr(szTempB,'*');
- *(sz-2) = 0x0;
- strcat(szTempB,info.cFileName);
- // copy the result string back to the aiString
- const size_t iLen = strlen(szTempB);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(p_szString->data,szTempB,iLen2);
- p_szString->length = iLen;
- return true;
- }
- }
- // check whether the 8.3 DOS name is matching
- if (0 == ASSIMP_stricmp(info.cAlternateFileName,p_szString->data))
- {
- strcat(szTempB,info.cAlternateFileName);
- // copy the result string back to the aiString
- const size_t iLen = strlen(szTempB);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(p_szString->data,szTempB,iLen2);
- p_szString->length = iLen;
- return true;
- }
- }
- }
- }
- while (FindNextFile(h, &info));
- FindClose(h);
- }
- return false;
- }
- //-------------------------------------------------------------------------------
- // find a valid path to a texture file
- //
- // Handle 8.3 syntax correctly, search the environment of the
- // executable and the asset for a texture with a name very similar to a given one
- //-------------------------------------------------------------------------------
- int FindValidPath(aiString* p_szString)
- {
- // first check whether we can directly load the file
- FILE* pFile = fopen(p_szString->data,"rb");
- if (pFile)fclose(pFile);
- else
- {
- // check whether we can use the directory of
- // the asset as relative base
- char szTemp[MAX_PATH*2];
- strcpy(szTemp, g_szFileName);
- char* szData = p_szString->data;
- if (*szData == '\\' || *szData == '/')++szData;
- char* szEnd = strrchr(szTemp,'\\');
- if (!szEnd)
- {
- szEnd = strrchr(szTemp,'/');
- if (!szEnd)szEnd = szTemp;
- }
- szEnd++;
- *szEnd = 0;
- strcat(szEnd,szData);
- pFile = fopen(szTemp,"rb");
- if (!pFile)
- {
- // convert the string to lower case
- for (unsigned int i = 0;;++i)
- {
- if ('\0' == szTemp[i])break;
- szTemp[i] = (char)tolower(szTemp[i]);
- }
- if(TryLongerPath(szTemp,p_szString))return 1;
- *szEnd = 0;
- // search common sub directories
- strcat(szEnd,"tex\\");
- strcat(szEnd,szData);
- pFile = fopen(szTemp,"rb");
- if (!pFile)
- {
- if(TryLongerPath(szTemp,p_szString))return 1;
- *szEnd = 0;
- strcat(szEnd,"textures\\");
- strcat(szEnd,szData);
- pFile = fopen(szTemp,"rb");
- if (!pFile)
- {
- if(TryLongerPath(szTemp, p_szString))return 1;
-
- // still unable to load ... however, don't spew
- // an error message here, simply let it and wait for
- // D3DXCreateTextureFromFileEx() to fail ;-)
- }
- return 0;
- }
- }
- fclose(pFile);
- // copy the result string back to the aiString
- const size_t iLen = strlen(szTemp);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(p_szString->data,szTemp,iLen2);
- p_szString->length = iLen;
- }
- return 1;
- }
- //-------------------------------------------------------------------------------
- // Load a texture into memory and create a native D3D texture resource
- //
- // The function tries to find a valid path for a texture
- //-------------------------------------------------------------------------------
- int LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
- {
- // first get a valid path to the texture
- FindValidPath(szPath);
- *p_ppiOut = NULL;
- // then call D3DX to load the texture
- if (FAILED(D3DXCreateTextureFromFileEx(
- g_piDevice,
- szPath->data,
- D3DX_DEFAULT,
- D3DX_DEFAULT,
- 0,
- 0,
- D3DFMT_A8R8G8B8,
- D3DPOOL_MANAGED,
- D3DX_DEFAULT,
- D3DX_DEFAULT,
- 0,
- NULL,
- NULL,
- p_ppiOut)))
- {
- // error ... use the default texture instead
- std::string sz = "[ERROR] Unable to load texture: ";
- sz.append(szPath->data);
- CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
- SetDefaultTexture(p_ppiOut);
- }
- return 1;
- }
- //-------------------------------------------------------------------------------
- // Delete all resources of a given material
- //
- // Must be called before CreateMaterial() to prevent memory leaking
- //-------------------------------------------------------------------------------
- void DeleteMaterial(AssetHelper::MeshHelper* pcIn)
- {
- if (!pcIn || !pcIn->piEffect)return;
- pcIn->piEffect->Release();
- // release all textures associated with the material
- if (pcIn->piDiffuseTexture)
- {
- pcIn->piDiffuseTexture->Release();
- pcIn->piDiffuseTexture = NULL;
- }
- if (pcIn->piSpecularTexture)
- {
- pcIn->piSpecularTexture->Release();
- pcIn->piSpecularTexture = NULL;
- }
- if (pcIn->piEmissiveTexture)
- {
- pcIn->piEmissiveTexture->Release();
- pcIn->piEmissiveTexture = NULL;
- }
- if (pcIn->piAmbientTexture)
- {
- pcIn->piAmbientTexture->Release();
- pcIn->piAmbientTexture = NULL;
- }
- if (pcIn->piOpacityTexture)
- {
- pcIn->piOpacityTexture->Release();
- pcIn->piOpacityTexture = NULL;
- }
- if (pcIn->piNormalTexture)
- {
- pcIn->piNormalTexture->Release();
- pcIn->piNormalTexture = NULL;
- }
- }
- //-------------------------------------------------------------------------------
- // Convert a height map to a normal map if necessary
- //
- // The function tries to detect the type of a texture automatically.
- // However, this wont work in every case.
- //-------------------------------------------------------------------------------
- void HMtoNMIfNecessary(IDirect3DTexture9* piTexture,IDirect3DTexture9** piTextureOut,
- bool bWasOriginallyHM = true)
- {
- bool bMustConvert = false;
- uintptr_t iElement = 3;
- *piTextureOut = piTexture;
- // Lock the input texture and try to determine its type.
- // Criterias:
- // - If r,g,b channel are identical it MUST be a height map
- // - If one of the rgb channels is used and the others are empty it
- // must be a height map, too.
- // - If the average color of the whole image is something inside the
- // purple range we can be sure it is a normal map
- //
- // - Otherwise we assume it is a normal map
- // To increase performance we take not every pixel
- D3DLOCKED_RECT sRect;
- D3DSURFACE_DESC sDesc;
- piTexture->GetLevelDesc(0,&sDesc);
- if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY)))
- {
- return;
- }
- const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4);
- struct SColor
- {
- union
- {
- struct {unsigned char b,g,r,a;};
- char _array[4];
- };
- };
- const SColor* pcData = (const SColor*)sRect.pBits;
- union
- {
- const SColor* pcPointer;
- const unsigned char* pcCharPointer;
- };
- pcPointer = pcData;
- // 1. If r,g,b channel are identical it MUST be a height map
- bool bIsEqual = true;
- for (unsigned int y = 0; y < sDesc.Height;++y)
- {
- for (unsigned int x = 0; x < sDesc.Width;++x)
- {
- if (pcPointer->b != pcPointer->r || pcPointer->b != pcPointer->g)
- {
- bIsEqual = false;
- break;
- }
- pcPointer++;
- }
- pcCharPointer += iPitchDiff;
- }
- if (bIsEqual)bMustConvert = true;
- else
- {
- // 2. If one of the rgb channels is used and the others are empty it
- // must be a height map, too.
- pcPointer = pcData;
- while (*pcCharPointer == 0)pcCharPointer++;
- iElement = (uintptr_t)(pcCharPointer - (unsigned char*)pcData) % 4;
- unsigned int aiIndex[3] = {0,1,2};
- if (3 != iElement)aiIndex[iElement] = 3;
- pcPointer = pcData;
- bIsEqual = true;
- if (3 != iElement)
- {
- for (unsigned int y = 0; y < sDesc.Height;++y)
- {
- for (unsigned int x = 0; x < sDesc.Width;++x)
- {
- for (unsigned int ii = 0; ii < 3;++ii)
- {
- // don't take the alpha channel into account.
- // if the texture was stored n RGB888 format D3DX has
- // converted it to ARGB8888 format with a fixed alpha channel
- if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0)
- {
- bIsEqual = false;
- break;
- }
- }
- pcPointer++;
- }
- pcCharPointer += iPitchDiff;
- }
- if (bIsEqual)bMustConvert = true;
- else
- {
- // If the average color of the whole image is something inside the
- // purple range we can be sure it is a normal map
- // (calculate the average color line per line to prevent overflows!)
- pcPointer = pcData;
- aiColor3D clrColor;
- for (unsigned int y = 0; y < sDesc.Height;++y)
- {
- aiColor3D clrColorLine;
- for (unsigned int x = 0; x < sDesc.Width;++x)
- {
- clrColorLine.r += pcPointer->r;
- clrColorLine.g += pcPointer->g;
- clrColorLine.b += pcPointer->b;
- pcPointer++;
- }
- clrColor.r += clrColorLine.r /= (float)sDesc.Width;
- clrColor.g += clrColorLine.g /= (float)sDesc.Width;
- clrColor.b += clrColorLine.b /= (float)sDesc.Width;
- pcCharPointer += iPitchDiff;
- }
- clrColor.r /= (float)sDesc.Height;
- clrColor.g /= (float)sDesc.Height;
- clrColor.b /= (float)sDesc.Height;
- if (!(clrColor.b > 215 &&
- clrColor.r > 100 && clrColor.r < 140 &&
- clrColor.g > 100 && clrColor.g < 140))
- {
- // Unable to detect. Believe the original value obtained from the loader
- if (bWasOriginallyHM)
- {
- bMustConvert = true;
- }
- }
- }
- }
- }
- piTexture->UnlockRect(0);
- // if the input data is assumed to be a height map we'll
- // need to convert it NOW
- if (bMustConvert)
- {
- D3DSURFACE_DESC sDesc;
- piTexture->GetLevelDesc(0, &sDesc);
- IDirect3DTexture9* piTempTexture;
- if(FAILED(g_piDevice->CreateTexture(
- sDesc.Width,
- sDesc.Height,
- piTexture->GetLevelCount(),
- sDesc.Usage,
- sDesc.Format,
- sDesc.Pool, &piTempTexture, NULL)))
- {
- CLogDisplay::Instance().AddEntry(
- "[ERROR] Unable to create normal map texture",
- D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
- return;
- }
- DWORD dwFlags;
- if (3 == iElement)dwFlags = D3DX_CHANNEL_LUMINANCE;
- else if (2 == iElement)dwFlags = D3DX_CHANNEL_RED;
- else if (1 == iElement)dwFlags = D3DX_CHANNEL_GREEN;
- else /*if (0 == iElement)*/dwFlags = D3DX_CHANNEL_BLUE;
- if(FAILED(D3DXComputeNormalMap(piTempTexture,
- piTexture,NULL,0,dwFlags,1.0f)))
- {
- CLogDisplay::Instance().AddEntry(
- "[ERROR] Unable to compute normal map from height map",
- D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
- piTempTexture->Release();
- return;
- }
- *piTextureOut = piTempTexture;
- piTexture->Release();
- }
- }
- //-------------------------------------------------------------------------------
- // Search for non-opaque pixels in a texture
- //
- // A pixel is considered to be non-opaque if its alpha value s less than 255
- //-------------------------------------------------------------------------------
- bool HasAlphaPixels(IDirect3DTexture9* piTexture)
- {
- D3DLOCKED_RECT sRect;
- D3DSURFACE_DESC sDesc;
- piTexture->GetLevelDesc(0,&sDesc);
- if (FAILED(piTexture->LockRect(0,&sRect,NULL,D3DLOCK_READONLY)))
- {
- return false;
- }
- const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4);
- struct SColor
- {
- unsigned char b,g,r,a;;
- };
- const SColor* pcData = (const SColor*)sRect.pBits;
- union
- {
- const SColor* pcPointer;
- const unsigned char* pcCharPointer;
- };
- pcPointer = pcData;
- for (unsigned int y = 0; y < sDesc.Height;++y)
- {
- for (unsigned int x = 0; x < sDesc.Width;++x)
- {
- if (pcPointer->a != 0xFF)
- {
- piTexture->UnlockRect(0);
- return true;
- }
- pcPointer++;
- }
- pcCharPointer += iPitchDiff;
- }
- piTexture->UnlockRect(0);
- return false;
- }
- //-------------------------------------------------------------------------------
- // Create the material for a mesh.
- //
- // The function checks whether an identical shader is already in use.
- // A shader is considered to be identical if it has the same input signature
- // and takes the same number of texture channels.
- //-------------------------------------------------------------------------------
- int CreateMaterial(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
- {
- ID3DXBuffer* piBuffer;
- D3DXMACRO sMacro[32];
- // extract all properties from the ASSIMP material structure
- const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex];
- //
- // DIFFUSE COLOR --------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE,
- (aiColor4D*)&pcMesh->vDiffuseColor))
- {
- pcMesh->vDiffuseColor.x = 1.0f;
- pcMesh->vDiffuseColor.y = 1.0f;
- pcMesh->vDiffuseColor.z = 1.0f;
- pcMesh->vDiffuseColor.w = 1.0f;
- }
- //
- // SPECULAR COLOR --------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR,
- (aiColor4D*)&pcMesh->vSpecularColor))
- {
- pcMesh->vSpecularColor.x = 1.0f;
- pcMesh->vSpecularColor.y = 1.0f;
- pcMesh->vSpecularColor.z = 1.0f;
- pcMesh->vSpecularColor.w = 1.0f;
- }
- //
- // AMBIENT COLOR --------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT,
- (aiColor4D*)&pcMesh->vAmbientColor))
- {
- pcMesh->vAmbientColor.x = 0.0f;
- pcMesh->vAmbientColor.y = 0.0f;
- pcMesh->vAmbientColor.z = 0.0f;
- pcMesh->vAmbientColor.w = 1.0f;
- }
- //
- // EMISSIVE COLOR -------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE,
- (aiColor4D*)&pcMesh->vEmissiveColor))
- {
- pcMesh->vEmissiveColor.x = 0.0f;
- pcMesh->vEmissiveColor.y = 0.0f;
- pcMesh->vEmissiveColor.z = 0.0f;
- pcMesh->vEmissiveColor.w = 1.0f;
- }
- //
- // Opacity --------------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity))
- {
- pcMesh->fOpacity = 1.0f;
- }
- //
- // Shading Model --------------------------------------------------
- //
- bool bDefault = false;
- if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode ))
- {
- bDefault = true;
- pcMesh->eShadingMode = aiShadingMode_Gouraud;
- }
- //
- // Shininess ------------------------------------------------------
- //
- if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess))
- {
- // assume 15 as default shininess
- pcMesh->fShininess = 15.0f;
- }
- else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong;
- aiString szPath;
- //
- // DIFFUSE TEXTURE ------------------------------------------------
- //
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath))
- {
- LoadTexture(&pcMesh->piDiffuseTexture,&szPath);
- }
- //
- // SPECULAR TEXTURE ------------------------------------------------
- //
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath))
- {
- LoadTexture(&pcMesh->piSpecularTexture,&szPath);
- }
- //
- // OPACITY TEXTURE ------------------------------------------------
- //
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath))
- {
- LoadTexture(&pcMesh->piOpacityTexture,&szPath);
- }
- else
- {
- // try to find out whether the diffuse texture has any
- // non-opaque pixels. If we find a few use it as opacity texture
- if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture))
- {
- pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
- pcMesh->piOpacityTexture->AddRef();
- }
- }
- //
- // AMBIENT TEXTURE ------------------------------------------------
- //
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath))
- {
- LoadTexture(&pcMesh->piAmbientTexture,&szPath);
- }
- //
- // EMISSIVE TEXTURE ------------------------------------------------
- //
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath))
- {
- LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
- }
- //
- // NORMAL/HEIGHT MAP ------------------------------------------------
- //
- bool bHM = false;
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath))
- {
- LoadTexture(&pcMesh->piNormalTexture,&szPath);
- }
- else
- {
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_BUMP(0),&szPath))
- {
- LoadTexture(&pcMesh->piNormalTexture,&szPath);
- }
- bHM = true;
- }
- // normal/height maps are sometimes mixed up. Try to detect the type
- // of the texture automatically
- if (pcMesh->piNormalTexture)
- {
- HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM);
- }
- // check whether a global background texture is contained
- // in this material. Some loaders set this value ...
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath))
- {
- CBackgroundPainter::Instance().SetTextureBG(szPath.data);
- }
- // BUGFIX: If the shininess is 0.0f disable phong lighting
- // This is a workaround for some meshes in the DX SDK (e.g. tiny.x)
- if (0.0f == pcMesh->fShininess)
- {
- pcMesh->eShadingMode = aiShadingMode_Gouraud;
- }
- // check whether we have already a material using the same
- // shader. This will decrease loading time rapidly ...
- for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
- {
- if (g_pcAsset->pcScene->mMeshes[i] == pcSource)
- {
- break;
- }
- AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i];
- if ((pcMesh->piDiffuseTexture != NULL ? true : false) !=
- (pc->piDiffuseTexture != NULL ? true : false))
- continue;
- if ((pcMesh->piSpecularTexture != NULL ? true : false) !=
- (pc->piSpecularTexture != NULL ? true : false))
- continue;
- if ((pcMesh->piAmbientTexture != NULL ? true : false) !=
- (pc->piAmbientTexture != NULL ? true : false))
- continue;
- if ((pcMesh->piEmissiveTexture != NULL ? true : false) !=
- (pc->piEmissiveTexture != NULL ? true : false))
- continue;
- if ((pcMesh->piNormalTexture != NULL ? true : false) !=
- (pc->piNormalTexture != NULL ? true : false))
- continue;
- if ((pcMesh->piOpacityTexture != NULL ? true : false) !=
- (pc->piOpacityTexture != NULL ? true : false))
- continue;
- if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) !=
- (pc->eShadingMode != aiShadingMode_Gouraud ? true : false))
- continue;
- if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false))
- continue;
- // we can reuse this material
- if (pc->piEffect)
- {
- pcMesh->piEffect = pc->piEffect;
- pc->bSharedFX = pcMesh->bSharedFX = true;
- pcMesh->piEffect->AddRef();
- return 2;
- }
- }
- g_iShaderCount++;
- // build macros for the HLSL compiler
- unsigned int iCurrent = 0;
- if (pcMesh->piDiffuseTexture)
- {
- sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (pcMesh->piSpecularTexture)
- {
- sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (pcMesh->piAmbientTexture)
- {
- sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (pcMesh->piEmissiveTexture)
- {
- sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (pcMesh->piNormalTexture)
- {
- sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (pcMesh->piOpacityTexture)
- {
- sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture)
- {
- sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK";
- sMacro[iCurrent].Definition = "a";
- ++iCurrent;
- }
- else
- {
- sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK";
- sMacro[iCurrent].Definition = "r";
- ++iCurrent;
- }
- }
- if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular)
- {
- sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- if (1.0f != pcMesh->fOpacity)
- {
- sMacro[iCurrent].Name = "AV_OPACITY";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- // If a cubemap is active, we'll need to lookup it for calculating
- // a physically correct reflection
- if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
- {
- sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP";
- sMacro[iCurrent].Definition = "1";
- ++iCurrent;
- }
- sMacro[iCurrent].Name = NULL;
- sMacro[iCurrent].Definition = NULL;
- // compile the shader
- if(FAILED( D3DXCreateEffect(g_piDevice,
- g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(),
- (const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer)))
- {
- // failed to compile the shader
- if( piBuffer)
- {
- MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
- piBuffer->Release();
- }
- // use the default material instead
- if (g_piDefaultEffect)
- {
- pcMesh->piEffect = g_piDefaultEffect;
- g_piDefaultEffect->AddRef();
- }
- // get the name of the material and use it in the log message
- if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) &&
- '\0' != szPath.data[0])
- {
- std::string sz = "[ERROR] Unable to load material: ";
- sz.append(szPath.data);
- CLogDisplay::Instance().AddEntry(sz);
- }
- else
- {
- CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED");
- }
- return 0;
- }
- if( piBuffer) piBuffer->Release();
- // now commit all constants to the shader
- //
- // This is not necessary for shared shader. Shader constants for
- // shared shaders are automatically recommited before the shader
- // is being used for a particular mesh
- if (1.0f != pcMesh->fOpacity)
- pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity);
- if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular)
- pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess);
- pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor);
- pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor);
- pcMesh->piEffect->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor);
- pcMesh->piEffect->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor);
- if (pcMesh->piDiffuseTexture)
- pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture);
- if (pcMesh->piOpacityTexture)
- pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture);
- if (pcMesh->piSpecularTexture)
- pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",pcMesh->piSpecularTexture);
- if (pcMesh->piAmbientTexture)
- pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",pcMesh->piAmbientTexture);
- if (pcMesh->piEmissiveTexture)
- pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture);
- if (pcMesh->piNormalTexture)
- pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture);
- if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
- {
- pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
- }
- return 1;
- }
- };
|