I'm following a book called "OpenGL Game Development", and I'm up to the 2.1 example at the end of Chapter 2, but when I run it, nothing renders. I downloaded the source code that comes with the book from www.wordware.com/files/openglgd, and replaced my source code with the book's, but I still get the same problem. Yet when I run the .exe that comes with the code, I see exactly what it should be rendering, rendered!
Here's what the source code-packaged .exe gets:
http://img137.imageshack.us/img137/5618/mapeditorgoodyu2.jpg
Here's what my code gets, and what I get when I replace my code with the book's code:
http://img167.imageshack.us/img167/9890/mapeditorbaddx6.jpg
I think it's possible he compiled the .exe with different code than what's in the book, per se, since the background color I have in my static window is different from the one in his. You can find the book's code at the link I posted, so I'll just put my code here:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#include <string>
#include <sstream>
#include "resource.h"
#include "RASTER.h"
const int DEFAULT_BUTTON_WIDTH = 100;
const int DEFAULT_BUTTON_HEIGHT = 20;
HINSTANCE GlobalInstance;
HMENU Menu;
HMENU PopupMenu;
HWND Window;
HWND RenderWindow;
HWND bCreateWall;
RASTER raster;
void ResizeGLWindow(long width, long height)
{
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-200, 200, -200, 200, -2000, 2000);
glMatrixMode(GL_MODELVIEW);
}
void SetGLDefaults()
{
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
void Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.6f, 0.6f, 0.6f, 1.0f);
glLoadIdentity();
glPushMatrix();
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glEnd();
glBegin(GL_QUADS);
glVertex3f(0.05f, -0.05f, 0.0f);
glVertex3f(0.95f, -0.05f, 0.0f);
glVertex3f(0.95f, -0.95f, 0.0f);
glVertex3f(0.05f, -0.95f, 0.0f);
glEnd();
glBegin(GL_POLYGON);
glVertex3f(-0.250f, -0.250f, 0.0f);
glVertex3f(-0.500f, -0.125f, 0.0f);
glVertex3f(-0.750f, -0.250f, 0.0f);
glVertex3f(-0.875f, -0.500f, 0.0f);
glVertex3f(-0.750f, -0.750f, 0.0f);
glVertex3f(-0.500f, -0.875f, 0.0f);
glVertex3f(-0.250f, -0.750f, 0.0f);
glVertex3f(-0.125f, -0.500f, 0.0f);
glEnd();
glBegin(GL_LINES);
glVertex3f(-0.25f, 0.25f, 0.0f);
glVertex3f(-0.75f, 0.75f, 0.0f);
glEnd();
glPopMatrix();
SwapBuffers(raster.hDC);
}
LRESULT CALLBACK MapDetailsDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
SetDlgItemText(hWnd, IDC_MAP_DETAILS_NAME, "Map Name");
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING, 0, LPARAM("Exit"));
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING, 0, LPARAM("Get Killed"));
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_SETCURSEL, 0, 1);
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_RESETCONTENT, 0, 0);
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING, 0, LPARAM("Single Player"));
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING, 0, LPARAM("Multi Player"));
SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_SETCURSEL, 0, 1);
break;
case WM_COMMAND:
if (wParam == IDOK)
{
long level_rule = (long)SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_GETCURSEL, 0, 0);
long level_type = (long)SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_GETCURSEL, 0, 0);
std::string temp = "Level Type: ";
std::stringstream strstream;
strstream << level_type << "\n";
temp += strstream.str();
strstream.str("");
strstream << "Level Rule: " << level_rule;
temp += strstream.str();
MessageBox(hWnd, temp.c_str(), "OK", MB_OK);
EndDialog(hWnd, 0);
}
else if (wParam == IDCANCEL)
EndDialog(hWnd, 0);
break;
}
return 0;
}
void DisplayPopupMenu(long x, long y)
{
RECT windowLocation;
GetWindowRect(Window, &windowLocation);
HMENU temp = GetSubMenu(PopupMenu, 0);
TrackPopupMenu(temp, TPM_LEFTALIGN | TPM_RIGHTBUTTON, windowLocation.left + x + 8, windowLocation.top + y + 48, 0, Window, 0);
}
void WMCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (lParam == (LPARAM)bCreateWall)
MessageBox(Window, "You Pressed bCreateWall!", "Congrats!", MB_OK);
else if (wParam == ID_FILE_EXIT)
PostQuitMessage(0);
else if (wParam == ID_MAP_DETAILS)
DialogBox(GlobalInstance, MAKEINTRESOURCE(IDD_MAP_DETAILS), 0, DLGPROC(MapDetailsDlgProc));
else if (wParam == ID_DRAWING_WIREFRAME)
{
CheckMenuItem(Menu, ID_DRAWING_WIREFRAME, MF_CHECKED);
CheckMenuItem(Menu, ID_DRAWING_SOLID, MF_UNCHECKED);
}
else if (wParam == ID_DRAWING_SOLID)
{
CheckMenuItem(Menu, ID_DRAWING_WIREFRAME, MF_UNCHECKED);
CheckMenuItem(Menu, ID_DRAWING_SOLID, MF_CHECKED);
}
else if (wParam == ID_POP_MOVE)
MessageBox(Window, "Move", "Click", MB_OK);
else if (wParam == ID_POP_DELETE)
MessageBox(Window, "Delete", "Click", MB_OK);
else if (wParam == ID_POP_TEXTURE)
MessageBox(Window, "Texture", "Click", MB_OK);
else if (wParam == ID_POP_DUPLICATE)
MessageBox(Window, "Duplicate", "Click", MB_OK);
}
void WMSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
RECT rect;
GetClientRect(Window, &rect);
MoveWindow(RenderWindow, DEFAULT_BUTTON_WIDTH, 0, rect.right-rect.left-DEFAULT_BUTTON_WIDTH, rect.bottom-rect.top, true);
GetClientRect(RenderWindow, &rect);
ResizeGLWindow(rect.right - rect.left, rect.bottom - rect.top);
}
LRESULT CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
WMCommand(hWnd, msg, wParam, lParam);
break;
case WM_SIZE:
WMSize(hWnd, msg, wParam, lParam);
break;
case WM_RBUTTONUP:
DisplayPopupMenu(LOWORD(lParam), HIWORD(lParam));
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
GlobalInstance = hInstance;
WNDCLASS wc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "ME";
wc.lpszMenuName = 0;
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wc))
{
MessageBox(0, "Error: Cannot Register Class", "ERROR!", MB_OK);
return 1;
}
Window = CreateWindow("ME", "Map Editor", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, 0);
if (!Window)
{
MessageBox(0, "Error: Failed to Create Window", "ERROR!", MB_OK);
return 1;
}
RECT rect;
GetClientRect(Window, &rect);
RenderWindow = CreateWindow("STATIC", 0, WS_CHILD | WS_VISIBLE | WS_BORDER, DEFAULT_BUTTON_WIDTH, 0, rect.right - rect.left - DEFAULT_BUTTON_WIDTH, rect.bottom - rect.top - 20, Window, 0, hInstance, 0);
if (!RenderWindow)
{
MessageBox(0, "Error: Failed to Create RenderWindow", "ERROR!", MB_OK);
return 1;
}
bCreateWall = CreateWindow("BUTTON", "Create Wall", WS_CHILD | WS_VISIBLE, 0, 100, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT, Window, 0, hInstance, 0);
if (!bCreateWall)
{
MessageBox(0, "Error: Failed to Create bCreateWall", "ERROR!", MB_OK);
return 1;
}
Menu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
SetMenu(Window, Menu);
PopupMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_POPUP_MENU));
if (!raster.Init(RenderWindow))
return 1;
GetClientRect(RenderWindow, &rect);
ResizeGLWindow(rect.right - rect.left, rect.bottom - rect.top);
MSG msg;
while (true)
{
Render();
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
raster.Release(RenderWindow);
return 0;
}
//RASTER.h
#pragma once
#include <windows.h>
class RASTER
{
public:
HDC hDC;
HGLRC glrc;
RASTER();
~RASTER();
bool Init(HWND hWnd, unsigned char color_bits = 24, unsigned char depth_bits = 32);
bool Release(HWND hWnd);
};
//--
// RASTER.cpp
//--
#include "RASTER.h"
RASTER::RASTER()
{}
RASTER::~RASTER()
{}
bool RASTER::Init(HWND hWnd, unsigned char color_bits, unsigned char depth_bits)
{
HDC hDC = GetDC(hWnd);
if (!hDC)
{
MessageBox(hWnd, "Error: Can't Get Device Context for Window", "ERROR", MB_OK | MB_ICONERROR);
return false;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.cColorBits = color_bits;
pfd.cDepthBits = depth_bits;
int PixelFormat = ChoosePixelFormat(hDC, &pfd);
if (!PixelFormat)
{
MessageBox(hWnd, "Error: Can't Choose Pixel Format", "ERROR", MB_OK | MB_ICONERROR);
ReleaseDC(hWnd, hDC);
hDC = 0;
return false;
}
if (!SetPixelFormat(hDC, PixelFormat, &pfd))
{
MessageBox(hWnd, "Error: Can't Set The Pixel Format", "ERROR", MB_OK | MB_ICONERROR);
ReleaseDC(hWnd, hDC);
hDC = 0;
return false;
}
HGLRC glrc = wglCreateContext(hDC);
if (!glrc)
{
MessageBox(hWnd, "Error: Can't Create GL Context", "ERROR", MB_OK | MB_ICONERROR);
ReleaseDC(hWnd, hDC);
hDC = 0;
return false;
}
if (!wglMakeCurrent(hDC, glrc))
{
MessageBox(hWnd, "Error: Can't Make Current GL Context", "ERROR", MB_OK | MB_ICONERROR);
wglDeleteContext(glrc);
ReleaseDC(hWnd, hDC);
glrc = 0;
hDC = 0;
return false;
}
return true;
}
bool RASTER::Release(HWND hWnd)
{
if (!hDC || !glrc)
return false;
if (!wglMakeCurrent(0, 0))
{
MessageBox(hWnd, "Error: Release of DC and RC Failed", "Release Error", MB_OK | MB_ICONERROR);
return false;
}
if (!wglDeleteContext(glrc))
{
MessageBox(hWnd, "Error: Release of Rendering Context Failed", "Release Error", MB_OK | MB_ICONERROR);
return false;
}
glrc = 0;
if (!ReleaseDC(hWnd, hDC))
{
MessageBox(hWnd, "Error: Release of Device Context Failed", "Release Error", MB_OK | MB_ICONERROR);
return false;
}
hDC = 0;
return true;
}