diff options
Diffstat (limited to 'libs/assimp/tools/assimp_view/MessageProc.cpp')
-rw-r--r-- | libs/assimp/tools/assimp_view/MessageProc.cpp | 2434 |
1 files changed, 2434 insertions, 0 deletions
diff --git a/libs/assimp/tools/assimp_view/MessageProc.cpp b/libs/assimp/tools/assimp_view/MessageProc.cpp new file mode 100644 index 0000000..e51c829 --- /dev/null +++ b/libs/assimp/tools/assimp_view/MessageProc.cpp @@ -0,0 +1,2434 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2022, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "assimp_view.h" +#include <assimp/Exporter.hpp> +#include <algorithm> + +#include <windowsx.h> +#include <commdlg.h> + +#ifdef __MINGW32__ +# include <mmsystem.h> +#else +# include <timeapi.h> +#endif + +namespace AssimpView { + +using namespace Assimp; + +// Static array to keep custom color values +COLORREF g_aclCustomColors[16] = {0}; + +// Global registry key +HKEY g_hRegistry = nullptr; + +// list of previous files (always 5) +std::vector<std::string> g_aPreviousFiles; + +// history menu item +HMENU g_hHistoryMenu = nullptr; + +float g_fACMR = 3.0f; + +#define AI_VIEW_NUM_RECENT_FILES 0x8 +#define AI_VIEW_RECENT_FILE_ID(_n_) (5678 + _n_) + +#define AI_VIEW_EXPORT_FMT_BASE 7912 +#define AI_VIEW_EXPORT_FMT_ID(_n_) (AI_VIEW_EXPORT_FMT_BASE + _n_) + +void UpdateHistory(); +void SaveHistory(); + +//------------------------------------------------------------------------------- +// Setup file associations for all formats supported by the library +// +// File associations are registered in HKCU\Software\Classes. They might +// be overwritten by global file associations. +//------------------------------------------------------------------------------- +void MakeFileAssociations() { + char szTemp2[MAX_PATH]; + char szTemp[MAX_PATH + 10]; + + GetModuleFileName(nullptr,szTemp2,MAX_PATH); + sprintf(szTemp,"%s %%1",szTemp2); + + HKEY hRegistry = nullptr; + + aiString list, tmp; + aiGetExtensionList(&list); + tmp = list; + + const char* sz = strtok(list.data,";"); + do { + char buf[256]; + ai_assert(sz[0] == '*'); + sprintf(buf,"Software\\Classes\\%s",sz+1); + + RegCreateKeyEx(HKEY_CURRENT_USER,buf,0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); + RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)"ASSIMPVIEW_CLASS",(DWORD)strlen("ASSIMPVIEW_CLASS")+1); + RegCloseKey(hRegistry); + } while ((sz = strtok(nullptr,";")) != nullptr); + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); + RegCloseKey(hRegistry); + + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\Classes\\ASSIMPVIEW_CLASS\\shell\\open\\command",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); + RegSetValueEx(hRegistry,"",0,REG_SZ,(const BYTE*)szTemp,(DWORD)strlen(szTemp)+1); + RegCloseKey(hRegistry); + + CLogDisplay::Instance().AddEntry("[OK] File associations have been registered", + D3DCOLOR_ARGB(0xFF,0,0xFF,0)); + + CLogDisplay::Instance().AddEntry(tmp.data,D3DCOLOR_ARGB(0xFF,0,0xFF,0)); +} + +//------------------------------------------------------------------------------- +// Handle command line parameters +// +// The function loads an asset specified on the command line as first argument +// Other command line parameters are not handled +//------------------------------------------------------------------------------- +void HandleCommandLine(char* p_szCommand) { + char* sz = p_szCommand; + //bool bQuak = false; + + if (strlen(sz) < 2) { + return; + } + + if (*sz == '\"') { + char* sz2 = strrchr(sz,'\"'); + if (sz2)*sz2 = 0; + sz++; // skip the starting quote + } + + strcpy( g_szFileName, sz ); + LoadAsset(); + + // update the history + UpdateHistory(); + + // Save the list of previous files to the registry + SaveHistory(); +} + +//------------------------------------------------------------------------------- +// Load the light colors from the registry +//------------------------------------------------------------------------------- +void LoadLightColors() { + DWORD dwTemp = 4; + RegQueryValueEx(g_hRegistry,"LightColor0",nullptr,nullptr, (BYTE*)&g_avLightColors[0],&dwTemp); + RegQueryValueEx(g_hRegistry,"LightColor1",nullptr,nullptr, (BYTE*)&g_avLightColors[1],&dwTemp); + RegQueryValueEx(g_hRegistry,"LightColor2",nullptr,nullptr, (BYTE*)&g_avLightColors[2],&dwTemp); +} + +//------------------------------------------------------------------------------- +// Save the light colors to the registry +//------------------------------------------------------------------------------- +void SaveLightColors() { + RegSetValueExA(g_hRegistry,"LightColor0",0,REG_DWORD,(const BYTE*)&g_avLightColors[0],4); + RegSetValueExA(g_hRegistry,"LightColor1",0,REG_DWORD,(const BYTE*)&g_avLightColors[1],4); + RegSetValueExA(g_hRegistry,"LightColor2",0,REG_DWORD,(const BYTE*)&g_avLightColors[2],4); +} + +//------------------------------------------------------------------------------- +// Save the checker pattern colors to the registry +//------------------------------------------------------------------------------- +void SaveCheckerPatternColors() { + // we have it as float4. save it as binary value --. + RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), + sizeof(D3DXVECTOR3)); + + RegSetValueExA(g_hRegistry,"CheckerPattern1",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetSecondCheckerColor(), + sizeof(D3DXVECTOR3)); +} + +//------------------------------------------------------------------------------- +// Load the checker pattern colors from the registry +//------------------------------------------------------------------------------- +void LoadCheckerPatternColors() { + DWORD dwTemp = sizeof(D3DXVECTOR3); + RegQueryValueEx(g_hRegistry,"CheckerPattern0",nullptr,nullptr, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); + + RegQueryValueEx(g_hRegistry,"CheckerPattern1",nullptr,nullptr, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetSecondCheckerColor(),&dwTemp); +} + +//------------------------------------------------------------------------------- +// Changed pp setup +//------------------------------------------------------------------------------- +void UpdatePPSettings() { + DWORD dwValue = ppsteps; + RegSetValueExA(g_hRegistry,"PostProcessing",0,REG_DWORD,(const BYTE*)&dwValue,4); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "Display Normals" state +//------------------------------------------------------------------------------- +void ToggleNormals() { + g_sOptions.bRenderNormals = !g_sOptions.bRenderNormals; + + // store this in the registry, too + DWORD dwValue = 0; + if (g_sOptions.bRenderNormals)dwValue = 1; + RegSetValueExA(g_hRegistry,"RenderNormals",0,REG_DWORD,(const BYTE*)&dwValue,4); +} + +static void storeRegKey(bool option, LPCSTR name) { + // store this in the registry, too + DWORD dwValue = 0; + if (option) { + dwValue = 1; + } + RegSetValueExA(g_hRegistry, name, 0, REG_DWORD, (const BYTE*)&dwValue, 4); + +} +//------------------------------------------------------------------------------- +// Toggle the "AutoRotate" state +//------------------------------------------------------------------------------- +void ToggleAutoRotate() { + g_sOptions.bRotate = !g_sOptions.bRotate; + storeRegKey(g_sOptions.bRotate, "AutoRotate"); + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Toggle the "FPS" state +//------------------------------------------------------------------------------- +void ToggleFPSView() { + g_bFPSView = !g_bFPSView; + SetupFPSView(); + storeRegKey(g_bFPSView, "FPSView"); +} + +//------------------------------------------------------------------------------- +// Toggle the "2 Light sources" state +//------------------------------------------------------------------------------- +void ToggleMultipleLights() { + g_sOptions.b3Lights = !g_sOptions.b3Lights; + storeRegKey(g_sOptions.b3Lights, "MultipleLights"); +} + +//------------------------------------------------------------------------------- +// Toggle the "LightRotate" state +//------------------------------------------------------------------------------- +void ToggleLightRotate() { + g_sOptions.bLightRotate = !g_sOptions.bLightRotate; + storeRegKey(g_sOptions.bLightRotate, "LightRotate"); +} + +//------------------------------------------------------------------------------- +// Toggle the "NoTransparency" state +//------------------------------------------------------------------------------- +void ToggleTransparency() { + g_sOptions.bNoAlphaBlending = !g_sOptions.bNoAlphaBlending; + storeRegKey(g_sOptions.bNoAlphaBlending, "NoTransparency"); +} + +//------------------------------------------------------------------------------- +// Toggle the "LowQuality" state +//------------------------------------------------------------------------------- +void ToggleLowQuality() { + g_sOptions.bLowQuality = !g_sOptions.bLowQuality; + storeRegKey(g_sOptions.bLowQuality, "LowQuality"); +} + +//------------------------------------------------------------------------------- +// Toggle the "Specular" state +//------------------------------------------------------------------------------- +void ToggleSpecular() { + g_sOptions.bNoSpecular = !g_sOptions.bNoSpecular; + + storeRegKey(g_sOptions.bNoSpecular, "NoSpecular"); + + // update all specular materials + CMaterialManager::Instance().UpdateSpecularMaterials(); +} + +//------------------------------------------------------------------------------- +// Toggle the "RenderMats" state +//------------------------------------------------------------------------------- +void ToggleMats() { + g_sOptions.bRenderMats = !g_sOptions.bRenderMats; + + storeRegKey(g_sOptions.bRenderMats, "RenderMats"); + + // update all specular materials + CMaterialManager::Instance().UpdateSpecularMaterials(); +} + +//------------------------------------------------------------------------------- +// Toggle the "Culling" state +//------------------------------------------------------------------------------- +void ToggleCulling() { + g_sOptions.bCulling = !g_sOptions.bCulling; + storeRegKey(g_sOptions.bCulling, "Culling"); +} + +//------------------------------------------------------------------------------- +// Toggle the "Skeleton" state +//------------------------------------------------------------------------------- +void ToggleSkeleton() { + g_sOptions.bSkeleton = !g_sOptions.bSkeleton; + storeRegKey(g_sOptions.bSkeleton, "Skeleton"); +} + +//------------------------------------------------------------------------------- +// Toggle the "WireFrame" state +//------------------------------------------------------------------------------- +void ToggleWireFrame() { + if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME) { + g_sOptions.eDrawMode = RenderOptions::NORMAL; + } else { + g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + } + + storeRegKey(RenderOptions::WIREFRAME == g_sOptions.eDrawMode, "Wireframe"); +} + +//------------------------------------------------------------------------------- +// Toggle the "MultiSample" state +//------------------------------------------------------------------------------- +void ToggleMS() { + g_sOptions.bMultiSample = !g_sOptions.bMultiSample; + DeleteAssetData(); + ShutdownDevice(); + if (0 == CreateDevice()) { + CLogDisplay::Instance().AddEntry( + "[ERROR] Failed to toggle MultiSampling mode"); + g_sOptions.bMultiSample = !g_sOptions.bMultiSample; + CreateDevice(); + } + CreateAssetData(); + + if (g_sOptions.bMultiSample) { + CLogDisplay::Instance().AddEntry( + "[OK] Changed MultiSampling mode to the maximum value for this device"); + } else { + CLogDisplay::Instance().AddEntry( + "[OK] MultiSampling has been disabled"); + } + + storeRegKey(g_sOptions.bMultiSample, "MultiSampling"); +} + +//------------------------------------------------------------------------------- +// Expand or collapse the UI +//------------------------------------------------------------------------------- +void ToggleUIState() { + // adjust the size + RECT sRect; + GetWindowRect(g_hDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + if (BST_UNCHECKED == IsDlgButtonChecked(g_hDlg,IDC_BLUBB)) { + SetWindowPos(g_hDlg,nullptr,0,0,sRect.right-214,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); + storeRegKey(false, "MultiSampling"); + } else { + SetWindowPos(g_hDlg,nullptr,0,0,sRect.right+214,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + + storeRegKey(true, "LastUIState"); + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),"<<"); + } + UpdateWindow(g_hDlg); +} + +//------------------------------------------------------------------------------- +// Load the background texture for the viewer +//------------------------------------------------------------------------------- +void LoadBGTexture() { + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"TextureSrc",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { + // Key was not found. Use C: + strcpy(szFileName,""); + } else { + // need to remove the file name + char* sz = strrchr(szFileName,'\\'); + if (!sz) + sz = strrchr(szFileName,'/'); + if (sz) + *sz = 0; + } + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(nullptr), + "Textures\0*.png;*.dds;*.tga;*.bmp;*.tif;*.ppm;*.ppx;*.jpg;*.jpeg;*.exr\0*.*\0", + nullptr, 0, 1, + szFileName, MAX_PATH, nullptr, 0, nullptr, + "Open texture as background", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".jpg", 0, nullptr, nullptr + }; + if(GetOpenFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"TextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + CBackgroundPainter::Instance().SetTextureBG(szFileName); +} + +//------------------------------------------------------------------------------- +// Reset the background color to a smart and nice grey +//------------------------------------------------------------------------------- +void ClearBG() { + D3DCOLOR clrColor = D3DCOLOR_ARGB(0xFF,100,100,100); + CBackgroundPainter::Instance().SetColor(clrColor); + + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); +} + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DCOLOR* pclrResult) { + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB((*pclrResult >> 16) & 0xff,(*pclrResult >> 8) & 0xff,*pclrResult & 0xff); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = nullptr; + clr.lpTemplateName = nullptr; + clr.lCustData = 0; + + ChooseColor(&clr); + + *pclrResult = D3DCOLOR_ARGB(0xFF, + GetRValue(clr.rgbResult), + GetGValue(clr.rgbResult), + GetBValue(clr.rgbResult)); +} + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DXVECTOR4* pclrResult) { + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB(clamp<unsigned char>(pclrResult->x * 255.0f), + clamp<unsigned char>(pclrResult->y * 255.0f), + clamp<unsigned char>(pclrResult->z * 255.0f)); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = nullptr; + clr.lpTemplateName = nullptr; + clr.lCustData = 0; + + ChooseColor(&clr); + + pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; + pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; + pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; +} + +//------------------------------------------------------------------------------- +// Let the user choose the background color for the viewer +//------------------------------------------------------------------------------- +void ChooseBGColor() { + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + D3DCOLOR clrColor; + DisplayColorDialog(&clrColor); + CBackgroundPainter::Instance().SetColor(clrColor); + + RegSetValueExA(g_hRegistry,"Color",0,REG_DWORD,(const BYTE*)&clrColor,4); +} + +//------------------------------------------------------------------------------- +// Display the OpenFile dialog and let the user choose a new slybox as bg +//------------------------------------------------------------------------------- +void LoadSkybox() { + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"SkyBoxSrc",nullptr,nullptr, + (BYTE*)szFileName,&dwTemp)) + { + // Key was not found. Use C: + strcpy(szFileName,""); + } + else + { + // need to remove the file name + char* sz = strrchr(szFileName,'\\'); + if (!sz) + sz = strrchr(szFileName,'/'); + if (sz) + *sz = 0; + } + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(nullptr), + "Skyboxes\0*.dds\0*.*\0", nullptr, 0, 1, + szFileName, MAX_PATH, nullptr, 0, nullptr, + "Open skybox as background", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".dds", 0, nullptr, nullptr + }; + if(GetOpenFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"SkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastSkyBoxSrc",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + RegSetValueExA(g_hRegistry,"LastTextureSrc",0,REG_SZ,(const BYTE*)"",MAX_PATH); + + CBackgroundPainter::Instance().SetCubeMapBG(szFileName); + return; +} + +template<class T> +inline +void SaveRelease(T **iface ) { + if (nullptr != iface) { + (*iface)->Release(); + *iface = nullptr; + } +} + +//------------------------------------------------------------------------------- +// Save a screenshot to an user-defined file +//------------------------------------------------------------------------------- +void SaveScreenshot() { + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"ScreenShot",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { + // Key was not found. Use C: + strcpy(szFileName,""); + } else { + // need to remove the file name + char* sz = strrchr(szFileName,'\\'); + if (!sz) + sz = strrchr(szFileName,'/'); + if (sz) + *sz = 0; + } + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(nullptr), + "PNG Images\0*.png", nullptr, 0, 1, + szFileName, MAX_PATH, nullptr, 0, nullptr, + "Save Screenshot to file", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ".png", 0, nullptr, nullptr + }; + if(GetSaveFileName(&sFilename1) == 0) return; + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"ScreenShot",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + + IDirect3DSurface9* pi = nullptr; + g_piDevice->GetRenderTarget(0,&pi); + if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,D3DXIFF_PNG,pi,nullptr,nullptr))) { + CLogDisplay::Instance().AddEntry("[ERROR] Unable to save screenshot", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + } else { + CLogDisplay::Instance().AddEntry("[INFO] The screenshot has been saved", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } + SaveRelease(&pi); +} + +//------------------------------------------------------------------------------- +// Get the amount of memory required for textures +//------------------------------------------------------------------------------- +void AddTextureMem(IDirect3DTexture9* pcTex, unsigned int& out) { + if (!pcTex) { + return; + } + + D3DSURFACE_DESC sDesc; + pcTex->GetLevelDesc(0,&sDesc); + + out += (sDesc.Width * sDesc.Height) << 2; +} + +//------------------------------------------------------------------------------- +// Display memory statistics +//------------------------------------------------------------------------------- +void DisplayMemoryConsumption() { + // first get the memory consumption for the aiScene + if (! g_pcAsset ||!g_pcAsset->pcScene) { + MessageBox(g_hDlg,"No asset is loaded. Can you guess how much memory I need to store nothing?", + "Memory consumption",MB_OK); + return; + } + unsigned int iScene = sizeof(aiScene); + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { + iScene += sizeof(aiMesh); + if (g_pcAsset->pcScene->mMeshes[i]->HasPositions()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + + if (g_pcAsset->pcScene->mMeshes[i]->HasNormals()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + + if (g_pcAsset->pcScene->mMeshes[i]->HasTangentsAndBitangents()) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices * 2; + + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) { + if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors(a)) { + iScene += sizeof(aiColor4D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + } else { + break; + } + } + for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { + if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords(a)) + iScene += sizeof(aiVector3D) * g_pcAsset->pcScene->mMeshes[i]->mNumVertices; + else break; + } + if (g_pcAsset->pcScene->mMeshes[i]->HasBones()) { + for (unsigned int p = 0; p < g_pcAsset->pcScene->mMeshes[i]->mNumBones;++p) { + iScene += sizeof(aiBone); + iScene += g_pcAsset->pcScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight); + } + } + iScene += (sizeof(aiFace) + 3 * sizeof(unsigned int))*g_pcAsset->pcScene->mMeshes[i]->mNumFaces; + } + // add all embedded textures + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumTextures;++i) { + const aiTexture* pc = g_pcAsset->pcScene->mTextures[i]; + if (0 != pc->mHeight) { + iScene += 4 * pc->mHeight * pc->mWidth; + } else { + iScene += pc->mWidth; + } + } + // add 30k for each material ... a string has 4k for example + iScene += g_pcAsset->pcScene->mNumMaterials * 30 * 1024; + + // now get the memory consumption required by D3D, first all textures + unsigned int iTexture = 0; + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { + AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; + + AddTextureMem(pc->piDiffuseTexture,iTexture); + AddTextureMem(pc->piSpecularTexture,iTexture); + AddTextureMem(pc->piAmbientTexture,iTexture); + AddTextureMem(pc->piEmissiveTexture,iTexture); + AddTextureMem(pc->piOpacityTexture,iTexture); + AddTextureMem(pc->piNormalTexture,iTexture); + AddTextureMem(pc->piShininessTexture,iTexture); + } + unsigned int iVRAM = iTexture; + + // now get the memory consumption of all vertex/index buffers + unsigned int iVB( 0 ), iIB(0); + for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { + AssetHelper:: MeshHelper* pc = g_pcAsset->apcMeshes[i]; + + union{ + D3DVERTEXBUFFER_DESC sDesc; + D3DINDEXBUFFER_DESC sDesc2; + }; + + if (pc->piVB) + { + pc->piVB->GetDesc(&sDesc); + iVB += sDesc.Size; + } + if (pc->piVBNormals) + { + pc->piVBNormals->GetDesc(&sDesc); + iVB += sDesc.Size; + } + if (pc->piIB) + { + pc->piIB->GetDesc(&sDesc2); + iIB += sDesc2.Size; + } + } + iVRAM += iVB + iIB; + // add the memory for the back buffer and depth stencil buffer + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.bottom -= sRect.top; + sRect.right -= sRect.left; + iVRAM += sRect.bottom * sRect.right * 8; + + char szOut[2048]; + sprintf(szOut, + "(1 KiB = 1024 bytes)\n\n" + "ASSIMP Import Data: \t%i KiB\n" + "Texture data:\t\t%i KiB\n" + "Vertex buffers:\t\t%i KiB\n" + "Index buffers:\t\t%i KiB\n" + "Video Memory:\t\t%i KiB\n\n" + "Total: \t\t\t%i KiB", + iScene / 1024,iTexture / 1024,iVB / 1024,iIB / 1024,iVRAM / 1024, + (iScene + iTexture + iVB + iIB + iVRAM) / 1024); + MessageBox(g_hDlg,szOut,"Memory consumption",MB_OK); +} + +//------------------------------------------------------------------------------- +// Save the list of recent files to the registry +//------------------------------------------------------------------------------- +void SaveHistory() { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { + char szName[66]; + sprintf(szName,"Recent%i",i+1); + + RegSetValueEx(g_hRegistry,szName,0,REG_SZ, + (const BYTE*)g_aPreviousFiles[i].c_str(),(DWORD)g_aPreviousFiles[i].length()); + } +} + +//------------------------------------------------------------------------------- +// Recover the file history +//------------------------------------------------------------------------------- +void LoadHistory() { + g_aPreviousFiles.resize(AI_VIEW_NUM_RECENT_FILES); + + char szFileName[MAX_PATH]; + + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) { + char szName[66]; + sprintf(szName,"Recent%i",i+1); + + DWORD dwTemp = MAX_PATH; + + szFileName[0] ='\0'; + if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,szName,nullptr,nullptr, + (BYTE*)szFileName,&dwTemp)) { + g_aPreviousFiles[i] = std::string(szFileName); + } + } + + // add sub items for all recent files + g_hHistoryMenu = CreateMenu(); + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { + const char* szText = g_aPreviousFiles[i].c_str(); + UINT iFlags = 0; + if ('\0' == *szText) { + szText = "<empty>"; + iFlags = MF_GRAYED | MF_DISABLED; + } + AppendMenu(g_hHistoryMenu,MF_STRING | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); + } + + ModifyMenu(GetMenu(g_hDlg),ID_VIEWER_RECENTFILES,MF_BYCOMMAND | MF_POPUP, + (UINT_PTR)g_hHistoryMenu,"Recent files"); +} + +//------------------------------------------------------------------------------- +// Clear the file history +//------------------------------------------------------------------------------- +void ClearHistory() { + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES; ++i) { + g_aPreviousFiles[i] = std::string(""); + } + + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { + ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), + MF_STRING | MF_BYCOMMAND | MF_GRAYED | MF_DISABLED,AI_VIEW_RECENT_FILE_ID(i),"<empty>"); + } + + SaveHistory(); +} + +//------------------------------------------------------------------------------- +// Update the file history +//------------------------------------------------------------------------------- +void UpdateHistory() { + if (!g_hHistoryMenu) { + return; + } + + std::string sz = std::string(g_szFileName); + if (g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES - 1] == sz) { + return; + } + + // add the new asset to the list of recent files + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES-1;++i) { + g_aPreviousFiles[i] = g_aPreviousFiles[i+1]; + } + g_aPreviousFiles[AI_VIEW_NUM_RECENT_FILES-1] = sz; + for (int i = AI_VIEW_NUM_RECENT_FILES-1; i >= 0;--i) { + const char* szText = g_aPreviousFiles[i].c_str(); + UINT iFlags = 0; + if ('\0' == *szText) { + szText = "<empty>"; + iFlags = MF_GRAYED | MF_DISABLED; + } + ModifyMenu(g_hHistoryMenu,AI_VIEW_RECENT_FILE_ID(i), + MF_STRING | MF_BYCOMMAND | iFlags,AI_VIEW_RECENT_FILE_ID(i),szText); + } +} + +//------------------------------------------------------------------------------- +// Open a new asset +//------------------------------------------------------------------------------- +void OpenAsset() { + char szFileName[MAX_PATH]; + + DWORD dwTemp = MAX_PATH; + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"CurrentApp",nullptr,nullptr, (BYTE*)szFileName,&dwTemp)) { + // Key was not found. Use C: + strcpy(szFileName,""); + } else { + // need to remove the file name + char* sz = strrchr(szFileName,'\\'); + if (!sz) + sz = strrchr(szFileName,'/'); + if (sz) + *sz = 0; + } + + // get a list of all file extensions supported by ASSIMP + aiString sz; + aiGetExtensionList(&sz); + + char szList[MAXLEN + 100]; + strcpy(szList,"ASSIMP assets"); + char* szCur = szList + 14; + strcpy(szCur,sz.data); + szCur += sz.length+1; + strcpy(szCur,"All files"); + szCur += 10; + strcpy(szCur,"*.*"); + szCur[4] = 0; + + OPENFILENAME sFilename1; + ZeroMemory(&sFilename1, sizeof(sFilename1)); + sFilename1.lStructSize = sizeof(sFilename1); + sFilename1.hwndOwner = g_hDlg; + sFilename1.hInstance = GetModuleHandle(nullptr); + sFilename1.lpstrFile = szFileName; + sFilename1.lpstrFile[0] = '\0'; + sFilename1.nMaxFile = sizeof(szList); + sFilename1.lpstrFilter = szList; + sFilename1.nFilterIndex = 1; + sFilename1.lpstrFileTitle = nullptr; + sFilename1.nMaxFileTitle = 0; + sFilename1.lpstrInitialDir = nullptr; + sFilename1.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + if (GetOpenFileName(&sFilename1) == 0) { + return; + } + + // Now store the file in the registry + RegSetValueExA(g_hRegistry,"CurrentApp",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + + if (0 != strcmp(g_szFileName,szFileName)) { + strcpy(g_szFileName, szFileName); + DeleteAssetData(); + DeleteAsset(); + LoadAsset(); + + // update the history + UpdateHistory(); + + // Save the list of previous files to the registry + SaveHistory(); + } +} + +//------------------------------------------------------------------------------- +void SetupPPUIState() { + // that's ugly. anyone willing to rewrite me from scratch? + HMENU hMenu = GetMenu(g_hDlg); + CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT +//------------------------------------------------------------------------------- +// Fill the 'export' top level menu with a list of all supported export formats +//------------------------------------------------------------------------------- +void PopulateExportMenu() { + // add sub items for all recent files + Exporter exp; + HMENU hm = ::CreateMenu(); + for(size_t i = 0; i < exp.GetExportFormatCount(); ++i) { + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(i); + char tmp[256]; + sprintf(tmp,"%s (%s)",e->description,e->id); + + AppendMenu(hm,MF_STRING,AI_VIEW_EXPORT_FMT_ID(i),tmp); + } + + ModifyMenu(GetMenu(g_hDlg),ID_EXPORT,MF_BYCOMMAND | MF_POPUP, + (UINT_PTR)hm,"Export"); +} + +//------------------------------------------------------------------------------- +// Export function +//------------------------------------------------------------------------------- +void DoExport(size_t formatId) { + if (!g_szFileName[0]) { + MessageBox(g_hDlg, "No model loaded", "Export", MB_ICONERROR); + return; + } + Exporter exp; + const aiExportFormatDesc* const e = exp.GetExportFormatDescription(formatId); + ai_assert(e); + + char szFileName[MAX_PATH*2]; + DWORD dwTemp = sizeof(szFileName); + if(ERROR_SUCCESS == RegQueryValueEx(g_hRegistry,"ModelExportDest",nullptr,nullptr,(BYTE*)szFileName, &dwTemp)) { + ai_assert(strlen(szFileName) <= MAX_PATH); + + // invent a nice default file name + char* sz = std::max(strrchr(szFileName,'\\'),strrchr(szFileName,'/')); + if (sz) { + strncpy(sz,std::max(strrchr(g_szFileName,'\\'),strrchr(g_szFileName,'/')),MAX_PATH); + } + } + else { + // Key was not found. Use the folder where the asset comes from + strncpy(szFileName,g_szFileName,MAX_PATH); + } + + // fix file extension + { char * const sz = strrchr(szFileName,'.'); + if(sz) { + ai_assert((sz - &szFileName[0]) + strlen(e->fileExtension) + 1 <= MAX_PATH); + strcpy(sz+1,e->fileExtension); + } + } + + // build the stupid info string for GetSaveFileName() - can't use sprintf() because the string must contain binary zeros. + char desc[256] = {0}; + char* c = strcpy(desc,e->description) + strlen(e->description)+1; + c += sprintf(c,"*.%s",e->fileExtension)+1; + strcpy(c, "*.*\0"); c += 4; + + ai_assert(c - &desc[0] <= 256); + + const std::string ext = "."+std::string(e->fileExtension); + OPENFILENAME sFilename1 = { + sizeof(OPENFILENAME), + g_hDlg,GetModuleHandle(nullptr), + desc, nullptr, 0, 1, + szFileName, MAX_PATH, nullptr, 0, nullptr, + "Export asset", + OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + 0, 1, ext.c_str(), 0, nullptr, nullptr + }; + if(::GetSaveFileName(&sFilename1) == 0) { + return; + } + + // Now store the file in the registry unless the user decided to stay in the model directory + const std::string sFinal = szFileName, sub = sFinal.substr(0,sFinal.find_last_of("\\/")); + if (strncmp(sub.c_str(),g_szFileName,sub.length())) { + RegSetValueExA(g_hRegistry,"ModelExportDest",0,REG_SZ,(const BYTE*)szFileName,MAX_PATH); + } + + // export the file + const aiReturn res = exp.Export(g_pcAsset->pcScene,e->id,sFinal.c_str(), + ppsteps | /* configurable pp steps */ + aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing + aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes + aiProcess_Triangulate | // triangulate polygons with more than 3 edges + aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space + aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives + 0 + ); + if (res == aiReturn_SUCCESS) { + CLogDisplay::Instance().AddEntry("[INFO] Exported file " + sFinal,D3DCOLOR_ARGB(0xFF,0x00,0xFF,0x00)); + return; + } + CLogDisplay::Instance().AddEntry("[INFO] Failure exporting file " + + sFinal,D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00)); +} +#endif + +//------------------------------------------------------------------------------- +// Initialize the user interface +//------------------------------------------------------------------------------- +void InitUI() { + SetDlgItemText(g_hDlg,IDC_EVERT,"0"); + SetDlgItemText(g_hDlg,IDC_EFACE,"0"); + SetDlgItemText(g_hDlg,IDC_EMAT,"0"); + SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); + SetDlgItemText(g_hDlg,IDC_ENODEWND,"0"); + SetDlgItemText(g_hDlg,IDC_ETEX,"0"); + SetDlgItemText(g_hDlg,IDC_EMESH,"0"); + +#ifndef ASSIMP_BUILD_NO_EXPORT + PopulateExportMenu(); +#endif + + // setup the default window title + SetWindowText(g_hDlg,AI_VIEW_CAPTION_BASE); + + // read some UI properties from the registry and apply them + DWORD dwValue; + DWORD dwTemp = sizeof( DWORD ); + + // store the key in a global variable for later use + RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ASSIMP\\Viewer", + 0,nullptr,0,KEY_ALL_ACCESS, nullptr, &g_hRegistry,nullptr); + + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LastUIState",nullptr,nullptr, (BYTE*)&dwValue,&dwTemp)) { + dwValue = 1; + } + if (0 == dwValue) { + // collapse the viewer + // adjust the size + RECT sRect; + GetWindowRect(g_hDlg,&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + RECT sRect2; + GetWindowRect(GetDlgItem ( g_hDlg, IDC_BLUBB ),&sRect2); + sRect2.left -= sRect.left; + sRect2.top -= sRect.top; + + SetWindowPos(g_hDlg,nullptr,0,0,sRect.right-214,sRect.bottom, + SWP_NOMOVE | SWP_NOZORDER); + SetWindowText(GetDlgItem(g_hDlg,IDC_BLUBB),">>"); + } else { + CheckDlgButton(g_hDlg,IDC_BLUBB,BST_CHECKED); + } + + // AutoRotate + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"AutoRotate",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.bRotate = false; + CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_UNCHECKED); + } else { + g_sOptions.bRotate = true; + CheckDlgButton(g_hDlg,IDC_AUTOROTATE,BST_CHECKED); + } + + // MultipleLights + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultipleLights",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.b3Lights = false; + CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_UNCHECKED); + } else { + g_sOptions.b3Lights = true; + CheckDlgButton(g_hDlg,IDC_3LIGHTS,BST_CHECKED); + } + + // Light rotate + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LightRotate",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.bLightRotate = false; + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_UNCHECKED); + } else { + g_sOptions.bLightRotate = true; + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE,BST_CHECKED); + } + + // NoSpecular + if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "NoSpecular", nullptr, nullptr, (BYTE*)&dwValue, &dwTemp)) { + dwValue = 0; + } + if (0 == dwValue) { + g_sOptions.bNoSpecular = false; + CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_UNCHECKED); + } else { + g_sOptions.bNoSpecular = true; + CheckDlgButton(g_hDlg,IDC_NOSPECULAR,BST_CHECKED); + } + + // LowQuality + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"LowQuality",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.bLowQuality = false; + CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_UNCHECKED); + } else { + g_sOptions.bLowQuality = true; + CheckDlgButton(g_hDlg,IDC_LOWQUALITY,BST_CHECKED); + } + + // LowQuality + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"NoTransparency",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.bNoAlphaBlending = false; + CheckDlgButton(g_hDlg,IDC_NOAB,BST_UNCHECKED); + } else { + g_sOptions.bNoAlphaBlending = true; + CheckDlgButton(g_hDlg,IDC_NOAB,BST_CHECKED); + } + + // DisplayNormals + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"RenderNormals",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_sOptions.bRenderNormals = false; + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_UNCHECKED); + } else { + g_sOptions.bRenderNormals = true; + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS,BST_CHECKED); + } + + // NoMaterials + if (ERROR_SUCCESS != RegQueryValueEx(g_hRegistry, "RenderMats", nullptr, nullptr, + (BYTE*)&dwValue, &dwTemp)) { + dwValue = 1; + } + if (0 == dwValue) { + g_sOptions.bRenderMats = false; + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_CHECKED); + } else { + g_sOptions.bRenderMats = true; + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT,BST_UNCHECKED); + } + + // MultiSampling + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"MultiSampling",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 1; + if (0 == dwValue) + { + g_sOptions.bMultiSample = false; + CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_UNCHECKED); + } else { + g_sOptions.bMultiSample = true; + CheckDlgButton(g_hDlg,IDC_TOGGLEMS,BST_CHECKED); + } + + // FPS Mode + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"FPSView",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) { + g_bFPSView = false; + CheckDlgButton(g_hDlg,IDC_ZOOM,BST_CHECKED); + } else { + g_bFPSView = true; + CheckDlgButton(g_hDlg,IDC_ZOOM,BST_UNCHECKED); + } + + // WireFrame + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"Wireframe",nullptr,nullptr, + (BYTE*)&dwValue,&dwTemp))dwValue = 0; + if (0 == dwValue) + { + g_sOptions.eDrawMode = RenderOptions::NORMAL; + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_UNCHECKED); + } + else + { + g_sOptions.eDrawMode = RenderOptions::WIREFRAME; + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_CHECKED); + } + + if(ERROR_SUCCESS != RegQueryValueEx(g_hRegistry,"PostProcessing",nullptr,nullptr,(BYTE*)&dwValue,&dwTemp)) + ppsteps = ppstepsdefault; + else ppsteps = dwValue; + + SetupPPUIState(); + LoadCheckerPatternColors(); + + SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMIN,TRUE,0); + SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETRANGEMAX,TRUE,10000); +} + +//------------------------------------------------------------------------------- +// Message procedure for the smooth normals dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) { + case WM_INITDIALOG: + { + char s[30]; + ::sprintf(s, "%.2f", g_smoothAngle); + SetDlgItemText(hwndDlg, IDC_EDITSM, s); + } + return TRUE; + + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + { + if (IDOK == LOWORD(wParam)) { + char s[30]; + GetDlgItemText(hwndDlg, IDC_EDITSM, s, 30); + g_smoothAngle = (float)atof(s); + + EndDialog(hwndDlg, 0); + } else if (IDCANCEL == LOWORD(wParam)) { + EndDialog(hwndDlg, 1); + } + } + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------------- +// Main message procedure of the application +// +// The function handles all incoming messages for the main window. +// However, if does not directly process input commands. +// NOTE: Due to the impossibility to process WM_CHAR messages in dialogs +// properly the code for all hotkeys has been moved to the WndMain +//------------------------------------------------------------------------------- +INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, WPARAM wParam,LPARAM lParam) { + UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(wParam); + + int xPos,yPos; + int xPos2,yPos2; + int fHalfX; + int fHalfY; + + TRACKMOUSEEVENT sEvent; + switch (uMsg) + { + case WM_INITDIALOG: + + g_hDlg = hwndDlg; + + // load the state of the user interface + InitUI(); + + // load the file history + LoadHistory(); + + // load the current color of the lights + LoadLightColors(); + return TRUE; + + case WM_HSCROLL: + + // XXX quick and dirty fix for #3029892 + if (GetDlgItem(g_hDlg, IDC_SLIDERANIM) == (HWND)lParam && g_pcAsset && g_pcAsset->pcScene->mAnimations) + { + double num = (double)SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_GETPOS,0,0); + const aiAnimation* anim = g_pcAsset->pcScene->mAnimations[ g_pcAsset->mAnimator->CurrentAnimIndex() ]; + + g_dCurrent = (anim->mDuration/anim->mTicksPerSecond) * num/10000; + g_pcAsset->mAnimator->Calculate(g_dCurrent); + } + break; + + case WM_MOUSEWHEEL: + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetTextureViewZoom ( GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f ); + } + else + { + if (!g_bFPSView) + { + g_sCamera.vPos.z += GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f; + } + else + { + g_sCamera.vPos += (GET_WHEEL_DELTA_WPARAM(wParam) / 50.0f) * + g_sCamera.vLookAt.Normalize(); + } + } + return TRUE; + + case WM_MOUSELEAVE: + + g_bMousePressed = false; + g_bMousePressedR = false; + g_bMousePressedM = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_LBUTTONDBLCLK: + + CheckDlgButton(hwndDlg,IDC_AUTOROTATE, + IsDlgButtonChecked(hwndDlg,IDC_AUTOROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleAutoRotate(); + return TRUE; + + + case WM_CLOSE: + PostQuitMessage(0); + DestroyWindow(hwndDlg); + return TRUE; + + case WM_NOTIFY: + + if (IDC_TREE1 == wParam) + { + NMTREEVIEW* pnmtv = (LPNMTREEVIEW) lParam; + + if (TVN_SELCHANGED == pnmtv->hdr.code) + CDisplay::Instance().OnSetup( pnmtv->itemNew.hItem ); + else if (NM_RCLICK == pnmtv->hdr.code) + { + // determine in which item the click was ... + POINT sPoint; + GetCursorPos(&sPoint); + ScreenToClient(GetDlgItem(g_hDlg,IDC_TREE1),&sPoint); + + TVHITTESTINFO sHit; + sHit.pt = sPoint; + TreeView_HitTest(GetDlgItem(g_hDlg,IDC_TREE1),&sHit); + CDisplay::Instance().ShowTreeViewContextMenu(sHit.hItem); + } + } + return TRUE; + + case WM_DRAWITEM: + { + // draw the two light colors + DRAWITEMSTRUCT* pcStruct = (DRAWITEMSTRUCT*)lParam; + + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + sRect.left = sRect.top = 0; + + bool bDraw = false; + + if(IDC_LCOLOR1 == pcStruct->CtlID) + { + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f); + szText = "Background #0"; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[0]) & 0xFF); + szText = "Light #0"; + } + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + + FillRect(pcStruct->hDC,&sRect,hbr); + + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,szText, static_cast<int>(strlen(szText))); + bDraw = true; + } + else if(IDC_LCOLOR2 == pcStruct->CtlID) + { + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f); + szText = "Background #1"; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[1]) & 0xFF); + szText = "Light #1"; + } + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + FillRect(pcStruct->hDC,&sRect,hbr); + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,szText, static_cast<int>(strlen(szText))); + bDraw = true; + } + else if(IDC_LCOLOR3 == pcStruct->CtlID) + { + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = g = b = 0; + szText = ""; + } + else if (!g_pcAsset) + { + r = g = b = 150;szText = ""; + } + else + { + r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[2]) & 0xFF); + szText = "Ambient"; + } + HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); + FillRect(pcStruct->hDC,&sRect,hbr); + + SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); + SetBkMode(pcStruct->hDC,TRANSPARENT); + TextOut(pcStruct->hDC,4,1,szText,static_cast<int>(strlen(szText))); + bDraw = true; + } + // draw the black border around the rects + if (bDraw) + { + SetBkColor(pcStruct->hDC,RGB(0,0,0)); + MoveToEx(pcStruct->hDC,0,0,nullptr); + LineTo(pcStruct->hDC,sRect.right-1,0); + LineTo(pcStruct->hDC,sRect.right-1,sRect.bottom-1); + LineTo(pcStruct->hDC,0,sRect.bottom-1); + LineTo(pcStruct->hDC,0,0); + } + } + return TRUE; + + case WM_DESTROY: + + // close the open registry key + RegCloseKey(g_hRegistry); + return TRUE; + + case WM_LBUTTONDOWN: + g_bMousePressed = true; + + // register a mouse track handler to be sure we'll know + // when the mouse leaves the display view again + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + + if (g_bMousePressedR) + { + g_bMousePressed = false; + g_bMousePressedR = false; + g_bMousePressedBoth = true; + return TRUE; + } + + // need to determine the position of the mouse and the + // distance from the center + //xPos = (int)(short)LOWORD(lParam); + //yPos = (int)(short)HIWORD(lParam); + + POINT sPoint; + GetCursorPos(&sPoint); + ScreenToClient(GetDlgItem(g_hDlg,IDC_RT),&sPoint); + xPos = xPos2 = sPoint.x; + yPos = yPos2 = sPoint.y; + + RECT sRect; + GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect); + sRect.right -= sRect.left; + sRect.bottom -= sRect.top; + + // if the mouse click was inside the viewer panel + // give the focus to it + if (xPos > 0 && xPos < sRect.right && yPos > 0 && yPos < sRect.bottom) + { + SetFocus(GetDlgItem(g_hDlg,IDC_RT)); + } + + // g_bInvert stores whether the mouse has started on the negative + // x or on the positive x axis of the imaginary coordinate system + // with origin p at the center of the HUD texture + xPos -= sRect.right/2; + yPos -= sRect.bottom/2; + + if (xPos > 0)g_bInvert = true; + else g_bInvert = false; + + D3DSURFACE_DESC sDesc; + g_pcTexture->GetLevelDesc(0,&sDesc); + + fHalfX = (int)(((float)sRect.right-(float)sDesc.Width) / 2.0f); + fHalfY = (int)(((float)sRect.bottom-(float)sDesc.Height) / 2.0f); + + // Determine the input operation to perform for this position + g_eClick = EClickPos_Outside; + if (xPos2 >= fHalfX && xPos2 < fHalfX + (int)sDesc.Width && + yPos2 >= fHalfY && yPos2 < fHalfY + (int)sDesc.Height && + nullptr != g_szImageMask) + { + // inside the texture. Lookup the grayscale value from it + xPos2 -= fHalfX; + yPos2 -= fHalfY; + + unsigned char chValue = g_szImageMask[xPos2 + yPos2 * sDesc.Width]; + if (chValue > 0xFF-20) + { + g_eClick = EClickPos_Circle; + } + else if (chValue < 0xFF-20 && chValue > 185) + { + g_eClick = EClickPos_CircleHor; + } + else if (chValue > 0x10 && chValue < 185) + { + g_eClick = EClickPos_CircleVert; + } + } + return TRUE; + + case WM_RBUTTONDOWN: + g_bMousePressedR = true; + + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + + if (g_bMousePressed) + { + g_bMousePressedR = false; + g_bMousePressed = false; + g_bMousePressedBoth = true; + } + + return TRUE; + + case WM_MBUTTONDOWN: + + + g_bMousePressedM = true; + + sEvent.cbSize = sizeof(TRACKMOUSEEVENT); + sEvent.dwFlags = TME_LEAVE; + sEvent.hwndTrack = g_hDlg; + sEvent.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&sEvent); + return TRUE; + + case WM_LBUTTONUP: + g_bMousePressed = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_RBUTTONUP: + g_bMousePressedR = false; + g_bMousePressedBoth = false; + return TRUE; + + case WM_MBUTTONUP: + g_bMousePressedM = false; + return TRUE; + + case WM_DROPFILES: + { + HDROP hDrop = (HDROP)wParam; + char szFile[MAX_PATH]; + DragQueryFile(hDrop,0,szFile,sizeof(szFile)); + const char* sz = strrchr(szFile,'.'); + if (!sz) { + sz = szFile; + } + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) { + // replace the selected texture with the new one ... + CDisplay::Instance().ReplaceCurrentTexture(szFile); + } else { + // check whether it is a typical texture file format ... + ++sz; + if (0 == ASSIMP_stricmp(sz,"png") || + 0 == ASSIMP_stricmp(sz,"bmp") || + 0 == ASSIMP_stricmp(sz,"jpg") || + 0 == ASSIMP_stricmp(sz,"tga") || + 0 == ASSIMP_stricmp(sz,"tif") || + 0 == ASSIMP_stricmp(sz,"hdr") || + 0 == ASSIMP_stricmp(sz,"ppm") || + 0 == ASSIMP_stricmp(sz,"pfm")) + { + CBackgroundPainter::Instance().SetTextureBG(szFile); + } + else if (0 == Assimp::ASSIMP_stricmp(sz,"dds")) + { + // DDS files could contain skyboxes, but they could also + // contain normal 2D textures. The easiest way to find this + // out is to open the file and check the header ... + FILE* pFile = fopen(szFile,"rb"); + if (!pFile) + return TRUE; + + // header of a dds file (begin) + /* + DWORD dwMagic + DWORD dwSize + DWORD dwFlags + DWORD dwHeight + DWORD dwWidth + DWORD dwPitchOrLinearSize + DWORD dwDepth + DWORD dwMipMapCount -> total with this: 32 + DWORD dwReserved1[11] -> total with this: 76 + DDPIXELFORMAT ddpfPixelFormat -> total with this: 108 + DWORD dwCaps1; -> total with this: 112 + DWORD dwCaps2; ---< here we are! + */ + DWORD dwCaps = 0; + fseek(pFile,112,SEEK_SET); + fread(&dwCaps,4,1,pFile); + + if (dwCaps & 0x00000400L /* DDSCAPS2_CUBEMAP_POSITIVEX */) { + CLogDisplay::Instance().AddEntry( + "[INFO] Assuming this dds file is a skybox ...", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + + CBackgroundPainter::Instance().SetCubeMapBG(szFile); + } else { + CBackgroundPainter::Instance().SetTextureBG(szFile); + } + fclose(pFile); + } else { + strcpy(g_szFileName,szFile); + + DeleteAsset(); + LoadAsset(); + UpdateHistory(); + SaveHistory(); + } + } + DragFinish(hDrop); + } + return TRUE; + + case WM_COMMAND: + HMENU hMenu = GetMenu(g_hDlg); + if (ID_VIEWER_QUIT == LOWORD(wParam)) { + PostQuitMessage(0); + DestroyWindow(hwndDlg); + } else if (IDC_COMBO1 == LOWORD(wParam)) { + if(HIWORD(wParam) == CBN_SELCHANGE) { + const size_t sel = static_cast<size_t>(ComboBox_GetCurSel(GetDlgItem(hwndDlg,IDC_COMBO1))); + if(g_pcAsset) { + g_pcAsset->mAnimator->SetAnimIndex(sel); + SendDlgItemMessage(hwndDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,0); + } + } + } else if (ID_VIEWER_RESETVIEW == LOWORD(wParam)) { + g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f); + g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f); + g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f); + g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f); + g_mWorldRotate = aiMatrix4x4(); + g_mWorld = aiMatrix4x4(); + + // don't forget to reset the st + CBackgroundPainter::Instance().ResetSB(); + } else if (ID__HELP == LOWORD(wParam)) { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_AVHELP), + hwndDlg,&HelpDialogProc); + } else if (ID__ABOUT == LOWORD(wParam)) { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_ABOUTBOX), + hwndDlg,&AboutMessageProc); + } else if (ID_TOOLS_LOGWINDOW == LOWORD(wParam)) { + CLogWindow::Instance().Show(); + } else if (ID__WEBSITE == LOWORD(wParam)) { + ShellExecute(nullptr,"open","http://assimp.sourceforge.net","","",SW_SHOW); + } else if (ID__WEBSITESF == LOWORD(wParam)) { + ShellExecute(nullptr,"open","https://sourceforge.net/projects/assimp","","",SW_SHOW); + } else if (ID_REPORTBUG == LOWORD(wParam)) { + ShellExecute(nullptr,"open","https://sourceforge.net/tracker/?func=add&group_id=226462&atid=1067632","","",SW_SHOW); + } else if (ID_FR == LOWORD(wParam)) { + ShellExecute(nullptr,"open","https://sourceforge.net/forum/forum.php?forum_id=817653","","",SW_SHOW); + } else if (ID_TOOLS_CLEARLOG == LOWORD(wParam)) { + CLogWindow::Instance().Clear(); + } else if (ID_TOOLS_SAVELOGTOFILE == LOWORD(wParam)) { + CLogWindow::Instance().Save(); + } else if (ID_VIEWER_MEMORYCONSUMATION == LOWORD(wParam)) { + DisplayMemoryConsumption(); + } else if (ID_VIEWER_H == LOWORD(wParam)) { + MakeFileAssociations(); + } else if (ID_BACKGROUND_CLEAR == LOWORD(wParam)) { + ClearBG(); + } else if (ID_BACKGROUND_SETCOLOR == LOWORD(wParam)) { + ChooseBGColor(); + } else if (ID_BACKGROUND_LOADTEXTURE == LOWORD(wParam)) { + LoadBGTexture(); + } else if (ID_BACKGROUND_LOADSKYBOX == LOWORD(wParam)) { + LoadSkybox(); + } else if (ID_VIEWER_SAVESCREENSHOTTOFILE == LOWORD(wParam)) { + SaveScreenshot(); + } else if (ID_VIEWER_OPEN == LOWORD(wParam)) { + OpenAsset(); + } else if (ID_TOOLS_FLIPNORMALS == LOWORD(wParam)) { + if (g_pcAsset && g_pcAsset->pcScene) { + g_pcAsset->FlipNormals(); + } + } + // this is ugly. anyone willing to rewrite it from scratch using wxwidgets or similar? + else if (ID_VIEWER_PP_JIV == LOWORD(wParam)) { + ppsteps ^= aiProcess_JoinIdenticalVertices; + CheckMenuItem(hMenu,ID_VIEWER_PP_JIV,ppsteps & aiProcess_JoinIdenticalVertices ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } else if (ID_VIEWER_PP_CTS == LOWORD(wParam)) { + ppsteps ^= aiProcess_CalcTangentSpace; + CheckMenuItem(hMenu,ID_VIEWER_PP_CTS,ppsteps & aiProcess_CalcTangentSpace ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } else if (ID_VIEWER_PP_FD == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindDegenerates; + CheckMenuItem(hMenu,ID_VIEWER_PP_FD,ppsteps & aiProcess_FindDegenerates ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } else if (ID_VIEWER_PP_FID == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindInvalidData; + CheckMenuItem(hMenu,ID_VIEWER_PP_FID,ppsteps & aiProcess_FindInvalidData ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FIM == LOWORD(wParam)) { + ppsteps ^= aiProcess_FindInstances; + CheckMenuItem(hMenu,ID_VIEWER_PP_FIM,ppsteps & aiProcess_FindInstances ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_FIN == LOWORD(wParam)) { + ppsteps ^= aiProcess_FixInfacingNormals; + CheckMenuItem(hMenu,ID_VIEWER_PP_FIN,ppsteps & aiProcess_FixInfacingNormals ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_GUV == LOWORD(wParam)) { + ppsteps ^= aiProcess_GenUVCoords; + CheckMenuItem(hMenu,ID_VIEWER_PP_GUV,ppsteps & aiProcess_GenUVCoords ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_ICL == LOWORD(wParam)) { + ppsteps ^= aiProcess_ImproveCacheLocality; + CheckMenuItem(hMenu,ID_VIEWER_PP_ICL,ppsteps & aiProcess_ImproveCacheLocality ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_OG == LOWORD(wParam)) { + if (ppsteps & aiProcess_PreTransformVertices) { + CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Pretransform Vertices\'"); + } + else { + ppsteps ^= aiProcess_OptimizeGraph; + CheckMenuItem(hMenu,ID_VIEWER_PP_OG,ppsteps & aiProcess_OptimizeGraph ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + } + else if (ID_VIEWER_PP_OM == LOWORD(wParam)) { + ppsteps ^= aiProcess_OptimizeMeshes; + CheckMenuItem(hMenu,ID_VIEWER_PP_OM,ppsteps & aiProcess_OptimizeMeshes ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_PTV == LOWORD(wParam)) { + if (ppsteps & aiProcess_OptimizeGraph) { + CLogDisplay::Instance().AddEntry("[ERROR] This setting is incompatible with \'Optimize Scenegraph\'"); + } + else { + ppsteps ^= aiProcess_PreTransformVertices; + CheckMenuItem(hMenu,ID_VIEWER_PP_PTV,ppsteps & aiProcess_PreTransformVertices ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + } + else if (ID_VIEWER_PP_RRM2 == LOWORD(wParam)) { + ppsteps ^= aiProcess_RemoveRedundantMaterials; + CheckMenuItem(hMenu,ID_VIEWER_PP_RRM2,ppsteps & aiProcess_RemoveRedundantMaterials ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_TUV == LOWORD(wParam)) { + ppsteps ^= aiProcess_TransformUVCoords; + CheckMenuItem(hMenu,ID_VIEWER_PP_TUV,ppsteps & aiProcess_TransformUVCoords ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_DB == LOWORD(wParam)) { + ppsteps ^= aiProcess_Debone; + CheckMenuItem(hMenu,ID_VIEWER_PP_DB,ppsteps & aiProcess_Debone ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_PP_VDS == LOWORD(wParam)) { + ppsteps ^= aiProcess_ValidateDataStructure; + CheckMenuItem(hMenu,ID_VIEWER_PP_VDS,ppsteps & aiProcess_ValidateDataStructure ? MF_CHECKED : MF_UNCHECKED); + UpdatePPSettings(); + } + else if (ID_VIEWER_RELOAD == LOWORD(wParam)) + { + DeleteAsset(); + LoadAsset(); + } + else if (ID_IMPORTSETTINGS_RESETTODEFAULT == LOWORD(wParam)) + { + ppsteps = ppstepsdefault; + UpdatePPSettings(); + SetupPPUIState(); + } + else if (ID_IMPORTSETTINGS_OPENPOST == LOWORD(wParam)) + { + ShellExecute(nullptr,"open","http://assimp.sourceforge.net/lib_html/ai_post_process_8h.html","","",SW_SHOW); + } + else if (ID_TOOLS_ORIGINALNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::ORIGINAL); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + } + } + + else if (ID_TOOLS_SMOOTHNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::SMOOTH); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_CHECKED); + } + } + else if (ID_TOOLS_HARDNORMALS == LOWORD(wParam)) + { + if (g_pcAsset && g_pcAsset->pcScene) + { + g_pcAsset->SetNormalSet(AssimpView::AssetHelper::HARD); + CheckMenuItem(hMenu,ID_TOOLS_ORIGINALNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + CheckMenuItem(hMenu,ID_TOOLS_HARDNORMALS,MF_BYCOMMAND | MF_CHECKED); + CheckMenuItem(hMenu,ID_TOOLS_SMOOTHNORMALS,MF_BYCOMMAND | MF_UNCHECKED); + } + } + else if (ID_TOOLS_STEREOVIEW == LOWORD(wParam)) + { + g_sOptions.bStereoView =! g_sOptions.bStereoView; + + HMENU menu = ::GetMenu(g_hDlg); + if (g_sOptions.bStereoView) { + ::ModifyMenu(menu,ID_TOOLS_STEREOVIEW, + MF_BYCOMMAND | MF_CHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + + CLogDisplay::Instance().AddEntry("[INFO] Switched to stereo mode", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } else { + ModifyMenu(menu,ID_TOOLS_STEREOVIEW, + MF_BYCOMMAND | MF_UNCHECKED | MF_STRING,ID_TOOLS_STEREOVIEW,"Stereo view"); + + CLogDisplay::Instance().AddEntry("[INFO] Switched to mono mode", + D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); + } + } else if (ID_TOOLS_SETANGLELIMIT == LOWORD(wParam)) { + DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOGSMOOTH),g_hDlg,&SMMessageProc); + } else if (ID_VIEWER_CLEARHISTORY == LOWORD(wParam)) { + ClearHistory(); + } else if (ID_VIEWER_CLOSEASSET == LOWORD(wParam)) { + DeleteAssetData(); + DeleteAsset(); + } + else if (BN_CLICKED == HIWORD(wParam)) + { + if (IDC_TOGGLEMS == LOWORD(wParam)) + { + ToggleMS(); + } + else if (IDC_TOGGLEMAT == LOWORD(wParam)) + { + ToggleMats(); + } + else if (IDC_LCOLOR1 == LOWORD(wParam)) + { + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetFirstCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[0]); + SaveLightColors(); + } + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + } + else if (IDC_LCOLOR2 == LOWORD(wParam)) + { + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast<D3DXVECTOR4*>(CDisplay::Instance().GetSecondCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[1]); + SaveLightColors(); + } + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + } + else if (IDC_LCOLOR3 == LOWORD(wParam)) + { + DisplayColorDialog(&g_avLightColors[2]); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); + SaveLightColors(); + } + else if (IDC_LRESET == LOWORD(wParam)) + { + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetFirstCheckerColor(D3DXVECTOR4(0.4f,0.4f,0.4f,1.0f)); + CDisplay::Instance().SetSecondCheckerColor(D3DXVECTOR4(0.6f,0.6f,0.6f,1.0f)); + SaveCheckerPatternColors(); + } + else + { + g_avLightColors[0] = D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF); + g_avLightColors[1] = D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00); + g_avLightColors[2] = D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05); + SaveLightColors(); + } + + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),nullptr,TRUE); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); + } + else if (IDC_NOSPECULAR == LOWORD(wParam)) + { + ToggleSpecular(); + } + else if (IDC_NOAB == LOWORD(wParam)) + { + ToggleTransparency(); + } + else if (IDC_ZOOM == LOWORD(wParam)) + { + ToggleFPSView(); + } + else if (IDC_BLUBB == LOWORD(wParam)) + { + ToggleUIState(); + } + else if (IDC_TOGGLENORMALS == LOWORD(wParam)) + { + ToggleNormals(); + } + else if (IDC_LOWQUALITY == LOWORD(wParam)) + { + ToggleLowQuality(); + } + else if (IDC_3LIGHTS == LOWORD(wParam)) + { + ToggleMultipleLights(); + } + else if (IDC_LIGHTROTATE == LOWORD(wParam)) + { + ToggleLightRotate(); + } + else if (IDC_AUTOROTATE == LOWORD(wParam)) + { + ToggleAutoRotate(); + } + else if (IDC_TOGGLEWIRE == LOWORD(wParam)) + { + ToggleWireFrame(); + } + else if (IDC_SHOWSKELETON == LOWORD(wParam)) + { + ToggleSkeleton(); + } + else if (IDC_BFCULL == LOWORD(wParam)) + { + ToggleCulling(); + } + else if (IDC_PLAY == LOWORD(wParam)) + { + g_bPlay = !g_bPlay; + SetDlgItemText(g_hDlg,IDC_PLAY,(g_bPlay ? "Stop" : "Play")); + + if (g_bPlay) + EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),FALSE); + else EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),TRUE); + } + } + // check the file history + for (unsigned int i = 0; i < AI_VIEW_NUM_RECENT_FILES;++i) + { + if (AI_VIEW_RECENT_FILE_ID(i) == LOWORD(wParam)) + { + strcpy(g_szFileName,g_aPreviousFiles[i].c_str()); + DeleteAssetData(); + DeleteAsset(); + LoadAsset(); + + // update and safe the history + UpdateHistory(); + SaveHistory(); + } + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + if (LOWORD(wParam) >= AI_VIEW_EXPORT_FMT_BASE && LOWORD(wParam) < AI_VIEW_EXPORT_FMT_BASE+Assimp::Exporter().GetExportFormatCount()) { + DoExport(LOWORD(wParam) - AI_VIEW_EXPORT_FMT_BASE); + } +#endif + + // handle popup menus for the tree window + CDisplay::Instance().HandleTreeViewPopup(wParam,lParam); + + return TRUE; + }; + return FALSE; + } + + +//------------------------------------------------------------------------------- +// Message prcoedure for the progress dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK ProgressMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) + { + case WM_INITDIALOG: + + SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0, + MAKELPARAM(0,500)); + + SetTimer(hwndDlg,0,40,nullptr); + return TRUE; + + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) + { +#if 0 + g_bLoadingCanceled = true; + TerminateThread(g_hThreadHandle,5); + g_pcAsset = nullptr; + + EndDialog(hwndDlg,0); +#endif + + // PROBLEM: If we terminate the loader thread, ASSIMP's state + // is undefined. Any further attempts to load assets will + // fail. + exit(5); +// return TRUE; + } + case WM_TIMER: + + UINT iPos = (UINT)SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_GETPOS,0,0); + iPos += 10; + if (iPos > 490)iPos = 0; + SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,iPos,0); + + if (g_bLoadingFinished) + { + EndDialog(hwndDlg,0); + return TRUE; + } + + return TRUE; + } + return FALSE; + } + + +//------------------------------------------------------------------------------- +// Message procedure for the about dialog +//------------------------------------------------------------------------------- +INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, + WPARAM wParam,LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + switch (uMsg) + { + case WM_CLOSE: + EndDialog(hwndDlg,0); + return TRUE; + + case WM_COMMAND: + + if (IDOK == LOWORD(wParam)) + { + EndDialog(hwndDlg,0); + return TRUE; + } + } + return FALSE; + } +} + +using namespace AssimpView; + +//------------------------------------------------------------------------------- +// Entry point to the application +//------------------------------------------------------------------------------- +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // needed for the RichEdit control in the about/help dialog + LoadLibrary( "riched20.dll" ); + + // load windows common controls library to get XP style + InitCommonControls(); + + // initialize the IDirect3D9 interface + g_hInstance = hInstance; + if (0 == InitD3D()) { + MessageBox(nullptr,"Failed to initialize Direct3D 9", + "ASSIMP ModelViewer",MB_OK); + return -6; + } + + // create the main dialog + HWND hDlg = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_DIALOGMAIN), + nullptr,&MessageProc); + + // ensure we get high priority + ::SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); + + // initialize the default logger if necessary + Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); + + CLogWindow::Instance().pcStream = new CMyLogStream(); + Assimp::DefaultLogger::get()->attachStream(CLogWindow::Instance().pcStream, + Assimp::DefaultLogger::Debugging | Assimp::DefaultLogger::Info | + Assimp::DefaultLogger::Err | Assimp::DefaultLogger::Warn); + + if (nullptr == hDlg) { + MessageBox(nullptr,"Failed to create dialog from resource", + "ASSIMP ModelViewer",MB_OK); + return -5; + } + + // display the window + g_hDlg = hDlg; + MSG uMsg; + memset(&uMsg,0,sizeof( MSG)); + ShowWindow( hDlg, nCmdShow ); + UpdateWindow( hDlg ); + + // create the D3D device object + if (0 == CreateDevice(g_sOptions.bMultiSample,false,true)) { + MessageBox(nullptr,"Failed to initialize Direct3D 9 (2)", + "ASSIMP ModelViewer",MB_OK); + return -4; + } + + CLogDisplay::Instance().AddEntry("[OK] Here we go!"); + + // create the log window + CLogWindow::Instance().Init(); + // set the focus to the main window + SetFocus(g_hDlg); + + // recover background skyboxes/textures from the last session + HKEY hRegistry; + union { + char szFileName[MAX_PATH]; + D3DCOLOR clrColor; + }; + DWORD dwTemp = MAX_PATH; + RegCreateKeyEx(HKEY_CURRENT_USER, + "Software\\ASSIMP\\Viewer",0,nullptr,0,KEY_ALL_ACCESS, nullptr, &hRegistry,nullptr); + if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastSkyBoxSrc",nullptr,nullptr, + (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) + { + CBackgroundPainter::Instance().SetCubeMapBG(szFileName); + } + else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"LastTextureSrc",nullptr,nullptr, + (BYTE*)szFileName,&dwTemp) && '\0' != szFileName[0]) + { + CBackgroundPainter::Instance().SetTextureBG(szFileName); + } + else if(ERROR_SUCCESS == RegQueryValueEx(hRegistry,"Color",nullptr,nullptr, + (BYTE*)&clrColor,&dwTemp)) + { + CBackgroundPainter::Instance().SetColor(clrColor); + } + RegCloseKey(hRegistry); + + // now handle command line arguments + HandleCommandLine(lpCmdLine); + + double adLast[30]; + for (int i = 0; i < 30;++i)adLast[i] = 0.0f; + int iCurrent = 0; + + double g_dCurTime = 0; + double g_dLastTime = 0; + while( uMsg.message != WM_QUIT ) + { + if( PeekMessage( &uMsg, nullptr, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &uMsg ); + DispatchMessage( &uMsg ); + + if (WM_CHAR == uMsg.message) + { + + switch ((char)uMsg.wParam) + { + case 'M': + case 'm': + + CheckDlgButton(g_hDlg,IDC_TOGGLEMS, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMS(); + break; + + case 'L': + case 'l': + + CheckDlgButton(g_hDlg,IDC_3LIGHTS, + IsDlgButtonChecked(g_hDlg,IDC_3LIGHTS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMultipleLights(); + break; + + case 'P': + case 'p': + + CheckDlgButton(g_hDlg,IDC_LOWQUALITY, + IsDlgButtonChecked(g_hDlg,IDC_LOWQUALITY) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleLowQuality(); + break; + + case 'D': + case 'd': + + CheckDlgButton(g_hDlg,IDC_TOGGLEMAT, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEMAT) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleMats(); + break; + + + case 'N': + case 'n': + + CheckDlgButton(g_hDlg,IDC_TOGGLENORMALS, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLENORMALS) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + ToggleNormals(); + break; + + + case 'S': + case 's': + + CheckDlgButton(g_hDlg,IDC_NOSPECULAR, + IsDlgButtonChecked(g_hDlg,IDC_NOSPECULAR) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleSpecular(); + break; + + case 'A': + case 'a': + + CheckDlgButton(g_hDlg,IDC_AUTOROTATE, + IsDlgButtonChecked(g_hDlg,IDC_AUTOROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleAutoRotate(); + break; + + + case 'R': + case 'r': + + CheckDlgButton(g_hDlg,IDC_LIGHTROTATE, + IsDlgButtonChecked(g_hDlg,IDC_LIGHTROTATE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleLightRotate(); + break; + + case 'Z': + case 'z': + + CheckDlgButton(g_hDlg,IDC_ZOOM, + IsDlgButtonChecked(g_hDlg,IDC_ZOOM) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleFPSView(); + break; + + + case 'W': + case 'w': + + CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE, + IsDlgButtonChecked(g_hDlg,IDC_TOGGLEWIRE) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleWireFrame(); + break; + + case 'K': + case 'k': + + CheckDlgButton(g_hDlg,IDC_SHOWSKELETON, + IsDlgButtonChecked(g_hDlg,IDC_SHOWSKELETON) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleSkeleton(); + break; + + case 'C': + case 'c': + + CheckDlgButton(g_hDlg,IDC_BFCULL, + IsDlgButtonChecked(g_hDlg,IDC_BFCULL) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleCulling(); + break; + + case 'T': + case 't': + + CheckDlgButton(g_hDlg,IDC_NOAB, + IsDlgButtonChecked(g_hDlg,IDC_NOAB) == BST_CHECKED + ? BST_UNCHECKED : BST_CHECKED); + + ToggleTransparency(); + break; + } + } + } + + + // render the scene + CDisplay::Instance().OnRender(); + + // measure FPS, average it out + g_dCurTime = timeGetTime(); + g_fElpasedTime = (float)((g_dCurTime - g_dLastTime) * 0.001); + g_dLastTime = g_dCurTime; + + adLast[iCurrent++] = 1.0f / g_fElpasedTime; + + double dFPS = 0.0; + for (int i = 0; i < 30; ++i) { + dFPS += adLast[ i ]; + } + dFPS /= 30.0; + + if (30 == iCurrent) { + iCurrent = 0; + if (dFPS != g_fFPS) { + g_fFPS = dFPS; + char szOut[256]; + + sprintf(szOut,"%i",(int)floorf((float)dFPS+0.5f)); + SetDlgItemText(g_hDlg,IDC_EFPS,szOut); + } + } + } + DeleteAsset(); + Assimp::DefaultLogger::kill(); + ShutdownDevice(); + ShutdownD3D(); + + return 0; +} |