diff options
Diffstat (limited to 'src/mesh/assimp-master/tools/assimp_view/Material.cpp')
-rw-r--r-- | src/mesh/assimp-master/tools/assimp_view/Material.cpp | 1494 |
1 files changed, 1494 insertions, 0 deletions
diff --git a/src/mesh/assimp-master/tools/assimp_view/Material.cpp b/src/mesh/assimp-master/tools/assimp_view/Material.cpp new file mode 100644 index 0000000..e3c023b --- /dev/null +++ b/src/mesh/assimp-master/tools/assimp_view/Material.cpp @@ -0,0 +1,1494 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "assimp_view.h" + +#include "MaterialManager.h" +#include "AssetHelper.h" + +#include <assimp/cimport.h> +#include <assimp/Importer.hpp> +#include <assimp/ai_assert.h> +#include <assimp/cfileio.h> +#include <assimp/postprocess.h> +#include <assimp/scene.h> +#include <assimp/IOSystem.hpp> +#include <assimp/IOStream.hpp> +#include <assimp/LogStream.hpp> +#include <assimp/DefaultLogger.hpp> +#include <assimp/StringComparison.h> + +#include <vector> +#include <algorithm> + +namespace AssimpView { + +using namespace Assimp; + +extern std::string g_szMaterialShader; +extern HINSTANCE g_hInstance /*= NULL*/; +extern HWND g_hDlg /*= NULL*/; +extern IDirect3D9* g_piD3D /*= NULL*/; +extern IDirect3DDevice9* g_piDevice /*= NULL*/; +extern IDirect3DVertexDeclaration9* gDefaultVertexDecl /*= NULL*/; +extern double g_fFPS /*= 0.0f*/; +extern char g_szFileName[ MAX_PATH ]; +extern ID3DXEffect* g_piDefaultEffect /*= NULL*/; +extern ID3DXEffect* g_piNormalsEffect /*= NULL*/; +extern ID3DXEffect* g_piPassThroughEffect /*= NULL*/; +extern ID3DXEffect* g_piPatternEffect /*= NULL*/; +extern bool g_bMousePressed /*= false*/; +extern bool g_bMousePressedR /*= false*/; +extern bool g_bMousePressedM /*= false*/; +extern bool g_bMousePressedBoth /*= false*/; +extern float g_fElpasedTime /*= 0.0f*/; +extern D3DCAPS9 g_sCaps; +extern bool g_bLoadingFinished /*= false*/; +extern HANDLE g_hThreadHandle /*= NULL*/; +extern float g_fWheelPos /*= -10.0f*/; +extern bool g_bLoadingCanceled /*= false*/; +extern IDirect3DTexture9* g_pcTexture /*= NULL*/; + +extern aiMatrix4x4 g_mWorld; +extern aiMatrix4x4 g_mWorldRotate; +extern aiVector3D g_vRotateSpeed /*= aiVector3D(0.5f,0.5f,0.5f)*/; + +extern aiVector3D g_avLightDirs[ 1 ] /* = + { aiVector3D(-0.5f,0.6f,0.2f) , + aiVector3D(-0.5f,0.5f,0.5f)} */; + + +extern POINT g_mousePos /*= {0,0};*/; +extern POINT g_LastmousePos /*= {0,0}*/; +extern bool g_bFPSView /*= false*/; +extern bool g_bInvert /*= false*/; +extern EClickPos g_eClick; +extern unsigned int g_iCurrentColor /*= 0*/; + +// NOTE: The light intensity is separated from the color, it can +// directly be manipulated using the middle mouse button. +// When the user chooses a color from the palette the intensity +// is reset to 1.0 +// index[2] is the ambient color +extern float g_fLightIntensity /*=0.0f*/; +extern D3DCOLOR g_avLightColors[ 3 ]; + +extern RenderOptions g_sOptions; +extern Camera g_sCamera; +extern AssetHelper *g_pcAsset /*= NULL*/; + + +// +// Contains the mask image for the HUD +// (used to determine the position of a click) +// +// The size of the image is identical to the size of the main +// HUD texture +// +extern unsigned char* g_szImageMask /*= NULL*/; + + +extern float g_fACMR /*= 3.0f*/; +extern IDirect3DQuery9* g_piQuery; + +extern bool g_bPlay /*= false*/; + +extern double g_dCurrent; +extern float g_smoothAngle /*= 80.f*/; + +extern unsigned int ppsteps, ppstepsdefault; +extern bool nopointslines; + +CMaterialManager CMaterialManager::s_cInstance; + +//------------------------------------------------------------------------------- +// 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; +} + +//------------------------------------------------------------------------------- +int CMaterialManager::UpdateSpecularMaterials() + { + if (g_pcAsset && g_pcAsset->pcScene) + { + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) + { + if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode) + { + this->DeleteMaterial(g_pcAsset->apcMeshes[i]); + this->CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]); + } + } + } + return 1; + } +//------------------------------------------------------------------------------- +int CMaterialManager::SetDefaultTexture(IDirect3DTexture9** p_ppiOut) +{ + if (sDefaultTexture) { + sDefaultTexture->AddRef(); + *p_ppiOut = sDefaultTexture; + return 1; + } + if(FAILED(g_piDevice->CreateTexture( + 256, + 256, + 0, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + p_ppiOut, + nullptr))) + { + CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + + *p_ppiOut = nullptr; + return 0; + } + D3DXFillTexture(*p_ppiOut,&FillFunc,nullptr); + sDefaultTexture = *p_ppiOut; + sDefaultTexture->AddRef(); + + // {9785DA94-1D96-426b-B3CB-BADC36347F5E} + static const GUID guidPrivateData = + { 0x9785da94, 0x1d96, 0x426b, + { 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } }; + + uint32_t iData = 0xFFFFFFFF; + (*p_ppiOut)->SetPrivateData(guidPrivateData,&iData,4,0); + return 1; +} +//------------------------------------------------------------------------------- +bool CMaterialManager::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,'.'); + if (!szExt)return false; + szExt++; + *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, '.'); + if (szExtFound) + { + ++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((unsigned char)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 = static_cast<ai_uint32>(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 = static_cast<ai_uint32>(iLen); + return true; + } + } + } + } + while (FindNextFile(h, &info)); + + FindClose(h); + } + return false; +} +//------------------------------------------------------------------------------- +int CMaterialManager::FindValidPath(aiString* p_szString) +{ + ai_assert(nullptr != p_szString); + aiString pcpy = *p_szString; + if ('*' == p_szString->data[0]) { + // '*' as first character indicates an embedded file + return 5; + } + + // 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], tmp2[MAX_PATH*2]; + strcpy(szTemp, g_szFileName); + strcpy(tmp2,szTemp); + + 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((unsigned char)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; + } + + // patch by mark sibly to look for textures files in the asset's base directory. + const char *path=pcpy.data; + const char *p=strrchr( path,'/' ); + if( !p ) p=strrchr( path,'\\' ); + if( p ){ + char *q=strrchr( tmp2,'/' ); + if( !q ) q=strrchr( tmp2,'\\' ); + if( q ){ + strcpy( q+1,p+1 ); + if((pFile=fopen( tmp2,"r" )) != nullptr){ + fclose( pFile ); + strcpy(p_szString->data,tmp2); + p_szString->length = static_cast<ai_uint32>(strlen(tmp2)); + return 1; + } + } + } + return 0; + } + } + fclose(pFile); + + // copy the result string back to the aiStr + const size_t len = strlen(szTemp); + size_t len2 = len+1; + len2 = len2 > MAXLEN ? MAXLEN : len2; + memcpy(p_szString->data, szTemp, len2); + p_szString->length = static_cast<ai_uint32>(len); + } + return 1; +} +//------------------------------------------------------------------------------- +int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath) +{ + ai_assert(nullptr != p_ppiOut); + ai_assert(nullptr != szPath); + + *p_ppiOut = nullptr; + + const std::string s = szPath->data; + TextureCache::iterator ff; + if ((ff = sCachedTextures.find(s)) != sCachedTextures.end()) { + *p_ppiOut = (*ff).second; + (*p_ppiOut)->AddRef(); + return 1; + } + + // first get a valid path to the texture + if( 5 == FindValidPath(szPath)) + { + // embedded file. Find its index + unsigned int iIndex = atoi(szPath->data+1); + if (iIndex < g_pcAsset->pcScene->mNumTextures) + { + if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight) + { + // it is an embedded file ... don't need the file format hint, + // simply let D3DX load the file + D3DXIMAGE_INFO info; + if (FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice, + g_pcAsset->pcScene->mTextures[iIndex]->pcData, + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + D3DX_DEFAULT, + D3DX_DEFAULT, + 1, + D3DUSAGE_AUTOGENMIPMAP, + D3DFMT_UNKNOWN, + D3DPOOL_MANAGED, + D3DX_DEFAULT, + D3DX_DEFAULT, + 0, + &info, + nullptr, + p_ppiOut))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#1): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + this->SetDefaultTexture(p_ppiOut); + return 1; + } + } + else + { + // fill a new texture ... + if(FAILED(g_piDevice->CreateTexture( + g_pcAsset->pcScene->mTextures[iIndex]->mWidth, + g_pcAsset->pcScene->mTextures[iIndex]->mHeight, + 0,D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_MANAGED,p_ppiOut,nullptr))) + { + std::string sz = "[ERROR] Unable to load embedded texture (#2): "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + this->SetDefaultTexture(p_ppiOut); + return 1; + } + + // now copy the data to it ... (assume non pow2 to be supported) + D3DLOCKED_RECT sLock; + (*p_ppiOut)->LockRect(0,&sLock,nullptr,0); + + const aiTexel* pcData = g_pcAsset->pcScene->mTextures[iIndex]->pcData; + + for (unsigned int y = 0; y < g_pcAsset->pcScene->mTextures[iIndex]->mHeight;++y) + { + memcpy(sLock.pBits,pcData,g_pcAsset->pcScene->mTextures[iIndex]-> + mWidth *sizeof(aiTexel)); + sLock.pBits = (char*)sLock.pBits + sLock.Pitch; + pcData += g_pcAsset->pcScene->mTextures[iIndex]->mWidth; + } + (*p_ppiOut)->UnlockRect(0); + (*p_ppiOut)->GenerateMipSubLevels(); + } + sCachedTextures[s] = *p_ppiOut; + (*p_ppiOut)->AddRef(); + return 1; + } + else + { + std::string sz = "[ERROR] Invalid index for embedded texture: "; + sz.append(szPath->data); + CLogDisplay::Instance().AddEntry(sz,D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0)); + + SetDefaultTexture(p_ppiOut); + return 1; + } + } + + // 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, + nullptr, + nullptr, + 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)); + + this->SetDefaultTexture(p_ppiOut); + } + sCachedTextures[s] = *p_ppiOut; + (*p_ppiOut)->AddRef(); + + return 1; +} +//------------------------------------------------------------------------------- +void CMaterialManager::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 = nullptr; + } + if (pcIn->piSpecularTexture) + { + pcIn->piSpecularTexture->Release(); + pcIn->piSpecularTexture = nullptr; + } + if (pcIn->piEmissiveTexture) + { + pcIn->piEmissiveTexture->Release(); + pcIn->piEmissiveTexture = nullptr; + } + if (pcIn->piAmbientTexture) + { + pcIn->piAmbientTexture->Release(); + pcIn->piAmbientTexture = nullptr; + } + if (pcIn->piOpacityTexture) + { + pcIn->piOpacityTexture->Release(); + pcIn->piOpacityTexture = nullptr; + } + if (pcIn->piNormalTexture) + { + pcIn->piNormalTexture->Release(); + pcIn->piNormalTexture = nullptr; + } + if (pcIn->piShininessTexture) + { + pcIn->piShininessTexture->Release(); + pcIn->piShininessTexture = nullptr; + } + if (pcIn->piLightmapTexture) + { + pcIn->piLightmapTexture->Release(); + pcIn->piLightmapTexture = nullptr; + } + pcIn->piEffect = nullptr; +} +//------------------------------------------------------------------------------- +void CMaterialManager::HMtoNMIfNecessary( + IDirect3DTexture9* piTexture, + IDirect3DTexture9** piTextureOut, + bool bWasOriginallyHM) +{ + ai_assert(nullptr != piTexture); + ai_assert(nullptr != piTextureOut); + + bool bMustConvert = false; + uintptr_t iElement = 3; + + *piTextureOut = piTexture; + + // Lock the input texture and try to determine its type. + // Criteria: + // - 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,nullptr,D3DLOCK_READONLY))) + { + return; + } + const int iPitchDiff = (int)sRect.Pitch - (int)(sDesc.Width * 4); + + struct SColor + { + union + { + struct {unsigned char b,g,r,a;} data; + 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->data.b != pcPointer->data.r || pcPointer->data.b != pcPointer->data.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->data.r; + clrColorLine.g += pcPointer->data.g; + clrColorLine.b += pcPointer->data.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 sDesc2; + piTexture->GetLevelDesc(0, &sDesc2); + + IDirect3DTexture9* piTempTexture; + if(FAILED(g_piDevice->CreateTexture( + sDesc2.Width, + sDesc2.Height, + piTexture->GetLevelCount(), + sDesc2.Usage, + sDesc2.Format, + sDesc2.Pool, &piTempTexture, nullptr))) + { + 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,nullptr,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(); + } +} +//------------------------------------------------------------------------------- +bool CMaterialManager::HasAlphaPixels(IDirect3DTexture9* piTexture) +{ + ai_assert(nullptr != piTexture); + + D3DLOCKED_RECT sRect; + D3DSURFACE_DESC sDesc; + piTexture->GetLevelDesc(0,&sDesc); + if (FAILED(piTexture->LockRect(0,&sRect,nullptr,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; +} +//------------------------------------------------------------------------------- +int CMaterialManager::CreateMaterial( + AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) +{ + ai_assert(nullptr != pcMesh); + ai_assert(nullptr != pcSource); + + ID3DXBuffer* piBuffer; + + D3DXMACRO sMacro[64]; + + // 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; + + + // + // Shininess strength ------------------------------------------------------ + // + if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) + { + // assume 1.0 as default shininess strength + pcMesh->fSpecularStrength = 1.0f; + } + + aiString szPath; + + aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap); + + bool bib =false; + if (pcSource->mTextureCoords[0]) + { + + // + // DIFFUSE TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) + { + LoadTexture(&pcMesh->piDiffuseTexture,&szPath); + + aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); + aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); + } + + // + // 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 + { + int flags = 0; + aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags); + + // 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 && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture)) + { + int iVal; + + // NOTE: This special value is set by the tree view if the user + // manually removes the alpha texture from the view ... + if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal)) + { + 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); + } + + // + // Shininess TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath)) + { + LoadTexture(&pcMesh->piShininessTexture,&szPath); + } + + // + // Lightmap TEXTURE ------------------------------------------------ + // + if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath)) + { + LoadTexture(&pcMesh->piLightmapTexture,&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_HEIGHT(0),&szPath)) + { + LoadTexture(&pcMesh->piNormalTexture,&szPath); + } + else bib = true; + 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) + // FIX: Added this check to the x-loader, but the line remains to + // catch other loader doing the same ... + if (0.0f == pcMesh->fShininess){ + pcMesh->eShadingMode = aiShadingMode_Gouraud; + } + + int two_sided = 0; + aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided); + pcMesh->twosided = (two_sided != 0); + + // 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 != nullptr ? true : false) != + (pc->piDiffuseTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piSpecularTexture != nullptr ? true : false) != + (pc->piSpecularTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piAmbientTexture != nullptr ? true : false) != + (pc->piAmbientTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piEmissiveTexture != nullptr ? true : false) != + (pc->piEmissiveTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piNormalTexture != nullptr ? true : false) != + (pc->piNormalTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piOpacityTexture != nullptr ? true : false) != + (pc->piOpacityTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piShininessTexture != nullptr ? true : false) != + (pc->piShininessTexture != nullptr ? true : false)) + continue; + if ((pcMesh->piLightmapTexture != nullptr ? true : false) != + (pc->piLightmapTexture != nullptr ? 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; + + if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones()) + continue; + + // we can reuse this material + if (pc->piEffect) + { + pcMesh->piEffect = pc->piEffect; + pc->bSharedFX = pcMesh->bSharedFX = true; + pcMesh->piEffect->AddRef(); + return 2; + } + } + m_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 (mapU == aiTextureMapMode_Wrap) + sMacro[iCurrent].Name = "AV_WRAPU"; + else if (mapU == aiTextureMapMode_Mirror) + sMacro[iCurrent].Name = "AV_MIRRORU"; + else // if (mapU == aiTextureMapMode_Clamp) + sMacro[iCurrent].Name = "AV_CLAMPU"; + + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + + if (mapV == aiTextureMapMode_Wrap) + sMacro[iCurrent].Name = "AV_WRAPV"; + else if (mapV == aiTextureMapMode_Mirror) + sMacro[iCurrent].Name = "AV_MIRRORV"; + else // if (mapV == aiTextureMapMode_Clamp) + sMacro[iCurrent].Name = "AV_CLAMPV"; + + 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; + } + char buff[32]; + if (pcMesh->piLightmapTexture) + { + sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + int idx; + if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx]) { + sMacro[iCurrent].Name = "AV_TWO_UV"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + + sMacro[iCurrent].Definition = "IN.TexCoord1"; + } + else sMacro[iCurrent].Definition = "IN.TexCoord0"; + sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD"; + + ++iCurrent;float f= 1.f; + aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f); + sprintf(buff,"%f",f); + + sMacro[iCurrent].Name = "LM_STRENGTH"; + sMacro[iCurrent].Definition = buff; + ++iCurrent; + } + if (pcMesh->piNormalTexture && !bib) + { + 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 (pcMesh->piShininessTexture) + { + sMacro[iCurrent].Name = "AV_SHININESS_TEXTURE"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + } + if (1.0f != pcMesh->fOpacity) + { + sMacro[iCurrent].Name = "AV_OPACITY"; + sMacro[iCurrent].Definition = "1"; + ++iCurrent; + } + + if( pcSource->HasBones()) + { + sMacro[iCurrent].Name = "AV_SKINNING"; + 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 = nullptr; + sMacro[iCurrent].Definition = nullptr; + + // compile the shader + if(FAILED( D3DXCreateEffect(g_piDevice, + g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(), + (const D3DXMACRO*)sMacro,nullptr,0,nullptr,&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; + } else + { + // use Fixed Function effect when working with shaderless cards + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + pcMesh->piEffect->SetTechnique( "MaterialFX_FF"); + } + + 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->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } + + 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 (pcMesh->piShininessTexture) + pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture); + if (pcMesh->piLightmapTexture) + pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); + + if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){ + pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); + } + + return 1; +} +//------------------------------------------------------------------------------- +int CMaterialManager::SetupMaterial ( + AssetHelper::MeshHelper* pcMesh, + const aiMatrix4x4& pcProj, + const aiMatrix4x4& aiMe, + const aiMatrix4x4& pcCam, + const aiVector3D& vPos) +{ + ai_assert(nullptr != pcMesh); + if (!pcMesh->piEffect)return 0; + + ID3DXEffect* piEnd = pcMesh->piEffect; + + piEnd->SetMatrix("WorldViewProjection", + (const D3DXMATRIX*)&pcProj); + + piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe); + piEnd->SetMatrix("WorldInverseTranspose", + (const D3DXMATRIX*)&pcCam); + + D3DXVECTOR4 apcVec[5]; + memset(apcVec,0,sizeof(apcVec)); + apcVec[0].x = g_avLightDirs[0].x; + apcVec[0].y = g_avLightDirs[0].y; + apcVec[0].z = g_avLightDirs[0].z; + apcVec[0].w = 0.0f; + apcVec[1].x = g_avLightDirs[0].x * -1.0f; + apcVec[1].y = g_avLightDirs[0].y * -1.0f; + apcVec[1].z = g_avLightDirs[0].z * -1.0f; + apcVec[1].w = 0.0f; + D3DXVec4Normalize(&apcVec[0],&apcVec[0]); + D3DXVec4Normalize(&apcVec[1],&apcVec[1]); + piEnd->SetVectorArray("afLightDir",apcVec,5); + + apcVec[0].x = ((g_avLightColors[0] >> 16) & 0xFF) / 255.0f; + apcVec[0].y = ((g_avLightColors[0] >> 8) & 0xFF) / 255.0f; + apcVec[0].z = ((g_avLightColors[0]) & 0xFF) / 255.0f; + apcVec[0].w = 1.0f; + + if( g_sOptions.b3Lights) + { + apcVec[1].x = ((g_avLightColors[1] >> 16) & 0xFF) / 255.0f; + apcVec[1].y = ((g_avLightColors[1] >> 8) & 0xFF) / 255.0f; + apcVec[1].z = ((g_avLightColors[1]) & 0xFF) / 255.0f; + apcVec[1].w = 0.0f; + } else + { + apcVec[1].x = 0.0f; + apcVec[1].y = 0.0f; + apcVec[1].z = 0.0f; + apcVec[1].w = 0.0f; + } + + apcVec[0] *= g_fLightIntensity; + apcVec[1] *= g_fLightIntensity; + piEnd->SetVectorArray("afLightColor",apcVec,5); + + apcVec[0].x = ((g_avLightColors[2] >> 16) & 0xFF) / 255.0f; + apcVec[0].y = ((g_avLightColors[2] >> 8) & 0xFF) / 255.0f; + apcVec[0].z = ((g_avLightColors[2]) & 0xFF) / 255.0f; + apcVec[0].w = 1.0f; + + apcVec[1].x = ((g_avLightColors[2] >> 16) & 0xFF) / 255.0f; + apcVec[1].y = ((g_avLightColors[2] >> 8) & 0xFF) / 255.0f; + apcVec[1].z = ((g_avLightColors[2]) & 0xFF) / 255.0f; + apcVec[1].w = 0.0f; + + // FIX: light intensity doesn't apply to ambient color + //apcVec[0] *= g_fLightIntensity; + //apcVec[1] *= g_fLightIntensity; + piEnd->SetVectorArray("afLightColorAmbient",apcVec,5); + + + apcVec[0].x = vPos.x; + apcVec[0].y = vPos.y; + apcVec[0].z = vPos.z; + piEnd->SetVector( "vCameraPos",&apcVec[0]); + + // if the effect instance is shared by multiple materials we need to + // recommit its whole state once per frame ... + if (pcMesh->bSharedFX) + { + // now commit all constants to the shader + if (1.0f != pcMesh->fOpacity) + pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); + if (pcMesh->eShadingMode != aiShadingMode_Gouraud) + { + pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); + pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } + + 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->piOpacityTexture) + pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture); + if (pcMesh->piDiffuseTexture) + pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture); + 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 (pcMesh->piShininessTexture) + pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture); + if (pcMesh->piLightmapTexture) + pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); + + if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) + { + piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); + } + } + + // disable culling, if necessary + if (pcMesh->twosided && g_sOptions.bCulling) { + g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); + } + + // setup the correct shader technique to be used for drawing + if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) + { + g_piDefaultEffect->SetTechnique( "MaterialFXSpecular_FF"); + } else + if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality) + { + if (g_sOptions.b3Lights) + piEnd->SetTechnique("MaterialFXSpecular_PS20_D2"); + else piEnd->SetTechnique("MaterialFXSpecular_PS20_D1"); + } + else + { + if (g_sOptions.b3Lights) + piEnd->SetTechnique("MaterialFXSpecular_D2"); + else piEnd->SetTechnique("MaterialFXSpecular_D1"); + } + + // activate the effect + UINT dwPasses = 0; + piEnd->Begin(&dwPasses,0); + piEnd->BeginPass(0); + return 1; +} +//------------------------------------------------------------------------------- +int CMaterialManager::EndMaterial (AssetHelper::MeshHelper* pcMesh) +{ + ai_assert(nullptr != pcMesh); + if (!pcMesh->piEffect)return 0; + + // end the effect + pcMesh->piEffect->EndPass(); + pcMesh->piEffect->End(); + + // re-enable culling if necessary + if (pcMesh->twosided && g_sOptions.bCulling) { + g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); + } + + return 1; +} + +} // end namespace AssimpView |