|
@@ -1 +1,2086 @@
|
|
|
-#include "stdafx.h"
|
|
|
+/*
|
|
|
+---------------------------------------------------------------------------
|
|
|
+Free 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));
|
|
|
+ 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
|
|
|
+ this->m_pcCurrentTexture->piTexture = piTexture;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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[iIndex];
|
|
|
+ if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity)
|
|
|
+ {
|
|
|
+ // 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;
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+int CDisplay::FillDefaultStatistics(void)
|
|
|
+{
|
|
|
+ // 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);
|
|
|
+
|
|
|
+ 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();
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+int CDisplay::OnSetupNormalView()
|
|
|
+{
|
|
|
+ // 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;
|
|
|
+
|
|
|
+ UpdateWindow(g_hDlg);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+int CDisplay::OnSetupNodeView(NodeInfo* pcNew)
|
|
|
+{
|
|
|
+ ai_assert(NULL != pcNew);
|
|
|
+
|
|
|
+ if (this->m_pcCurrentNode == pcNew)return 2;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ this->m_pcCurrentMaterial = pcNew;
|
|
|
+ this->SetViewMode(VIEWMODE_MATERIAL);
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
|
|
|
+{
|
|
|
+ ai_assert(NULL != pcNew);
|
|
|
+
|
|
|
+ if (this->m_pcCurrentTexture == pcNew)return 2;
|
|
|
+ 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));
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
+ // convert 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+template <class type, class intype>
|
|
|
+type clamp(intype in)
|
|
|
+{
|
|
|
+ // for unsigned types only ...
|
|
|
+ intype mask = (0x1u << (sizeof(type)*8))-1;
|
|
|
+ return (type)std::max((intype)0,std::min(in,mask));
|
|
|
+}
|
|
|
+//-------------------------------------------------------------------------------
|
|
|
+int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
|
|
|
+{
|
|
|
+ // helper class
|
|
|
+ struct Info
|
|
|
+ {
|
|
|
+ Info( D3DXVECTOR4* p1,
|
|
|
+ AssetHelper::MeshHelper* p2,
|
|
|
+ const char* p3)
|
|
|
+ : pclrColor(p1),pMesh(p2),szShaderParam(p3) {}
|
|
|
+
|
|
|
+ D3DXVECTOR4* pclrColor;
|
|
|
+ AssetHelper::MeshHelper* pMesh;
|
|
|
+ const char* szShaderParam;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 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)
|
|
|
+ {
|
|
|
+ // 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // clear the color buffer in magenta
|
|
|
+ g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
|
|
|
+ D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
|
|
|
+
|
|
|
+ if (!g_piPatternEffect)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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;
|
|
|
+}
|
|
|
+};
|
|
|
+
|