2
0

Display.cpp 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2024, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. #include "assimp_view.h"
  35. #include "AnimEvaluator.h"
  36. #include "SceneAnimator.h"
  37. #include <assimp/StringUtils.h>
  38. #include <commdlg.h>
  39. namespace AssimpView {
  40. using namespace Assimp;
  41. extern std::string g_szCheckerBackgroundShader;
  42. struct SVertex
  43. {
  44. float x,y,z,w,u,v;
  45. };
  46. CDisplay CDisplay::s_cInstance;
  47. extern COLORREF g_aclCustomColors[16] /*= {0}*/;
  48. extern HKEY g_hRegistry;
  49. extern float g_fLoadTime;
  50. //-------------------------------------------------------------------------------
  51. // Table of colors used for normal vectors.
  52. //-------------------------------------------------------------------------------
  53. D3DXVECTOR4 g_aclNormalColors[14] =
  54. {
  55. D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0xFF / 255.0f, 1.0f), // white
  56. D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // red
  57. D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // green
  58. D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // blue
  59. D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // yellow
  60. D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // magenta
  61. D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0xFF / 255.0f,1.0f), // wtf
  62. D3DXVECTOR4(0xFF / 255.0f,0x60 / 255.0f,0x60 / 255.0f,1.0f), // light red
  63. D3DXVECTOR4(0x60 / 255.0f,0xFF / 255.0f,0x60 / 255.0f,1.0f), // light green
  64. D3DXVECTOR4(0x60 / 255.0f,0x60 / 255.0f,0xFF / 255.0f,1.0f), // light blue
  65. D3DXVECTOR4(0xA0 / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // dark red
  66. D3DXVECTOR4(0x00 / 255.0f,0xA0 / 255.0f,0x00 / 255.0f,1.0f), // dark green
  67. D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xA0 / 255.0f,1.0f), // dark blue
  68. D3DXVECTOR4(0x88 / 255.0f,0x88 / 255.0f,0x88 / 255.0f, 1.0f) // gray
  69. };
  70. //-------------------------------------------------------------------------------
  71. // Recursively count the number of nodes in an asset's node graph
  72. // Used by LoadAsset()
  73. //-------------------------------------------------------------------------------
  74. void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
  75. {
  76. *piCnt = *piCnt+1;
  77. for (unsigned int i = 0; i < pcNode->mNumChildren; ++i) {
  78. GetNodeCount(pcNode->mChildren[i], piCnt);
  79. }
  80. }
  81. //-------------------------------------------------------------------------------
  82. int CDisplay::EnableAnimTools(BOOL hm) {
  83. EnableWindow(GetDlgItem(g_hDlg,IDC_PLAY),hm);
  84. EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),hm);
  85. if (hm == FALSE) {
  86. g_dCurrent = 0.0;
  87. SendDlgItemMessage(g_hDlg, IDC_SLIDERANIM, TBM_SETPOS, TRUE, LPARAM(0));
  88. }
  89. return 1;
  90. }
  91. //-------------------------------------------------------------------------------
  92. // Fill animation combo box
  93. int CDisplay::FillAnimList(void) {
  94. if (0 != g_pcAsset->pcScene->mNumAnimations)
  95. {
  96. // now fill in all animation names
  97. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations; ++i)
  98. {
  99. std::string animationLabel(g_pcAsset->pcScene->mAnimations[i]->mName.data);
  100. if (animationLabel.empty())
  101. {
  102. animationLabel = std::string("Animation ") + std::to_string(i) + " (UNNAMED)";
  103. }
  104. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
  105. (LPARAM)animationLabel.c_str());
  106. }
  107. // also add a dummy - 'none'
  108. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,(LPARAM)"none");
  109. // select first
  110. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_SETCURSEL,0,0);
  111. EnableAnimTools(TRUE);
  112. }
  113. else // tools remain disabled
  114. EnableAnimTools(FALSE);
  115. return 1;
  116. }
  117. //-------------------------------------------------------------------------------
  118. // Clear the list of animations
  119. int CDisplay::ClearAnimList(void)
  120. {
  121. // clear the combo box
  122. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
  123. EnableAnimTools(FALSE);
  124. return 1;
  125. }
  126. //-------------------------------------------------------------------------------
  127. // Clear the tree view
  128. int CDisplay::ClearDisplayList(void)
  129. {
  130. // clear the combo box
  131. TreeView_DeleteAllItems(GetDlgItem(g_hDlg,IDC_TREE1));
  132. this->Reset();
  133. return 1;
  134. }
  135. //-------------------------------------------------------------------------------
  136. // Add a specific node to the display list
  137. int CDisplay::AddNodeToDisplayList(
  138. unsigned int iIndex,
  139. unsigned int iDepth,
  140. aiNode* pcNode,
  141. HTREEITEM hRoot)
  142. {
  143. ai_assert(nullptr != pcNode);
  144. ai_assert(nullptr != hRoot);
  145. char chTemp[MAXLEN];
  146. if(0 == pcNode->mName.length) {
  147. if (iIndex >= 100) {
  148. iIndex += iDepth * 1000;
  149. }
  150. else if (iIndex >= 10)
  151. {
  152. iIndex += iDepth * 100;
  153. }
  154. else
  155. iIndex += iDepth * 10;
  156. ai_snprintf(chTemp, MAXLEN,"Node %u",iIndex);
  157. }
  158. else {
  159. ai_snprintf(chTemp, MAXLEN,"%s",pcNode->mName.data);
  160. }
  161. ai_snprintf(chTemp+strlen(chTemp), MAXLEN- strlen(chTemp), iIndex ? " (%i)" : " (%i meshes)",pcNode->mNumMeshes);
  162. TVITEMEXW tvi;
  163. TVINSERTSTRUCTW sNew;
  164. wchar_t tmp[512];
  165. int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512);
  166. tvi.pszText = tmp;
  167. tvi.cchTextMax = (int)t;
  168. tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM;
  169. tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
  170. tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
  171. tvi.lParam = (LPARAM)5;
  172. sNew.itemex = tvi;
  173. sNew.hInsertAfter = TVI_LAST;
  174. sNew.hParent = hRoot;
  175. // add the item to the list
  176. HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
  177. TVM_INSERTITEMW,
  178. 0,
  179. (LPARAM)(LPTVINSERTSTRUCT)&sNew);
  180. // recursively add all child nodes
  181. ++iDepth;
  182. for (unsigned int i = 0; i< pcNode->mNumChildren;++i){
  183. AddNodeToDisplayList(i,iDepth,pcNode->mChildren[i],hTexture);
  184. }
  185. // add the node to the list
  186. NodeInfo info;
  187. info.hTreeItem = hTexture;
  188. info.psNode = pcNode;
  189. this->AddNode(info);
  190. return 1;
  191. }
  192. //-------------------------------------------------------------------------------
  193. int CDisplay::AddMeshToDisplayList(unsigned int iIndex, HTREEITEM hRoot)
  194. {
  195. aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex];
  196. char chTemp[MAXLEN];
  197. if(0 == pcMesh->mName.length) {
  198. ai_snprintf(chTemp,MAXLEN,"Mesh %u",iIndex);
  199. }
  200. else {
  201. ai_snprintf(chTemp,MAXLEN,"%s",pcMesh->mName.data);
  202. }
  203. ai_snprintf(chTemp+strlen(chTemp),MAXLEN-strlen(chTemp), iIndex ? " (%i)" : " (%i faces)",pcMesh->mNumFaces);
  204. TVITEMEXW tvi;
  205. TVINSERTSTRUCTW sNew;
  206. wchar_t tmp[512];
  207. int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512);
  208. tvi.pszText = tmp;
  209. tvi.cchTextMax = (int)t;
  210. tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM;
  211. tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
  212. tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_NODE];
  213. tvi.lParam = (LPARAM)5;
  214. sNew.itemex = tvi;
  215. sNew.hInsertAfter = TVI_LAST;
  216. sNew.hParent = hRoot;
  217. // add the item to the list
  218. HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
  219. TVM_INSERTITEMW,
  220. 0,
  221. (LPARAM)(LPTVINSERTSTRUCT)&sNew);
  222. // add the mesh to the list of all mesh entries in the scene browser
  223. MeshInfo info;
  224. info.hTreeItem = hTexture;
  225. info.psMesh = pcMesh;
  226. AddMesh(info);
  227. return 1;
  228. }
  229. //-------------------------------------------------------------------------------
  230. // Replace the currently selected texture by another one
  231. int CDisplay::ReplaceCurrentTexture(const char* szPath)
  232. {
  233. ai_assert(nullptr != szPath);
  234. // well ... try to load it
  235. IDirect3DTexture9* piTexture = nullptr;
  236. aiString szString;
  237. strcpy(szString.data,szPath);
  238. szString.length = static_cast<ai_uint32>(strlen(szPath));
  239. CMaterialManager::Instance().LoadTexture(&piTexture,&szString);
  240. if (!piTexture) {
  241. CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this texture",
  242. D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
  243. return 0;
  244. }
  245. // we must also change the icon of the corresponding tree
  246. // view item if the default texture was previously set
  247. TVITEMEX tvi;
  248. tvi.mask = TVIF_SELECTEDIMAGE | TVIF_IMAGE;
  249. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
  250. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
  251. TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1),
  252. m_pcCurrentTexture->hTreeItem);
  253. // update all meshes referencing this material
  254. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  255. {
  256. if (this->m_pcCurrentTexture->iMatIndex != g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  257. continue;
  258. AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i];
  259. IDirect3DTexture9** tex = nullptr;
  260. const char* tex_string = nullptr;
  261. switch (this->m_pcCurrentTexture->iType)
  262. {
  263. case aiTextureType_DIFFUSE:
  264. tex = &pcMesh->piDiffuseTexture;
  265. tex_string = "DIFFUSE_TEXTURE";
  266. break;
  267. case aiTextureType_AMBIENT:
  268. tex = &pcMesh->piAmbientTexture;
  269. tex_string = "AMBIENT_TEXTURE";
  270. break;
  271. case aiTextureType_SPECULAR:
  272. tex = &pcMesh->piSpecularTexture;
  273. tex_string = "SPECULAR_TEXTURE";
  274. break;
  275. case aiTextureType_EMISSIVE:
  276. tex = &pcMesh->piEmissiveTexture;
  277. tex_string = "EMISSIVE_TEXTURE";
  278. break;
  279. case aiTextureType_LIGHTMAP:
  280. tex = &pcMesh->piLightmapTexture;
  281. tex_string = "LIGHTMAP_TEXTURE";
  282. break;
  283. case aiTextureType_DISPLACEMENT:
  284. case aiTextureType_REFLECTION:
  285. case aiTextureType_UNKNOWN:
  286. break;
  287. case aiTextureType_SHININESS:
  288. tex = &pcMesh->piShininessTexture;
  289. tex_string = "SHININESS_TEXTURE";
  290. break;
  291. case aiTextureType_NORMALS:
  292. case aiTextureType_HEIGHT:
  293. // special handling here
  294. if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture) {
  295. piTexture->AddRef();
  296. pcMesh->piNormalTexture->Release();
  297. pcMesh->piNormalTexture = piTexture;
  298. CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,&pcMesh->piNormalTexture,true);
  299. m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture;
  300. if (!pcMesh->bSharedFX) {
  301. pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture);
  302. }
  303. }
  304. break;
  305. default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
  306. tex = &pcMesh->piOpacityTexture;
  307. tex_string = "OPACITY_TEXTURE";
  308. break;
  309. };
  310. if (tex && *tex && *tex != piTexture)
  311. {
  312. (**tex).Release();
  313. *tex = piTexture;
  314. m_pcCurrentTexture->piTexture = tex;
  315. pcMesh->piEffect->SetTexture(tex_string,piTexture);
  316. }
  317. }
  318. return 1;
  319. }
  320. //-------------------------------------------------------------------------------
  321. int CDisplay::AddTextureToDisplayList(unsigned int iType,
  322. unsigned int iIndex,
  323. const aiString* szPath,
  324. HTREEITEM hFX,
  325. unsigned int iUVIndex /*= 0*/,
  326. const float fBlendFactor /*= 0.0f*/,
  327. aiTextureOp eTextureOp /*= aiTextureOp_Multiply*/,
  328. unsigned int iMesh /*= 0*/)
  329. {
  330. ai_assert(nullptr != szPath);
  331. char chTemp[512];
  332. char chTempEmb[256];
  333. const char* sz = strrchr(szPath->data,'\\');
  334. if (!sz)sz = strrchr(szPath->data,'/');
  335. if (!sz)
  336. {
  337. if ('*' == *szPath->data)
  338. {
  339. int iIndex2 = atoi(szPath->data+1);
  340. ai_snprintf(chTempEmb,256,"Embedded #%i",iIndex2);
  341. sz = chTempEmb;
  342. }
  343. else
  344. {
  345. sz = szPath->data;
  346. }
  347. }
  348. bool bIsExtraOpacity = 0 != (iType & 0x40000000);
  349. const char* szType;
  350. IDirect3DTexture9** piTexture;
  351. switch (iType)
  352. {
  353. case aiTextureType_DIFFUSE:
  354. piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture;
  355. szType = "Diffuse";
  356. break;
  357. case aiTextureType_SPECULAR:
  358. piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture;
  359. szType = "Specular";
  360. break;
  361. case aiTextureType_AMBIENT:
  362. piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture;
  363. szType = "Ambient";
  364. break;
  365. case aiTextureType_EMISSIVE:
  366. piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture;
  367. szType = "Emissive";
  368. break;
  369. case aiTextureType_HEIGHT:
  370. piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
  371. szType = "Heightmap";
  372. break;
  373. case aiTextureType_NORMALS:
  374. piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture;
  375. szType = "Normalmap";
  376. break;
  377. case aiTextureType_SHININESS:
  378. piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture;
  379. szType = "Shininess";
  380. break;
  381. case aiTextureType_LIGHTMAP:
  382. piTexture = &g_pcAsset->apcMeshes[iMesh]->piLightmapTexture;
  383. szType = "Lightmap";
  384. break;
  385. case aiTextureType_DISPLACEMENT:
  386. piTexture = nullptr;
  387. szType = "Displacement";
  388. break;
  389. case aiTextureType_REFLECTION:
  390. piTexture = nullptr;
  391. szType = "Reflection";
  392. break;
  393. case aiTextureType_UNKNOWN:
  394. piTexture = nullptr;
  395. szType = "Unknown";
  396. break;
  397. default: // opacity + opacity | mask
  398. piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture;
  399. szType = "Opacity";
  400. break;
  401. };
  402. if (bIsExtraOpacity) {
  403. ai_snprintf(chTemp,512,"%s %i (<copy of diffuse #1>)",szType,iIndex+1);
  404. }
  405. else
  406. ai_snprintf(chTemp,512,"%s %i (%s)",szType,iIndex+1,sz);
  407. TVITEMEX tvi;
  408. TVINSERTSTRUCT sNew;
  409. tvi.pszText = chTemp;
  410. tvi.cchTextMax = (int)strlen(chTemp);
  411. tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE;
  412. tvi.lParam = (LPARAM)20;
  413. // find out whether this is the default texture or not
  414. if (piTexture && *piTexture) {
  415. // {9785DA94-1D96-426b-B3CB-BADC36347F5E}
  416. static const GUID guidPrivateData =
  417. { 0x9785da94, 0x1d96, 0x426b,
  418. { 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
  419. uint32_t iData = 0;
  420. DWORD dwSize = 4;
  421. (*piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize);
  422. if (0xFFFFFFFF == iData)
  423. {
  424. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
  425. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
  426. }
  427. else
  428. {
  429. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
  430. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE];
  431. }
  432. }
  433. else
  434. {
  435. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
  436. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID];
  437. }
  438. sNew.itemex = tvi;
  439. sNew.hInsertAfter = TVI_LAST;
  440. sNew.hParent = hFX;
  441. // add the item to the list
  442. HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
  443. TVM_INSERTITEM,
  444. 0,
  445. (LPARAM)(LPTVINSERTSTRUCT)&sNew);
  446. // add it to the list
  447. CDisplay::TextureInfo sInfo;
  448. sInfo.iUV = iUVIndex;
  449. sInfo.fBlend = fBlendFactor;
  450. sInfo.eOp = eTextureOp;
  451. sInfo.szPath = szPath->data;
  452. sInfo.hTreeItem = hTexture;
  453. sInfo.piTexture = piTexture;
  454. sInfo.iType = iType;
  455. sInfo.iMatIndex = g_pcAsset->pcScene->mMeshes[iMesh]->mMaterialIndex;
  456. AddTexture(sInfo);
  457. return 1;
  458. }
  459. //-------------------------------------------------------------------------------
  460. int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot, unsigned int iIndex) {
  461. ai_assert(nullptr != hRoot);
  462. aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[iIndex];
  463. if (g_pcAsset->pcScene->mNumMeshes == 0) {
  464. return -1;
  465. }
  466. // find the first mesh using this material index
  467. unsigned int iMesh = 0;
  468. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) {
  469. if (iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex) {
  470. iMesh = i;
  471. break;
  472. }
  473. }
  474. // use the name of the material, if possible
  475. char chTemp[512];
  476. aiString szOut;
  477. if (AI_SUCCESS != aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szOut)) {
  478. ai_snprintf(chTemp,512,"Material %i",iIndex+1);
  479. } else {
  480. ai_snprintf(chTemp,512,"%s (%i)",szOut.data,iIndex+1);
  481. }
  482. TVITEMEXW tvi;
  483. TVINSERTSTRUCTW sNew;
  484. wchar_t tmp[512];
  485. int t = MultiByteToWideChar(CP_UTF8,0,chTemp,-1,tmp,512);
  486. tvi.pszText = tmp;
  487. tvi.cchTextMax = (int)t;
  488. tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_PARAM ;
  489. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
  490. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
  491. tvi.lParam = (LPARAM)10;
  492. sNew.itemex = tvi;
  493. sNew.hInsertAfter = TVI_LAST;
  494. sNew.hParent = hRoot;
  495. // add the item to the list
  496. HTREEITEM hTexture = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
  497. TVM_INSERTITEMW,
  498. 0,
  499. (LPARAM)(LPTVINSERTSTRUCT)&sNew);
  500. // for each texture in the list ... add it
  501. unsigned int iUV;
  502. float fBlend;
  503. aiTextureOp eOp;
  504. aiString szPath;
  505. bool bNoOpacity = true;
  506. for (unsigned int i = 0; i <= AI_TEXTURE_TYPE_MAX;++i) {
  507. unsigned int iNum = 0;
  508. while (true) {
  509. if (AI_SUCCESS != aiGetMaterialTexture(pcMat,(aiTextureType)i,iNum, &szPath,nullptr, &iUV,&fBlend,&eOp)) {
  510. break;
  511. }
  512. if (aiTextureType_OPACITY == i) {
  513. bNoOpacity = false;
  514. }
  515. AddTextureToDisplayList(i,iNum,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
  516. ++iNum;
  517. }
  518. }
  519. AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iMesh];
  520. if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity) {
  521. // check whether the diffuse texture is not a default texture
  522. // {9785DA94-1D96-426b-B3CB-BADC36347F5E}
  523. static const GUID guidPrivateData =
  524. { 0x9785da94, 0x1d96, 0x426b,
  525. { 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
  526. uint32_t iData = 0;
  527. DWORD dwSize = 4;
  528. if(FAILED( pcMesh->piDiffuseTexture->GetPrivateData(guidPrivateData,&iData,&dwSize) || 0xffffffff == iData)) {
  529. // seems the diffuse texture contains alpha, therefore it has been
  530. // added to the opacity channel, too. Add a special value ...
  531. AddTextureToDisplayList(aiTextureType_OPACITY | 0x40000000,
  532. 0,&szPath,hTexture,iUV,fBlend,eOp,iMesh);
  533. }
  534. }
  535. // add the material to the list
  536. MaterialInfo info;
  537. info.hTreeItem = hTexture;
  538. info.psMaterial = pcMat;
  539. info.iIndex = iIndex;
  540. info.piEffect = g_pcAsset->apcMeshes[iMesh]->piEffect;
  541. this->AddMaterial(info);
  542. return 1;
  543. }
  544. //-------------------------------------------------------------------------------
  545. // Expand all elements in the tree-view
  546. int CDisplay::ExpandTree() {
  547. // expand all materials
  548. for (std::vector< MaterialInfo >::iterator i = m_asMaterials.begin(); i != m_asMaterials.end();++i) {
  549. TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
  550. }
  551. // expand all nodes
  552. for (std::vector< NodeInfo >::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i) {
  553. TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),(*i).hTreeItem,TVE_EXPAND);
  554. }
  555. TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),m_hRoot,TVE_EXPAND);
  556. return 1;
  557. }
  558. //-------------------------------------------------------------------------------
  559. // Get image list for tree view
  560. int CDisplay::LoadImageList() {
  561. if (!m_hImageList) {
  562. // First, create the image list we will need.
  563. // FIX: Need RGB888 color space to display all colors correctly
  564. HIMAGELIST hIml = ImageList_Create( 16,16,ILC_COLOR24, 5, 0 );
  565. // Load the bitmaps and add them to the image lists.
  566. HBITMAP hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BFX));
  567. m_aiImageList[AI_VIEW_IMGLIST_MATERIAL] = ImageList_Add(hIml, hBmp, nullptr);
  568. DeleteObject(hBmp);
  569. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BNODE));
  570. m_aiImageList[AI_VIEW_IMGLIST_NODE] = ImageList_Add(hIml, hBmp, nullptr);
  571. DeleteObject(hBmp);
  572. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTX));
  573. m_aiImageList[AI_VIEW_IMGLIST_TEXTURE] = ImageList_Add(hIml, hBmp, nullptr);
  574. DeleteObject(hBmp);
  575. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BTXI));
  576. m_aiImageList[AI_VIEW_IMGLIST_TEXTURE_INVALID] = ImageList_Add(hIml, hBmp, nullptr);
  577. DeleteObject(hBmp);
  578. hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BROOT));
  579. m_aiImageList[AI_VIEW_IMGLIST_MODEL] = ImageList_Add(hIml, hBmp, nullptr);
  580. DeleteObject(hBmp);
  581. // Associate the image list with the tree.
  582. TreeView_SetImageList(GetDlgItem(g_hDlg,IDC_TREE1), hIml, TVSIL_NORMAL);
  583. m_hImageList = hIml;
  584. }
  585. return 1;
  586. }
  587. //-------------------------------------------------------------------------------
  588. // Fill tree view
  589. int CDisplay::FillDisplayList(void) {
  590. LoadImageList();
  591. // Initialize the tree view window.
  592. // fill in the first entry
  593. TVITEMEX tvi;
  594. TVINSERTSTRUCT sNew;
  595. tvi.pszText = (char*) "Model";
  596. tvi.cchTextMax = (int)strlen(tvi.pszText);
  597. tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE | TVIF_HANDLE | TVIF_STATE;
  598. tvi.state = TVIS_EXPANDED;
  599. tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MODEL];
  600. tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MODEL];
  601. tvi.lParam = (LPARAM)0;
  602. sNew.itemex = tvi;
  603. sNew.hInsertAfter = TVI_ROOT;
  604. sNew.hParent = 0;
  605. // add the root item to the tree
  606. m_hRoot = (HTREEITEM)SendMessage(GetDlgItem(g_hDlg,IDC_TREE1),
  607. TVM_INSERTITEM,
  608. 0,
  609. (LPARAM)(LPTVINSERTSTRUCT)&sNew);
  610. // add each loaded material to the tree
  611. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMaterials; ++i)
  612. AddMaterialToDisplayList(m_hRoot,i);
  613. // add each mesh to the tree
  614. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes; ++i)
  615. AddMeshToDisplayList(i,m_hRoot);
  616. // now add all loaded nodes recursively
  617. AddNodeToDisplayList(0,0,g_pcAsset->pcScene->mRootNode,m_hRoot);
  618. // now expand all parent nodes in the tree
  619. ExpandTree();
  620. // everything reacts a little bit slowly if D3D is rendering,
  621. // so give GDI a small hint to leave the couch and work ;-)
  622. UpdateWindow(g_hDlg);
  623. return 1;
  624. }
  625. //-------------------------------------------------------------------------------
  626. // Main render loop
  627. int CDisplay::OnRender()
  628. {
  629. // update possible animation
  630. if( g_pcAsset)
  631. {
  632. static double lastRenderTime = 0.;
  633. ai_assert( g_pcAsset->mAnimator);
  634. double currentTime = clock() / double(CLOCKS_PER_SEC);
  635. if (g_bPlay) {
  636. g_dCurrent += currentTime - lastRenderTime;
  637. double time = g_dCurrent;
  638. aiAnimation* mAnim = g_pcAsset->mAnimator->CurrentAnim();
  639. if (mAnim && mAnim->mDuration > 0.0) {
  640. double tps = mAnim->mTicksPerSecond ? mAnim->mTicksPerSecond : ANIM_DEFAULT_TICKS_PER_SECOND;
  641. time = fmod(time, mAnim->mDuration/tps);
  642. SendDlgItemMessage(g_hDlg, IDC_SLIDERANIM, TBM_SETPOS, TRUE, LPARAM(ANIM_SLIDER_MAX * (time / (mAnim->mDuration / tps))));
  643. }
  644. g_pcAsset->mAnimator->Calculate( time );
  645. }
  646. lastRenderTime = currentTime;
  647. }
  648. // begin the frame
  649. g_piDevice->BeginScene();
  650. switch (m_iViewMode)
  651. {
  652. case VIEWMODE_FULL:
  653. case VIEWMODE_NODE:
  654. RenderFullScene();
  655. break;
  656. case VIEWMODE_MATERIAL:
  657. RenderMaterialView();
  658. break;
  659. case VIEWMODE_TEXTURE:
  660. RenderTextureView();
  661. break;
  662. };
  663. // Now render the log display in the upper right corner of the window
  664. CLogDisplay::Instance().OnRender();
  665. // present the back-buffer
  666. g_piDevice->EndScene();
  667. g_piDevice->Present(nullptr,nullptr,nullptr,nullptr);
  668. // don't remove this, problems on some older machines (AMD timing bug)
  669. Sleep(10);
  670. return 1;
  671. }
  672. //-------------------------------------------------------------------------------
  673. // Update UI
  674. void UpdateColorFieldsInUI()
  675. {
  676. InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),nullptr,TRUE);
  677. InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),nullptr,TRUE);
  678. InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),nullptr,TRUE);
  679. UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1));
  680. UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2));
  681. UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3));
  682. }
  683. //-------------------------------------------------------------------------------
  684. // FIll statistics UI
  685. int CDisplay::FillDefaultStatistics(void)
  686. {
  687. if (!g_pcAsset)
  688. {
  689. // clear all stats edit controls
  690. SetDlgItemText(g_hDlg,IDC_EVERT,"0");
  691. SetDlgItemText(g_hDlg,IDC_EFACE,"0");
  692. SetDlgItemText(g_hDlg,IDC_EMAT,"0");
  693. SetDlgItemText(g_hDlg,IDC_EMESH,"0");
  694. SetDlgItemText(g_hDlg,IDC_ENODEWND,"0");
  695. SetDlgItemText(g_hDlg,IDC_ESHADER,"0");
  696. SetDlgItemText(g_hDlg,IDC_ELOAD,"");
  697. SetDlgItemText(g_hDlg,IDC_ETEX,"0");
  698. return 1;
  699. }
  700. // get the number of vertices/faces in the model
  701. unsigned int iNumVert = 0;
  702. unsigned int iNumFaces = 0;
  703. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  704. {
  705. iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices;
  706. iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces;
  707. }
  708. // and fill the statistic edit controls
  709. char szOut[1024];
  710. ai_snprintf(szOut,1024,"%i",(int)iNumVert);
  711. SetDlgItemText(g_hDlg,IDC_EVERT,szOut);
  712. ai_snprintf(szOut, 1024,"%i",(int)iNumFaces);
  713. SetDlgItemText(g_hDlg,IDC_EFACE,szOut);
  714. ai_snprintf(szOut, 1024,"%i",(int)g_pcAsset->pcScene->mNumMaterials);
  715. SetDlgItemText(g_hDlg,IDC_EMAT,szOut);
  716. ai_snprintf(szOut, 1024,"%i",(int)g_pcAsset->pcScene->mNumMeshes);
  717. SetDlgItemText(g_hDlg,IDC_EMESH,szOut);
  718. // need to get the number of nodes
  719. iNumVert = 0;
  720. GetNodeCount(g_pcAsset->pcScene->mRootNode,&iNumVert);
  721. ai_snprintf(szOut, 1024,"%i",(int)iNumVert);
  722. SetDlgItemText(g_hDlg,IDC_ENODEWND,szOut);
  723. // now get the number of unique shaders generated for the asset
  724. // (even if the environment changes this number won't change)
  725. ai_snprintf(szOut, 1024,"%i", CMaterialManager::Instance().GetShaderCount());
  726. SetDlgItemText(g_hDlg,IDC_ESHADER,szOut);
  727. sprintf(szOut,"%.5f",(float)g_fLoadTime);
  728. SetDlgItemText(g_hDlg,IDC_ELOAD,szOut);
  729. UpdateColorFieldsInUI();
  730. UpdateWindow(g_hDlg);
  731. return 1;
  732. }
  733. //-------------------------------------------------------------------------------
  734. // Reset UI
  735. int CDisplay::Reset(void)
  736. {
  737. // clear all lists
  738. m_asMaterials.clear();
  739. m_asTextures.clear();
  740. m_asNodes.clear();
  741. m_asMeshes.clear();
  742. m_hRoot = nullptr;
  743. return OnSetupNormalView();
  744. }
  745. //-------------------------------------------------------------------------------
  746. // reset to standard statistics view
  747. void ShowNormalUIComponents()
  748. {
  749. ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW);
  750. ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_SHOW);
  751. ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_SHOW);
  752. ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_SHOW);
  753. ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_SHOW);
  754. ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_SHOW);
  755. ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_HIDE);
  756. }
  757. //-------------------------------------------------------------------------------
  758. int CDisplay::OnSetupNormalView()
  759. {
  760. if (VIEWMODE_NODE == m_iViewMode)
  761. {
  762. ShowNormalUIComponents();
  763. }
  764. // now ... change the meaning of the statistics fields back
  765. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:");
  766. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Nodes:");
  767. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
  768. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"Shaders:");
  769. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:");
  770. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:");
  771. SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Loading Time:");
  772. FillDefaultStatistics();
  773. SetViewMode(VIEWMODE_FULL);
  774. // for debugging
  775. m_pcCurrentMaterial = nullptr;
  776. m_pcCurrentTexture = nullptr;
  777. m_pcCurrentNode = nullptr;
  778. // redraw the color fields in the UI --- their purpose has possibly changed
  779. UpdateColorFieldsInUI();
  780. UpdateWindow(g_hDlg);
  781. return 1;
  782. }
  783. //-------------------------------------------------------------------------------
  784. int CDisplay::OnSetupNodeView(NodeInfo* pcNew)
  785. {
  786. ai_assert(nullptr != pcNew);
  787. if (m_pcCurrentNode == pcNew)return 2;
  788. // now ... change the meaning of the statistics fields back
  789. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Vertices:");
  790. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Faces:");
  791. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"Materials:");
  792. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Meshes:");
  793. ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_HIDE);
  794. ShowWindow(GetDlgItem(g_hDlg,IDC_ENODEWND),SW_HIDE);
  795. ShowWindow(GetDlgItem(g_hDlg,IDC_NUMSHADERS),SW_HIDE);
  796. ShowWindow(GetDlgItem(g_hDlg,IDC_LOADTIME),SW_HIDE);
  797. ShowWindow(GetDlgItem(g_hDlg,IDC_ESHADER),SW_HIDE);
  798. ShowWindow(GetDlgItem(g_hDlg,IDC_ELOAD),SW_HIDE);
  799. ShowWindow(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),SW_SHOW);
  800. char szTemp[1024];
  801. sprintf(szTemp,
  802. "%.2f %.2f %.2f\r\n"
  803. "%.2f %.2f %.2f\r\n"
  804. "%.2f %.2f %.2f\r\n"
  805. "%.2f %.2f %.2f\r\n",
  806. pcNew->psNode->mTransformation.a1,
  807. pcNew->psNode->mTransformation.b1,
  808. pcNew->psNode->mTransformation.c1,
  809. pcNew->psNode->mTransformation.a2,
  810. pcNew->psNode->mTransformation.b2,
  811. pcNew->psNode->mTransformation.c2,
  812. pcNew->psNode->mTransformation.a3,
  813. pcNew->psNode->mTransformation.b3,
  814. pcNew->psNode->mTransformation.c3,
  815. pcNew->psNode->mTransformation.a4,
  816. pcNew->psNode->mTransformation.b4,
  817. pcNew->psNode->mTransformation.c4);
  818. SetWindowText(GetDlgItem(g_hDlg,IDC_VIEWMATRIX),szTemp);
  819. m_pcCurrentNode = pcNew;
  820. SetViewMode(VIEWMODE_NODE);
  821. return 1;
  822. }
  823. //-------------------------------------------------------------------------------
  824. int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew)
  825. {
  826. ai_assert(nullptr != pcNew);
  827. if (m_pcCurrentMaterial == pcNew)return 2;
  828. if (VIEWMODE_NODE == m_iViewMode)
  829. ShowNormalUIComponents();
  830. m_pcCurrentMaterial = pcNew;
  831. SetViewMode(VIEWMODE_MATERIAL);
  832. // redraw the color fields in the UI --- their purpose has possibly changed
  833. UpdateColorFieldsInUI();
  834. UpdateWindow(g_hDlg);
  835. return 1;
  836. }
  837. //-------------------------------------------------------------------------------
  838. int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
  839. {
  840. ai_assert(nullptr != pcNew);
  841. if (this->m_pcCurrentTexture == pcNew)return 2;
  842. if (VIEWMODE_NODE == this->m_iViewMode)
  843. {
  844. ShowNormalUIComponents();
  845. }
  846. if ((aiTextureType_OPACITY | 0x40000000) == pcNew->iType)
  847. {
  848. // for opacity textures display a warn message
  849. CLogDisplay::Instance().AddEntry("[INFO] This texture is not existing in the "
  850. "original mesh",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
  851. CLogDisplay::Instance().AddEntry("It is a copy of the alpha channel of the first "
  852. "diffuse texture",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
  853. }
  854. // check whether the pattern background effect is supported
  855. if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0))
  856. {
  857. CLogDisplay::Instance().AddEntry("[WARN] The background shader won't work "
  858. "on your system, it required PS 3.0 hardware. A default color is used ...",
  859. D3DCOLOR_ARGB(0xFF,0xFF,0x00,0));
  860. }
  861. this->m_fTextureZoom = 1000.0f;
  862. this->m_vTextureOffset.x = this->m_vTextureOffset.y = 0.0f;
  863. this->m_pcCurrentTexture = pcNew;
  864. this->SetViewMode(VIEWMODE_TEXTURE);
  865. // now ... change the meaning of the statistics fields
  866. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMVERTS),"Width:");
  867. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMNODES),"Height:");
  868. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMFACES),"Format:");
  869. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMSHADERS),"MIPs:");
  870. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMATS),"UV:");
  871. SetWindowText(GetDlgItem(g_hDlg,IDC_NUMMESHES),"Blend:");
  872. SetWindowText(GetDlgItem(g_hDlg,IDC_LOADTIME),"Op:");
  873. // and fill them with data
  874. D3DSURFACE_DESC sDesc;
  875. if (pcNew->piTexture && *pcNew->piTexture) {
  876. (*pcNew->piTexture)->GetLevelDesc(0,&sDesc);
  877. char szTemp[128];
  878. sprintf(szTemp,"%i",sDesc.Width);
  879. SetWindowText(GetDlgItem(g_hDlg,IDC_EVERT),szTemp);
  880. sprintf(szTemp,"%i",sDesc.Height);
  881. SetWindowText(GetDlgItem(g_hDlg,IDC_ENODEWND),szTemp);
  882. sprintf(szTemp,"%i",(*pcNew->piTexture)->GetLevelCount());
  883. SetWindowText(GetDlgItem(g_hDlg,IDC_ESHADER),szTemp);
  884. sprintf(szTemp,"%u",pcNew->iUV);
  885. SetWindowText(GetDlgItem(g_hDlg,IDC_EMAT),szTemp);
  886. sprintf(szTemp,"%f",pcNew->fBlend);
  887. SetWindowText(GetDlgItem(g_hDlg,IDC_EMESH),szTemp);
  888. const char* szOp;
  889. switch (pcNew->eOp)
  890. {
  891. case aiTextureOp_Add:
  892. szOp = "add";
  893. break;
  894. case aiTextureOp_Subtract:
  895. szOp = "sub";
  896. break;
  897. case aiTextureOp_Divide:
  898. szOp = "div";
  899. break;
  900. case aiTextureOp_SignedAdd:
  901. szOp = "addsign";
  902. break;
  903. case aiTextureOp_SmoothAdd:
  904. szOp = "addsmooth";
  905. break;
  906. default:
  907. szOp = "mul";
  908. break;
  909. };
  910. SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp);
  911. // NOTE: Format is always ARGB8888 since other formats are
  912. // converted to this format ...
  913. SetWindowText(GetDlgItem(g_hDlg,IDC_EFACE),"ARGB8");
  914. // check whether this is the default texture
  915. if (pcNew->piTexture)
  916. {
  917. // {9785DA94-1D96-426b-B3CB-BADC36347F5E}
  918. static const GUID guidPrivateData =
  919. { 0x9785da94, 0x1d96, 0x426b,
  920. { 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } };
  921. uint32_t iData = 0;
  922. DWORD dwSize = 4;
  923. (*pcNew->piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize);
  924. if (0xFFFFFFFF == iData)
  925. {
  926. CLogDisplay::Instance().AddEntry("[ERROR] Texture could not be loaded. "
  927. "The displayed texture is a default texture",
  928. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  929. return 0;
  930. }
  931. }
  932. }
  933. // redraw the color fields in the UI --- their purpose has possibly changed
  934. UpdateColorFieldsInUI();
  935. UpdateWindow(g_hDlg);
  936. return 1;
  937. }
  938. //-------------------------------------------------------------------------------
  939. int CDisplay::OnSetup(HTREEITEM p_hTreeItem)
  940. {
  941. // search in our list for the item
  942. union {
  943. TextureInfo* pcNew;
  944. NodeInfo* pcNew2;
  945. MaterialInfo* pcNew3;
  946. };
  947. pcNew = nullptr;
  948. for (std::vector<TextureInfo>::iterator i = m_asTextures.begin();i != m_asTextures.end();++i){
  949. if (p_hTreeItem == (*i).hTreeItem) {
  950. pcNew = &(*i);
  951. break;
  952. }
  953. }
  954. if (pcNew) {
  955. return OnSetupTextureView(pcNew);
  956. }
  957. // search the node list
  958. for (std::vector<NodeInfo>::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i){
  959. if (p_hTreeItem == (*i).hTreeItem) {
  960. pcNew2 = &(*i);
  961. break;
  962. }
  963. }
  964. if (pcNew2) {
  965. return OnSetupNodeView(pcNew2);
  966. }
  967. // search the material list
  968. for (std::vector<MaterialInfo>::iterator i = m_asMaterials.begin();i != m_asMaterials.end();++i){
  969. if (p_hTreeItem == (*i).hTreeItem){
  970. pcNew3 = &(*i);
  971. break;
  972. }
  973. }
  974. if (pcNew3) {
  975. return OnSetupMaterialView(pcNew3);
  976. }
  977. return OnSetupNormalView();
  978. }
  979. //-------------------------------------------------------------------------------
  980. int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem)
  981. {
  982. ai_assert(nullptr != hItem);
  983. HMENU hDisplay = nullptr;
  984. // search in our list for the item
  985. TextureInfo* pcNew = nullptr;
  986. for (std::vector<TextureInfo>::iterator
  987. i = m_asTextures.begin();
  988. i != m_asTextures.end();++i)
  989. {
  990. if (hItem == (*i).hTreeItem) {
  991. pcNew = &(*i);
  992. break;
  993. }
  994. }
  995. if (pcNew)
  996. {
  997. HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_TXPOPUP));
  998. hDisplay = GetSubMenu(hMenu,0);
  999. }
  1000. // search in the material list for the item
  1001. MaterialInfo* pcNew2 = nullptr;
  1002. for (std::vector<MaterialInfo>::iterator
  1003. i = m_asMaterials.begin();
  1004. i != m_asMaterials.end();++i)
  1005. {
  1006. if (hItem == (*i).hTreeItem) {
  1007. pcNew2 = &(*i);
  1008. break;
  1009. }
  1010. }
  1011. if (pcNew2)
  1012. {
  1013. HMENU hMenu = LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MATPOPUP));
  1014. hDisplay = GetSubMenu(hMenu,0);
  1015. }
  1016. if (nullptr != hDisplay)
  1017. {
  1018. // select this entry (this should all OnSetup())
  1019. TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),hItem,TVGN_CARET);
  1020. // FIX: Render the scene once that the correct texture/material
  1021. // is displayed while the context menu is active
  1022. OnRender();
  1023. POINT sPoint;
  1024. GetCursorPos(&sPoint);
  1025. TrackPopupMenu(hDisplay, TPM_LEFTALIGN, sPoint.x, sPoint.y, 0,
  1026. g_hDlg,nullptr);
  1027. }
  1028. return 1;
  1029. }
  1030. //-------------------------------------------------------------------------------
  1031. int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam)
  1032. {
  1033. // get the current selected material
  1034. std::vector<Info> apclrOut;
  1035. const char* szMatKey = "";
  1036. switch (LOWORD(wParam))
  1037. {
  1038. case ID_SOLONG_CLEARDIFFUSECOLOR:
  1039. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  1040. {
  1041. if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  1042. {
  1043. apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vDiffuseColor,
  1044. g_pcAsset->apcMeshes[i],"DIFFUSE_COLOR"));
  1045. }
  1046. }
  1047. szMatKey = "$clr.diffuse";
  1048. break;
  1049. case ID_SOLONG_CLEARSPECULARCOLOR:
  1050. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  1051. {
  1052. if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  1053. {
  1054. apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vSpecularColor,
  1055. g_pcAsset->apcMeshes[i],"SPECULAR_COLOR"));
  1056. }
  1057. }
  1058. szMatKey = "$clr.specular";
  1059. break;
  1060. case ID_SOLONG_CLEARAMBIENTCOLOR:
  1061. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  1062. {
  1063. if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  1064. {
  1065. apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vAmbientColor,
  1066. g_pcAsset->apcMeshes[i],"AMBIENT_COLOR"));
  1067. }
  1068. }
  1069. szMatKey = "$clr.ambient";
  1070. break;
  1071. case ID_SOLONG_CLEAREMISSIVECOLOR:
  1072. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  1073. {
  1074. if (this->m_pcCurrentMaterial->iIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  1075. {
  1076. apclrOut.push_back( Info( &g_pcAsset->apcMeshes[i]->vEmissiveColor,
  1077. g_pcAsset->apcMeshes[i],"EMISSIVE_COLOR"));
  1078. }
  1079. }
  1080. szMatKey = "$clr.emissive";
  1081. break;
  1082. default:
  1083. // let the next function do this ... no spaghetti code ;-)
  1084. HandleTreeViewPopup2(wParam,lParam);
  1085. };
  1086. if (!apclrOut.empty())
  1087. {
  1088. aiColor4D clrOld = *((aiColor4D*)(apclrOut.front().pclrColor));
  1089. CHOOSECOLOR clr;
  1090. clr.lStructSize = sizeof(CHOOSECOLOR);
  1091. clr.hwndOwner = g_hDlg;
  1092. clr.Flags = CC_RGBINIT | CC_FULLOPEN;
  1093. clr.rgbResult = RGB(
  1094. clamp<unsigned char>(clrOld.r * 255.0f),
  1095. clamp<unsigned char>(clrOld.g * 255.0f),
  1096. clamp<unsigned char>(clrOld.b * 255.0f));
  1097. clr.lpCustColors = g_aclCustomColors;
  1098. clr.lpfnHook = nullptr;
  1099. clr.lpTemplateName = nullptr;
  1100. clr.lCustData = 0;
  1101. ChooseColor(&clr);
  1102. clrOld.r = (float)(((unsigned int)clr.rgbResult) & 0xFF) / 255.0f;
  1103. clrOld.g = (float)(((unsigned int)clr.rgbResult >> 8) & 0xFF) / 255.0f;
  1104. clrOld.b = (float)(((unsigned int)clr.rgbResult >> 16) & 0xFF) / 255.0f;
  1105. // update the color values in the mesh instances and
  1106. // update all shaders ...
  1107. for (std::vector<Info>::iterator
  1108. i = apclrOut.begin();
  1109. i != apclrOut.end();++i)
  1110. {
  1111. *((*i).pclrColor) = *((D3DXVECTOR4*)&clrOld);
  1112. if (!(*i).pMesh->bSharedFX)
  1113. {
  1114. (*i).pMesh->piEffect->SetVector((*i).szShaderParam,(*i).pclrColor);
  1115. }
  1116. }
  1117. // change the material key ...
  1118. aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[
  1119. this->m_pcCurrentMaterial->iIndex];
  1120. pcMat->AddProperty<aiColor4D>(&clrOld,1,szMatKey,0,0);
  1121. if (ID_SOLONG_CLEARSPECULARCOLOR == LOWORD(wParam) &&
  1122. aiShadingMode_Gouraud == apclrOut.front().pMesh->eShadingMode)
  1123. {
  1124. CLogDisplay::Instance().AddEntry("[INFO] You have just changed the specular "
  1125. "material color",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
  1126. CLogDisplay::Instance().AddEntry(
  1127. "This is great, especially since there is currently no specular shading",
  1128. D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
  1129. }
  1130. }
  1131. return 1;
  1132. }
  1133. //-------------------------------------------------------------------------------
  1134. int CALLBACK TreeViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  1135. {
  1136. if (lParamSort == lParam1)return -1;
  1137. if (lParamSort == lParam2)return 1;
  1138. return 0;
  1139. }
  1140. //-------------------------------------------------------------------------------
  1141. int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM /*lParam*/)
  1142. {
  1143. char szFileName[MAX_PATH];
  1144. DWORD dwTemp = MAX_PATH;
  1145. switch (LOWORD(wParam))
  1146. {
  1147. case ID_HEY_REPLACE:
  1148. {
  1149. // get a path to a new texture
  1150. if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ReplaceTextureSrc",nullptr,nullptr,
  1151. (BYTE*)szFileName,&dwTemp))
  1152. {
  1153. // Key was not found. Use C:
  1154. strcpy(szFileName,"");
  1155. }
  1156. else
  1157. {
  1158. // need to remove the file name
  1159. char* sz = strrchr(szFileName,'\\');
  1160. if (!sz)
  1161. sz = strrchr(szFileName,'/');
  1162. if (sz)
  1163. *sz = 0;
  1164. }
  1165. OPENFILENAME sFilename1 = {
  1166. sizeof(OPENFILENAME),
  1167. g_hDlg,GetModuleHandle(nullptr),
  1168. "Textures\0*.png;*.dds;*.tga;*.bmp;*.tif;*.ppm;*.ppx;*.jpg;*.jpeg;*.exr\0*.*\0",
  1169. nullptr, 0, 1,
  1170. szFileName, MAX_PATH, nullptr, 0, nullptr,
  1171. "Replace this texture",
  1172. OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR,
  1173. 0, 1, ".jpg", 0, nullptr, nullptr
  1174. };
  1175. if(GetOpenFileName(&sFilename1) == 0) return 0;
  1176. // Now store the file in the registry
  1177. RegSetValueExA(g_hRegistry,"ReplaceTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
  1178. this->ReplaceCurrentTexture(szFileName);
  1179. }
  1180. return 1;
  1181. case ID_HEY_EXPORT:
  1182. {
  1183. if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureExportDest",nullptr,nullptr,
  1184. (BYTE*)szFileName,&dwTemp))
  1185. {
  1186. // Key was not found. Use C:
  1187. strcpy(szFileName,"");
  1188. }
  1189. else
  1190. {
  1191. // need to remove the file name
  1192. char* sz = strrchr(szFileName,'\\');
  1193. if (!sz)
  1194. sz = strrchr(szFileName,'/');
  1195. if (sz)
  1196. *sz = 0;
  1197. }
  1198. OPENFILENAME sFilename1 = {
  1199. sizeof(OPENFILENAME),
  1200. g_hDlg,GetModuleHandle(nullptr),
  1201. "Textures\0*.png;*.dds;*.bmp;*.tif;*.pfm;*.jpg;*.jpeg;*.hdr\0*.*\0", nullptr, 0, 1,
  1202. szFileName, MAX_PATH, nullptr, 0, nullptr,
  1203. "Export texture to file",
  1204. OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR,
  1205. 0, 1, ".png", 0, nullptr, nullptr
  1206. };
  1207. if(GetSaveFileName(&sFilename1) == 0) return 0;
  1208. // Now store the file in the registry
  1209. RegSetValueExA(g_hRegistry,"TextureExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH);
  1210. // determine the file format ...
  1211. D3DXIMAGE_FILEFORMAT eFormat = D3DXIFF_PNG;
  1212. const char* sz = strrchr(szFileName,'.');
  1213. if (sz)
  1214. {
  1215. ++sz;
  1216. if (0 == Assimp::ASSIMP_stricmp(sz,"pfm"))eFormat = D3DXIFF_PFM;
  1217. else if (0 == Assimp::ASSIMP_stricmp(sz,"dds"))eFormat = D3DXIFF_DDS;
  1218. else if (0 == Assimp::ASSIMP_stricmp(sz,"jpg"))eFormat = D3DXIFF_JPG;
  1219. else if (0 == Assimp::ASSIMP_stricmp(sz,"jpeg"))eFormat = D3DXIFF_JPG;
  1220. else if (0 == Assimp::ASSIMP_stricmp(sz,"hdr"))eFormat = D3DXIFF_HDR;
  1221. else if (0 == Assimp::ASSIMP_stricmp(sz,"bmp"))eFormat = D3DXIFF_BMP;
  1222. }
  1223. // get a pointer to the first surface of the current texture
  1224. IDirect3DSurface9* pi = nullptr;
  1225. (*this->m_pcCurrentTexture->piTexture)->GetSurfaceLevel(0,&pi);
  1226. if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,eFormat,pi,nullptr,nullptr)))
  1227. {
  1228. CLogDisplay::Instance().AddEntry("[ERROR] Unable to export texture",
  1229. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  1230. }
  1231. else
  1232. {
  1233. CLogDisplay::Instance().AddEntry("[INFO] The texture has been exported",
  1234. D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0));
  1235. }
  1236. if(pi)pi->Release();
  1237. }
  1238. return 1;
  1239. case ID_HEY_REMOVE:
  1240. {
  1241. if(IDYES != MessageBox(g_hDlg,"To recover the texture you need to reload the model. Do you wish to continue?",
  1242. "Remove texture",MB_YESNO)) {
  1243. return 1;
  1244. }
  1245. aiMaterial* pcMat = (aiMaterial*)g_pcAsset->pcScene->mMaterials[
  1246. m_pcCurrentTexture->iMatIndex];
  1247. unsigned int s;
  1248. if (m_pcCurrentTexture->iType == (aiTextureType_OPACITY | 0x40000000))
  1249. {
  1250. // set a special property to indicate that no alpha channel is required
  1251. int iVal = 1;
  1252. pcMat->AddProperty<int>(&iVal,1,"no_a_from_d",0,0);
  1253. s = aiTextureType_OPACITY;
  1254. }
  1255. else s = m_pcCurrentTexture->iType;
  1256. pcMat->RemoveProperty(AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0));
  1257. // need to update all meshes associated with this material
  1258. for (unsigned int i = 0;i < g_pcAsset->pcScene->mNumMeshes;++i)
  1259. {
  1260. if (m_pcCurrentTexture->iMatIndex == g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex)
  1261. {
  1262. CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
  1263. CMaterialManager::Instance().CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
  1264. }
  1265. }
  1266. // find the corresponding MaterialInfo structure
  1267. const unsigned int iMatIndex = m_pcCurrentTexture->iMatIndex;
  1268. for (std::vector<MaterialInfo>::iterator
  1269. a = m_asMaterials.begin();
  1270. a != m_asMaterials.end();++a)
  1271. {
  1272. if (iMatIndex == (*a).iIndex)
  1273. {
  1274. // good news. we will also need to find all other textures
  1275. // associated with this item ...
  1276. for (std::vector<TextureInfo>::iterator
  1277. n = m_asTextures.begin();
  1278. n != m_asTextures.end();++n)
  1279. {
  1280. if ((*n).iMatIndex == iMatIndex)
  1281. {
  1282. n = m_asTextures.erase(n);
  1283. if (m_asTextures.end() == n)break;
  1284. }
  1285. }
  1286. // delete this material from all lists ...
  1287. TreeView_DeleteItem(GetDlgItem(g_hDlg,IDC_TREE1),(*a).hTreeItem);
  1288. this->m_asMaterials.erase(a);
  1289. break;
  1290. }
  1291. }
  1292. // add the new material to the list and make sure it will be fully expanded
  1293. AddMaterialToDisplayList(m_hRoot,iMatIndex);
  1294. HTREEITEM hNewItem = m_asMaterials.back().hTreeItem;
  1295. TreeView_Expand(GetDlgItem(g_hDlg,IDC_TREE1),hNewItem,TVE_EXPAND);
  1296. // we need to sort the list, materials come first, then nodes
  1297. TVSORTCB sSort;
  1298. sSort.hParent = m_hRoot;
  1299. sSort.lParam = 10;
  1300. sSort.lpfnCompare = &TreeViewCompareFunc;
  1301. TreeView_SortChildrenCB(GetDlgItem(g_hDlg,IDC_TREE1),&sSort,0);
  1302. // the texture was selected, but the silly user has just deleted it
  1303. // ... go back to normal viewing mode
  1304. TreeView_Select(GetDlgItem(g_hDlg,IDC_TREE1),m_hRoot,TVGN_CARET);
  1305. return 1;
  1306. }
  1307. }
  1308. return 0;
  1309. }
  1310. //-------------------------------------------------------------------------------
  1311. // Setup stereo view
  1312. int CDisplay::SetupStereoView()
  1313. {
  1314. if (nullptr != g_pcAsset && nullptr != g_pcAsset->pcScene->mRootNode)
  1315. {
  1316. // enable the RED, GREEN and ALPHA channels
  1317. g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
  1318. D3DCOLORWRITEENABLE_RED |
  1319. D3DCOLORWRITEENABLE_ALPHA |
  1320. D3DCOLORWRITEENABLE_GREEN);
  1321. // move the camera a little bit to the left
  1322. g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
  1323. }
  1324. return 1;
  1325. }
  1326. //-------------------------------------------------------------------------------
  1327. // Do the actual rendering pass for the stereo view
  1328. int CDisplay::RenderStereoView(const aiMatrix4x4& m)
  1329. {
  1330. // and rerender the scene
  1331. if (nullptr != g_pcAsset && nullptr != g_pcAsset->pcScene->mRootNode)
  1332. {
  1333. // enable the BLUE, GREEN and ALPHA channels
  1334. g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
  1335. D3DCOLORWRITEENABLE_GREEN |
  1336. D3DCOLORWRITEENABLE_ALPHA |
  1337. D3DCOLORWRITEENABLE_BLUE);
  1338. // clear the z-buffer
  1339. g_piDevice->Clear(0,nullptr,D3DCLEAR_ZBUFFER,0,1.0f,0);
  1340. // move the camera a little bit to the right
  1341. g_sCamera.vPos += g_sCamera.vRight * 0.06f;
  1342. RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
  1343. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
  1344. RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
  1345. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
  1346. // (move back to the original position)
  1347. g_sCamera.vPos -= g_sCamera.vRight * 0.03f;
  1348. // re-enable all channels
  1349. g_piDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
  1350. D3DCOLORWRITEENABLE_RED |
  1351. D3DCOLORWRITEENABLE_GREEN |
  1352. D3DCOLORWRITEENABLE_ALPHA |
  1353. D3DCOLORWRITEENABLE_BLUE);
  1354. }
  1355. return 1;
  1356. }
  1357. //-------------------------------------------------------------------------------
  1358. // Process input for the texture view
  1359. int CDisplay::HandleInputTextureView()
  1360. {
  1361. HandleMouseInputTextureView();
  1362. HandleKeyboardInputTextureView();
  1363. return 1;
  1364. }
  1365. //-------------------------------------------------------------------------------
  1366. // Get input for the current state
  1367. int CDisplay::HandleInput()
  1368. {
  1369. if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  1370. HandleMouseInputSkyBox();
  1371. // handle input commands
  1372. HandleMouseInputLightRotate();
  1373. HandleMouseInputLightIntensityAndColor();
  1374. if(g_bFPSView)
  1375. {
  1376. HandleMouseInputFPS();
  1377. HandleKeyboardInputFPS();
  1378. }
  1379. else HandleMouseInputLocal();
  1380. // compute auto rotation depending on the time which has passed
  1381. if (g_sOptions.bRotate)
  1382. {
  1383. aiMatrix4x4 mMat;
  1384. D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
  1385. g_vRotateSpeed.x * g_fElpasedTime,
  1386. g_vRotateSpeed.y * g_fElpasedTime,
  1387. g_vRotateSpeed.z * g_fElpasedTime);
  1388. g_mWorldRotate = g_mWorldRotate * mMat;
  1389. }
  1390. // Handle rotations of light source(s)
  1391. if (g_sOptions.bLightRotate)
  1392. {
  1393. aiMatrix4x4 mMat;
  1394. D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
  1395. g_vRotateSpeed.x * g_fElpasedTime * 0.5f,
  1396. g_vRotateSpeed.y * g_fElpasedTime * 0.5f,
  1397. g_vRotateSpeed.z * g_fElpasedTime * 0.5f);
  1398. D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[0],
  1399. (D3DXVECTOR3*)&g_avLightDirs[0],(D3DXMATRIX*)&mMat);
  1400. g_avLightDirs[0].Normalize();
  1401. }
  1402. return 1;
  1403. }
  1404. //-------------------------------------------------------------------------------
  1405. // Process input for an empty scene view to allow for sky-box rotations
  1406. int CDisplay::HandleInputEmptyScene()
  1407. {
  1408. if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  1409. {
  1410. if (g_bFPSView)
  1411. {
  1412. HandleMouseInputFPS();
  1413. HandleKeyboardInputFPS();
  1414. }
  1415. HandleMouseInputSkyBox();
  1416. // need to store the last mouse position in the global variable
  1417. // HandleMouseInputFPS() is doing this internally
  1418. if (!g_bFPSView)
  1419. {
  1420. g_LastmousePos.x = g_mousePos.x;
  1421. g_LastmousePos.y = g_mousePos.y;
  1422. }
  1423. }
  1424. return 1;
  1425. }
  1426. //-------------------------------------------------------------------------------
  1427. // Draw the HUD on top of the scene
  1428. int CDisplay::DrawHUD()
  1429. {
  1430. // HACK: (thom) can't get the effect to work on non-shader cards, therefore deactivated for the moment
  1431. if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
  1432. return 1;
  1433. // get the dimension of the back buffer
  1434. RECT sRect;
  1435. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  1436. sRect.right -= sRect.left;
  1437. sRect.bottom -= sRect.top;
  1438. // commit the texture to the shader
  1439. // FIX: Necessary because the texture view is also using this shader
  1440. g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture);
  1441. // NOTE: The shader might be used for other purposes, too.
  1442. // So ensure the right technique is there
  1443. if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
  1444. g_piPassThroughEffect->SetTechnique( "PassThrough_FF");
  1445. else
  1446. g_piPassThroughEffect->SetTechnique("PassThrough");
  1447. // build vertices for drawing from system memory
  1448. UINT dw;
  1449. g_piPassThroughEffect->Begin(&dw,0);
  1450. g_piPassThroughEffect->BeginPass(0);
  1451. D3DSURFACE_DESC sDesc;
  1452. g_pcTexture->GetLevelDesc(0,&sDesc);
  1453. SVertex as[4];
  1454. float fHalfX = ((float)sRect.right-(float)sDesc.Width) / 2.0f;
  1455. float fHalfY = ((float)sRect.bottom-(float)sDesc.Height) / 2.0f;
  1456. as[1].x = fHalfX;
  1457. as[1].y = fHalfY;
  1458. as[1].z = 0.2f;
  1459. as[1].w = 1.0f;
  1460. as[1].u = 0.0f;
  1461. as[1].v = 0.0f;
  1462. as[3].x = (float)sRect.right-fHalfX;
  1463. as[3].y = fHalfY;
  1464. as[3].z = 0.2f;
  1465. as[3].w = 1.0f;
  1466. as[3].u = 1.0f;
  1467. as[3].v = 0.0f;
  1468. as[0].x = fHalfX;
  1469. as[0].y = (float)sRect.bottom-fHalfY;
  1470. as[0].z = 0.2f;
  1471. as[0].w = 1.0f;
  1472. as[0].u = 0.0f;
  1473. as[0].v = 1.0f;
  1474. as[2].x = (float)sRect.right-fHalfX;
  1475. as[2].y = (float)sRect.bottom-fHalfY;
  1476. as[2].z = 0.2f;
  1477. as[2].w = 1.0f;
  1478. as[2].u = 1.0f;
  1479. as[2].v = 1.0f;
  1480. as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
  1481. as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
  1482. g_piDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  1483. g_piDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  1484. // draw the screen-filling squad
  1485. DWORD dw2;g_piDevice->GetFVF(&dw2);
  1486. g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  1487. g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
  1488. &as,sizeof(SVertex));
  1489. // end the effect and recover the old vertex format
  1490. g_piPassThroughEffect->EndPass();
  1491. g_piPassThroughEffect->End();
  1492. g_piDevice->SetFVF(dw2);
  1493. return 1;
  1494. }
  1495. //-------------------------------------------------------------------------------
  1496. // Render the full scene, all nodes
  1497. int CDisplay::RenderFullScene()
  1498. {
  1499. // reset the color index used for drawing normals
  1500. g_iCurrentColor = 0;
  1501. aiMatrix4x4 pcProj;
  1502. GetProjectionMatrix(pcProj);
  1503. vPos = GetCameraMatrix(mViewProjection);
  1504. mViewProjection = mViewProjection * pcProj;
  1505. // setup wireframe/solid rendering mode
  1506. if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
  1507. g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
  1508. else g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  1509. if (g_sOptions.bCulling)
  1510. g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
  1511. else g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
  1512. // for high-quality mode, enable anisotropic texture filtering
  1513. if (g_sOptions.bLowQuality) {
  1514. for (DWORD d = 0; d < 8;++d) {
  1515. g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  1516. g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  1517. g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
  1518. }
  1519. }
  1520. else {
  1521. for (DWORD d = 0; d < 8;++d) {
  1522. g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
  1523. g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
  1524. g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
  1525. g_piDevice->SetSamplerState(d,D3DSAMP_MAXANISOTROPY,g_sCaps.MaxAnisotropy);
  1526. }
  1527. }
  1528. // draw the scene background (clear and texture 2d)
  1529. CBackgroundPainter::Instance().OnPreRender();
  1530. // setup the stereo view if necessary
  1531. if (g_sOptions.bStereoView)
  1532. SetupStereoView();
  1533. // draw all opaque objects in the scene
  1534. aiMatrix4x4 m;
  1535. if (nullptr != g_pcAsset && nullptr != g_pcAsset->pcScene->mRootNode)
  1536. {
  1537. HandleInput();
  1538. m = g_mWorld * g_mWorldRotate;
  1539. RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
  1540. }
  1541. // if a cube texture is loaded as background image, the user
  1542. // should be able to rotate it even if no asset is loaded
  1543. HandleInputEmptyScene();
  1544. // draw the scene background
  1545. CBackgroundPainter::Instance().OnPostRender();
  1546. // draw all non-opaque objects in the scene
  1547. if (nullptr != g_pcAsset && nullptr != g_pcAsset->pcScene->mRootNode)
  1548. {
  1549. // disable the z-buffer
  1550. if (!g_sOptions.bNoAlphaBlending) {
  1551. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
  1552. }
  1553. RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
  1554. if (!g_sOptions.bNoAlphaBlending) {
  1555. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
  1556. }
  1557. }
  1558. // setup the stereo view if necessary
  1559. if (g_sOptions.bStereoView)
  1560. RenderStereoView(m);
  1561. // render the skeleton if necessary
  1562. if (g_sOptions.bSkeleton && nullptr != g_pcAsset && nullptr != g_pcAsset->pcScene->mRootNode) {
  1563. // disable the z-buffer
  1564. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
  1565. if (g_sOptions.eDrawMode != RenderOptions::WIREFRAME) {
  1566. g_piDevice->SetRenderState(D3DRS_ZENABLE,FALSE);
  1567. }
  1568. g_piDevice->SetVertexDeclaration( gDefaultVertexDecl);
  1569. // this is very similar to the code in SetupMaterial()
  1570. ID3DXEffect* piEnd = g_piNormalsEffect;
  1571. aiMatrix4x4 pcProj2 = m * mViewProjection;
  1572. D3DXVECTOR4 vVector(1.f,0.f,0.f,1.f);
  1573. piEnd->SetVector("OUTPUT_COLOR",&vVector);
  1574. piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj2);
  1575. UINT dwPasses = 0;
  1576. piEnd->Begin(&dwPasses,0);
  1577. piEnd->BeginPass(0);
  1578. RenderSkeleton(g_pcAsset->pcScene->mRootNode,m,m);
  1579. piEnd->EndPass();piEnd->End();
  1580. g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
  1581. g_piDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
  1582. }
  1583. // draw the HUD texture on top of the rendered scene using
  1584. // pre-projected vertices
  1585. if (!g_bFPSView && g_pcAsset && g_pcTexture)
  1586. DrawHUD();
  1587. return 1;
  1588. }
  1589. //-------------------------------------------------------------------------------
  1590. int CDisplay::RenderMaterialView()
  1591. {
  1592. return 1;
  1593. }
  1594. //-------------------------------------------------------------------------------
  1595. // Render animation skeleton
  1596. int CDisplay::RenderSkeleton (aiNode* piNode,const aiMatrix4x4& piMatrix, const aiMatrix4x4& parent)
  1597. {
  1598. aiMatrix4x4 me = g_pcAsset->mAnimator->GetGlobalTransform( piNode);
  1599. me.Transpose();
  1600. //me *= piMatrix;
  1601. if (piNode->mParent) {
  1602. AssetHelper::LineVertex data[2];
  1603. data[0].dColorDiffuse = data[1].dColorDiffuse = D3DCOLOR_ARGB(0xff,0xff,0,0);
  1604. data[0].vPosition.x = parent.d1;
  1605. data[0].vPosition.y = parent.d2;
  1606. data[0].vPosition.z = parent.d3;
  1607. data[1].vPosition.x = me.d1;
  1608. data[1].vPosition.y = me.d2;
  1609. data[1].vPosition.z = me.d3;
  1610. g_piDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,&data,sizeof(AssetHelper::LineVertex));
  1611. }
  1612. // render all child nodes
  1613. for (unsigned int i = 0; i < piNode->mNumChildren;++i)
  1614. RenderSkeleton(piNode->mChildren[i],piMatrix, me );
  1615. return 1;
  1616. }
  1617. //-------------------------------------------------------------------------------
  1618. // Render a single node
  1619. int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
  1620. bool bAlpha /*= false*/)
  1621. {
  1622. aiMatrix4x4 aiMe = g_pcAsset->mAnimator->GetGlobalTransform( piNode);
  1623. aiMe.Transpose();
  1624. aiMe *= piMatrix;
  1625. bool bChangedVM = false;
  1626. if (VIEWMODE_NODE == m_iViewMode && m_pcCurrentNode)
  1627. {
  1628. if (piNode != m_pcCurrentNode->psNode)
  1629. {
  1630. // directly call our children
  1631. for (unsigned int i = 0; i < piNode->mNumChildren;++i)
  1632. RenderNode(piNode->mChildren[i],piMatrix,bAlpha );
  1633. return 1;
  1634. }
  1635. m_iViewMode = VIEWMODE_FULL;
  1636. bChangedVM = true;
  1637. }
  1638. aiMatrix4x4 pcProj = aiMe * mViewProjection;
  1639. aiMatrix4x4 pcCam = aiMe;
  1640. pcCam.Inverse().Transpose();
  1641. // VERY UNOPTIMIZED, much stuff is redundant. Who cares?
  1642. if (!g_sOptions.bRenderMats && !bAlpha)
  1643. {
  1644. // this is very similar to the code in SetupMaterial()
  1645. ID3DXEffect* piEnd = g_piDefaultEffect;
  1646. // commit transformation matrices to the shader
  1647. piEnd->SetMatrix("WorldViewProjection",
  1648. (const D3DXMATRIX*)&pcProj);
  1649. piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
  1650. piEnd->SetMatrix("WorldInverseTranspose",
  1651. (const D3DXMATRIX*)&pcCam);
  1652. if ( CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  1653. {
  1654. pcCam = pcCam * pcProj;
  1655. piEnd->SetMatrix("ViewProj",(const D3DXMATRIX*)&pcCam);
  1656. pcCam.Inverse();
  1657. piEnd->SetMatrix("InvViewProj",(const D3DXMATRIX*)&pcCam);
  1658. }
  1659. // commit light colors and direction to the shader
  1660. D3DXVECTOR4 apcVec[5];
  1661. apcVec[0].x = g_avLightDirs[0].x;
  1662. apcVec[0].y = g_avLightDirs[0].y;
  1663. apcVec[0].z = g_avLightDirs[0].z;
  1664. apcVec[0].w = 0.0f;
  1665. apcVec[1].x = g_avLightDirs[0].x * -1.0f;
  1666. apcVec[1].y = g_avLightDirs[0].y * -1.0f;
  1667. apcVec[1].z = g_avLightDirs[0].z * -1.0f;
  1668. apcVec[1].w = 0.0f;
  1669. D3DXVec4Normalize(&apcVec[0],&apcVec[0]);
  1670. D3DXVec4Normalize(&apcVec[1],&apcVec[1]);
  1671. piEnd->SetVectorArray("afLightDir",apcVec,5);
  1672. apcVec[0].x = ((g_avLightColors[0] >> 16) & 0xFF) / 255.0f;
  1673. apcVec[0].y = ((g_avLightColors[0] >> 8) & 0xFF) / 255.0f;
  1674. apcVec[0].z = ((g_avLightColors[0]) & 0xFF) / 255.0f;
  1675. apcVec[0].w = 1.0f;
  1676. if( g_sOptions.b3Lights)
  1677. {
  1678. apcVec[1].x = ((g_avLightColors[1] >> 16) & 0xFF) / 255.0f;
  1679. apcVec[1].y = ((g_avLightColors[1] >> 8) & 0xFF) / 255.0f;
  1680. apcVec[1].z = ((g_avLightColors[1]) & 0xFF) / 255.0f;
  1681. apcVec[1].w = 0.0f;
  1682. } else
  1683. {
  1684. apcVec[1].x = 0.0f;
  1685. apcVec[1].y = 0.0f;
  1686. apcVec[1].z = 0.0f;
  1687. apcVec[1].w = 0.0f;
  1688. }
  1689. apcVec[0] *= g_fLightIntensity;
  1690. apcVec[1] *= g_fLightIntensity;
  1691. piEnd->SetVectorArray("afLightColor",apcVec,5);
  1692. apcVec[0].x = vPos.x;
  1693. apcVec[0].y = vPos.y;
  1694. apcVec[0].z = vPos.z;
  1695. piEnd->SetVector( "vCameraPos",&apcVec[0]);
  1696. // setup the best technique
  1697. if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
  1698. {
  1699. g_piDefaultEffect->SetTechnique( "DefaultFXSpecular_FF");
  1700. } else
  1701. if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
  1702. {
  1703. if (g_sOptions.b3Lights)
  1704. piEnd->SetTechnique("DefaultFXSpecular_PS20_D2");
  1705. else piEnd->SetTechnique("DefaultFXSpecular_PS20_D1");
  1706. }
  1707. else
  1708. {
  1709. if (g_sOptions.b3Lights)
  1710. piEnd->SetTechnique("DefaultFXSpecular_D2");
  1711. else piEnd->SetTechnique("DefaultFXSpecular_D1");
  1712. }
  1713. // setup the default material
  1714. UINT dwPasses = 0;
  1715. piEnd->Begin(&dwPasses,0);
  1716. piEnd->BeginPass(0);
  1717. }
  1718. D3DXVECTOR4 vVector = g_aclNormalColors[g_iCurrentColor];
  1719. if (++g_iCurrentColor == 14)
  1720. {
  1721. g_iCurrentColor = 0;
  1722. }
  1723. if (! (!g_sOptions.bRenderMats && bAlpha ))
  1724. {
  1725. for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
  1726. {
  1727. const aiMesh* mesh = g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]];
  1728. AssetHelper::MeshHelper* helper = g_pcAsset->apcMeshes[piNode->mMeshes[i]];
  1729. // don't render the mesh if the render pass is incorrect
  1730. if (g_sOptions.bRenderMats && (helper->piOpacityTexture || helper->fOpacity != 1.0f) && !mesh->HasBones())
  1731. {
  1732. if (!bAlpha)continue;
  1733. }
  1734. else if (bAlpha)continue;
  1735. // Upload bone matrices. This maybe is the wrong place to do it, but for the heck of it I don't understand this code flow
  1736. if( mesh->HasBones())
  1737. {
  1738. if( helper->piEffect)
  1739. {
  1740. static float matrices[4*4*60];
  1741. float* tempmat = matrices;
  1742. const std::vector<aiMatrix4x4>& boneMats = g_pcAsset->mAnimator->GetBoneMatrices( piNode, i);
  1743. ai_assert( boneMats.size() == mesh->mNumBones);
  1744. for( unsigned int a = 0; a < mesh->mNumBones; a++)
  1745. {
  1746. const aiMatrix4x4& mat = boneMats[a];
  1747. *tempmat++ = mat.a1; *tempmat++ = mat.a2; *tempmat++ = mat.a3; *tempmat++ = mat.a4;
  1748. *tempmat++ = mat.b1; *tempmat++ = mat.b2; *tempmat++ = mat.b3; *tempmat++ = mat.b4;
  1749. *tempmat++ = mat.c1; *tempmat++ = mat.c2; *tempmat++ = mat.c3; *tempmat++ = mat.c4;
  1750. *tempmat++ = mat.d1; *tempmat++ = mat.d2; *tempmat++ = mat.d3; *tempmat++ = mat.d4;
  1751. //tempmat += 4;
  1752. }
  1753. if( g_sOptions.bRenderMats)
  1754. {
  1755. helper->piEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60);
  1756. } else
  1757. {
  1758. g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60);
  1759. g_piDefaultEffect->CommitChanges();
  1760. }
  1761. }
  1762. } else
  1763. {
  1764. // upload identity matrices instead. Only the first is ever going to be used in meshes without bones
  1765. if( !g_sOptions.bRenderMats)
  1766. {
  1767. D3DXMATRIX identity( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  1768. g_piDefaultEffect->SetMatrixTransposeArray( "gBoneMatrix", &identity, 1);
  1769. g_piDefaultEffect->CommitChanges();
  1770. }
  1771. }
  1772. // now setup the material
  1773. if (g_sOptions.bRenderMats)
  1774. {
  1775. CMaterialManager::Instance().SetupMaterial( helper, pcProj, aiMe, pcCam, vPos);
  1776. }
  1777. g_piDevice->SetVertexDeclaration( gDefaultVertexDecl);
  1778. if (g_sOptions.bNoAlphaBlending) {
  1779. // manually disable alpha-blending
  1780. g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
  1781. }
  1782. if (bAlpha)CMeshRenderer::Instance().DrawSorted(piNode->mMeshes[i],aiMe);
  1783. else CMeshRenderer::Instance().DrawUnsorted(piNode->mMeshes[i]);
  1784. // now end the material
  1785. if (g_sOptions.bRenderMats)
  1786. {
  1787. CMaterialManager::Instance().EndMaterial( helper);
  1788. }
  1789. // render normal vectors?
  1790. if (g_sOptions.bRenderNormals && helper->piVBNormals)
  1791. {
  1792. // this is very similar to the code in SetupMaterial()
  1793. ID3DXEffect* piEnd = g_piNormalsEffect;
  1794. piEnd->SetVector("OUTPUT_COLOR",&vVector);
  1795. piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj);
  1796. UINT dwPasses = 0;
  1797. piEnd->Begin(&dwPasses,0);
  1798. piEnd->BeginPass(0);
  1799. g_piDevice->SetStreamSource(0, helper->piVBNormals, 0, sizeof(AssetHelper::LineVertex));
  1800. g_piDevice->DrawPrimitive(D3DPT_LINELIST,0, g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices);
  1801. piEnd->EndPass();
  1802. piEnd->End();
  1803. }
  1804. }
  1805. // end the default material
  1806. if (!g_sOptions.bRenderMats)
  1807. {
  1808. g_piDefaultEffect->EndPass();
  1809. g_piDefaultEffect->End();
  1810. }
  1811. }
  1812. // render all child nodes
  1813. for (unsigned int i = 0; i < piNode->mNumChildren;++i)
  1814. RenderNode(piNode->mChildren[i],piMatrix,bAlpha );
  1815. // need to reset the viewmode?
  1816. if (bChangedVM)
  1817. m_iViewMode = VIEWMODE_NODE;
  1818. return 1;
  1819. }
  1820. //-------------------------------------------------------------------------------
  1821. int CDisplay::RenderPatternBG()
  1822. {
  1823. if (!g_piPatternEffect)
  1824. {
  1825. // the pattern effect won't work on ps_2_0 cards
  1826. if (g_sCaps.PixelShaderVersion >= D3DPS_VERSION(3,0))
  1827. {
  1828. // seems we have not yet compiled this shader.
  1829. // and NOW is the best time to do that ...
  1830. ID3DXBuffer* piBuffer = nullptr;
  1831. if(FAILED( D3DXCreateEffect(g_piDevice,
  1832. g_szCheckerBackgroundShader.c_str(),
  1833. (UINT)g_szCheckerBackgroundShader.length(),
  1834. nullptr,
  1835. nullptr,
  1836. D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,
  1837. nullptr,
  1838. &g_piPatternEffect,&piBuffer)))
  1839. {
  1840. if( piBuffer)
  1841. {
  1842. MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
  1843. piBuffer->Release();
  1844. }
  1845. return 0;
  1846. }
  1847. if( piBuffer)
  1848. {
  1849. piBuffer->Release();
  1850. piBuffer = nullptr;
  1851. }
  1852. }
  1853. else
  1854. {
  1855. // clear the color buffer in magenta
  1856. // (hopefully this is ugly enough that every ps_2_0 cards owner
  1857. // runs to the next shop to buy himself a new card ...)
  1858. g_piDevice->Clear(0,nullptr,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  1859. D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
  1860. return 1;
  1861. }
  1862. }
  1863. // clear the depth buffer only
  1864. g_piDevice->Clear(0,nullptr,D3DCLEAR_ZBUFFER,
  1865. D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 );
  1866. // setup the colors to be used ...
  1867. g_piPatternEffect->SetVector("COLOR_ONE",&m_avCheckerColors[0]);
  1868. g_piPatternEffect->SetVector("COLOR_TWO",&m_avCheckerColors[1]);
  1869. // setup the shader
  1870. UINT dw;
  1871. g_piPatternEffect->Begin(&dw,0);
  1872. g_piPatternEffect->BeginPass(0);
  1873. RECT sRect;
  1874. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  1875. sRect.right -= sRect.left;
  1876. sRect.bottom -= sRect.top;
  1877. struct SVertex
  1878. {
  1879. float x,y,z,w;
  1880. };
  1881. // build the screen-filling rectangle
  1882. SVertex as[4];
  1883. as[1].x = 0.0f;
  1884. as[1].y = 0.0f;
  1885. as[1].z = 0.2f;
  1886. as[3].x = (float)sRect.right;
  1887. as[3].y = 0.0f;
  1888. as[3].z = 0.2f;
  1889. as[0].x = 0.0f;
  1890. as[0].y = (float)sRect.bottom;
  1891. as[0].z = 0.2f;
  1892. as[2].x = (float)sRect.right;
  1893. as[2].y = (float)sRect.bottom;
  1894. as[2].z = 0.2f;
  1895. as[0].w = 1.0f;
  1896. as[1].w = 1.0f;
  1897. as[2].w = 1.0f;
  1898. as[3].w = 1.0f;
  1899. as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
  1900. as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
  1901. // draw the rectangle
  1902. DWORD dw2;g_piDevice->GetFVF(&dw2);
  1903. g_piDevice->SetFVF(D3DFVF_XYZRHW);
  1904. g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
  1905. &as,sizeof(SVertex));
  1906. g_piDevice->SetFVF(dw2);
  1907. // cleanup
  1908. g_piPatternEffect->EndPass();
  1909. g_piPatternEffect->End();
  1910. return 1;
  1911. }
  1912. //-------------------------------------------------------------------------------
  1913. int CDisplay::RenderTextureView()
  1914. {
  1915. if (!g_pcAsset || !g_pcAsset->pcScene)return 0;
  1916. // handle input
  1917. this->HandleInputTextureView();
  1918. // render the background
  1919. RenderPatternBG();
  1920. // it might be that there is no texture ...
  1921. if (!m_pcCurrentTexture->piTexture)
  1922. {
  1923. return 0;
  1924. }
  1925. RECT sRect;
  1926. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  1927. sRect.right -= sRect.left;
  1928. sRect.bottom -= sRect.top;
  1929. // commit the texture to the shader
  1930. g_piPassThroughEffect->SetTexture("TEXTURE_2D",*m_pcCurrentTexture->piTexture);
  1931. if (aiTextureType_OPACITY == m_pcCurrentTexture->iType)
  1932. {
  1933. g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromR");
  1934. }
  1935. else if ((aiTextureType_OPACITY | 0x40000000) == m_pcCurrentTexture->iType)
  1936. {
  1937. g_piPassThroughEffect->SetTechnique("PassThroughAlphaFromA");
  1938. }
  1939. else if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
  1940. g_piPassThroughEffect->SetTechnique( "PassThrough_FF");
  1941. else
  1942. g_piPassThroughEffect->SetTechnique("PassThrough");
  1943. UINT dw;
  1944. g_piPassThroughEffect->Begin(&dw,0);
  1945. g_piPassThroughEffect->BeginPass(0);
  1946. if (aiTextureType_HEIGHT == m_pcCurrentTexture->iType ||
  1947. aiTextureType_NORMALS == m_pcCurrentTexture->iType || g_sOptions.bNoAlphaBlending)
  1948. {
  1949. // manually disable alpha blending
  1950. g_piDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
  1951. }
  1952. // build a rectangle which centers the texture
  1953. // scaling is OK, but no stretching
  1954. D3DSURFACE_DESC sDesc;
  1955. if ( m_pcCurrentTexture->piTexture && *m_pcCurrentTexture->piTexture) { /* just a dirty fix */
  1956. (*m_pcCurrentTexture->piTexture)->GetLevelDesc(0,&sDesc);
  1957. struct SVertex{float x,y,z,w,u,v;};
  1958. SVertex as[4];
  1959. const float nx = (float)sRect.right;
  1960. const float ny = (float)sRect.bottom;
  1961. const float x = (float)sDesc.Width;
  1962. const float y = (float)sDesc.Height;
  1963. float f = std::min((nx-30) / x,(ny-30) / y) * (m_fTextureZoom/1000.0f);
  1964. float fHalfX = (nx - (f * x)) / 2.0f;
  1965. float fHalfY = (ny - (f * y)) / 2.0f;
  1966. as[1].x = fHalfX + m_vTextureOffset.x;
  1967. as[1].y = fHalfY + m_vTextureOffset.y;
  1968. as[1].z = 0.2f;
  1969. as[1].w = 1.0f;
  1970. as[1].u = 0.0f;
  1971. as[1].v = 0.0f;
  1972. as[3].x = nx-fHalfX + m_vTextureOffset.x;
  1973. as[3].y = fHalfY + m_vTextureOffset.y;
  1974. as[3].z = 0.2f;
  1975. as[3].w = 1.0f;
  1976. as[3].u = 1.0f;
  1977. as[3].v = 0.0f;
  1978. as[0].x = fHalfX + m_vTextureOffset.x;
  1979. as[0].y = ny-fHalfY + m_vTextureOffset.y;
  1980. as[0].z = 0.2f;
  1981. as[0].w = 1.0f;
  1982. as[0].u = 0.0f;
  1983. as[0].v = 1.0f;
  1984. as[2].x = nx-fHalfX + m_vTextureOffset.x;
  1985. as[2].y = ny-fHalfY + m_vTextureOffset.y;
  1986. as[2].z = 0.2f;
  1987. as[2].w = 1.0f;
  1988. as[2].u = 1.0f;
  1989. as[2].v = 1.0f;
  1990. as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
  1991. as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
  1992. // draw the rectangle
  1993. DWORD dw2;g_piDevice->GetFVF(&dw2);
  1994. g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  1995. g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
  1996. &as,sizeof(SVertex));
  1997. g_piDevice->SetFVF(dw2);
  1998. }
  1999. g_piPassThroughEffect->EndPass();
  2000. g_piPassThroughEffect->End();
  2001. // do we need to draw UV coordinates?
  2002. return 1;
  2003. }
  2004. }