#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 <../code/StringComparison.h>
#include <vector>
#include <algorithm>
namespace AssimpView {
using namespace Assimp;
extern std::string g_szMaterialShader;
extern HINSTANCE g_hInstance ;
extern HWND g_hDlg ;
extern IDirect3D9* g_piD3D ;
extern IDirect3DDevice9* g_piDevice ;
extern IDirect3DVertexDeclaration9* gDefaultVertexDecl ;
extern double g_fFPS ;
extern char g_szFileName[ MAX_PATH ];
extern ID3DXEffect* g_piDefaultEffect ;
extern ID3DXEffect* g_piNormalsEffect ;
extern ID3DXEffect* g_piPassThroughEffect ;
extern ID3DXEffect* g_piPatternEffect ;
extern bool g_bMousePressed ;
extern bool g_bMousePressedR ;
extern bool g_bMousePressedM ;
extern bool g_bMousePressedBoth ;
extern float g_fElpasedTime ;
extern D3DCAPS9 g_sCaps;
extern bool g_bLoadingFinished ;
extern HANDLE g_hThreadHandle ;
extern float g_fWheelPos ;
extern bool g_bLoadingCanceled ;
extern IDirect3DTexture9* g_pcTexture ;
extern aiMatrix4x4 g_mWorld;
extern aiMatrix4x4 g_mWorldRotate;
extern aiVector3D g_vRotateSpeed ;
extern aiVector3D g_avLightDirs[ 1 ] ;
extern POINT g_mousePos ;
extern POINT g_LastmousePos ;
extern bool g_bFPSView ;
extern bool g_bInvert ;
extern EClickPos g_eClick;
extern unsigned int g_iCurrentColor ;
extern float g_fLightIntensity ;
extern D3DCOLOR g_avLightColors[ 3 ];
extern RenderOptions g_sOptions;
extern Camera g_sCamera;
extern AssetHelper *g_pcAsset ;
extern unsigned char* g_szImageMask ;
extern float g_fACMR ;
extern IDirect3DQuery9* g_piQuery;
extern bool g_bPlay ;
extern double g_dCurrent;
extern float g_smoothAngle ;
extern unsigned int ppsteps, ppstepsdefault;
extern bool nopointslines;
CMaterialManager CMaterialManager::s_cInstance;
VOID WINAPI FillFunc(D3DXVECTOR4* pOut,
CONST D3DXVECTOR2* pTexCoord,
CONST D3DXVECTOR2* pTexelSize,
LPVOID pData)
{
UNREFERENCED_PARAMETER(pData);
UNREFERENCED_PARAMETER(pTexelSize);
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,
NULL)))
{
CLogDisplay::Instance().AddEntry("[ERROR] Unable to create default texture",
D3DCOLOR_ARGB(0xFF,0xFF,0,0));
*p_ppiOut = NULL;
return 0;
}
D3DXFillTexture(*p_ppiOut,&FillFunc,NULL);
sDefaultTexture = *p_ppiOut;
sDefaultTexture->AddRef();
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);
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;
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(info.cFileName[i]);
if (0 == memcmp(info.cFileName,szFile2, min(iSizeFound,iSize)))
{
char* sz = strrchr(szTempB,'*');
*(sz-2) = 0x0;
strcat(szTempB,info.cFileName);
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;
}
}
if (0 == ASSIMP_stricmp(info.cAlternateFileName,p_szString->data))
{
strcat(szTempB,info.cAlternateFileName);
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;
}
int CMaterialManager::FindValidPath(aiString* p_szString)
{
ai_assert(NULL != p_szString);
aiString pcpy = *p_szString;
if ('*' == p_szString->data[0]) {
return 5;
}
FILE* pFile = fopen(p_szString->data,"rb");
if (pFile)fclose(pFile);
else
{
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)
{
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;
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;
}
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" ))){
fclose( pFile );
strcpy(p_szString->data,tmp2);
p_szString->length = strlen(tmp2);
return 1;
}
}
}
return 0;
}
}
fclose(pFile);
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;
}
int CMaterialManager::LoadTexture(IDirect3DTexture9** p_ppiOut,aiString* szPath)
{
ai_assert(NULL != p_ppiOut);
ai_assert(NULL != szPath);
*p_ppiOut = NULL;
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;
}
if( 5 == FindValidPath(szPath))
{
unsigned int iIndex = atoi(szPath->data+1);
if (iIndex < g_pcAsset->pcScene->mNumTextures)
{
if (0 == g_pcAsset->pcScene->mTextures[iIndex]->mHeight)
{
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,
NULL,
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
{
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,NULL)))
{
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;
}
D3DLOCKED_RECT sLock;
(*p_ppiOut)->LockRect(0,&sLock,NULL,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;
}
}
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)))
{
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();
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;
}
if (pcIn->piShininessTexture)
{
pcIn->piShininessTexture->Release();
pcIn->piShininessTexture = NULL;
}
if (pcIn->piLightmapTexture)
{
pcIn->piLightmapTexture->Release();
pcIn->piLightmapTexture = NULL;
}
pcIn->piEffect = NULL;
}
void CMaterialManager::HMtoNMIfNecessary(
IDirect3DTexture9* piTexture,
IDirect3DTexture9** piTextureOut,
bool bWasOriginallyHM)
{
ai_assert(NULL != piTexture);
ai_assert(NULL != piTextureOut);
bool bMustConvert = false;
uintptr_t iElement = 3;
*piTextureOut = piTexture;
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;
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
{
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)
{
if (aiIndex[ii] != 3 && pcPointer->_array[aiIndex[ii]] != 0)
{
bIsEqual = false;
break;
}
}
pcPointer++;
}
pcCharPointer += iPitchDiff;
}
if (bIsEqual)bMustConvert = true;
else
{
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))
{
if (bWasOriginallyHM)
{
bMustConvert = true;
}
}
}
}
}
piTexture->UnlockRect(0);
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 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();
}
}
bool CMaterialManager::HasAlphaPixels(IDirect3DTexture9* piTexture)
{
ai_assert(NULL != 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;
}
int CMaterialManager::CreateMaterial(
AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
{
ai_assert(NULL != pcMesh);
ai_assert(NULL != pcSource);
ID3DXBuffer* piBuffer;
D3DXMACRO sMacro[64];
const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex];
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;
}
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;
}
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;
}
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;
}
if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity))
{
pcMesh->fOpacity = 1.0f;
}
bool bDefault = false;
if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode ))
{
bDefault = true;
pcMesh->eShadingMode = aiShadingMode_Gouraud;
}
if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess))
{
pcMesh->fShininess = 15.0f;
}
else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong;
if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength))
{
pcMesh->fSpecularStrength = 1.0f;
}
aiString szPath;
aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap);
bool bib =false;
if (pcSource->mTextureCoords[0])
{
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);
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath))
{
LoadTexture(&pcMesh->piSpecularTexture,&szPath);
}
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);
if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture))
{
int iVal;
if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal))
{
pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture;
pcMesh->piOpacityTexture->AddRef();
}
}
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath))
{
LoadTexture(&pcMesh->piAmbientTexture,&szPath);
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath))
{
LoadTexture(&pcMesh->piEmissiveTexture,&szPath);
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath))
{
LoadTexture(&pcMesh->piShininessTexture,&szPath);
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath))
{
LoadTexture(&pcMesh->piLightmapTexture,&szPath);
}
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;
}
if (pcMesh->piNormalTexture)
{
HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM);
}
}
if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath))
{
CBackgroundPainter::Instance().SetTextureBG(szPath.data);
}
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);
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->piShininessTexture != NULL ? true : false) !=
(pc->piShininessTexture != NULL ? true : false))
continue;
if ((pcMesh->piLightmapTexture != NULL ? true : false) !=
(pc->piLightmapTexture != 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;
if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones())
continue;
if (pc->piEffect)
{
pcMesh->piEffect = pc->piEffect;
pc->bSharedFX = pcMesh->bSharedFX = true;
pcMesh->piEffect->AddRef();
return 2;
}
}
m_iShaderCount++;
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 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 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 (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;
if(FAILED( D3DXCreateEffect(g_piDevice,
g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(),
(const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer)))
{
if( piBuffer)
{
MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
piBuffer->Release();
}
if (g_piDefaultEffect)
{
pcMesh->piEffect = g_piDefaultEffect;
g_piDefaultEffect->AddRef();
}
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
{
if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
pcMesh->piEffect->SetTechnique( "MaterialFX_FF");
}
if( piBuffer) piBuffer->Release();
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(NULL != 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;
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 (pcMesh->bSharedFX)
{
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());
}
}
if (pcMesh->twosided && g_sOptions.bCulling) {
g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
}
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");
}
UINT dwPasses = 0;
piEnd->Begin(&dwPasses,0);
piEnd->BeginPass(0);
return 1;
}
int CMaterialManager::EndMaterial (AssetHelper::MeshHelper* pcMesh)
{
ai_assert(NULL != pcMesh);
if (!pcMesh->piEffect)return 0;
pcMesh->piEffect->EndPass();
pcMesh->piEffect->End();
if (pcMesh->twosided && g_sOptions.bCulling) {
g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
}
return 1;
}
};