Original Post
Hey everyone, I just started learning OpenGL and I had initially started using NeHe's tutorials. Although, I began to have issues when it came to the texture mapping tutorial. I know that this is an infamous issue with him and I used the bmp.h/bmp.cpp fix... If I use only NeHe's code, it all works fine now, but the problem is that I began using the ZeusCMD tutorials and he encapsulates all the Win32 functions into separate header and source files. I like this method a lot more than NeHe's because it's cleaner and a lot easier to use. Anyway, when I use NeHe's texture loading code in my project and my own drawing functions it always renders a blank cube... just a black cube. I get no warnings or errors, it just renders a black cube. I don't know if I'm just missing something obvious, but I though I'd ask you guys if you had any hints. Thanks! I use Dev-C++ v.5, and yes, the texture file does exist and is in the directory specified =) Here are my files: glutil.h glutil.cpp bmp.h bmp.cpp main.cpp [Edited by - GokuLives on July 25, 2006 11:57:43 AM]
// glutil.h
// Defines OpenGL classes to be used in future projects
//
// Based on OpenGL tutorials from http://www.zeuscmd.com/tutorials/opengl/
#ifndef GLUTIL_H
#define GLUTIL_H
// OpenGL libraries
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#include <windows.h> // For WinAPI calls
#include <gl/gl.h> // For OpenGL functions
#include <gl/glu.h> // For OpenGL Utility functions
#include <stdio.h> // I/O
class OpenGL
{
public :
// allocates memory for the OpenGL class
static OpenGL *create()
{ return instance = new OpenGL; }
~OpenGL() { if (instance) delete instance; }
// sets up the window
bool initGL(char *t, int w = 640, int h = 480, bool full = false, int bpp = 32);
// handles swapping between fullscreen and windowed modes
bool changeDisplaySettings(int w, int h, bool full, int bpp);
// functions to enter and exit the Windows message loop
void runMessageLoop();
void endMessageLoop() const { finished = true; }
// just displays an error
void displayError(char *title);
void setInitFunc(bool (*i)())
{ init = i; }
void setDisplayFunc(void (*d)())
{ display = d; }
void setIdleFunc(void (*i)())
{ idle = i; }
void setResizeFunc(void (*r)(int w, int h))
{ resize = r; }
// the following functions are needed to access data in private variables
HWND getHWND() const
{ return hwnd; }
bool isKeyDown(int key) const
{ return keys[key]; }
void keyUp(int key)
{ keys[key] = false; }
bool isMouseDownL() const
{ return mouseDownL; }
int getMouseX() const
{ return mouseX; }
int getMouseY() const
{ return mouseY; }
int getWidth() const { return width; }
int getHeight() const { return height; }
private :
// OpenGL constructor
OpenGL() {}
// destroys our window
void killGL();
// standard Win32 WndProc event handling function
static LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
// private variables
static OpenGL *instance;
static char *title;
static int width;
static int height;
static int bits;
static bool fullscreen;
static bool active;
static bool finished;
static bool keys[256];
static int mouseX;
static int mouseY;
static bool mouseDownL;
// handles
static HDC hdc; // allows graphical contents of a window to be modified
static HWND hwnd; // handle for our window
static HGLRC hrc; // allows OpenGL to draw to the window
static bool (*init)(); // handles any OpenGL initialization code
// executes when program starts & when display settings change
static void (*display)(); // contains all code used to render a single frame of OpenGL application
static void (*idle)(); // contains extra processing that needs to be done every frame
static void (*resize)(int w, int h); // called each time our window is resized
};
#endif
// glutil.cpp
// Implements the OpenGL class functions defined in glutil.h
//
// Based on OpenGL tutorials from http://www.zeuscmd.com/tutorials/opengl/
#include "glutil.h"
// initialize all the variables
OpenGL *OpenGL::instance = NULL;
char *OpenGL::title = "";
int OpenGL::width = 640;
int OpenGL::height = 480;
int OpenGL::bits = 16;
bool OpenGL::fullscreen = false;
bool OpenGL::active = false;
bool OpenGL::finished = false;
bool OpenGL::keys[256];
int OpenGL::mouseX = 0;
int OpenGL::mouseY = 0;
bool OpenGL::mouseDownL = false;
HDC OpenGL::hdc = NULL;
HWND OpenGL::hwnd = NULL;
HGLRC OpenGL::hrc = NULL;
bool (*OpenGL::init)() = NULL;
void (*OpenGL::display)() = NULL;
void (*OpenGL::idle)() = NULL;
void (*OpenGL::resize)(int w, int h) = NULL;
//////////////////////////////////////////////////////////////
// begin initGL
bool OpenGL::initGL(char *t, int w, int h, bool full, int bpp)
{
title = t;
width = w;
height = h;
fullscreen = full;
bits = bpp;
// retrieve the instance of the application
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc; // variable for the window class
unsigned int pixelFormat; // pixel format variable
DWORD style; // stores the window style
// window class properties
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGLTest";
// register the window class
if (!RegisterClassEx(&wc))
{
displayError("Registering Window Class");
return false;
}
// if window is to be run in fullscreen a change in display is needed
if (fullscreen)
{
DEVMODE displaySettings;
memset(&displaySettings, 0, sizeof(displaySettings));
displaySettings.dmSize = sizeof(displaySettings);
displaySettings.dmPelsWidth = width;
displaySettings.dmPelsHeight = height;
displaySettings.dmBitsPerPel = bits;
displaySettings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (ChangeDisplaySettings(&displaySettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
displayError("Cannot change to requested display mode");
fullscreen = false;
killGL();
return false;
}
}
// if fullscreen use a borderless window style and remove the mouse cursor
if (fullscreen)
{
style = WS_POPUP;
ShowCursor(false);
}
else
{
style = WS_OVERLAPPEDWINDOW;
}
// adjust the window size in order to get a window that is the size we want
// NOT including the title bar and border
RECT rect;
rect.left = 0; rect.top = 0;
rect.right = width; rect.bottom = height;
AdjustWindowRectEx(▭, style, FALSE, 0);
// create the window
if (!(hwnd = CreateWindowEx(
WS_EX_APPWINDOW,
"OpenGLTest",
title,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
0, 0,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
hInstance,
NULL)))
{
killGL();
displayError("Creating Window");
return false;
}
// structure that specifies data stored for every pixel in window
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(pfd),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0, // Color bits
0, 0, // Alpha bits
0, 0, 0, 0, 0, // Accumulation bits
16, // Depth buffer
0, // Stencil buffer
0, // Auxillary buffer
PFD_MAIN_PLANE,
0, // reserved
0, 0, 0 // Layer masks
};
// retrieve device context
if (!(hdc = GetDC(hwnd)))
{
killGL();
displayError("Retrieving DC");
return false;
}
// allows Windows to find a pixel format that most closely matches our descriptor
if(!(pixelFormat = ChoosePixelFormat(hdc, &pfd)))
{
killGL();
displayError("Choosing Pixel Format");
return false;
}
// sets the pixel format
if (!SetPixelFormat(hdc, pixelFormat, &pfd))
{
killGL();
displayError("Setting Pixel Format");
return false;
}
// create an OpenGL rendering context
if (!(hrc = wglCreateContext(hdc)))
{
killGL();
displayError("Creating Rendering Context");
return false;
}
// assign device and rendering context to current thread
if (!wglMakeCurrent(hdc, hrc))
{
killGL();
displayError("Activating Rendering Context");
return false;
}
// show the window, set it in the foreground and give it focus
ShowWindow(hwnd, SW_SHOW);
SetForegroundWindow(hwnd);
SetFocus(hwnd);
// if a resize function has been assigned, resize the window
if (resize)
{
resize(width, height);
}
// run initialization code
if (init)
{
return init();
}
return true;
}
//////////////////////////////////////////////////////////////
// end initGL
//////////////////////////////////////////////////////////////
// begin changeDisplaySettings
bool OpenGL::changeDisplaySettings(int w, int h, bool full, int bpp)
{
// to prevent issues, kill old window and create a new one
killGL();
int oldWidth = width;
int oldHeight = height;
bool oldFull = fullscreen;
int oldBpp = bits;
if (!initGL(title, w, h, full, bpp))
{
initGL(title, oldWidth, oldHeight, oldFull, oldBpp);
return false;
}
if (init)
{
return init();
}
return true;
}
//////////////////////////////////////////////////////////////
// end changeDisplaySettings
//////////////////////////////////////////////////////////////
// begin killGL
void OpenGL::killGL()
{
// if fullscreen, return to normal mode
if (fullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(true);
}
// deactivate and destroy the rendering context
if (hrc)
{
if (!wglMakeCurrent(NULL, NULL))
{
displayError("Deactivating Rendering Context");
}
if (!wglDeleteContext(hrc))
{
displayError("Deleting Rendering Context");
}
hrc = NULL;
}
// release device context
if (hdc && !ReleaseDC(hwnd, hdc))
{
displayError("Releasing Device Context");
}
hdc = NULL;
// destroy window
if (hwnd && !DestroyWindow(hwnd))
{
displayError("Destroying Window");
}
hwnd = NULL;
// unregister window class
if (!UnregisterClass("OpenGLTest", GetModuleHandle(NULL)))
{
displayError("Unregistering Class");
}
}
//////////////////////////////////////////////////////////////
// end killGL
//////////////////////////////////////////////////////////////
// begin Windows message loop
LRESULT OpenGL::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
// stops the window from rendering if minimized
case WM_ACTIVATE :
{
active = HIWORD(wParam) ? false : true;
return 0;
}
case WM_CLOSE :
{
PostQuitMessage(0);
return 0;
}
case WM_SIZE :
{
width = LOWORD(lParam);
height = HIWORD(lParam);
if (resize)
{
resize(LOWORD(lParam), HIWORD(lParam));
}
return 0;
}
case WM_KEYDOWN :
{
keys[wParam] = true;
return 0;
}
case WM_KEYUP :
{
keys[wParam] = false;
return 0;
}
case WM_MOUSEMOVE :
{
mouseX = LOWORD(lParam);
mouseY = height - (HIWORD(lParam) + 1);
return 0;
}
case WM_LBUTTONDOWN : mouseDownL = true; return 0;
case WM_LBUTTONUP : mouseDownL = false; return 0;
} // end switch
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//////////////////////////////////////////////////////////////
// end Windows message loop
//////////////////////////////////////////////////////////////
// begin displayError
void OpenGL::displayError(char *title)
{
// buffer to store message
LPVOID lpMsgBuf;
// format the message
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0,
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// display the message
MessageBox(NULL, (LPCTSTR)lpMsgBuf, title, MB_OK | MB_ICONERROR);
// free the buffer
LocalFree(lpMsgBuf);
}
//////////////////////////////////////////////////////////////
// end displayError
//////////////////////////////////////////////////////////////
// begin runMessageLoop
void OpenGL::runMessageLoop()
{
MSG msg;
while(!finished)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // check for a message
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (active) // if not minimized, execute idle() for additional processing
{
if (idle)
{
idle();
if (keys[VK_F1]) // F1 Key - toggle fullscreen
{
keys[VK_F1] = false;
fullscreen = !fullscreen;
if (fullscreen)
fullscreen = this->changeDisplaySettings(
1024, 768, true, 32
);
else
this->changeDisplaySettings(
500, 500, false, 32
);
}
else if (keys[VK_ESCAPE]) // Esc Key - end message loop
this->endMessageLoop();
}
display(); // write to the back buffer
SwapBuffers(hdc); // swap display buffers
}
}
killGL(); // once loop is over, destroy window
}
//////////////////////////////////////////////////////////////
// end runMessageLoop
//---------------------------------------------------------------------------
class AUX_RGBImageRec {
void convertBGRtoRGB();
public:
byte *data;
DWORD sizeX;
DWORD sizeY;
bool NoErrors;
AUX_RGBImageRec(): NoErrors(false), data(NULL) {};
AUX_RGBImageRec(const char *FileName);
~AUX_RGBImageRec();
bool loadFile(const char *FileName);
friend AUX_RGBImageRec *auxDIBImageLoad(const char *FileName);
};
//--------------------------------------------------------------
#include <windows.h> // Header File For Windows - has structures for BMP format
#include <stdio.h> // Header File For Standard Input/Output
#include <stdlib.h>
#include "BMP.h"
/*------------------------------------------------------------------
BMP Loader - a quick and dirty substitute for GLaux
if you only use GLaux to load BMP files will load any format of a
windows DIB BMP format graphics file Only works on a windows box
Caution! memory for the data is allocated using 'new'.
In the NeHe tutorials the memory is reclaimed using 'free'.
For the small tutorials its not a big deal but not a good practice in
larger projects (heap trashing not good). J.M. Doyle : 12 Jan 2003
------------------------------------------------------------------*/
AUX_RGBImageRec *auxDIBImageLoad(const char *FileName)
{
return new AUX_RGBImageRec(FileName);
}
void AUX_RGBImageRec::convertBGRtoRGB()
{
const DWORD BitmapLength = sizeX * sizeY * 3;
byte Temp; // not quick but it works
for(DWORD i=0; i< BitmapLength; i += 3)
{
Temp = data;
data = data[i+2];
data[i+2] = Temp;
}
}
AUX_RGBImageRec::AUX_RGBImageRec(const char *FileName): data(NULL), NoErrors(false)
{
loadFile(FileName);
}
AUX_RGBImageRec::~AUX_RGBImageRec()
{
if (data != NULL) delete data;
data = NULL;
}
bool AUX_RGBImageRec::loadFile(const char* Filename)
{
BITMAPINFO BMInfo; // need the current OpenGL device contexts in order to make use of windows DIB utilities
const HDC gldc = wglGetCurrentDC(); // a handle for the current OpenGL Device Contexts
// assume there are errors until file is loaded successfully into memory
NoErrors = false; // release old data since this object could be used to load multiple Textures
if(data != NULL) delete data; // windows needs this info to determine what header info we are looking for
BMInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // Get windows to determine color bit depth in the file for us
BMInfo.bmiHeader.biBitCount = 0; // Get windows to open and load the BMP file and handle the messy decompression if the file is compressed
// assume perfect world and no errors in reading file, Ha Ha
HANDLE DIBHandle = LoadImage(0,Filename, IMAGE_BITMAP, 0, 0,LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_LOADFROMFILE); // use windows to get header info of bitmap - assume no errors in header format
GetDIBits(gldc, (HBITMAP)DIBHandle, 0,0, NULL, &BMInfo, DIB_RGB_COLORS);
sizeX = BMInfo.bmiHeader.biWidth;
sizeY = BMInfo.bmiHeader.biHeight; // change color depth to 24 bits (3 bytes (BGR) / pixel)
BMInfo.bmiHeader.biBitCount = 24; // don't want the data compressed
BMInfo.bmiHeader.biCompression = BI_RGB;
const DWORD BitmapLength = sizeX * sizeY * 3; // 3 bytes (BGR) per pixel (24bp)
// allocate enough memory to hold the pixel data in client memory
data = new byte[BitmapLength]; // Get windows to do the dirty work of converting the BMP into the format needed by OpenGL
// if file is already 24 bit color then this is a waste of time but makes for short code
// Get the actual Texel data from the BMP object
if (GetDIBits(gldc, (HBITMAP)DIBHandle, 0, sizeY, data, &BMInfo, DIB_RGB_COLORS))
{
NoErrors = true;
convertBGRtoRGB(); // NOTE: BMP is in BGR format but OpenGL needs RGB unless you use GL_BGR_EXT
}
DeleteObject(DIBHandle); // don't need the BMP Object anymore
return NoErrors;
}
// main.cpp
// Creates OpenGL windows using basecode in glutil.h & glutil.cpp
//
// Based on OpenGL tutorials from http://www.zeuscmd.com/tutorials/opengl/
// include our header file
#include "glutil.h"
#include "bmp.h"
// pointer to the OpenGL class located in glutil.h
OpenGL *opengl;
// variables to hold rotation values
float xrot = 0.0f;
float yrot = 0.0f;
// used to store the changes in mouse position
float xdiff = 0.0f;
float ydiff = 0.0f;
// used for zoom in/out
float zval = 5.0f;
// used to store texture
GLuint texture[1];
// simply draws a cube out of 6 quads
void drawBox()
{
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
}
AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
{
FILE *File=NULL; // File Handle
if (!Filename) // Make Sure A Filename Was Given
{
return NULL; // If Not Return NULL
}
File=fopen(Filename,"r"); // Check To See If The File Exists
if (File) // Does The File Exist?
{
fclose(File); // Close The Handle
return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
}
return NULL; // If Load Failed Return NULL
}
int LoadGLTextures() // Load Bitmaps And Convert To Textures
{
int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[0]); // Create The Texture
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
return Status; // Return The Status
}
// initialize any data required for the program
bool init()
{
LoadGLTextures();
// clear our window with grey & draw with black
glClearColor(0.93f, 0.93f, 0.93f, 0.0f);
glColor3f(0.0f, 0.0f, 0.0f);
// enable the depth buffer
glEnable(GL_DEPTH_TEST);
// sets the depth function mode
// ---- draws objects according to depth or the order they were draw
// ---- in the case of equivalent depth
glDepthFunc(GL_LEQUAL);
// clear depth buffer and initialize all the values in it to 1
// this will allow all primatives to appear on the screen
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
// enable texturing
glEnable(GL_TEXTURE_2D);
return true;
}
// contains all info that is rendered to the buffer
void display()
{
// clear color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// place a camera 2 units away from the origin, looking at the origin
gluLookAt(
0.0f, 0.0f, zval, // camera location
0.0f, 0.0f, 0.0f, // camera direction
0.0f, 1.0f, 0.0f); // up axis
// apply rotation transformations
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
// draw the cube, binding the texture to it
drawBox();
glFlush();
}
// when window is resized, objects are resized accordingly
void resize(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// pass the new width and height to the glViewport() function
glViewport(0, 0, w, h);
// 45 degree field-of-view, aspect ratio, near clipping, far clipping
gluPerspective(45.0f, 1.0f * w / h, 1.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// used for any additional processing per frame
void idle()
{
static bool mouseDown = false;
// handles movement of the mouse with the left button clicked
if (opengl->isMouseDownL())
{
if (!mouseDown)
{
mouseDown = true;
xdiff = opengl->getMouseX() - yrot;
ydiff = opengl->getMouseY() + xrot;
}
yrot = opengl->getMouseX() - xdiff;
xrot = -opengl->getMouseY() + ydiff;
}
else
// if mouse button is up, still rotate cube by itself
{
mouseDown = false;
xrot += 0.3f;
yrot += 0.4f;
}
// if 'Page Up' is hit, zoom in
if (opengl->isKeyDown(VK_PRIOR))
{
//opengl->keyUp(VK_PRIOR);
zval += 0.02f;
}
// if 'Page Down' is hit, zoom out
if (opengl->isKeyDown(VK_NEXT))
{
//opengl->keyUp(VK_NEXT);
zval -= 0.02f;
}
}
////////////////////////////////////////////////////////////////////////////////
// MAIN FUNCTION
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
// create and instantiate our OpenGL object
opengl = OpenGL::create();
// assign the init, display and idle functions to our object
opengl->setInitFunc(init);
opengl->setDisplayFunc(display);
opengl->setIdleFunc(idle);
opengl->setResizeFunc(resize);
// create a window by calling the initGL() functions
// --- creates a 500x500 32-bit windowed window
if (!opengl->initGL("OpenGL Test Window", 500, 500, false, 32))
{
return 1;
}
// run message loop to continue the progrem
opengl->runMessageLoop();
return 0;
}