⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 The goal of this project is to explore the idea of point-based radiosity, which is a shooting radio
💻 CPP
字号:
 /*+-------------------------------------------------------------------
  Ben Landon
  CSCI E-235
  Final Project

  This is the main application file for a program that 
  attempts to do "Point-Based Radiosity".  See the readme.txt
  file for more details.

*/

#include <windows.h>
#include <stdio.h>
#include "gl_common.h"
#include "wgl.h"
#include "HemiCube.hpp"
#include "Scene.hpp"
#include "ppm_util.hpp"
#include "pgm_util.hpp"
#include "resource.h"

/*+-------------------------------------------------------------------
  Function Prototypes 

*/

static void panic_and_exit (int code, const char* message);
static void setup (HWND hwnd);
static void cleanup (HWND hwnd);
static void load_debugging_texture (void);

static void render_scene (void);

LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, 
			      WPARAM wParam, LPARAM lParam);

static void on_size_event (HWND hwnd, unsigned int width, unsigned int height);
static bool on_key_down (HWND hwnd, TCHAR key);
static bool on_command (HWND hwnd, int command);
static float do_one_radiosity_step (void);
static void do_radiosity (void);


/*+-------------------------------------------------------------------
  Global Variables

*/
unsigned int g_window_width = 500;
unsigned int g_window_height = 500;

HemiCube* g_hemi_cube = NULL;
Scene* g_scene = NULL;
GLuint g_tex_id = 0;

GLuint g_debugging_texture = 0;

Point brightest_texel_point;
HDC g_hdc = NULL;

bool g_show_projected_points = false;
bool g_use_gl_points = false;

/*+-------------------------------------------------------------------
    panic_and_exit

    This function does no cleanup, it just shows an error
    message and exits.

*/
void panic_and_exit (int code, const char* message)
{
    MessageBox(NULL, 
	       message, 
	       "Panic - Something went really wrong", 
	       MB_ICONSTOP);                

    exit(code);
}

/*+-------------------------------------------------------------------
  setup 

*/
void setup (HWND hwnd)
{
    HGLRC hglrc = setup_opengl(hwnd);
    SetWindowLong(hwnd, GWL_USERDATA, (LONG)hglrc);
    
    g_hemi_cube = new HemiCube();
    g_scene = Scene::load_simple_scene();    

    load_debugging_texture();
    do_one_radiosity_step();
}


/*+-------------------------------------------------------------------
  cleanup

  This function is executed once at shutdown.

*/
void cleanup (HWND hwnd)
{
    HGLRC hglrc = (HGLRC)GetWindowLong(hwnd, GWL_USERDATA);

    if (hglrc)
    {
	cleanup_opengl(hglrc);
    }
    
    if (g_hemi_cube)
    {
	delete g_hemi_cube;
	g_hemi_cube = NULL;
    }
    
    if (g_scene)
    {
	delete g_scene;
	g_scene = NULL;
    }

    if (g_debugging_texture != 0)
    {
	glDeleteTextures(1, &g_debugging_texture);
	g_debugging_texture = 0;
    }

    HMENU hMenu = GetMenu(hwnd);
    
    SetMenu(hwnd, NULL);

    DestroyMenu(hMenu);

    ReleaseDC(hwnd, g_hdc);
}


/*+-------------------------------------------------------------------
  load_debugging_texture

  Load the texture used in debugging. This is a polka dot pattern.
  It is useful just to make sure that the texture coordinates are
  set properly .

*/
void load_debugging_texture (void)
{
    FILE* file = fopen("polka_dots.ppm", "rb");

    unsigned char* data = NULL;
    unsigned int width = 0;
    unsigned int height = 0;
    unsigned int color_depth = 0;

    if (file && read_PPM_file (file, &data, &width, &height, &color_depth))
    {
	glGenTextures(1, &g_debugging_texture);

	glBindTexture(GL_TEXTURE_2D, g_debugging_texture);

	int rc = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,
				   GL_RGB, GL_UNSIGNED_BYTE, data);

    }

    fclose(file);
    file = NULL;
}

/*+-------------------------------------------------------------------
  debug_render_scene 

  Render the simple scene in the Scene object into 
  a small viewport.  This is useful for debugging.

*/
void debug_render_scene (void)
{
    glViewport(0, 0, g_window_width, g_window_height);
    glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -20.0f);
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(40.0f, 1.0f, 1.0f, 60.0f);

    if (g_scene)
    {
	g_scene->draw_with_accumulation_textures();
	
        glDisable(GL_DEPTH_TEST);

        if (g_show_projected_points)
            g_scene->debug_draw_splats();

        g_scene->draw_wireframe();
    }

    // Draw the brightest texel as a big 
    // magenta dot
    float point_size;
    glGetFloatv(GL_POINT_SIZE, &point_size);
    glPointSize(10.0);

    glBegin(GL_POINTS);
    glColor3f(1.0f, 0.0f, 1.0f);

    glVertex3f(brightest_texel_point.x(),
	       brightest_texel_point.y(),
	       brightest_texel_point.z());

    glEnd();

    glPointSize(point_size);
}


/*+-------------------------------------------------------------------
  render_scene

*/
void render_scene (void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    glRasterPos2i(0, 0);

    debug_render_scene();
    SwapBuffers(g_hdc);
}


/*+------------------------------------------------------------------
    do_one_radiosity_step    

*/
float do_one_radiosity_step (void)
{
    assert(g_hemi_cube != NULL);
    assert(g_scene != NULL);
    assert(g_scene->num_triangles() > 0);
    
    Color brightest_texel_color;
    
    // Clear the scene of any existing splats
    g_scene->clear_all_splats();

    int total_splats_in_scene = g_scene->debug_num_splats();

    int u, v;
    u = v = 0;

    SceneTriangle* triangle = 
	g_scene->get_brightest_texel(brightest_texel_point, 
				     brightest_texel_color, u, v);
    
    // FIXME - This is where we should check the energy 
    // epsilon.
    assert(triangle != NULL);
    
    g_hemi_cube->render_buffers(*g_scene,
				brightest_texel_point, 
				triangle->normal(),
				brightest_texel_color
				);
    
    
    g_hemi_cube->reconstruct(*g_scene);

    // Now tell the scene to accumulate the splats 
    // that were created in the reconstruction method.
    g_scene->accumulate_all_splats(g_use_gl_points);

    // Subtract the emitting texel from the emissive
    // texture that just emitted into the scene.
    triangle->subtract_emissive_texel(brightest_texel_color, 
                                          u, v);
    
    g_scene->reset_gl_textures();

    // Return the sum (( R + B + G ) * A) of the
    // emitting texel.  This is interesting information
    // to have to see if the radiosity process is
    // converging (it usually doesn't at this point).
    return brightest_texel_color.sum();
}


/*+-------------------------------------------------------------------
  do_radiosity

  Invoke "do_one_radiosity_step" 100 times. 

*/
void do_radiosity (void)
{
    char message[64];
    int counter = 0;
    while (counter < 100)
    {
        float intensity = do_one_radiosity_step();
    	sprintf(message, "Step: %d: %f\n", counter++, intensity);
	    OutputDebugString(message);        
        render_scene();
    }
}


/*+-------------------------------------------------------------------
  on_size_event

  Proces a WM_SIZE event.  The HWND, width and height parameters 
  are  passed to this function.

*/
void on_size_event (HWND hwnd, unsigned int width, unsigned int height)
{
    g_window_width = width;
    g_window_height = height;
    set_viewport(g_window_width, g_window_height, 1.0f);              
}


/*+-------------------------------------------------------------------
  on_key_down 
  
  Called when a key is pressed.  This function should return
  true if the message is processed, false otherwise.

*/
bool on_key_down (HWND hwnd, TCHAR key)
{
    bool handled = false;
    if ((key == 'g') || (key == 'G')) // G for Go!
    {
        do_radiosity();        
        handled = true;
    }        
    else if ((key == 's') || (key == 'S')) // S for step
    {	
  	do_one_radiosity_step();                
        handled = true;
    }
    else if ((key == 'd') || (key == 'D')) // D for debug
    {
        g_show_projected_points = !g_show_projected_points;
        handled = true;
    }
    else if ((key == 'p') || (key == 'P')) // P for points
    {
        g_use_gl_points = !g_use_gl_points;
        handled = true;
    }

    InvalidateRect(hwnd, NULL, TRUE);
    
    return handled;
}


/*+-------------------------------------------------------------------
  on_command

  Process menu commands

*/
bool on_command (HWND hwnd, int command)
{
    switch(command)
    {
    case IDM_FILE_EXIT:
	DestroyWindow(hwnd);
	return true;
    }

    return false;
}


/*+-------------------------------------------------------------------
  MainWndProc

  Event handler callback for the main application window.

*/
LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam,
			      LPARAM lParam)
{
    switch(message)
    {
    case WM_DESTROY:
	cleanup(hwnd);
	PostQuitMessage(1);
	return 0L;

    case WM_PAINT:
	{
	    PAINTSTRUCT ps;
	    HDC hdc = BeginPaint(hwnd, &ps);
	    render_scene();
	 
	    EndPaint(hwnd, &ps);
	}
	return 0L;
	
    case WM_SIZE:
	on_size_event(hwnd, LOWORD(lParam), HIWORD(lParam));
	return 0L;

    case WM_CHAR:
	if (on_key_down(hwnd, (TCHAR)wParam))
	    return 0L;
	else
	    break;

    case WM_COMMAND:
	if (on_command(hwnd, LOWORD(wParam)))
	    return 0L;
	else
	    break;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}


/*+-------------------------------------------------------------------
  WinMain 
  
  
*/
int WINAPI WinMain (HINSTANCE hInstance, 
		    HINSTANCE /* hPrevInstance */,
		    LPSTR /* lpszCmdLine */,
		    int nCmdShow)
{
    
    MSG msg;
    WNDCLASSEX wndclassx;

    char szClassName[] = "CSCIE235_RADIOSITY";

    ZeroMemory(&wndclassx, sizeof(wndclassx));

    wndclassx.cbSize = sizeof(wndclassx);
    wndclassx.style = CS_HREDRAW | CS_VREDRAW;
    wndclassx.lpfnWndProc = MainWndProc;
    wndclassx.cbClsExtra = 0;
    wndclassx.cbWndExtra = 0;
    wndclassx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclassx.hCursor = LoadCursor(NULL, IDC_ARROW);

    // This is an application that uses OpenGL for rendering,
    // we don't need a GDI background
    wndclassx.hbrBackground = NULL;
    wndclassx.hInstance = hInstance;
    wndclassx.lpszMenuName = NULL;
    wndclassx.lpszClassName = szClassName;
    wndclassx.hIconSm = NULL;
    
    ATOM aRC = RegisterClassEx(&wndclassx);

    if (!aRC)
    {
	panic_and_exit(-1, "Could not register windows class");
    }

    HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));

    HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, szClassName, 
			       "Ben's Project",
			       WS_OVERLAPPEDWINDOW,
			       CW_USEDEFAULT,
			       CW_USEDEFAULT,
			       g_window_width,
			       g_window_height,
			       NULL, 
			       hMenu, 
			       hInstance, NULL);
    
    setup(hwnd);

    g_hdc = GetDC(hwnd);

    glClear(GL_COLOR_BUFFER_BIT);

    SwapBuffers(g_hdc);
    
    glClear(GL_COLOR_BUFFER_BIT);
    
    SwapBuffers(g_hdc);

  

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    GLfloat point_sizes[] = { -1.0f, -1.0f };
    glGetFloatv(GL_POINT_SIZE_RANGE, point_sizes);

    while (GetMessage(&msg, 0, 0, 0))
    {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
    }

    return msg.wParam;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -