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