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