added pretransformvertices postprocess step bugfixes in the 3ds material system. transparency is now displayed correctly Node view in the viewer display the local transformation matrix now Fixed wrong directory name. "unused" renamed to "extra" ---> all is WIP ... git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@50 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
2204 lines
66 KiB
C++
2204 lines
66 KiB
C++
/*
|
|
---------------------------------------------------------------------------
|
|
Open Asset Import Library (ASSIMP)
|
|
---------------------------------------------------------------------------
|
|
|
|
Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 "stdafx.h"
|
|
#include "assimp_view.h"
|
|
|
|
|
|
namespace AssimpView {
|
|
|
|
|
|
CDisplay CDisplay::s_cInstance;
|
|
|
|
extern COLORREF g_aclCustomColors[16] /*= {0}*/;
|
|
extern HKEY g_hRegistry;
|
|
extern float g_fLoadTime;
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Table of colors used for normal vectors.
|
|
//-------------------------------------------------------------------------------
|
|
D3DXVECTOR4 g_aclNormalColors[14] =
|
|
{
|
|
D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0xFF / 255.0f, 1.0f), // white
|
|
|
|
D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // red
|
|
D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // green
|
|
D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // blue
|
|
|
|
D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // yellow
|
|
D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // magenta
|
|
D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0xFF / 255.0f,1.0f), // wtf
|
|
|
|
D3DXVECTOR4(0xFF / 255.0f,0x60 / 255.0f,0x60 / 255.0f,1.0f), // light red
|
|
D3DXVECTOR4(0x60 / 255.0f,0xFF / 255.0f,0x60 / 255.0f,1.0f), // light green
|
|
D3DXVECTOR4(0x60 / 255.0f,0x60 / 255.0f,0xFF / 255.0f,1.0f), // light blue
|
|
|
|
D3DXVECTOR4(0xA0 / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // dark red
|
|
D3DXVECTOR4(0x00 / 255.0f,0xA0 / 255.0f,0x00 / 255.0f,1.0f), // dark green
|
|
D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xA0 / 255.0f,1.0f), // dark blue
|
|
|
|
D3DXVECTOR4(0x88 / 255.0f,0x88 / 255.0f,0x88 / 255.0f, 1.0f) // gray
|
|
};
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Recursivly count the number of nodes in an asset's node graph
|
|
// Used by LoadAsset()
|
|
//-------------------------------------------------------------------------------
|
|
void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
|
|
{
|
|
*piCnt = *piCnt+1;
|
|
for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
|
|
GetNodeCount(pcNode->mChildren[i],piCnt);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::FillAnimList(void)
|
|
{
|
|
if (0 == g_pcAsset->pcScene->mNumAnimations)
|
|
{
|
|
// disable all UI components related to animations
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),FALSE);
|
|
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),FALSE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),FALSE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),FALSE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE);
|
|
}
|
|
else
|
|
{
|
|
// reenable all animation components if they have been
|
|
// disabled for a previous mesh
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),TRUE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),TRUE);
|
|
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),TRUE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),TRUE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),TRUE);
|
|
EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),TRUE);
|
|
|
|
// now fill in all animation names
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i)
|
|
{
|
|
SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
|
|
( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::ClearAnimList(void)
|
|
{
|
|
// clear the combo box
|
|
SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::ClearDisplayList(void)
|
|
{
|
|
// clear the combo box
|
|
TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1));
|
|
this->Reset();
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::AddNodeToDisplayList(
|
|
unsigned int iIndex,
|
|
unsigned int iDepth,
|
|
aiNode* pcNode,
|
|
HTREEITEM hRoot)
|
|
{
|
|
ai_assert(NULL != pcNode);
|
|
ai_assert(NULL != hRoot);
|
|
|
|
char chTemp[512];
|
|
|
|
if(0 == pcNode->mName.length)
|
|
{
|
|
if (iIndex >= 100)
|
|
{
|
|
iIndex += iDepth * 1000;
|
|
}
|
|
else if (iIndex >= 10)
|
|
{
|
|
iIndex += iDepth * 100;
|
|
}
|
|
else iIndex += iDepth * 10;
|
|
sprintf(chTemp,"Node %i",iIndex);
|
|
}
|
|
else strcpy(chTemp,pcNode->mName.data);
|
|
|
|
TVITEMEX tvi;
|
|
TVINSERTSTRUCT sNew;
|
|
tvi.pszText = chTemp;
|
|
tvi.cchTextMax = (int)strlen(chTemp);
|
|
tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM;
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
|
|
tvi.lParam = (LPARAM)5;
|
|
|
|
sNew.itemex = tvi;
|
|
sNew.hInsertAfter = TVI_LAST;
|
|
sNew.hParent = hRoot;
|
|
|
|
// add the item to the list
|
|
HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
|
|
TVM_INSERTITEM,
|
|
0,
|
|
(LPARAM)(LPTVINSERTSTRUCT)&sNew);
|
|
|
|
// recursively add all child nodes
|
|
++iDepth;
|
|
for (unsigned int i = 0; i< pcNode->mNumChildren;++i)
|
|
{
|
|
AddNodeToDisplayList(i,iDepth,pcNode->mChildren[i],hTexture);
|
|
}
|
|
|
|
// add the node to the list
|
|
NodeInfo info;
|
|
info.hTreeItem = hTexture;
|
|
info.psNode = pcNode;
|
|
this->AddNode(info);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::ReplaceCurrentTexture(const char* szPath)
|
|
{
|
|
ai_assert(NULL != szPath);
|
|
|
|
// well ... try to load it
|
|
IDirect3DTexture9* piTexture = NULL;
|
|
aiString szString;
|
|
strcpy(szString.data,szPath);
|
|
szString.length = strlen(szPath);
|
|
CMaterialManager::Instance().LoadTexture(&piTexture,&szString);
|
|
|
|
if (!piTexture)
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this texture",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
|
|
return 0;
|
|
}
|
|
|
|
// we must also change the icon of the corresponding tree
|
|
// view item if the default texture was previously set
|
|
TVITEMEX tvi;
|
|
tvi.mask = TVIF_SELECTEDIMAGE | TVIF_IMAGE;
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
|
|
|
|
TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1),
|
|
this->m_pcCurrentTexture->hTreeItem);
|
|
|
|
// change this in the old aiMaterial structure, too
|
|
Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)
|
|
g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
|
|
|
|
// update all meshes referencing this material
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentTexture->iMatIndex != g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
continue;
|
|
|
|
AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i];
|
|
switch (this->m_pcCurrentTexture->iType)
|
|
{
|
|
case AI_TEXTYPE_DIFFUSE:
|
|
if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture != piTexture)
|
|
{
|
|
pcMesh->piDiffuseTexture->Release();
|
|
pcMesh->piDiffuseTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piDiffuseTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
case AI_TEXTYPE_AMBIENT:
|
|
if (pcMesh->piAmbientTexture && pcMesh->piAmbientTexture != piTexture)
|
|
{
|
|
pcMesh->piAmbientTexture->Release();
|
|
pcMesh->piAmbientTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piAmbientTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
case AI_TEXTYPE_SPECULAR:
|
|
if (pcMesh->piSpecularTexture && pcMesh->piSpecularTexture != piTexture)
|
|
{
|
|
pcMesh->piSpecularTexture->Release();
|
|
pcMesh->piSpecularTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piSpecularTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
case AI_TEXTYPE_EMISSIVE:
|
|
if (pcMesh->piEmissiveTexture && pcMesh->piEmissiveTexture != piTexture)
|
|
{
|
|
pcMesh->piEmissiveTexture->Release();
|
|
pcMesh->piEmissiveTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piEmissiveTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
case AI_TEXTYPE_SHININESS:
|
|
if (pcMesh->piShininessTexture && pcMesh->piShininessTexture != piTexture)
|
|
{
|
|
pcMesh->piShininessTexture->Release();
|
|
pcMesh->piShininessTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piShininessTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
case AI_TEXTYPE_NORMALS:
|
|
case AI_TEXTYPE_HEIGHT:
|
|
if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture)
|
|
{
|
|
pcMesh->piNormalTexture->Release();
|
|
pcMesh->piNormalTexture = piTexture;
|
|
CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,
|
|
&pcMesh->piNormalTexture,true);
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
|
|
if (pcMesh->piOpacityTexture && pcMesh->piOpacityTexture != piTexture)
|
|
{
|
|
pcMesh->piOpacityTexture->Release();
|
|
pcMesh->piOpacityTexture = piTexture;
|
|
this->m_pcCurrentTexture->piTexture = &pcMesh->piOpacityTexture;
|
|
|
|
if (!pcMesh->bSharedFX)
|
|
{
|
|
pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",piTexture);
|
|
}
|
|
}
|
|
break;
|
|
};
|
|
}
|
|
|
|
// now update the material itself
|
|
aiString szOld;
|
|
const char* szKey = NULL;
|
|
switch (this->m_pcCurrentTexture->iType)
|
|
{
|
|
case AI_TEXTYPE_DIFFUSE:
|
|
szKey = AI_MATKEY_TEXTURE_DIFFUSE(0);
|
|
break;
|
|
case AI_TEXTYPE_AMBIENT:
|
|
szKey = AI_MATKEY_TEXTURE_AMBIENT(0);
|
|
break;
|
|
case AI_TEXTYPE_SPECULAR:
|
|
szKey = AI_MATKEY_TEXTURE_SPECULAR(0);
|
|
break;
|
|
case AI_TEXTYPE_EMISSIVE:
|
|
szKey = AI_MATKEY_TEXTURE_EMISSIVE(0);
|
|
break;
|
|
case AI_TEXTYPE_NORMALS:
|
|
szKey = AI_MATKEY_TEXTURE_NORMALS(0);
|
|
break;
|
|
case AI_TEXTYPE_HEIGHT:
|
|
szKey = AI_MATKEY_TEXTURE_HEIGHT(0);
|
|
break;
|
|
case AI_TEXTYPE_SHININESS:
|
|
szKey = AI_MATKEY_TEXTURE_SHININESS(0);
|
|
break;
|
|
default: //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
|
|
szKey = AI_MATKEY_TEXTURE_OPACITY(0);
|
|
break;
|
|
};
|
|
ai_assert(NULL != szKey);
|
|
|
|
aiGetMaterialString(pcMat,szKey,&szOld);
|
|
pcMat->AddProperty(&szString,szKey);
|
|
|
|
char szBuffer[512];
|
|
sprintf(szBuffer,"%s%s",szKey,"_old");
|
|
|
|
if (AI_SUCCESS != aiGetMaterialString(pcMat, szBuffer, &szOld))
|
|
{
|
|
pcMat->AddProperty(&szOld,szBuffer );
|
|
}
|
|
else if (szString.length == szOld.length &&
|
|
0 == Assimp::ASSIMP_stricmp(szString.data,szOld.data))
|
|
{
|
|
pcMat->RemoveProperty(szBuffer);
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::AddTextureToDisplayList(unsigned int iType,
|
|
unsigned int iIndex,
|
|
const aiString* szPath,
|
|
HTREEITEM hFX,
|
|
unsigned int iUVIndex /*= 0*/,
|
|
const float fBlendFactor /*= 0.0f*/,
|
|
aiTextureOp eTextureOp /*= aiTextureOp_Multiply*/,
|
|
unsigned int iMesh /*= 0*/)
|
|
{
|
|
ai_assert(NULL != szPath);
|
|
ai_assert(NULL != pcMat);
|
|
|
|
char chTemp[512];
|
|
char chTempEmb[256];
|
|
const char* sz = strrchr(szPath->data,'\\');
|
|
if (!sz)sz = strrchr(szPath->data,'/');
|
|
if (!sz)
|
|
{
|
|
if ('*' == *szPath->data)
|
|
{
|
|
int iIndex = atoi(szPath->data+1);
|
|
sprintf(chTempEmb,"Embedded #%i",iIndex);
|
|
sz = chTempEmb;
|
|
}
|
|
else
|
|
{
|
|
sz = szPath->data;
|
|
}
|
|
}
|
|
|
|
bool bIsExtraOpacity = 0 != (iType & 0x40000000);
|
|
const char* szType;
|
|
IDirect3DTexture9** piTexture;
|
|
switch (iType)
|
|
{
|
|
case AI_TEXTYPE_DIFFUSE:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture;
|
|
szType = "Diffuse";break;
|
|
case AI_TEXTYPE_SPECULAR:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture;
|
|
szType = "Specular";break;
|
|
case AI_TEXTYPE_AMBIENT:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture;
|
|
szType = "Ambient";break;
|
|
case AI_TEXTYPE_EMISSIVE:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture;
|
|
szType = "Emissive";break;
|
|
case AI_TEXTYPE_HEIGHT:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
|
|
szType = "HeightMap";break;
|
|
case AI_TEXTYPE_NORMALS:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
|
|
szType = "NormalMap";break;
|
|
case AI_TEXTYPE_SHININESS:
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture;
|
|
szType = "Shininess";break;
|
|
default: // opacity + opacity | mask
|
|
piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture;
|
|
szType = "Opacity";break;
|
|
};
|
|
if (bIsExtraOpacity)
|
|
{
|
|
sprintf(chTemp,"%s %i (<copy of diffuse #1>)",szType,iIndex+1);
|
|
}
|
|
else sprintf(chTemp,"%s %i (%s)",szType,iIndex+1,sz);
|
|
|
|
TVITEMEX tvi;
|
|
TVINSERTSTRUCT sNew;
|
|
tvi.pszText = chTemp;
|
|
tvi.cchTextMax = (int)strlen(chTemp);
|
|
tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_HANDLE;
|
|
tvi.lParam = (LPARAM)20;
|
|
|
|
// find out whether this is the default texture or not
|
|
|
|
if (piTexture)
|
|
{
|
|
// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
|
|
static const GUID guidPrivateData =
|
|
{ 0x9785da94, 0x1d96, 0x426b,
|
|
{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
|
|
|
|
uint32_t iData = 0;
|
|
DWORD dwSize = 4;
|
|
(*piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize);
|
|
|
|
if (0xFFFFFFFF == iData)
|
|
{
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
|
|
}
|
|
else
|
|
{
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
|
|
}
|
|
|
|
sNew.itemex = tvi;
|
|
sNew.hInsertAfter = TVI_LAST;
|
|
sNew.hParent = hFX;
|
|
|
|
// add the item to the list
|
|
HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
|
|
TVM_INSERTITEM,
|
|
0,
|
|
(LPARAM)(LPTVINSERTSTRUCT)&sNew);
|
|
|
|
// add it to the list
|
|
CDisplay::TextureInfo sInfo;
|
|
sInfo.iUV = iUVIndex;
|
|
sInfo.fBlend = fBlendFactor;
|
|
sInfo.eOp = eTextureOp;
|
|
sInfo.szPath = szPath->data;
|
|
sInfo.hTreeItem = hTexture;
|
|
sInfo.piTexture = piTexture;
|
|
sInfo.iType = iType;
|
|
sInfo.iMatIndex = g_pcAsset->pcScene->mMeshes[iMesh]->mMaterialIndex;
|
|
this->AddTexture(sInfo);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot,
|
|
unsigned int iIndex)
|
|
{
|
|
ai_assert(NULL != hRoot);
|
|
|
|
aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[iIndex];
|
|
|
|
|
|
// find the first mesh using this material index
|
|
unsigned int iMesh = 0;
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
iMesh = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// use the name of the material, if possible
|
|
char chTemp[512];
|
|
aiString szOut;
|
|
if (AI_SUCCESS != aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szOut))
|
|
{
|
|
sprintf(chTemp,"Material %i",iIndex+1);
|
|
}
|
|
else
|
|
{
|
|
sprintf(chTemp,"%s (%i)",szOut.data,iIndex+1);
|
|
}
|
|
TVITEMEX tvi;
|
|
TVINSERTSTRUCT sNew;
|
|
tvi.pszText = chTemp;
|
|
tvi.cchTextMax = (int)strlen(chTemp);
|
|
tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM ;
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
|
|
tvi.lParam = (LPARAM)10;
|
|
//tvi.state = TVIS_EXPANDED | TVIS_EXPANDEDONCE ;
|
|
|
|
sNew.itemex = tvi;
|
|
sNew.hInsertAfter = TVI_LAST;
|
|
sNew.hParent = hRoot;
|
|
|
|
// add the item to the list
|
|
HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
|
|
TVM_INSERTITEM,
|
|
0,
|
|
(LPARAM)(LPTVINSERTSTRUCT)&sNew);
|
|
|
|
// for each texture in the list ... add it
|
|
// NOTE: This expects that AI_TEXTYPE_DIFFUSE is 7
|
|
ai_assert(7 == AI_TEXTYPE_DIFFUSE);
|
|
unsigned int iUV;
|
|
float fBlend;
|
|
aiTextureOp eOp;
|
|
aiString szPath;
|
|
bool bNoOpacity = true;
|
|
for (unsigned int i = 0; i < 8;++i)
|
|
{
|
|
unsigned int iNum = 0;
|
|
while (true)
|
|
{
|
|
if (AI_SUCCESS != aiGetMaterialTexture(pcMat,iNum,i,
|
|
&szPath,&iUV,&fBlend,&eOp))
|
|
{
|
|
break;
|
|
}
|
|
if (AI_TEXTYPE_OPACITY == i)bNoOpacity = false;
|
|
AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
|
|
++iNum;
|
|
}
|
|
}
|
|
|
|
AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iMesh];
|
|
|
|
if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity)
|
|
{
|
|
// check whether the diffuse texture is not a default texture
|
|
|
|
// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
|
|
static const GUID guidPrivateData =
|
|
{ 0x9785da94, 0x1d96, 0x426b,
|
|
{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
|
|
|
|
uint32_t iData = 0;
|
|
DWORD dwSize = 4;
|
|
if(FAILED( pcMesh->piDiffuseTexture->GetPrivateData(guidPrivateData,&iData,&dwSize) ||
|
|
0xffffffff == iData))
|
|
{
|
|
// seems the diffuse texture contains alpha, therefore it has been
|
|
// added to the opacity channel, too. Add a special value ...
|
|
AddTextureToDisplayList(AI_TEXTYPE_OPACITY | 0x40000000,
|
|
0,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
|
|
}
|
|
}
|
|
|
|
// add the material to the list
|
|
MaterialInfo info;
|
|
info.hTreeItem = hTexture;
|
|
info.psMaterial = pcMat;
|
|
info.iIndex = iIndex;
|
|
info.piEffect = g_pcAsset->apcMeshes[iMesh]->piEffect;
|
|
this->AddMaterial(info);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::ExpandTree()
|
|
{
|
|
// expand all materials
|
|
for (std::vector< MaterialInfo >::iterator
|
|
i = this->m_asMaterials.begin();
|
|
i != this->m_asMaterials.end();++i)
|
|
{
|
|
TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
|
|
}
|
|
// expand all nodes
|
|
for (std::vector< NodeInfo >::iterator
|
|
i = this->m_asNodes.begin();
|
|
i != this->m_asNodes.end();++i)
|
|
{
|
|
TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
|
|
}
|
|
TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVE_EXPAND);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::LoadImageList(void)
|
|
{
|
|
if (!this->m_hImageList)
|
|
{
|
|
// First, create the image list we will need.
|
|
// FIX: Need RGB888 color space to display all colors correctly
|
|
HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, 5, 0 );
|
|
|
|
// Load the bitmaps and add them to the image lists.
|
|
HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX));
|
|
this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL] = ImageList_Add(hIml, hBmp, NULL);
|
|
DeleteObject(hBmp);
|
|
|
|
hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE));
|
|
this->m_aiImageList[AI_VIEW_IMGLIST_NODE] = ImageList_Add(hIml, hBmp, NULL);
|
|
DeleteObject(hBmp);
|
|
|
|
hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX));
|
|
this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE] = ImageList_Add(hIml, hBmp, NULL);
|
|
DeleteObject(hBmp);
|
|
|
|
hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTXI));
|
|
this->m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID] = ImageList_Add(hIml, hBmp, NULL);
|
|
DeleteObject(hBmp);
|
|
|
|
hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT));
|
|
this->m_aiImageList[AI_VIEW_IMGLIST_MODEL] = ImageList_Add(hIml, hBmp, NULL);
|
|
DeleteObject(hBmp);
|
|
|
|
// Associate the image list with the tree.
|
|
TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL);
|
|
|
|
this->m_hImageList = hIml;
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::FillDisplayList(void)
|
|
{
|
|
this->LoadImageList();
|
|
|
|
// Initialize the tree view window.
|
|
// fill in the first entry
|
|
TVITEMEX tvi;
|
|
TVINSERTSTRUCT sNew;
|
|
tvi.pszText = "Model";
|
|
tvi.cchTextMax = (int)strlen(tvi.pszText);
|
|
tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE;
|
|
tvi.state = TVIS_EXPANDED;
|
|
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MODEL];
|
|
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MODEL];
|
|
tvi.lParam = (LPARAM)0;
|
|
|
|
sNew.itemex = tvi;
|
|
sNew.hInsertAfter = TVI_ROOT;
|
|
sNew.hParent = 0;
|
|
|
|
// add the root item to the tree
|
|
this->m_hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
|
|
TVM_INSERTITEM,
|
|
0,
|
|
(LPARAM)(LPTVINSERTSTRUCT)&sNew);
|
|
|
|
// add each loaded material to the tree
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials;++i)
|
|
{
|
|
AddMaterialToDisplayList(this->m_hRoot,i);
|
|
}
|
|
|
|
// now add all loaded nodes recursively
|
|
AddNodeToDisplayList(0,0,g_pcAsset->pcScene->mRootNode,this->m_hRoot);
|
|
|
|
// now expand all parent nodes in the tree
|
|
this->ExpandTree();
|
|
|
|
// everything reacts a little bit slowly if D3D is rendering,
|
|
// so give GDI a small hint to leave the couch and work ;-)
|
|
UpdateWindow(g_hDlg);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnRender()
|
|
{
|
|
// begin the frame
|
|
g_piDevice->BeginScene();
|
|
|
|
switch (this->m_iViewMode)
|
|
{
|
|
case VIEWMODE_FULL:
|
|
case VIEWMODE_NODE:
|
|
this->RenderFullScene();
|
|
break;
|
|
case VIEWMODE_MATERIAL:
|
|
this->RenderMaterialView();
|
|
break;
|
|
case VIEWMODE_TEXTURE:
|
|
this->RenderTextureView();
|
|
break;
|
|
};
|
|
|
|
// Now render the log display in the upper right corner of the window
|
|
CLogDisplay::Instance().OnRender();
|
|
|
|
// present the backbuffer
|
|
g_piDevice->EndScene();
|
|
g_piDevice->Present(NULL,NULL,NULL,NULL);
|
|
|
|
// don't remove this, problems on some older machines (AMD timing bug)
|
|
Sleep(10);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void UpdateColorFieldsInUI()
|
|
{
|
|
InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE);
|
|
InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE);
|
|
InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE);
|
|
|
|
UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1));
|
|
UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2));
|
|
UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3));
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::FillDefaultStatistics(void)
|
|
{
|
|
if (!g_pcAsset)
|
|
{
|
|
// clear all stats edit controls
|
|
SetDlgItemText(g_hDlg,IDC_EVERT,"0");
|
|
SetDlgItemText(g_hDlg,IDC_EFACE,"0");
|
|
SetDlgItemText(g_hDlg,IDC_EMAT,"0");
|
|
SetDlgItemText(g_hDlg,IDC_ENODE,"0");
|
|
SetDlgItemText(g_hDlg,IDC_ESHADER,"0");
|
|
SetDlgItemText(g_hDlg,IDC_ETEX,"0");
|
|
return 1;
|
|
}
|
|
|
|
// get the number of vertices/faces in the model
|
|
unsigned int iNumVert = 0;
|
|
unsigned int iNumFaces = 0;
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices;
|
|
iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces;
|
|
}
|
|
// and fill the statistic edit controls
|
|
char szOut[1024];
|
|
sprintf(szOut,"%i",(int)iNumVert);
|
|
SetDlgItemText(g_hDlg,IDC_EVERT,szOut);
|
|
sprintf(szOut,"%i",(int)iNumFaces);
|
|
SetDlgItemText(g_hDlg,IDC_EFACE,szOut);
|
|
sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMaterials);
|
|
SetDlgItemText(g_hDlg,IDC_EMAT,szOut);
|
|
sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMeshes);
|
|
SetDlgItemText(g_hDlg,IDC_EMESH,szOut);
|
|
|
|
// need to get the number of nodes
|
|
iNumVert = 0;
|
|
GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert);
|
|
sprintf(szOut,"%i",(int)iNumVert);
|
|
SetDlgItemText(g_hDlg,IDC_ENODEWND,szOut);
|
|
|
|
// now get the number of unique shaders generated for the asset
|
|
// (even if the environment changes this number won't change)
|
|
sprintf(szOut,"%i", CMaterialManager::Instance().GetShaderCount());
|
|
SetDlgItemText(g_hDlg,IDC_ESHADER,szOut);
|
|
|
|
sprintf(szOut,"%.5f",(float)g_fLoadTime);
|
|
SetDlgItemText(g_hDlg,IDC_ELOAD,szOut);
|
|
|
|
UpdateColorFieldsInUI();
|
|
UpdateWindow(g_hDlg);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::Reset(void)
|
|
{
|
|
// clear all lists
|
|
this->m_asMaterials.clear();
|
|
this->m_asTextures.clear();
|
|
this->m_asNodes.clear();
|
|
|
|
this->m_hRoot = NULL;
|
|
|
|
return this->OnSetupNormalView();
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
void ShowNormalUIComponents()
|
|
{
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_SHOW);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_HIDE);
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnSetupNormalView()
|
|
{
|
|
if (VIEWMODE_NODE == this->m_iViewMode)
|
|
{
|
|
ShowNormalUIComponents();
|
|
}
|
|
|
|
// now ... change the meaning of the statistics fields back
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Verts:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"Shd:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Mats:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Mesh:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Time:");
|
|
|
|
this->FillDefaultStatistics();
|
|
this->SetViewMode(VIEWMODE_FULL);
|
|
|
|
// for debugging
|
|
this->m_pcCurrentMaterial = NULL;
|
|
this->m_pcCurrentTexture = NULL;
|
|
this->m_pcCurrentNode = NULL;
|
|
|
|
// redraw the color fields in the UI --- their purpose has possibly changed
|
|
UpdateColorFieldsInUI();
|
|
UpdateWindow(g_hDlg);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnSetupNodeView(NodeInfo* pcNew)
|
|
{
|
|
ai_assert(NULL != pcNew);
|
|
|
|
if (this->m_pcCurrentNode == pcNew)return 2;
|
|
|
|
// now ... change the meaning of the statistics fields back
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Verts:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Mats:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Mesh:");
|
|
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_HIDE);
|
|
ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_SHOW);
|
|
|
|
char szTemp[1024];
|
|
sprintf(szTemp,
|
|
"%.2f %.2f %.2f\r\n"
|
|
"%.2f %.2f %.2f\r\n"
|
|
"%.2f %.2f %.2f\r\n"
|
|
"%.2f %.2f %.2f\r\n",
|
|
pcNew->psNode->mTransformation.a1,
|
|
pcNew->psNode->mTransformation.b1,
|
|
pcNew->psNode->mTransformation.c1,
|
|
pcNew->psNode->mTransformation.a2,
|
|
pcNew->psNode->mTransformation.b2,
|
|
pcNew->psNode->mTransformation.c2,
|
|
pcNew->psNode->mTransformation.a3,
|
|
pcNew->psNode->mTransformation.b3,
|
|
pcNew->psNode->mTransformation.c3,
|
|
pcNew->psNode->mTransformation.a4,
|
|
pcNew->psNode->mTransformation.b4,
|
|
pcNew->psNode->mTransformation.c4);
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),szTemp);
|
|
|
|
|
|
this->m_pcCurrentNode = pcNew;
|
|
this->SetViewMode(VIEWMODE_NODE);
|
|
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew)
|
|
{
|
|
ai_assert(NULL != pcNew);
|
|
|
|
if (this->m_pcCurrentMaterial == pcNew)return 2;
|
|
|
|
if (VIEWMODE_NODE == this->m_iViewMode)
|
|
{
|
|
ShowNormalUIComponents();
|
|
}
|
|
|
|
this->m_pcCurrentMaterial = pcNew;
|
|
this->SetViewMode(VIEWMODE_MATERIAL);
|
|
|
|
|
|
// redraw the color fields in the UI --- their purpose has possibly changed
|
|
UpdateColorFieldsInUI();
|
|
UpdateWindow(g_hDlg);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
|
|
{
|
|
ai_assert(NULL != pcNew);
|
|
|
|
if (this->m_pcCurrentTexture == pcNew)return 2;
|
|
|
|
if (VIEWMODE_NODE == this->m_iViewMode)
|
|
{
|
|
ShowNormalUIComponents();
|
|
}
|
|
|
|
if ((AI_TEXTYPE_OPACITY | 0x40000000) == pcNew->iType)
|
|
{
|
|
// for opacity textures display a warn message
|
|
CLogDisplay::Instance().AddEntry("[INFO] This texture is not existing in the "
|
|
"original mesh",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
|
|
CLogDisplay::Instance().AddEntry("It is a copy of the alpha channel of the first "
|
|
"diffuse texture",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
|
|
}
|
|
|
|
// check whether the pattern background effect is supported
|
|
if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0))
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[WARN] The background shader won't work "
|
|
"on your system, it required PS 3.0 hardware. A default color is used ...",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0x00,0));
|
|
}
|
|
|
|
this->m_fTextureZoom = 1000.0f;
|
|
this->m_vTextureOffset.x = this->m_vTextureOffset.y = 0.0f;
|
|
|
|
this->m_pcCurrentTexture = pcNew;
|
|
this->SetViewMode(VIEWMODE_TEXTURE);
|
|
|
|
// now ... change the meaning of the statistics fields
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Width:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Height:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Format:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"MIPs:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"UV:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Blend:");
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Op:");
|
|
|
|
// and fill them with data
|
|
D3DSURFACE_DESC sDesc;
|
|
(*pcNew->piTexture)->GetLevelDesc(0,&sDesc);
|
|
char szTemp[128];
|
|
|
|
sprintf(szTemp,"%i",sDesc.Width);
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_EVERT),szTemp);
|
|
|
|
sprintf(szTemp,"%i",sDesc.Height);
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_ENODEWND),szTemp);
|
|
|
|
sprintf(szTemp,"%i",(*pcNew->piTexture)->GetLevelCount());
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_ESHADER),szTemp);
|
|
|
|
sprintf(szTemp,"%i",pcNew->iUV);
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_EMAT),szTemp);
|
|
|
|
sprintf(szTemp,"%f",pcNew->fBlend);
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_EMESH),szTemp);
|
|
|
|
const char* szOp;
|
|
switch (pcNew->eOp)
|
|
{
|
|
case aiTextureOp_Add:
|
|
szOp = "add";break;
|
|
case aiTextureOp_Subtract:
|
|
szOp = "sub";break;
|
|
case aiTextureOp_Divide:
|
|
szOp = "div";break;
|
|
case aiTextureOp_SignedAdd:
|
|
szOp = "addsign";break;
|
|
case aiTextureOp_SmoothAdd:
|
|
szOp = "addsmooth";break;
|
|
default: szOp = "mul";
|
|
};
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp);
|
|
|
|
// NOTE: Format is always ARGB8888 since other formats are
|
|
// converted to this format ...
|
|
SetWindowText(GetDlgItem(g_hDlg,IDC_EFACE),"ARGB8");
|
|
|
|
// check whether this is the default texture
|
|
if (pcNew->piTexture)
|
|
{
|
|
// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
|
|
static const GUID guidPrivateData =
|
|
{ 0x9785da94, 0x1d96, 0x426b,
|
|
{ 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
|
|
|
|
uint32_t iData = 0;
|
|
DWORD dwSize = 4;
|
|
(*pcNew->piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize);
|
|
|
|
if (0xFFFFFFFF == iData)
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[ERROR] Texture could not be loaded. "
|
|
"The displayed texture is a default texture",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0,0));
|
|
return 0;
|
|
}
|
|
}
|
|
// redraw the color fields in the UI --- their purpose has possibly changed
|
|
UpdateColorFieldsInUI();
|
|
UpdateWindow(g_hDlg);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::OnSetup(HTREEITEM p_hTreeItem)
|
|
{
|
|
// search in our list for the item
|
|
|
|
union {
|
|
TextureInfo* pcNew;
|
|
NodeInfo* pcNew2;
|
|
MaterialInfo* pcNew3; };
|
|
|
|
pcNew = NULL;
|
|
for (std::vector<TextureInfo>::iterator
|
|
i = this->m_asTextures.begin();
|
|
i != this->m_asTextures.end();++i)
|
|
{
|
|
if (p_hTreeItem == (*i).hTreeItem)
|
|
{
|
|
pcNew = &(*i);
|
|
break;
|
|
}
|
|
}
|
|
if (pcNew)
|
|
{
|
|
return this->OnSetupTextureView(pcNew);
|
|
}
|
|
|
|
// seach the node list
|
|
for (std::vector<NodeInfo>::iterator
|
|
i = this->m_asNodes.begin();
|
|
i != this->m_asNodes.end();++i)
|
|
{
|
|
if (p_hTreeItem == (*i).hTreeItem)
|
|
{
|
|
pcNew2 = &(*i);
|
|
break;
|
|
}
|
|
}
|
|
if (pcNew2)
|
|
{
|
|
return this->OnSetupNodeView(pcNew2);
|
|
}
|
|
|
|
// seach the material list
|
|
for (std::vector<MaterialInfo>::iterator
|
|
i = this->m_asMaterials.begin();
|
|
i != this->m_asMaterials.end();++i)
|
|
{
|
|
if (p_hTreeItem == (*i).hTreeItem)
|
|
{
|
|
pcNew3 = &(*i);
|
|
break;
|
|
}
|
|
}
|
|
if (pcNew3)
|
|
{
|
|
return this->OnSetupMaterialView(pcNew3);
|
|
}
|
|
return this->OnSetupNormalView();
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem)
|
|
{
|
|
ai_assert(NULL != hItem);
|
|
|
|
HMENU hDisplay = NULL;
|
|
|
|
// search in our list for the item
|
|
TextureInfo* pcNew = NULL;
|
|
for (std::vector<TextureInfo>::iterator
|
|
i = this->m_asTextures.begin();
|
|
i != this->m_asTextures.end();++i)
|
|
{
|
|
if (hItem == (*i).hTreeItem)
|
|
{
|
|
pcNew = &(*i);
|
|
break;
|
|
}
|
|
}
|
|
if (pcNew)
|
|
{
|
|
HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_TXPOPUP));
|
|
hDisplay = GetSubMenu(hMenu,0);
|
|
|
|
//this->OnSetupTextureView(pcNew);
|
|
}
|
|
|
|
// search in the material list for the item
|
|
MaterialInfo* pcNew2 = NULL;
|
|
for (std::vector<MaterialInfo>::iterator
|
|
i = this->m_asMaterials.begin();
|
|
i != this->m_asMaterials.end();++i)
|
|
{
|
|
if (hItem == (*i).hTreeItem)
|
|
{
|
|
pcNew2 = &(*i);
|
|
break;
|
|
}
|
|
}
|
|
if (pcNew2)
|
|
{
|
|
HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MATPOPUP));
|
|
hDisplay = GetSubMenu(hMenu,0);
|
|
|
|
//this->OnSetupMaterialView(pcNew2);
|
|
}
|
|
if (NULL != hDisplay)
|
|
{
|
|
// select this entry (this should all OnSetup())
|
|
TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),hItem,TVGN_CARET);
|
|
|
|
// FIX: Render the scene once that the correct texture/material
|
|
// is displayed while the context menu is active
|
|
this->OnRender();
|
|
|
|
POINT sPoint;
|
|
GetCursorPos(&sPoint);
|
|
TrackPopupMenu(hDisplay, TPM_LEFTALIGN, sPoint.x, sPoint.y, 0,
|
|
g_hDlg,NULL);
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
|
|
{
|
|
// get the current selected material
|
|
std::vector<Info> apclrOut;
|
|
const char* szMatKey;
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ID_SOLONG_CLEARDIFFUSECOLOR:
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vDiffuseColor,
|
|
g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR"));
|
|
}
|
|
}
|
|
szMatKey = AI_MATKEY_COLOR_DIFFUSE;
|
|
break;
|
|
case ID_SOLONG_CLEARSPECULARCOLOR:
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vSpecularColor,
|
|
g_pcAsset->apcMeshes[i],"SPECULAR_COLOR"));
|
|
}
|
|
}
|
|
szMatKey = AI_MATKEY_COLOR_SPECULAR;
|
|
break;
|
|
case ID_SOLONG_CLEARAMBIENTCOLOR:
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vAmbientColor,
|
|
g_pcAsset->apcMeshes[i],"AMBIENT_COLOR"));
|
|
}
|
|
}
|
|
szMatKey = AI_MATKEY_COLOR_AMBIENT;
|
|
break;
|
|
case ID_SOLONG_CLEAREMISSIVECOLOR:
|
|
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vEmissiveColor,
|
|
g_pcAsset->apcMeshes[i],"EMISSIVE_COLOR"));
|
|
}
|
|
}
|
|
szMatKey = AI_MATKEY_COLOR_EMISSIVE;
|
|
break;
|
|
default:
|
|
|
|
// let the next function do this ... no spaghetti code ;-)
|
|
this->HandleTreeViewPopup2(wParam,lParam);
|
|
};
|
|
if (!apclrOut.empty())
|
|
{
|
|
aiColor4D clrOld = *((aiColor4D*)(apclrOut.front().pclrColor));
|
|
|
|
CHOOSECOLOR clr;
|
|
clr.lStructSize = sizeof(CHOOSECOLOR);
|
|
clr.hwndOwner = g_hDlg;
|
|
clr.Flags = CC_RGBINIT | CC_FULLOPEN;
|
|
clr.rgbResult = RGB(
|
|
clamp<unsigned char>(clrOld.r * 255.0f),
|
|
clamp<unsigned char>(clrOld.g * 255.0f),
|
|
clamp<unsigned char>(clrOld.b * 255.0f));
|
|
clr.lpCustColors = g_aclCustomColors;
|
|
clr.lpfnHook = NULL;
|
|
clr.lpTemplateName = NULL;
|
|
clr.lCustData = NULL;
|
|
|
|
ChooseColor(&clr);
|
|
|
|
clrOld.r = (float)(((unsigned int)clr.rgbResult) & 0xFF) / 255.0f;
|
|
clrOld.g = (float)(((unsigned int)clr.rgbResult >> 8) & 0xFF) / 255.0f;
|
|
clrOld.b = (float)(((unsigned int)clr.rgbResult >> 16) & 0xFF) / 255.0f;
|
|
|
|
// update the color values in the mesh instances and
|
|
// update all shaders ...
|
|
for (std::vector<Info>::iterator
|
|
i = apclrOut.begin();
|
|
i != apclrOut.end();++i)
|
|
{
|
|
*((*i).pclrColor) = *((D3DXVECTOR4*)&clrOld);
|
|
if (!(*i).pMesh->bSharedFX)
|
|
{
|
|
(*i).pMesh->piEffect->SetVector((*i).szShaderParam,(*i).pclrColor);
|
|
}
|
|
}
|
|
|
|
// change the material key ...
|
|
Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[
|
|
this->m_pcCurrentMaterial->iIndex];
|
|
pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey);
|
|
|
|
if (ID_SOLONG_CLEARSPECULARCOLOR == LOWORD(wParam) &&
|
|
aiShadingMode_Gouraud == apclrOut.front().pMesh->eShadingMode)
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[INFO] You have just changed the specular "
|
|
"material color",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
|
|
CLogDisplay::Instance().AddEntry(
|
|
"This is great, especially since there is currently no specular shading",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CALLBACK TreeViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
if (lParamSort == lParam1)return -1;
|
|
if (lParamSort == lParam2)return 1;
|
|
return 0;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam)
|
|
{
|
|
char szFileName[MAX_PATH];
|
|
DWORD dwTemp = MAX_PATH;
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ID_HEY_REPLACE:
|
|
{
|
|
// get a path to a new texture
|
|
if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ReplaceTextureSrc",NULL,NULL,
|
|
(BYTE*)szFileName,&dwTemp))
|
|
{
|
|
// Key was not found. Use C:
|
|
strcpy(szFileName,"");
|
|
}
|
|
else
|
|
{
|
|
// need to remove the file name
|
|
char* sz = strrchr(szFileName,'\\');
|
|
if (!sz)sz = strrchr(szFileName,'/');
|
|
if (!sz)*sz = 0;
|
|
}
|
|
OPENFILENAME sFilename1 = {
|
|
sizeof(OPENFILENAME),
|
|
g_hDlg,GetModuleHandle(NULL),
|
|
"Textures\0*.png;*.dds;*.tga;*.bmp;*.tif;*.ppm;*.ppx;*.jpg;*.jpeg;*.exr\0*.*\0",
|
|
NULL, 0, 1,
|
|
szFileName, MAX_PATH, NULL, 0, NULL,
|
|
"Replace this texture",
|
|
OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR,
|
|
0, 1, ".jpg", 0, NULL, NULL
|
|
};
|
|
if(GetOpenFileName(&sFilename1) == 0) return 0;
|
|
|
|
// Now store the file in the registry
|
|
RegSetValueExA(g_hRegistry,"ReplaceTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
|
|
this->ReplaceCurrentTexture(szFileName);
|
|
}
|
|
return 1;
|
|
|
|
case ID_HEY_EXPORT:
|
|
{
|
|
if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureExportDest",NULL,NULL,
|
|
(BYTE*)szFileName,&dwTemp))
|
|
{
|
|
// Key was not found. Use C:
|
|
strcpy(szFileName,"");
|
|
}
|
|
else
|
|
{
|
|
// need to remove the file name
|
|
char* sz = strrchr(szFileName,'\\');
|
|
if (!sz)sz = strrchr(szFileName,'/');
|
|
if (!sz)*sz = 0;
|
|
}
|
|
OPENFILENAME sFilename1 = {
|
|
sizeof(OPENFILENAME),
|
|
g_hDlg,GetModuleHandle(NULL),
|
|
"Textures\0*.png;*.dds;*.bmp;*.tif;*.pfm;*.jpg;*.jpeg;*.hdr\0*.*\0", NULL, 0, 1,
|
|
szFileName, MAX_PATH, NULL, 0, NULL,
|
|
"Export texture to file",
|
|
OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR,
|
|
0, 1, ".png", 0, NULL, NULL
|
|
};
|
|
if(GetSaveFileName(&sFilename1) == 0) return 0;
|
|
|
|
// Now store the file in the registry
|
|
RegSetValueExA(g_hRegistry,"TextureExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
|
|
|
|
// determine the file format ...
|
|
D3DXIMAGE_FILEFORMAT eFormat = D3DXIFF_PNG;
|
|
const char* sz = strrchr(szFileName,'.');
|
|
if (sz)
|
|
{
|
|
++sz;
|
|
if (0 == Assimp::ASSIMP_stricmp(sz,"pfm"))eFormat = D3DXIFF_PFM;
|
|
else if (0 == Assimp::ASSIMP_stricmp(sz,"dds"))eFormat = D3DXIFF_DDS;
|
|
else if (0 == Assimp::ASSIMP_stricmp(sz,"jpg"))eFormat = D3DXIFF_JPG;
|
|
else if (0 == Assimp::ASSIMP_stricmp(sz,"jpeg"))eFormat = D3DXIFF_JPG;
|
|
else if (0 == Assimp::ASSIMP_stricmp(sz,"hdr"))eFormat = D3DXIFF_HDR;
|
|
else if (0 == Assimp::ASSIMP_stricmp(sz,"bmp"))eFormat = D3DXIFF_BMP;
|
|
}
|
|
|
|
// get a pointer to the first surface of the current texture
|
|
IDirect3DSurface9* pi = NULL;
|
|
(*this->m_pcCurrentTexture->piTexture)->GetSurfaceLevel(0,&pi);
|
|
if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,eFormat,pi,NULL,NULL)))
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[ERROR] Unable to export texture",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0,0));
|
|
}
|
|
else
|
|
{
|
|
CLogDisplay::Instance().AddEntry("[INFO] The texture has been exported",
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
|
|
}
|
|
if(pi)pi->Release();
|
|
}
|
|
return 1;
|
|
|
|
case ID_HEY_REMOVE:
|
|
{
|
|
|
|
if(IDYES != MessageBox(g_hDlg,"To recover the texture you need to reload the model. Do you wish to continue?",
|
|
"Remove texture",MB_YESNO))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)g_pcAsset->pcScene->mMaterials[
|
|
this->m_pcCurrentTexture->iMatIndex];
|
|
|
|
switch (this->m_pcCurrentTexture->iType)
|
|
{
|
|
case AI_TEXTYPE_DIFFUSE:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_DIFFUSE(0));
|
|
break;
|
|
case AI_TEXTYPE_SPECULAR:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SPECULAR(0));
|
|
break;
|
|
case AI_TEXTYPE_AMBIENT:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_AMBIENT(0));
|
|
break;
|
|
case AI_TEXTYPE_EMISSIVE:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_EMISSIVE(0));
|
|
break;
|
|
case AI_TEXTYPE_NORMALS:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_NORMALS(0));
|
|
break;
|
|
case AI_TEXTYPE_HEIGHT:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_HEIGHT(0));
|
|
break;
|
|
case AI_TEXTYPE_SHININESS:
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_SHININESS(0));
|
|
break;
|
|
case (AI_TEXTYPE_OPACITY | 0x40000000):
|
|
|
|
// set a special property to indicate that no alpha channel is required
|
|
{int iVal = 1;
|
|
pcMat->AddProperty<int>(&iVal,1,"no_a_from_d");}
|
|
|
|
break;
|
|
default: //case AI_TEXTYPE_OPACITY
|
|
pcMat->RemoveProperty(AI_MATKEY_TEXTURE_OPACITY(0));
|
|
};
|
|
|
|
// need to update all meshes associated with this material
|
|
for (unsigned int i = 0;i < g_pcAsset->pcScene->mNumMeshes;++i)
|
|
{
|
|
if (this->m_pcCurrentTexture->iMatIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
|
|
{
|
|
CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
|
|
CMaterialManager::Instance().CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
|
|
}
|
|
}
|
|
// find the corresponding MaterialInfo structure
|
|
const unsigned int iMatIndex = this->m_pcCurrentTexture->iMatIndex;
|
|
for (std::vector<MaterialInfo>::iterator
|
|
a = this->m_asMaterials.begin();
|
|
a != this->m_asMaterials.end();++a)
|
|
{
|
|
if (iMatIndex == (*a).iIndex)
|
|
{
|
|
// good news. we will also need to find all other textures
|
|
// associated with this item ...
|
|
for (std::vector<TextureInfo>::iterator
|
|
n = this->m_asTextures.begin();
|
|
n != this->m_asTextures.end();++n)
|
|
{
|
|
if ((*n).iMatIndex == iMatIndex)
|
|
{
|
|
n = this->m_asTextures.erase(n);
|
|
if (this->m_asTextures.end() == n)break;
|
|
}
|
|
}
|
|
// delete this material from all lists ...
|
|
TreeView_DeleteItem(GetDlgItem(g_hDlg,IDC_TREE1),(*a).hTreeItem);
|
|
this->m_asMaterials.erase(a);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// add the new material to the list and make sure it will be fully expanded
|
|
AddMaterialToDisplayList(this->m_hRoot,iMatIndex);
|
|
HTREEITEM hNewItem = this->m_asMaterials.back().hTreeItem;
|
|
TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),hNewItem,TVE_EXPAND);
|
|
|
|
// we need to sort the list, materials come first, then nodes
|
|
TVSORTCB sSort;
|
|
sSort.hParent = this->m_hRoot;
|
|
sSort.lParam = 10;
|
|
sSort.lpfnCompare = &TreeViewCompareFunc;
|
|
TreeView_SortChildrenCB(GetDlgItem(g_hDlg,IDC_TREE1),&sSort,0);
|
|
|
|
// the texture was selected, but the silly user has just deleted it
|
|
// ... go back to normal viewing mode
|
|
TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),this->m_hRoot,TVGN_CARET);
|
|
return 1;
|
|
}
|
|
|
|
case ID_HEY_RESETTEXTURE:
|
|
{
|
|
aiString szOld;
|
|
aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
|
|
switch (this->m_pcCurrentTexture->iType)
|
|
{
|
|
case AI_TEXTYPE_DIFFUSE:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_SPECULAR:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_AMBIENT:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_EMISSIVE:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_NORMALS:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_HEIGHT:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0) "_old",&szOld);
|
|
break;
|
|
case AI_TEXTYPE_SHININESS:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0) "_old",&szOld);
|
|
break;
|
|
default : //case AI_TEXTYPE_OPACITY && case AI_TEXTYPE_OPACITY | 0x40000000:
|
|
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0) "_old",&szOld);
|
|
break;
|
|
};
|
|
if (0 != szOld.length)this->ReplaceCurrentTexture(szOld.data);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::SetupStereoView()
|
|
{
|
|
if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
|
|
{
|
|
// enable the RED, GREEN and ALPHA channels
|
|
g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
|
|
D3DCOLORWRITEENABLE_RED |
|
|
D3DCOLORWRITEENABLE_ALPHA |
|
|
D3DCOLORWRITEENABLE_GREEN);
|
|
|
|
// move the camera a little bit to the left
|
|
g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderStereoView(const aiMatrix4x4& m)
|
|
{
|
|
// and rerender the scene
|
|
if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
|
|
{
|
|
// enable the BLUE, GREEN and ALPHA channels
|
|
g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
|
|
D3DCOLORWRITEENABLE_GREEN |
|
|
D3DCOLORWRITEENABLE_ALPHA |
|
|
D3DCOLORWRITEENABLE_BLUE);
|
|
|
|
// clear the z-buffer
|
|
g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,0,1.0f,0);
|
|
|
|
// move the camera a little bit to the right
|
|
g_sCamera.vPos += g_sCamera.vRight * 0.06f;
|
|
|
|
RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
|
|
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
|
|
RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
|
|
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
|
|
|
|
// (move back to the original position)
|
|
g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
|
|
|
|
// reenable all channels
|
|
g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
|
|
D3DCOLORWRITEENABLE_RED |
|
|
D3DCOLORWRITEENABLE_GREEN |
|
|
D3DCOLORWRITEENABLE_ALPHA |
|
|
D3DCOLORWRITEENABLE_BLUE);
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::HandleInputTextureView()
|
|
{
|
|
HandleMouseInputTextureView();
|
|
HandleKeyboardInputTextureView();
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::HandleInput()
|
|
{
|
|
if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
|
|
HandleMouseInputSkyBox();
|
|
|
|
// handle input commands
|
|
HandleMouseInputLightRotate();
|
|
HandleMouseInputLightIntensityAndColor();
|
|
if(g_bFPSView)
|
|
{
|
|
HandleMouseInputFPS();
|
|
HandleKeyboardInputFPS();
|
|
}
|
|
else HandleMouseInputLocal();
|
|
|
|
// compute auto rotation depending on the time which has passed
|
|
if (g_sOptions.bRotate)
|
|
{
|
|
aiMatrix4x4 mMat;
|
|
D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
|
|
g_vRotateSpeed.x * g_fElpasedTime,
|
|
g_vRotateSpeed.y * g_fElpasedTime,
|
|
g_vRotateSpeed.z * g_fElpasedTime);
|
|
g_mWorldRotate = g_mWorldRotate * mMat;
|
|
}
|
|
|
|
// Handle rotations of light source(s)
|
|
if (g_sOptions.bLightRotate)
|
|
{
|
|
aiMatrix4x4 mMat;
|
|
D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
|
|
g_vRotateSpeed.x * g_fElpasedTime * 0.5f,
|
|
g_vRotateSpeed.y * g_fElpasedTime * 0.5f,
|
|
g_vRotateSpeed.z * g_fElpasedTime * 0.5f);
|
|
|
|
D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[0],
|
|
(D3DXVECTOR3*)&g_avLightDirs[0],(D3DXMATRIX*)&mMat);
|
|
|
|
// 2 lights to rotate?
|
|
if (g_sOptions.b3Lights)
|
|
{
|
|
D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[1],
|
|
(D3DXVECTOR3*)&g_avLightDirs[1],(D3DXMATRIX*)&mMat);
|
|
|
|
g_avLightDirs[1].Normalize();
|
|
}
|
|
g_avLightDirs[0].Normalize();
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::HandleInputEmptyScene()
|
|
{
|
|
if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
|
|
{
|
|
if (g_bFPSView)
|
|
{
|
|
HandleMouseInputFPS();
|
|
HandleKeyboardInputFPS();
|
|
}
|
|
HandleMouseInputSkyBox();
|
|
|
|
// need to store the last mouse position in the global variable
|
|
// HandleMouseInputFPS() is doing this internally
|
|
if (!g_bFPSView)
|
|
{
|
|
g_LastmousePos.x = g_mousePos.x;
|
|
g_LastmousePos.y = g_mousePos.y;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::DrawHUD()
|
|
{
|
|
// get the dimension of the back buffer
|
|
RECT sRect;
|
|
GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
|
|
sRect.right -= sRect.left;
|
|
sRect.bottom -= sRect.top;
|
|
|
|
struct SVertex
|
|
{
|
|
float x,y,z,w,u,v;
|
|
};
|
|
|
|
// commit the texture to the shader
|
|
// FIX: Necessary because the texture view is also using this shader
|
|
g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture);
|
|
|
|
// NOTE: The shader might be used for other purposes, too.
|
|
// So ensure the right technique is there
|
|
g_piPassThroughEffect->SetTechnique("PassThrough");
|
|
|
|
// build vertices for drawing from system memory
|
|
UINT dw;
|
|
g_piPassThroughEffect->Begin(&dw,0);
|
|
g_piPassThroughEffect->BeginPass(0);
|
|
|
|
D3DSURFACE_DESC sDesc;
|
|
g_pcTexture->GetLevelDesc(0,&sDesc);
|
|
SVertex as[4];
|
|
float fHalfX = ((float)sRect.right-(float)sDesc.Width) / 2.0f;
|
|
float fHalfY = ((float)sRect.bottom-(float)sDesc.Height) / 2.0f;
|
|
as[1].x = fHalfX;
|
|
as[1].y = fHalfY;
|
|
as[1].z = 0.2f;
|
|
as[1].w = 1.0f;
|
|
as[1].u = 0.0f;
|
|
as[1].v = 0.0f;
|
|
|
|
as[3].x = (float)sRect.right-fHalfX;
|
|
as[3].y = fHalfY;
|
|
as[3].z = 0.2f;
|
|
as[3].w = 1.0f;
|
|
as[3].u = 1.0f;
|
|
as[3].v = 0.0f;
|
|
|
|
as[0].x = fHalfX;
|
|
as[0].y = (float)sRect.bottom-fHalfY;
|
|
as[0].z = 0.2f;
|
|
as[0].w = 1.0f;
|
|
as[0].u = 0.0f;
|
|
as[0].v = 1.0f;
|
|
|
|
as[2].x = (float)sRect.right-fHalfX;
|
|
as[2].y = (float)sRect.bottom-fHalfY;
|
|
as[2].z = 0.2f;
|
|
as[2].w = 1.0f;
|
|
as[2].u = 1.0f;
|
|
as[2].v = 1.0f;
|
|
|
|
as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
|
|
as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
|
|
|
|
// draw the screen-filling squad
|
|
DWORD dw2;g_piDevice->GetFVF(&dw2);
|
|
g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
|
g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
|
|
&as,sizeof(SVertex));
|
|
|
|
// end the effect and recover the old vertex format
|
|
g_piPassThroughEffect->EndPass();
|
|
g_piPassThroughEffect->End();
|
|
|
|
g_piDevice->SetFVF(dw2);
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderFullScene()
|
|
{
|
|
// reset the color index used for drawing normals
|
|
g_iCurrentColor = 0;
|
|
|
|
// reset frame counter and rotation tracker
|
|
CMeshRenderer::Instance().OnBeginFrame();
|
|
|
|
// setup wireframe/solid rendering mode
|
|
if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
|
|
{
|
|
g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
|
|
}
|
|
else g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
|
|
|
|
// draw the scene background (clear and texture 2d)
|
|
CBackgroundPainter::Instance().OnPreRender();
|
|
|
|
// setup the stereo view if necessary
|
|
if (g_sOptions.bStereoView)
|
|
{
|
|
this->SetupStereoView();
|
|
}
|
|
|
|
// draw all opaque objects in the scene
|
|
aiMatrix4x4 m;
|
|
if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
|
|
{
|
|
this->HandleInput();
|
|
m = g_mWorld * g_mWorldRotate;
|
|
RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
|
|
}
|
|
|
|
// if a cube texture is loaded as background image, the user
|
|
// should be able to rotate it even if no asset is loaded
|
|
this->HandleInputEmptyScene();
|
|
|
|
// draw the scene background
|
|
CBackgroundPainter::Instance().OnPostRender();
|
|
|
|
// draw all non-opaque objects in the scene
|
|
if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
|
|
{
|
|
// disable the z-buffer
|
|
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
|
|
RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
|
|
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
|
|
}
|
|
|
|
// setup the stereo view if necessary
|
|
if (g_sOptions.bStereoView)
|
|
{
|
|
this->RenderStereoView(m);
|
|
}
|
|
|
|
// draw the HUD texture on top of the rendered scene using
|
|
// pre-projected vertices
|
|
if (!g_bFPSView && g_pcAsset && g_pcTexture)
|
|
{
|
|
this->DrawHUD();
|
|
}
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderMaterialView()
|
|
{
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
|
|
bool bAlpha /*= false*/)
|
|
{
|
|
aiMatrix4x4 mTemp = piNode->mTransformation;
|
|
mTemp.Transpose();
|
|
aiMatrix4x4 aiMe = mTemp * piMatrix;
|
|
|
|
bool bChangedVM = false;
|
|
if (VIEWMODE_NODE == this->m_iViewMode && this->m_pcCurrentNode)
|
|
{
|
|
if (piNode != this->m_pcCurrentNode->psNode)
|
|
{
|
|
if (0 != piNode->mNumChildren)
|
|
{
|
|
// directly call our children
|
|
for (unsigned int i = 0; i < piNode->mNumChildren;++i)
|
|
{
|
|
RenderNode(piNode->mChildren[i],aiMe,bAlpha );
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
this->m_iViewMode = VIEWMODE_FULL;
|
|
bChangedVM = true;
|
|
}
|
|
|
|
aiMatrix4x4 pcProj;
|
|
GetProjectionMatrix(pcProj);
|
|
|
|
aiMatrix4x4 pcCam;
|
|
aiVector3D vPos = GetCameraMatrix(pcCam);
|
|
pcProj = (aiMe * pcCam) * pcProj;
|
|
|
|
pcCam = aiMe;
|
|
pcCam.Inverse().Transpose();
|
|
|
|
// VERY UNOPTIMIZED, much stuff is redundant. Who cares?
|
|
if (!g_sOptions.bRenderMats && !bAlpha)
|
|
{
|
|
// this is very similar to the code in SetupMaterial()
|
|
ID3DXEffect* piEnd = g_piDefaultEffect;
|
|
|
|
// commit transformation matrices to the shader
|
|
piEnd->SetMatrix("WorldViewProjection",
|
|
(const D3DXMATRIX*)&pcProj);
|
|
|
|
piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
|
|
piEnd->SetMatrix("WorldInverseTranspose",
|
|
(const D3DXMATRIX*)&pcCam);
|
|
|
|
if ( CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
|
|
{
|
|
pcCam = pcCam * pcProj;
|
|
piEnd->SetMatrix("ViewProj",(const D3DXMATRIX*)&pcCam);
|
|
pcCam.Inverse();
|
|
piEnd->SetMatrix("InvViewProj",(const D3DXMATRIX*)&pcCam);
|
|
}
|
|
|
|
// commit light colors and direction to the shader
|
|
D3DXVECTOR4 apcVec[5];
|
|
apcVec[0].x = g_avLightDirs[0].x;
|
|
apcVec[0].y = g_avLightDirs[0].y;
|
|
apcVec[0].z = g_avLightDirs[0].z;
|
|
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;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
apcVec[0] *= g_fLightIntensity;
|
|
apcVec[1] *= g_fLightIntensity;
|
|
piEnd->SetVectorArray("afLightColor",apcVec,5);
|
|
|
|
apcVec[0].x = vPos.x;
|
|
apcVec[0].y = vPos.y;
|
|
apcVec[0].z = vPos.z;
|
|
piEnd->SetVector( "vCameraPos",&apcVec[0]);
|
|
|
|
// setup the best technique
|
|
if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
|
|
{
|
|
if (g_sOptions.b3Lights)
|
|
piEnd->SetTechnique("DefaultFXSpecular_PS20_D2");
|
|
else piEnd->SetTechnique("DefaultFXSpecular_PS20_D1");
|
|
}
|
|
else
|
|
{
|
|
if (g_sOptions.b3Lights)
|
|
piEnd->SetTechnique("DefaultFXSpecular_D2");
|
|
else piEnd->SetTechnique("DefaultFXSpecular_D1");
|
|
}
|
|
|
|
// setup the default material
|
|
UINT dwPasses = 0;
|
|
piEnd->Begin(&dwPasses,0);
|
|
piEnd->BeginPass(0);
|
|
}
|
|
D3DXVECTOR4 vVector = g_aclNormalColors[g_iCurrentColor];
|
|
if (++g_iCurrentColor == 14)
|
|
{
|
|
g_iCurrentColor = 0;
|
|
}
|
|
if (! (!g_sOptions.bRenderMats && bAlpha))
|
|
{
|
|
for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
|
|
{
|
|
// don't render the mesh if the render pass is incorrect
|
|
if (g_sOptions.bRenderMats && (
|
|
g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piOpacityTexture ||
|
|
g_pcAsset->apcMeshes[piNode->mMeshes[i]]->fOpacity != 1.0f))
|
|
{
|
|
if (!bAlpha)continue;
|
|
}
|
|
else if (bAlpha)continue;
|
|
|
|
// now setup the material
|
|
if (g_sOptions.bRenderMats)
|
|
{
|
|
CMaterialManager::Instance().SetupMaterial(
|
|
g_pcAsset->apcMeshes[piNode->mMeshes[i]],pcProj,aiMe,pcCam,vPos);
|
|
}
|
|
|
|
if (bAlpha)CMeshRenderer::Instance().DrawSorted(piNode->mMeshes[i],aiMe);
|
|
else CMeshRenderer::Instance().DrawUnsorted(piNode->mMeshes[i]);
|
|
|
|
// now end the material
|
|
if (g_sOptions.bRenderMats)
|
|
{
|
|
CMaterialManager::Instance().EndMaterial(
|
|
g_pcAsset->apcMeshes[piNode->mMeshes[i]]);
|
|
}
|
|
|
|
// render normal vectors?
|
|
if (g_sOptions.bRenderNormals && g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals)
|
|
{
|
|
// this is very similar to the code in SetupMaterial()
|
|
ID3DXEffect* piEnd = g_piNormalsEffect;
|
|
|
|
piEnd->SetVector("OUTPUT_COLOR",&vVector);
|
|
|
|
piEnd->SetMatrix("WorldViewProjection",
|
|
(const D3DXMATRIX*)&pcProj);
|
|
|
|
UINT dwPasses = 0;
|
|
piEnd->Begin(&dwPasses,0);
|
|
piEnd->BeginPass(0);
|
|
|
|
g_piDevice->SetStreamSource(0,
|
|
g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals,0,
|
|
sizeof(AssetHelper::LineVertex));
|
|
|
|
g_piDevice->DrawPrimitive(D3DPT_LINELIST,0,
|
|
g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices);
|
|
|
|
piEnd->EndPass();
|
|
piEnd->End();
|
|
}
|
|
}
|
|
// end the default material
|
|
if (!g_sOptions.bRenderMats)
|
|
{
|
|
g_piDefaultEffect->EndPass();
|
|
g_piDefaultEffect->End();
|
|
}
|
|
}
|
|
// render all child nodes
|
|
for (unsigned int i = 0; i < piNode->mNumChildren;++i)
|
|
{
|
|
RenderNode(piNode->mChildren[i],aiMe,bAlpha );
|
|
}
|
|
// need to reset the viewmode?
|
|
if (bChangedVM)
|
|
this->m_iViewMode = VIEWMODE_NODE;
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderPatternBG()
|
|
{
|
|
if (!g_piPatternEffect)
|
|
{
|
|
// the pattern effect won't work on ps_2_0 cards
|
|
if (g_sCaps.PixelShaderVersion >= D3DPS_VERSION(3,0))
|
|
{
|
|
// seems we have not yet compiled this shader.
|
|
// and NOW is the best time to do that ...
|
|
ID3DXBuffer* piBuffer = NULL;
|
|
if(FAILED( D3DXCreateEffect(g_piDevice,
|
|
g_szCheckerBackgroundShader.c_str(),
|
|
(UINT)g_szCheckerBackgroundShader.length(),
|
|
NULL,
|
|
NULL,
|
|
D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,
|
|
NULL,
|
|
&g_piPatternEffect,&piBuffer)))
|
|
{
|
|
if( piBuffer)
|
|
{
|
|
MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
|
|
piBuffer->Release();
|
|
}
|
|
return 0;
|
|
}
|
|
if( piBuffer)
|
|
{
|
|
piBuffer->Release();
|
|
piBuffer = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// clear the color buffer in magenta
|
|
// (hopefully this is ugly enough that every ps_2_0 cards owner
|
|
// runs to the next shop to buy himself a new card ...)
|
|
g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// clear the depth buffer only
|
|
g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,
|
|
D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
|
|
|
|
// setup the colors to be used ...
|
|
g_piPatternEffect->SetVector("COLOR_ONE",&this->m_avCheckerColors[0]);
|
|
g_piPatternEffect->SetVector("COLOR_TWO",&this->m_avCheckerColors[1]);
|
|
|
|
// setup the shader
|
|
UINT dw;
|
|
g_piPatternEffect->Begin(&dw,0);
|
|
g_piPatternEffect->BeginPass(0);
|
|
|
|
RECT sRect;
|
|
GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
|
|
sRect.right -= sRect.left;
|
|
sRect.bottom -= sRect.top;
|
|
|
|
struct SVertex
|
|
{
|
|
float x,y,z,w;
|
|
};
|
|
// build the screen-filling rectangle
|
|
SVertex as[4];
|
|
as[1].x = 0.0f;
|
|
as[1].y = 0.0f;
|
|
as[1].z = 0.2f;
|
|
as[3].x = (float)sRect.right;
|
|
as[3].y = 0.0f;
|
|
as[3].z = 0.2f;
|
|
as[0].x = 0.0f;
|
|
as[0].y = (float)sRect.bottom;
|
|
as[0].z = 0.2f;
|
|
as[2].x = (float)sRect.right;
|
|
as[2].y = (float)sRect.bottom;
|
|
as[2].z = 0.2f;
|
|
|
|
as[0].w = 1.0f;
|
|
as[1].w = 1.0f;
|
|
as[2].w = 1.0f;
|
|
as[3].w = 1.0f;
|
|
|
|
as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
|
|
as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
|
|
|
|
// draw the rectangle
|
|
DWORD dw2;g_piDevice->GetFVF(&dw2);
|
|
g_piDevice->SetFVF(D3DFVF_XYZRHW);
|
|
g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
|
|
&as,sizeof(SVertex));
|
|
g_piDevice->SetFVF(dw2);
|
|
|
|
// cleanup
|
|
g_piPatternEffect->EndPass();
|
|
g_piPatternEffect->End();
|
|
return 1;
|
|
}
|
|
//-------------------------------------------------------------------------------
|
|
int CDisplay::RenderTextureView()
|
|
{
|
|
if (!g_pcAsset || !g_pcAsset->pcScene)return 0;
|
|
|
|
// handle input
|
|
this->HandleInputTextureView();
|
|
|
|
// render the background
|
|
this->RenderPatternBG();
|
|
|
|
// it might be that there is no texture ...
|
|
if (!this->m_pcCurrentTexture->piTexture)
|
|
{
|
|
// FIX: no such log message. it would be repeated to often
|
|
//CLogDisplay::Instance().AddEntry("Unable to display texture. Image is unreachable.",
|
|
// D3DCOLOR_ARGB(0xFF,0xFF,0,0));
|
|
return 0;
|
|
}
|
|
|
|
|
|
RECT sRect;
|
|
GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
|
|
sRect.right -= sRect.left;
|
|
sRect.bottom -= sRect.top;
|
|
|
|
// commit the texture to the shader
|
|
g_piPassThroughEffect->SetTexture("TEXTURE_2D",*this->m_pcCurrentTexture->piTexture);
|
|
|
|
if (AI_TEXTYPE_OPACITY == this->m_pcCurrentTexture->iType)
|
|
{
|
|
g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR");
|
|
}
|
|
else if ((AI_TEXTYPE_OPACITY | 0x40000000) == this->m_pcCurrentTexture->iType)
|
|
{
|
|
g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA");
|
|
}
|
|
else g_piPassThroughEffect->SetTechnique("PassThrough");
|
|
|
|
UINT dw;
|
|
g_piPassThroughEffect->Begin(&dw,0);
|
|
g_piPassThroughEffect->BeginPass(0);
|
|
|
|
if (AI_TEXTYPE_HEIGHT == this->m_pcCurrentTexture->iType ||
|
|
AI_TEXTYPE_NORMALS == this->m_pcCurrentTexture->iType)
|
|
{
|
|
// manually disable alpha blending
|
|
g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
|
|
}
|
|
|
|
// build a rectangle which centers the texture
|
|
// scaling is OK, but no stretching
|
|
D3DSURFACE_DESC sDesc;
|
|
(*this->m_pcCurrentTexture->piTexture)->GetLevelDesc(0,&sDesc);
|
|
|
|
struct SVertex{float x,y,z,w,u,v;};
|
|
SVertex as[4];
|
|
|
|
const float nx = (float)sRect.right;
|
|
const float ny = (float)sRect.bottom;
|
|
const float x = (float)sDesc.Width;
|
|
const float y = (float)sDesc.Height;
|
|
float f = std::min((nx-30) / x,(ny-30) / y) * (this->m_fTextureZoom/1000.0f);
|
|
|
|
float fHalfX = (nx - (f * x)) / 2.0f;
|
|
float fHalfY = (ny - (f * y)) / 2.0f;
|
|
as[1].x = fHalfX + this->m_vTextureOffset.x;
|
|
as[1].y = fHalfY + this->m_vTextureOffset.y;
|
|
as[1].z = 0.2f;
|
|
as[1].w = 1.0f;
|
|
as[1].u = 0.0f;
|
|
as[1].v = 0.0f;
|
|
as[3].x = nx-fHalfX + this->m_vTextureOffset.x;
|
|
as[3].y = fHalfY + this->m_vTextureOffset.y;
|
|
as[3].z = 0.2f;
|
|
as[3].w = 1.0f;
|
|
as[3].u = 1.0f;
|
|
as[3].v = 0.0f;
|
|
as[0].x = fHalfX + this->m_vTextureOffset.x;
|
|
as[0].y = ny-fHalfY + this->m_vTextureOffset.y;
|
|
as[0].z = 0.2f;
|
|
as[0].w = 1.0f;
|
|
as[0].u = 0.0f;
|
|
as[0].v = 1.0f;
|
|
as[2].x = nx-fHalfX + this->m_vTextureOffset.x;
|
|
as[2].y = ny-fHalfY + this->m_vTextureOffset.y;
|
|
as[2].z = 0.2f;
|
|
as[2].w = 1.0f;
|
|
as[2].u = 1.0f;
|
|
as[2].v = 1.0f;
|
|
as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
|
|
as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
|
|
|
|
// draw the rectangle
|
|
DWORD dw2;g_piDevice->GetFVF(&dw2);
|
|
g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
|
g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
|
|
&as,sizeof(SVertex));
|
|
g_piDevice->SetFVF(dw2);
|
|
|
|
g_piPassThroughEffect->EndPass();
|
|
g_piPassThroughEffect->End();
|
|
|
|
// do we need to draw UV coordinates?
|
|
return 1;
|
|
}
|
|
};
|
|
|