summaryrefslogtreecommitdiff
path: root/libs/assimp/tools/assimp_view/Material.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/tools/assimp_view/Material.cpp')
-rw-r--r--libs/assimp/tools/assimp_view/Material.cpp1494
1 files changed, 1494 insertions, 0 deletions
diff --git a/libs/assimp/tools/assimp_view/Material.cpp b/libs/assimp/tools/assimp_view/Material.cpp
new file mode 100644
index 0000000..e3c023b
--- /dev/null
+++ b/libs/assimp/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