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