1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
5
6 Copyright (c) 2006-2015, 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
42 #include "assimp_view.h"
43 #include "StringUtils.h"
44
45 namespace AssimpView {
46
47 extern std::string g_szSkyboxShader;
48
49 // From: U3D build 1256 (src\kernel\graphic\scenegraph\SkyBox.cpp)
50 // ------------------------------------------------------------------------------
51 /** \brief Vertex structure for the skybox
52 */
53 // ------------------------------------------------------------------------------
54 struct SkyBoxVertex
55 {
56 float x,y,z;
57 float u,v,w;
58 };
59
60
61 // ------------------------------------------------------------------------------
62 /** \brief Vertices for the skybox
63 */
64 // ------------------------------------------------------------------------------
65 SkyBoxVertex g_cubeVertices_indexed[] =
66 {
67 { -1.0f, 1.0f, -1.0f, -1.0f,1.0f,-1.0f }, // 0
68 { 1.0f, 1.0f, -1.0f, 1.0f,1.0f,-1.0f }, // 1
69 { -1.0f, -1.0f, -1.0f, -1.0f,-1.0f,-1.0f }, // 2
70 { 1.0f,-1.0f,-1.0f, 1.0f,-1.0f,-1.0f }, // 3
71 {-1.0f, 1.0f, 1.0f, -1.0f,1.0f,1.0f }, // 4
72 {-1.0f,-1.0f, 1.0f, -1.0f,-1.0f,1.0f }, // 5
73 { 1.0f, 1.0f, 1.0f, 1.0f,1.0f,1.0f }, // 6
74 { 1.0f,-1.0f, 1.0f, 1.0f,-1.0f,1.0f } // 7
75 };
76
77
78 // ------------------------------------------------------------------------------
79 /** \brief Indices for the skybox
80 */
81 // ------------------------------------------------------------------------------
82 unsigned short g_cubeIndices[] =
83 {
84 0, 1, 2, 3, 2, 1,4, 5, 6,
85 7, 6, 5, 4, 6, 0, 1, 6, 0,
86 5, 2, 7,3, 2, 7, 1, 6, 3,
87 7, 3, 6, 0, 2, 4, 5, 4, 2,
88 };
89
90 CBackgroundPainter CBackgroundPainter::s_cInstance;
91
92 //-------------------------------------------------------------------------------
SetColor(D3DCOLOR p_clrNew)93 void CBackgroundPainter::SetColor (D3DCOLOR p_clrNew)
94 {
95 if (TEXTURE_CUBE == eMode)
96 RemoveSBDeps();
97
98 clrColor = p_clrNew;
99 eMode = SIMPLE_COLOR;
100
101 if (pcTexture)
102 {
103 pcTexture->Release();
104 pcTexture = NULL;
105 }
106 }
107 //-------------------------------------------------------------------------------
RemoveSBDeps()108 void CBackgroundPainter::RemoveSBDeps()
109 {
110 MODE e = eMode;
111 eMode = SIMPLE_COLOR;
112 if (g_pcAsset && g_pcAsset->pcScene)
113 {
114 for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
115 {
116 if (aiShadingMode_Gouraud != g_pcAsset->apcMeshes[i]->eShadingMode)
117 {
118 CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
119 CMaterialManager::Instance().CreateMaterial(
120 g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
121 }
122 }
123 }
124 eMode = e;
125 }
126 //-------------------------------------------------------------------------------
ResetSB()127 void CBackgroundPainter::ResetSB()
128 {
129 mMatrix = aiMatrix4x4();
130 }
131 //-------------------------------------------------------------------------------
SetCubeMapBG(const char * p_szPath)132 void CBackgroundPainter::SetCubeMapBG (const char* p_szPath)
133 {
134 bool bHad = false;
135 if (pcTexture)
136 {
137 pcTexture->Release();
138 pcTexture = NULL;
139 if(TEXTURE_CUBE ==eMode)bHad = true;
140 }
141
142 eMode = TEXTURE_CUBE;
143
144 szPath = std::string( p_szPath );
145
146 // ARRRGHH... ugly. TODO: Rewrite this!
147 aiString sz;
148 sz.Set(szPath);
149 CMaterialManager::Instance().FindValidPath(&sz);
150 szPath = std::string( sz.data );
151
152 // now recreate all native resources
153 RecreateNativeResource();
154
155 if (SIMPLE_COLOR != this->eMode)
156 {
157 // this influences all material with specular components
158 if (!bHad)
159 {
160 if (g_pcAsset && g_pcAsset->pcScene)
161 {
162 for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
163 {
164 if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode)
165 {
166 CMaterialManager::Instance().DeleteMaterial(g_pcAsset->apcMeshes[i]);
167 CMaterialManager::Instance().CreateMaterial(
168 g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
169 }
170 }
171 }
172 }
173 else
174 {
175 if (g_pcAsset && g_pcAsset->pcScene)
176 {
177 for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
178 {
179 if (aiShadingMode_Phong == g_pcAsset->apcMeshes[i]->eShadingMode)
180 {
181 g_pcAsset->apcMeshes[i]->piEffect->SetTexture(
182 "lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
183 }
184 }
185 }
186 }
187 }
188 }
189 //-------------------------------------------------------------------------------
RotateSB(const aiMatrix4x4 * pm)190 void CBackgroundPainter::RotateSB(const aiMatrix4x4* pm)
191 {
192 this->mMatrix = mMatrix * (*pm);
193 }
194 //-------------------------------------------------------------------------------
SetTextureBG(const char * p_szPath)195 void CBackgroundPainter::SetTextureBG (const char* p_szPath)
196 {
197 if (TEXTURE_CUBE == this->eMode)this->RemoveSBDeps();
198
199 if (pcTexture)
200 {
201 pcTexture->Release();
202 pcTexture = NULL;
203 }
204
205 eMode = TEXTURE_2D;
206 szPath = std::string( p_szPath );
207
208 // ARRRGHH... ugly. TODO: Rewrite this!
209 aiString sz;
210 sz.Set(szPath);
211 CMaterialManager::Instance().FindValidPath(&sz);
212 szPath = std::string( sz.data );
213
214 // now recreate all native resources
215 RecreateNativeResource();
216 }
217 //-------------------------------------------------------------------------------
OnPreRender()218 void CBackgroundPainter::OnPreRender()
219 {
220 if (SIMPLE_COLOR != eMode)
221 {
222 // clear the z-buffer only (in wireframe mode we must also clear
223 // the color buffer )
224 if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
225 {
226 g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET,
227 D3DCOLOR_ARGB(0xff,100,100,100),1.0f,0);
228 }
229 else
230 {
231 g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,0,1.0f,0);
232 }
233
234 if (TEXTURE_2D == eMode)
235 {
236 RECT sRect;
237 GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
238 sRect.right -= sRect.left;
239 sRect.bottom -= sRect.top;
240
241 struct SVertex
242 {
243 float x,y,z,w,u,v;
244 };
245
246 UINT dw;
247 this->piSkyBoxEffect->Begin(&dw,0);
248 this->piSkyBoxEffect->BeginPass(0);
249
250 SVertex as[4];
251 as[1].x = 0.0f;
252 as[1].y = 0.0f;
253 as[1].z = 0.2f;
254 as[1].w = 1.0f;
255 as[1].u = 0.0f;
256 as[1].v = 0.0f;
257
258 as[3].x = (float)sRect.right;
259 as[3].y = 0.0f;
260 as[3].z = 0.2f;
261 as[3].w = 1.0f;
262 as[3].u = 1.0f;
263 as[3].v = 0.0f;
264
265 as[0].x = 0.0f;
266 as[0].y = (float)sRect.bottom;
267 as[0].z = 0.2f;
268 as[0].w = 1.0f;
269 as[0].u = 0.0f;
270 as[0].v = 1.0f;
271
272 as[2].x = (float)sRect.right;
273 as[2].y = (float)sRect.bottom;
274 as[2].z = 0.2f;
275 as[2].w = 1.0f;
276 as[2].u = 1.0f;
277 as[2].v = 1.0f;
278
279 as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
280 as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
281
282 DWORD dw2;g_piDevice->GetFVF(&dw2);
283 g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
284
285 g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
286 &as,sizeof(SVertex));
287
288 piSkyBoxEffect->EndPass();
289 piSkyBoxEffect->End();
290
291 g_piDevice->SetFVF(dw2);
292 }
293 return;
294 }
295 // clear both the render target and the z-buffer
296 g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
297 clrColor,1.0f,0);
298 }
299 //-------------------------------------------------------------------------------
OnPostRender()300 void CBackgroundPainter::OnPostRender()
301 {
302 if (TEXTURE_CUBE == eMode)
303 {
304 aiMatrix4x4 pcProj;
305 GetProjectionMatrix(pcProj);
306
307 aiMatrix4x4 pcCam;
308 aiVector3D vPos = GetCameraMatrix(pcCam);
309
310 aiMatrix4x4 aiMe;
311 aiMe[3][0] = vPos.x;
312 aiMe[3][1] = vPos.y;
313 aiMe[3][2] = vPos.z;
314 aiMe = mMatrix * aiMe;
315
316 pcProj = (aiMe * pcCam) * pcProj;
317
318 piSkyBoxEffect->SetMatrix("WorldViewProjection",
319 (const D3DXMATRIX*)&pcProj);
320
321 UINT dwPasses;
322 piSkyBoxEffect->Begin(&dwPasses,0);
323 piSkyBoxEffect->BeginPass(0);
324
325 DWORD dw2;
326 g_piDevice->GetFVF(&dw2);
327 g_piDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0));
328
329 g_piDevice->DrawIndexedPrimitiveUP(
330 D3DPT_TRIANGLELIST,0,8,12,g_cubeIndices,D3DFMT_INDEX16,
331 g_cubeVertices_indexed,sizeof(SkyBoxVertex));
332
333 g_piDevice->SetFVF(dw2);
334
335 piSkyBoxEffect->EndPass();
336 piSkyBoxEffect->End();
337 }
338 }
339 //-------------------------------------------------------------------------------
ReleaseNativeResource()340 void CBackgroundPainter::ReleaseNativeResource()
341 {
342 if ( piSkyBoxEffect)
343 {
344 piSkyBoxEffect->Release();
345 piSkyBoxEffect = NULL;
346 }
347 if (pcTexture)
348 {
349 pcTexture->Release();
350 pcTexture = NULL;
351 }
352 }
353 //-------------------------------------------------------------------------------
RecreateNativeResource()354 void CBackgroundPainter::RecreateNativeResource()
355 {
356 if (SIMPLE_COLOR == eMode)return;
357 if (TEXTURE_CUBE == eMode)
358 {
359
360 // many skyboxes are 16bit FP format which isn't supported
361 // with bilinear filtering on older cards
362 D3DFORMAT eFmt = D3DFMT_UNKNOWN;
363 if(FAILED(g_piD3D->CheckDeviceFormat(0,D3DDEVTYPE_HAL,
364 D3DFMT_X8R8G8B8,D3DUSAGE_QUERY_FILTER,D3DRTYPE_CUBETEXTURE,D3DFMT_A16B16G16R16F)))
365 {
366 eFmt = D3DFMT_A8R8G8B8;
367 }
368
369 if (FAILED(D3DXCreateCubeTextureFromFileEx(
370 g_piDevice,
371 szPath.c_str(),
372 D3DX_DEFAULT,
373 0,
374 0,
375 eFmt,
376 D3DPOOL_MANAGED,
377 D3DX_DEFAULT,
378 D3DX_DEFAULT,
379 0,
380 NULL,
381 NULL,
382 (IDirect3DCubeTexture9**)&pcTexture)))
383 {
384 const char* szEnd = strrchr(szPath.c_str(),'\\');
385 if (!szEnd)szEnd = strrchr(szPath.c_str(),'/');
386 if (!szEnd)szEnd = szPath.c_str()-1;
387
388 char szTemp[1024];
389 ai_snprintf(szTemp,1024,"[ERROR] Unable to load background cubemap %s",szEnd+1);
390
391 CLogDisplay::Instance().AddEntry(szTemp,
392 D3DCOLOR_ARGB(0xFF,0xFF,0,0));
393
394 eMode = SIMPLE_COLOR;
395 return;
396 }
397 else CLogDisplay::Instance().AddEntry("[OK] The skybox has been imported successfully",
398 D3DCOLOR_ARGB(0xFF,0,0xFF,0));
399 }
400 else
401 {
402 if (FAILED(D3DXCreateTextureFromFileEx(
403 g_piDevice,
404 szPath.c_str(),
405 D3DX_DEFAULT,
406 D3DX_DEFAULT,
407 0,
408 0,
409 D3DFMT_A8R8G8B8,
410 D3DPOOL_MANAGED,
411 D3DX_DEFAULT,
412 D3DX_DEFAULT,
413 0,
414 NULL,
415 NULL,
416 (IDirect3DTexture9**)&pcTexture)))
417 {
418 const char* szEnd = strrchr(szPath.c_str(),'\\');
419 if (!szEnd)szEnd = strrchr(szPath.c_str(),'/');
420 if (!szEnd)szEnd = szPath.c_str()-1;
421
422 char szTemp[1024];
423 ai_snprintf(szTemp,1024,"[ERROR] Unable to load background texture %s",szEnd+1);
424
425 CLogDisplay::Instance().AddEntry(szTemp,
426 D3DCOLOR_ARGB(0xFF,0xFF,0,0));
427
428 eMode = SIMPLE_COLOR;
429 return;
430 }
431 else CLogDisplay::Instance().AddEntry("[OK] The background texture has been imported successfully",
432 D3DCOLOR_ARGB(0xFF,0,0xFF,0));
433 }
434 if (!piSkyBoxEffect)
435 {
436 ID3DXBuffer* piBuffer = NULL;
437 if(FAILED( D3DXCreateEffect(
438 g_piDevice,
439 g_szSkyboxShader.c_str(),
440 (UINT)g_szSkyboxShader.length(),
441 NULL,
442 NULL,
443 AI_SHADER_COMPILE_FLAGS,
444 NULL,
445 &piSkyBoxEffect,&piBuffer)))
446 {
447 // failed to compile the shader
448 if( piBuffer) {
449 MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
450 piBuffer->Release();
451 }
452
453 CLogDisplay::Instance().AddEntry("[ERROR] Unable to compile skybox shader",
454 D3DCOLOR_ARGB(0xFF,0xFF,0,0));
455 eMode = SIMPLE_COLOR;
456 return ;
457 }
458 }
459 // commit the correct textures to the shader
460 if (TEXTURE_CUBE == eMode)
461 {
462 piSkyBoxEffect->SetTexture("lw_tex_envmap",pcTexture);
463 piSkyBoxEffect->SetTechnique("RenderSkyBox");
464 }
465 else if (TEXTURE_2D == eMode)
466 {
467 piSkyBoxEffect->SetTexture("TEXTURE_2D",pcTexture);
468 piSkyBoxEffect->SetTechnique("RenderImage2D");
469 }
470 }
471 };