/*** Crealysm 3D engine, by Cristiaan Kop - updated 12-07-2015 ***/ /*** ============================================================================== ***/ /*** cpp file with main program ***/ /** ASSET VIEWER, FEATURES SHOULD INCLUDE -- VIEWING X FILE -- TEXTURE MAPPING -- NORMAL MAPPING ON/OFF -- CAMERA MOUSELOOK -- ROTATE OBJECT 6DOF -- LIGHTING CONTROLS (ENABLE, DISABLE, INTENSITY, COLOR) -- DIRECTIONAL AND POINT LIGHT (DIRECTION AND POSITION CHANGABLE) -- COLLISION TESTING, OBB, AABB, SPHERE /************************/ /** DESIGN TOPICS */ /************************/ /* PLAYER DOESN'T NEED OWN BOUNDING VOLUME - LINK TO MESH INST? (FP VIEW?) /* CLEANER DESIGN PLAYER COLLISIONS (PRE-CONDITION = SORTING!) /* CLEANER DESIGN BULLET COLLISIONS (PRE-CONDITION = SORTING!) /* ENTITY MANAGER, ADD TO VECTORS?? /* - WHAT ABOUT THE RENDERQUEUE?? ADD TO VECTORS AND UPDATE IN RENDERQUEU (PRO- OR REACTIVE) /* - MESH INST IS GAME OBJECT OR NOT( COLLISIONS, ETC.) /* GAME OBJECTS LINKED TO MESH INST? - TEMP: MESHINST CLASS: ALIVE BOOL + SET AND GET FUNCTION?? CULLING/ UPDATING ETC. /* WEAPON/ PLAYER INTERACTION/ UPDATING (AMMO = PLAYER!!) /* WEAPON SELECTION AND SOUNDS LOGICS; IMPLEMENT /************************/ /** MATH TOPICS */ /************************/ /* SPOT LIGHTS?? (SCENE, CD3DLIGHT, UBERSHADER ETC.) /************************/ /** APPET PIPELINE */ /************************/ /* NAMING CONVENTIONS & DEPENDENCIES, LINKING & CHECKING /* MATERIALS UNIQUE BY MULTIPLE PROPERTIES, NOT ONLY TEX FILENAME /* DX11 AND BEN HARPER BOOK ! /************************/ /** IO */ /************************/ /* SCENE FROM .X FILE? MULTIPLE MESHES VS RENDERABLES ?? SCENE FORMAT/EDITOR? /************************/ /** SHADERS + D3D11 */ /************************/ /* EFFECT PER OBJECT?? (GLOW ETC.) /* MULTIPLE RENDERTARGETS: POSTPROCESSING FX, HDR/BLOOM? /* SPECULAR MAPPING USING ALPHA OF DIFF TEXTURE? (SPECULAR MAPPING!) /* PERFORMANCE:XMFLOAT4X4A's CHANGED TO XMFLOAT4X4 CAMERA, ALIGN- STD VECTOR /************************/ /** SCENE MANAGER */ /************************/ /* CAMERA NOW 1 ON 1 RELATION WITH SCENE, OK OR INDEPENDENT? /* SHARE TEXTURES, OBJECTS ETC -> NOW UNIQUE PER SCENE (REDUNDANCY!!) /* RENDERQUEUE NOW D3D RENDERER BOUND, NOT PER SCENE; OK OR INDEPENDENT? /* SCENE GRAPH: CREATE SCENE HIERARCHY, NODES, QUADS, PORTALS ETC; CULLING /************************/ /** PERFORMANCE/ OTHER */ /************************/ /* LOD's, MESHES (PROGRESSIVE?) /* ANIMATIONS: RENDERABLES PUBLIC IN MESHINST (DEPENDS ON ANIMATIONS LATER ON) - CHILD/ PARENT RELATIONS??? HIERARCHY /* PERFORMANCE: OCCLUSION CULLING /* RISK: SCENEMANAGER RETURNS PTR TO D3DSCENES -> SO PUBLIC /* FOOTSTEPS ONLY X AND Z, NO Y MOVEMENT - TEMP FIXED NOW /* RENDERFRAME OPTIMIZATION; BATCHES/ MESH INSTANCING? /* FUNCTIONAL: D3DXMESH, HIERARCHY, ANIMATIONS/ BONES AND SKINNING /* FUNCTIONAL: ANIMATED SKYBOX, DAY/NIGHT, WEATHER? (2 TEXTURES?) /* FUNCTIONAL: 3D AUDIO USING FMOD, INSTEAD OF DIY; INCL HEADING /* PERFORMANCE:QUEUE SORTING, RADIX INSTEAD OF STD::SORT? /* PERFORMANCE:DIST TO CAM INST/ RENDERABLES ALL DONE NOW, NOT VISIBLE ONLY /* IO SCENE FILEFORMAT IMPROVEMENTS, KEYWORDS, COMMENTS ETC /* IO SCENE FILEFORMAT: ASCII -> BINARY (REQUIRES EDITOR!) /** D3DX LEFT OVERS, 21-5-2014 ** D3D.H D3DXSPRITE D3DFONT.H D3DXFONT D3DMESH.H D3DXMESH / D3DXBUFFER / D3DXMATERIAL D3DSCENE.H D3DXSPRITE D3DSHADER.H D3DXEFFECTPOOL D3DFX.H D3DXEFFECT D3DFXHANDLES D3DXHANDLE D3DSKYBOX.H D3DXEFFECT D3DXSPRITE.H D3DXSPRITE, D3DXIMAGE_INFO D3DXHELPER.H D3DXIMAGE_INFO */ #include #include #include #include "main.h" #include "Crealysm_main_app.h" #include "Crealysm_text.h" #pragma comment(lib, "winmm.lib") #ifdef _DEBUG #include "vld.h" #endif using namespace std; using namespace Crealysm_general; bool active = false; MSG msg; /**************************************************************************************/ /*** CREALYSM MAIN OBJECT ***/ /**************************************************************************************/ Crealysm_game::CMainApp _mainApp; std::string graphicsSettingsFile = "data/settings.dat"; std::string applBaseFile = "data/assetviewer.dat"; /**************************************************************************************/ /*** WINMAIN ***/ /*** ==> usage: main windows function ***/ /*** ==> initialized crealysm, loads the scene and starts main loop ***/ /**************************************************************************************/ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if(AppRunning()) return(INT)msg.wParam; /** STARTUP Crealysm engine **/ if(!StartCrealysm(hInstance, nCmdShow)) return (INT)msg.wParam; /*** INIT the game **/ if(!_mainApp.Init(hInstance, nCmdShow)) return (INT)msg.wParam; /** main loop **/ int framesPassed = 0; bool run = true; while(run) { _mainApp.mInput.UpdateKeys(); while(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if(msg.message == WM_QUIT) run = false; } _mainApp.mTimer.Update(); if(active) { if(_mainApp.mD3d.CheckDevice()) { // FPS calculation and updating Windowtext each 'fps' frames (windowed mode only) ++framesPassed; #ifdef _DEBUG if(framesPassed >= 60 && _mainApp.mD3d.mSettings.GetWindowed()) { std::wstring winText = _mainApp.mTimer.GetFpsString(); if(_mainApp.mD3d.mSettings.GetVsync()) winText.append(L" - VSYNC enabled"); else winText.append(L" - VSYNC disabled"); SetWindowText(_mainApp.mD3d.GetHwnd(), winText.c_str()); framesPassed = 0; } #endif // Game updating, including player, audio etc. => each update, using DeltaT (25-5-2015) if(!_mainApp.Update()) { run = false; } // Rendering if(!_mainApp.Render()) { _mainApp.mD3d.MsgBoxError(err_render); run = false; } } } } // DEBUGGING: SHOW FRAME AND RUNTIME + AVG FPS AFTER EXITING #ifdef _DEBUG char temptext[50]; int runningTime = (int)_mainApp.mTimer.GetRunningTime(); if(runningTime > 1) { int framesRendered = _mainApp.mD3d.GetFramesRendered(); int averageFps = framesRendered / runningTime; sprintf_s(temptext, "Running time: %i \n", runningTime); OutputDebugStringA(temptext); sprintf_s(temptext, "Frames rendered: %i \n", framesRendered); OutputDebugStringA(temptext); sprintf_s(temptext, "Average FPS: %i \n", averageFps); OutputDebugStringA(temptext); } #endif return (INT)msg.wParam; } /**************************************************************************************/ /*** APPRUNNING ***/ /*** ==> usage: @application startup ***/ /*** ==> returns is the applications is already running ***/ /**************************************************************************************/ bool AppRunning() { HANDLE Mutex = CreateMutex(NULL, true, L"Crealysm"); if(GetLastError() != 0) { MessageBox(NULL, err_running.c_str(), err_windowtext.c_str(), MB_ICONEXCLAMATION); return true; } return false; } /**************************************************************************************/ /*** STARTCREALYSM ***/ /*** ==> usage: startup Crealysm engine based on given parameters ***/ /*** ==> initializes all directx9 components and reads in the 3d scene ***/ /**************************************************************************************/ bool StartCrealysm(HINSTANCE pInstance, const int pCmdShow) { // MAIN APP if(!_mainApp.mD3d.LoadSettings(graphicsSettingsFile)) return false; if(!_mainApp.mD3d.InitWindowClass(WindowProc, pCmdShow, pInstance)) { _mainApp.mD3d.MsgBoxError(err_wc); return false; } // LOAD APPLICATION MAIN DATA if(!_mainApp.mApplIO.Load(applBaseFile)) { _mainApp.mD3d.MsgBoxError(err_IO_applbase); return false; } // START CREALYSM ENGINE if(!_mainApp.StartCrealysm()) return false; return true; } /**************************************************************************************/ /*** D3D->HWND WINDOWPROC ***/ /**************************************************************************************/ LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int sleeptime = 100; switch(message) { // HANDLE KEYBOARD INPUT SOURCE DATA case WM_KEYDOWN: { if(wParam == VK_SHIFT) { if(GetKeyState(VK_LSHIFT) & 0x8000) _mainApp.mInput.SetKeyState(VK_LSHIFT, true); if(GetKeyState(VK_RSHIFT) & 0x8000) _mainApp.mInput.SetKeyState(VK_RSHIFT, true); } if(wParam == VK_CONTROL) { if(GetKeyState(VK_LCONTROL) & 0x8000) _mainApp.mInput.SetKeyState(VK_LCONTROL, true); if(GetKeyState(VK_RCONTROL) & 0x8000) _mainApp.mInput.SetKeyState(VK_RCONTROL, true); } _mainApp.mInput.SetKeyState(wParam, true); break; } case WM_KEYUP: { if(wParam == VK_SHIFT) { if(!(GetKeyState(VK_LSHIFT) & 0x8000)) _mainApp.mInput.SetKeyState(VK_LSHIFT, false); if(!(GetKeyState(VK_RSHIFT) & 0x8000)) _mainApp.mInput.SetKeyState(VK_RSHIFT, false); } if(wParam == VK_CONTROL) { if(!(GetKeyState(VK_LCONTROL) & 0x8000)) _mainApp.mInput.SetKeyState(VK_LCONTROL, false); if(!(GetKeyState(VK_RCONTROL) & 0x8000)) _mainApp.mInput.SetKeyState(VK_RCONTROL, false); } _mainApp.mInput.SetKeyState(wParam, false); break; } // RAW INPUT: MOUSE case WM_INPUT: { UINT bufferSize; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER)); GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (LPVOID)_mainApp.mInput.GetMouseBufferPtr(), &bufferSize, sizeof(RAWINPUTHEADER)); _mainApp.mInput.UpdateMouseRaw(); } break; case WM_KILLFOCUS: #ifdef _DEBUG OutputDebugString(L"WM_KILLFOCUS message was called\n"); ShowWindow(_mainApp.mD3d.GetHwnd(), SW_MINIMIZE); #endif active = false; _mainApp.SetState(STATE_INACTIVE); break; case WM_SETFOCUS: #ifdef _DEBUG OutputDebugString(L"WM_SETFOCUS message was called\n"); #endif PostMessage(_mainApp.mD3d.GetHwnd(), WM_ACTIVATEAPP, true, 0); case WM_ACTIVATE: if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { #ifdef _DEBUG OutputDebugString(L"WM_ACTIVATE message was called, activated\n"); ShowWindow(_mainApp.mD3d.GetHwnd(), SW_RESTORE); #endif active = true; _mainApp.SetState(STATE_MENU); Sleep(sleeptime); break; } else { #ifdef _DEBUG OutputDebugString(L"WM_ACTIVATE message was called, deactivated\n"); #endif active = false; _mainApp.SetState(STATE_INACTIVE); Sleep(sleeptime); } break; case WM_SIZE: if(wParam == SIZE_MINIMIZED) { #ifdef _DEBUG ShowWindow(_mainApp.mD3d.GetHwnd(), SW_MINIMIZE); #endif active = false; _mainApp.SetState(STATE_INACTIVE); } else { #ifdef _DEBUG OutputDebugString(L"WM_SIZE message was called, not minimized\n"); #endif active = true; _mainApp.SetState(STATE_MENU); break; } break; case WM_ACTIVATEAPP: if(!wParam) { #ifdef _DEBUG OutputDebugString(L"WM_ACTIVATEAPP message was called, deactivated\n"); #endif active = false; _mainApp.SetState(STATE_INACTIVE); Sleep(sleeptime); } if(wParam) { #ifdef _DEBUG OutputDebugString(L"WM_ACTIVATEAPP message was called, activated\n"); #endif if(_mainApp.mD3d.GetDevicePtr()) { if(!_mainApp.mD3d.CheckDevice()) { bool devok = false; #ifdef _DEBUG OutputDebugString(L"D3D Device NOT OK at WM_ACTIVATEAPP\n"); #endif while(1) { Sleep(sleeptime); switch (_mainApp.mD3d.GetDevicePtr()->TestCooperativeLevel()) { case D3D_OK: return 0; case D3DERR_DEVICELOST: #ifdef _DEBUG OutputDebugString(L"D3D Device is lost\n"); #endif break; case D3DERR_DEVICENOTRESET: { Sleep(sleeptime); _mainApp.mD3d.OnLostDevice(); if(!_mainApp.mD3d.ResetDevice()) break; else { _mainApp.mD3d.OnResetDevice(); #ifdef _DEBUG OutputDebugString(L"Reset D3D device done and resources reallocated\n"); #endif } active = true; _mainApp.SetState(STATE_MENU); break; } case D3DERR_DRIVERINTERNALERROR: PostQuitMessage(WM_QUIT); } } } else { #ifdef _DEBUG OutputDebugString(L"D3D Device OK at WM_ACTIVATEAPP\n"); ShowWindow(_mainApp.mD3d.GetHwnd(), SW_RESTORE); #endif active = true; _mainApp.SetState(STATE_MENU); } } else { #ifdef _DEBUG OutputDebugString(L"D3DDEV is NULL at WM_ACTIVATEAPP\n"); #endif active = true; _mainApp.SetState(STATE_MENU); } } break; case WM_DESTROY: active = false; _mainApp.mAudio.StopMusic(); PostQuitMessage(0); break; case WM_CLOSE: DestroyWindow(_mainApp.mD3d.GetHwnd()); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }