www.pudn.com > 32709.zip > application.cpp


/*************************************************** 
 * Developer: Clinton Jon Selke                    * 
 *   Version: Totally FreeWare (Do what you will)  * 
 *   Section: Application Implementation           * 
 ***************************************************/ 
  
#include "application.h" 
#include "winexception.h" 
#include "vector3.h" 
 
const char *Application::WINDOW_CLASS_NAME = "ParticalSim"; 
const char *Application::WINDOW_CAPTION    = "Partical Sim v0.0.1 (ESCAPE -> Quits)"; 
const int   Application::WINDOW_WIDTH      = 400; 
const int   Application::WINDOW_HEIGHT     = 400; 
 
Application::Application(): 
    _is_running(false), 
    _error_code(0), 
    _hwnd(0), _hdc(0), _hrc(0), 
    _particle_system( 
        Vector3(0.f, 0.f, 0.f), // position of particle system 
        Vector3(0.f, 0.f, 0.f), // velocity of particle system 
        2.0f,                   // min dying age of particle 
        5.0f,                   // max dying age of particle 
        0.15f,                  // starting particle size 
        0.10f,                  // finishing particle size 
        1.f,                    // starting particle transparency 
        0.3f,                   // finishing particle transparency 
        0.4f,                   // min particle speed 
        0.9f,                   // max particle speed 
        0.005f,                 // particle creation delay 
        Vector3(0.f, 0.f, 1.f), // starting particle colour 
        Vector3(1.f, 0.f, 0.f), // finishing particle colour 
        Vector3(0.f, -100.f, 0.f),// gravity 
        1000                    // max number of particles 
    ) {} 
 
Application::~Application() {} 
 
int Application::run() { 
    // Initialise window and opengl api 
    initWindow(); 
    initOpenGL(); 
     
    // Show the window 
    ShowWindow(_hwnd, SW_SHOW); 
    UpdateWindow(_hwnd); 
     
    // Set _is_running flag to true 
    _is_running = true; 
     
    // Config opengl 
    glClearDepth(1.f); 
    glClearColor(0.f, 0.f, 0.f, 0.f); 
    glAccum(GL_MULT, 0.5); 
    glShadeModel(GL_SMOOTH); 
    glDisable(GL_DEPTH_TEST); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE); 
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); 
    glEnable(GL_TEXTURE_2D); 
    _particle_system.loadTexture(); 
 
    // Perform message loop 
    MSG msg; 
    while (_is_running) { 
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        } 
 
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
         
        glPushMatrix(); 
        _particle_system.draw(); 
        glPopMatrix(); 
         
        Sleep(10); 
        _particle_system.calculate(0.012f); 
         
        SwapBuffers(_hdc); 
    } 
 
    // Release window and opengl api 
    killOpenGL(); 
    killWindow(); 
 
    // Return error code 
    return _error_code; 
} 
 
void Application::initWindow() { 
    // Grab the handle to this application 
    HINSTANCE hinst = GetModuleHandle(0); 
     
    // Register window class 
    WNDCLASSEX wc; 
    wc.cbSize        = sizeof(wc); 
    wc.style         = CS_VREDRAW | CS_HREDRAW; 
    wc.lpfnWndProc   = windowProcedure; 
    wc.cbClsExtra    = 0; 
    wc.cbWndExtra    = 0; 
    wc.hInstance     = hinst; 
    wc.hIcon         = LoadIcon(0, IDI_APPLICATION); 
    wc.hCursor       = LoadCursor(0, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
    wc.lpszMenuName  = 0; 
    wc.lpszClassName = WINDOW_CLASS_NAME; 
    wc.hIconSm       = LoadIcon(0, IDI_APPLICATION); 
    if (!RegisterClassEx(&wc)) { 
        throw WinException("Unable to register window class"); 
    } 
     
    // Grab screen dimensions 
    RECT scrn_rect; 
    GetClientRect(GetDesktopWindow(), &scrn_rect); 
     
    // Create window 
    _hwnd = CreateWindowEx( 
        0,                  // dwExStyle 
        WINDOW_CLASS_NAME,  // lpszClassName 
        WINDOW_CAPTION,     // lpszWindowName 
        WS_SYSMENU | 
        WS_MINIMIZEBOX,     // dwStyle 
        (scrn_rect.right + 1 - WINDOW_WIDTH) >> 1,   // x 
        (scrn_rect.bottom + 1 - WINDOW_HEIGHT) >> 1, // y 
        WINDOW_WIDTH,       // nWidth 
        WINDOW_HEIGHT,      // nHeight 
        0,                  // hWndParent 
        0,                  // hMenu 
        hinst,              // hInstance 
        0                   // lpParam 
    ); 
    if (!_hwnd) { 
        UnregisterClass(WINDOW_CLASS_NAME, hinst); 
        throw WinException("Unable to create window"); 
    } 
     
    // Store address of application object in window 
    SetWindowLong(_hwnd, GWL_USERDATA, (LONG)this); 
} 
 
void Application::initOpenGL() { 
    PIXELFORMATDESCRIPTOR pfd; 
     
    // Grab a reference to the window's DC 
    _hdc = GetDC(_hwnd); 
     
    // Set the pixel format for the DC 
    ZeroMemory(&pfd, sizeof(pfd)); 
    pfd.nSize = sizeof(pfd); 
    pfd.nVersion = 1; 
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; 
    pfd.iPixelType = PFD_TYPE_RGBA; 
    pfd.cColorBits = 24; 
    pfd.cDepthBits = 16; 
    pfd.iLayerType = PFD_MAIN_PLANE; 
    SetPixelFormat(_hdc, ChoosePixelFormat(_hdc, &pfd), &pfd); 
     
    // Create and enable render context 
    _hrc = wglCreateContext(_hdc); 
    wglMakeCurrent(_hdc, _hrc); 
} 
 
void Application::killWindow() { 
    if (_hwnd) { DestroyWindow(_hwnd); } 
    UnregisterClass(WINDOW_CLASS_NAME, GetModuleHandle(0)); 
} 
 
void Application::killOpenGL() { 
    // Delete and disable render context 
    wglDeleteContext(_hrc); 
    wglMakeCurrent(0, 0); 
     
    // Release the DC reference back to the window 
    ReleaseDC(_hwnd, _hdc); 
     
    // Clear handles 
    _hdc = 0; 
    _hrc = 0; 
} 
 
LRESULT CALLBACK Application::windowProcedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 
    Application *app = (Application *)GetWindowLong(hwnd, GWL_USERDATA); 
     
    switch (msg) { 
        case WM_CREATE: 
            return 0; 
        case WM_CLOSE: 
            app->_error_code = 0; 
            DestroyWindow(hwnd); 
            return 0; 
        case WM_KEYDOWN: 
            switch (wparam) { 
                case VK_ESCAPE: 
                    app->_error_code = 0; 
                    DestroyWindow(hwnd); 
            } 
            return 0; 
        case WM_DESTROY: 
            app->_hwnd = 0; 
            app->_is_running = false; 
            return 0; 
        default: 
            return DefWindowProc(hwnd, msg, wparam, lparam); 
    } 
}