#### Archived

This topic is now archived and is closed to further replies.

# Computer Science Final Project

## Recommended Posts

I am currently taking AP Computer Science A at my high school, and we are working on our final projects. We are allowed to work off of a base code, and I will be using NeHe''s (I hope my teacher will accept an OpenGL program, since we never even did graphics in class, just regular old DOS programming). The project must include classes and at least one AP class (I am using apvector, which is just a class for creating an array). I will be creating a room with a spinning cube inside. I also have implemented a primitive form of shading for the class Draw() function (it darkens the colors towards the back... primitive, I know, but I haven''t reached texture mapping or lighting in the tuts yet). I had a little problem with apvectors and my Cube class, but I have ironed that out. The room looks pretty good right now, and only one thing is keeping me from being "finished." The cube does not spin. Here are a few snippets of code that I thought were relevant. Can anyone figure out my problem? Creating the cube objects:

// Create cube objects

Cube room(6.0f,6.0f,15.0f);
Cube cube(1.0f,1.0f,1.0f);

// Modify cube parameters

room.SetColor(0.5f,0.5f,0.5f);
room.ShowDepth(TRUE);
room.SetPosition(0.0f,-1.0f,-7.0f);
cube.IsRotation(TRUE);
cube.SetColor(0.2f,0.1f,1.0f);
cube.SetPosition(0.0f,-1.0f,-5.0f);
cube.SetRotation(2.0f,1.0f,1.0f,0.0f);

apvector <Cube> cubes(2);
cubes[0] = room;
cubes[1] = cube;

The apvector with the two cubes (yes, the room is a rectangle, but I felt like calling the class Cube) gets passed the the DrawGLScene function:
  DrawGLScene(cubes);				// Draw The Scene
Here is the DrawGLScene function:

int DrawGLScene(apvector <Cube> cubes)								// Here''s Where We Do All The Drawing

{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer

// Draw the objects

for (int i = 0; i < cubes.length(); i++)
{
cubes[i].Draw();
}

return TRUE;								// Everything Went OK

}

The member functions that modify rotation paramaters:

void Cube::IsRotation(BOOL rotation)
{
myRotate = rotation;
}

void Cube::SetRotation(GLfloat change, GLfloat x, GLfloat y, GLfloat z)
{
myChange = change;
myRot[0] = x;
myRot[1] = y;
myRot[2] = z;
}

And finally, the Draw() function, which draws the cube based on all the private data members (I omitted the actual plotting of the vertices and my primitive shading code to save space):

void Cube::Draw()
{
if(amIDefined)
{
glTranslatef(myPosition[0],myPosition[1],myPosition[2]);

if(myRotate)
{
glRotatef(myAngle,myRot[0],myRot[1],myRot[2]);
myAngle += myChange;
}

//Start drawing the cube

(Insert vertice drawing code here)
glEnd();

}
}

Ok, there is all the code I think is relevant for someone to find my problem. If you want anymore code, feel free to ask. I get no errors when I compile, and everything draws to the screen fine, it''s just that the cube sits there and does not spin. Thanks for any help you can provide, Dan Carroll

##### Share on other sites
it looks like you are missing one or a couple of:

glPushMatrix()
glPopMatrix()

look deeper into the NeHe tuts to find out where exactly to call them

-me

##### Share on other sites
Yep. Are you using gluLookAt or something similar? If so, you don't want to use glLoadIdentity, as it will destroy your modelview matrix. Use
glLoadIdentity();gluLookAt(...);for (all cubes) {    glPushMatrix();    glTranslate(...);    ...    // DrawCube    ...    glPopMatrix();}

If you're not using gluLookAt, what do you use?

[edited by - IndirectX on May 1, 2002 8:49:39 PM]

##### Share on other sites

you are definitely missing the push and pop matrix calls which render your translate and rotate openGL calls useless.

-me

##### Share on other sites
Thanks for the quick replies.

IndirectX: I am not using gluLookAt (don''t even know what it is). I am just building the objects using glTranslatef and glVertex3f (very simple stuff here, along the lines of tutorial 5).

Palidine: I don''t think it has anything to do with those Matrix functions, since I have never encountered them before (again, we are looking at complexity along the lines of tutorial 5).

I am pretty sure it is a very simple code/class error that I am not catching. I programmed this without classes and it worked fine. So I am losing something in the modification to my Cube class.

##### Share on other sites
quote:
Original post by Palidine

LOL! I forgot to put it in my pseudocode; that''s fixed.

Erunama: seeing that you do pretty much the same thing as Tutorial 5 does, are you initializing myAngle to 0? Step through your code and make sure that all your variables have reasonable values.

[rant]
I really dislike AP coding conventions, as well as their questions. The worst coding style I''ve ever seen (speaking of questions on the AP test). Intentionally giving you code snippets that will make anyone say "Why the hell did they do that?"

I took APCS A last year in my school, we have 32MB PII boxes with BC++4 and no help files whatsoever. No Win32 fun over there. :D
[/rant]

##### Share on other sites
I think I figured it out. But first some assumptions (if I make the wrong assumptions, the solution might not be correct). I think you use the glRotatef function incorrectly.

assumption: You have myRot[] float 3 array. Does this store the angles the cube is at?

glRotatef works like this:

glRotatef(angle, x, y, z) in which angle is the amount to rotate and x, y and z the axis. if:
x=1.0f
y=0.5f
z=0.0f
then it would rotate (1.0f * angle) degrees on the x axis
(0.5f * angle) degrees on the y axis and
(0.0f * angle) degrees on the z axis.

To rotate correctly on the angles stored in MyRot[] use 3 calls:

glRotatef(MyRot[0], 1.0f, 0.0f, 0.0f);
glRotatef(MyRot[1], 0.0f, 1.0f, 0.0f);
glRotatef(MyRot[2], 0.0f, 0.0f, 1.0f);

Hope this helps

- An eye for an eye will make the world go blind -

##### Share on other sites
Hi everyone !

Erunama, I think your problem comes from your call to glLoadIdentity() since it is used to reinitialize the matrix from wich you are doing your position calculation to the identity matrix. That means that, with this call, you''re rotating your cube by an angle of 2° along your x and y axis from it''s original orientation, not from it''s current orientation. I guess that''s one of the reasons why your cube doesn''t seems like it''s spinning.
Btw you should really use the glPushMatrix() / glPopMatrix() calls since it allows you to do any transformation you want between this two calls without affecting anything that is done outside the calls. I mean this the right way to get your cube spinning indepently from your room. Otherwise your cube and your room would be rotating the same way and you wouldn''t notice the change.
Is the room.myRotate default value false ? That''s another point that you''ve not precised.

So your code might look something like this :

for (int i = 0; i < cubes.length(); i++) {
cubes.Draw();
}

void Cube::Draw(){
if(amIDefined) {

glPushMatrix();
glTranslatef(myPosition[0],myPosition[1],myPosition[2]); if(myRotate) {
glRotatef(myAngle,myRot[0],myRot[1],myRot[2]); myAngle += myChange;
}
//Start drawing the cube
(Insert vertice drawing code here)
glEnd();
glPopMatrix();
}
}

Hope I''ve been clear enough and your demo will be working correctly soon. I''m still learning too and I don''t pretend that this is the answer to your problem, just that this the way I would do it.

Good luck.

##### Share on other sites
Let me clarify some of the questions you guys had.

IndirectX - Yes, I am pretty sure everything is being initialized correctly. Here is my constructor:

    Cube::Cube(GLfloat x, GLfloat y, GLfloat z)  : amIDefined(TRUE),    myLength(z),	myHeight(y),	myWidth(x),	myDepth(FALSE),	myRotate(FALSE),	myAngle(0.0f),	myChange(0.0f),	myRot(3),	myPosition(3),	myColor(3){	// set default position to center of screen	myPosition[0] = 0.0f;	myPosition[1] = 0.0f;	myPosition[2] = 0.0f;	// set default color to white	myColor[0] = 1.0f;	myColor[1] = 1.0f;	myColor[2] = 1.0f;}

And yes, I dislike the whole AP coding stuff too (I take the test May 9th, but I have been doing practice questions in class). I also hate the AP classes they use, such as apmatrix, apstring, and apvector. What is the point of teaching something that we will not use outside of the class? It's not like I am going to bring along my AP files to my first job as a programmer. They should just teach the regular C++ strings and arrays.

smarechal: The array holds the axis for the cube to spin around (so in you example, x, y, and z would be stored in myRot[0], myRot[1], and myRot[2], respectively). The angle is myAngle, which is initialized to 0.0f, and is increased by myChange every time Draw() is called.

Trexmaster: I have not yet tried your code, but let me first enter a rebuttal to what you said. The cube alway starts from it's original position (0 degrees), and I am rotating it by myAngle. But every time Draw() is called, myAngle is increased by myChange. Therefore, through the first five calls, myAngle should be 0.0f, 2.0f, 4.0f, 6.0f, 8.0f. myAngle would continually be increased, therefore spinning.

A few of you have recommended using glPushMatrix() and glPopMatrix(), which I want to avoid using since I have no idea what they do. There must be some bug that I am not catching, because this program worked before I starting using classes (without Push and PopMatrix(), just glLoadIdentity).

Can anyone figure out my problem? Need more code?

Edit: Just for the record, I tried your code Trexmaster and it did not solve the problem. Thanks for your help though.

[edited by - Erunama on May 2, 2002 4:49:50 PM]

##### Share on other sites
the reason for using such a library is becuase it makes exponential easier to get the concpet across. a good teacher will ween you off using the classes so by the end of you sequence you would be using only c++ code and classes you created (ie reimplement some of the basic classes). later on you could begin using STL, and such.

apvector from the code looks very much like an STL template so dont be so sure that you are not just using STL wrappers. though i think the classes you are using are probably designed with more error checking and you can actually see the code. thus be able to understand what is happening and not treat it as a blackbox.

also for reference. dont create varible names with my infront of them to show there are your varibles. it is not required and makes things look wierd. instead pick names that describe the varible, if you like prefixes, put the varible type infront. like flRot or iLength. this is merely a style concern, because it looks a bit unprofessional currrently. you dont need to change it if you dont want to for this project, but i would siggest starting to tear away from that. you probably picked up the habit from tutorials or how the teacher taught things.

##### Share on other sites
Here''s a quick explanation of how matrix stacks work in OpenGL. The main matrix stack is the modelview matrix. This is basically the locator (or coordinates I guess) for where in space the next object is going to be drawn (does that make sense?). Its called a stack because you can pile different matrices on. When you call glLoadIdentity() you are reseting this stack (I think, or maybe just having the top matrix an identity matrix). When you call glTranslate*() or glRotate*() you''re putting another matrix on the stack. The order you put them on the stack matters too. If you translate first, then rotate, the resulting stack is different than had you rotated then translated.

How glPushMatrix() and glPopMatrix() work is you can ''push the stack'' and that will save that place. After a push you may add more transforms, but when you pop, everything you added after the push will be erased, and it''ll be in the same position it was when you pushed. You can push multiple times, and the pop will revert the stack to the most recent push. I wonder if I''m making this seem a whole lot harder than it really is...?

--Buzzy

##### Share on other sites
Well, the explanation kind of makes sense, but I am really not looking into matrix stacks right now. I am more concerned with getting this program to run correctly. There have been a lot of helpful, concerned comments, but I still can''t get the cube to spin. I think the solution might be a lot simpler than some of you imagine, since the original program (without classes) worked perfectly (a simple glLoadIdentity, translate, rotate, and then draw).

What''s going wrong in my code?

p.s.: a person, the reason I use ''my'' is because I was taught to use it in order to mark the private data members. I think it is kind of helpful and it makes sense. While it may not be the best way to do it, I was taught that way, and since this project is going to be graded by my teacher, I better use the techniques she teaches.

##### Share on other sites
quote:
Original post by a person

also for reference. dont create varible names with my infront of them to show there are your varibles. it is not required and makes things look wierd. instead pick names that describe the varible, if you like prefixes, put the varible type infront. like flRot or iLength. this is merely a style concern, because it looks a bit unprofessional currrently. you dont need to change it if you dont want to for this project, but i would siggest starting to tear away from that. you probably picked up the habit from tutorials or how the teacher taught things.

--begin 100% subjective ranting--

The my prefixing is also enforced in coding style at at least one of the top 8 CS universities, and presumably will spread more and more. Its very convienant for declaring instance variables/member variables. And looks much more logical than some of the other notations I have seen such as m_someVar; Incidentally the notation spreads further to inherited public vars which should be prefixed with our. Ie: ourSomeVar. The type specifier prefixes are also specified, so a boolean instance var would be: bMyDone;

Very easy to understand and read at a glance. The example you gave, iLength gives no indication as to what type of variable it is.. I suppose you prefer m_iLength, g_iLength??? *shudder*

--end 100% subjective ranting--

##### Share on other sites
Ahem.. do you have a loop around your call to DrawGLScene(cubes); ? hmmmm

##### Share on other sites
Do this:

for(int i = 0; i <= 10000; i++)
{

glPushMatrix();

glRotatef(i, 1, 1, 1);

glBegin(GL_TRIANGLES);

glVertex3f(-1, 0, 0);
glVertex3f(0, 1, 0);
glVertex3f(1, 0, 0);

// The above just draws a flat triangle

glEnd();

glPopMatrix();

}

After this you should see the flat triangle spinning. You can draw other objects after the glPopMatrix() line... just the flat triangle will spin.

You NEED to call glPushMatrix() and glPopMatrix() to tell OpenGL to rotate just the triangle, otherwise it will spin all the world. Calling them, just objects beeing drawed between them will be affected by the rotation.

Try this code, you'll see.

See you!

[edited by - ChacaL on May 2, 2002 12:55:48 AM]

[edited by - ChacaL on May 3, 2002 2:35:19 AM]

##### Share on other sites
Domninus: Yes, I am working off NeHe''s base code, so my Main function is exactly the same (except that I declare the objects within Main and pass an apvector to DrawGLScene, rather than passing nothing).

Chacal: Well, I can definitely see how that works, but I don''t like the way it works at all. It will have to go through the for loop 10000 times before jumping out of the loop, which means the program will not monitor for any keystrokes during that time. Also, when it reaches the end, the angle will be 10000. When the function is called the next time, the angle will be 0, and since 10000 is not a multiple of 360 (I don''t think it is), there will be a slight ''skip.''

##### Share on other sites
Well, since it seems like no one can find the problem, I might as well post all of the code.

I will do each file in a seperate post (not sure if there is a length restriction).

My main file (final_project.cpp):

     /**************************************************************************|                       AP Computer Science A                                ||                          FINAL PROJECT                                     ||                                                                            ||                      Created by: Dan Carroll                               ||                                                                            ||  Base code created by Jeff Molofee (NeHe)                                  ||	  - code is available for download at http://nehe.gamedev.net/           ||	  - Jeff's tutorials were used to gain an understanding of the OpenGL    ||	     API and to learn the commands necessary for this particular         ||		 project. While this program is simplistic, it will be used as       ||		 the basis for further exploration in 3d graphics programming.       ||                                                                            ||  Code modified to display a rotating cube inside a rectangular room        ||	- A Cube class was created to draw cubes of various sizes and colors     ||		(rectangular cubes can also be created)                              ||	- The apvector class is being utilized to hold multiple Cube objects     ||		and allow for more than one cube to be drawn easily (by only         ||		sending one apvector to the DrawGLScene function, rather than        ||		individual objects). The apvector class is also being used to hold	 ||		variables for the cube's color, position, and rotation parameters.	 ||                                                                            ||                                                                            ||  Last modified: May 3, 2002		                                         ||                                                                            | \**************************************************************************/#include <windows.h>								// Header File For Windows#include <gl\gl.h>								// Header File For The OpenGL32 Library#include <gl\glu.h>								// Header File For The GLu32 Library#include <gl\glaux.h>								// Header File For The GLaux Library#include "cube.h"								// Header file for the Cube class#include "apvector.h"							// Header file for the AP vector classHGLRC		hRC=NULL;							// Permanent Rendering ContextHDC		hDC=NULL;							// Private GDI Device ContextHWND		hWnd=NULL;							// Holds Our Window HandleHINSTANCE	hInstance;							// Holds The Instance Of The ApplicationBOOL	keys[256];								// Array Used For The Keyboard RoutineBOOL	active=TRUE;								// Window Active Flag Set To TRUE By DefaultBOOL	fullscreen=TRUE;							// Fullscreen Flag Set To Fullscreen Mode By DefaultGLfloat cuberot;							// Rotation angle for the spinning cubeLRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);				// Declaration For WndProcGLvoid ReSizeGLScene(GLsizei width, GLsizei height)				// Resize And Initialize The GL Window{	if (height==0)								// Prevent A Divide By Zero By	{		height=1;							// Making Height Equal One	}	glViewport(0, 0, width, height);					// Reset The Current Viewport	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix	glLoadIdentity();							// Reset The Projection Matrix	// Calculate The Aspect Ratio Of The Window	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);	glMatrixMode(GL_MODELVIEW);						// Select The Modelview Matrix	glLoadIdentity();							// Reset The Modelview Matrix}int InitGL(GLvoid)								// All Setup For OpenGL Goes Here{	glShadeModel(GL_SMOOTH);						// Enables Smooth Shading	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);					// Black Background	glClearDepth(1.0f);							// Depth Buffer Setup	glEnable(GL_DEPTH_TEST);						// Enables Depth Testing	glDepthFunc(GL_LEQUAL);							// The Type Of Depth Test To Do	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations	return TRUE;								// Initialization Went OK}int DrawGLScene(apvector <Cube> cubes)								// Here's Where We Do All The Drawing{	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer	// Draw the objects	for (int i = 0; i < cubes.length(); i++)	{		glLoadIdentity();		cubes[i].Draw();	}/*	glLoadIdentity();	glTranslatef(0.0f,-1.0f,-7.0f);	cubes[0].Draw();	glLoadIdentity();	glTranslatef(0.0f,-1.0f,-5.0f);	cubes[1].Draw();*/	return TRUE;								// Everything Went OK}GLvoid KillGLWindow(GLvoid)							// Properly Kill The Window{	if (fullscreen)								// Are We In Fullscreen Mode?	{		ChangeDisplaySettings(NULL,0);					// If So Switch Back To The Desktop		ShowCursor(TRUE);						// Show Mouse Pointer	}	if (hRC)								// Do We Have A Rendering Context?	{		if (!wglMakeCurrent(NULL,NULL))					// Are We Able To Release The DC And RC Contexts?		{			MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		}		if (!wglDeleteContext(hRC))					// Are We Able To Delete The RC?		{			MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		}		hRC=NULL;							// Set RC To NULL	}	if (hDC && !ReleaseDC(hWnd,hDC))					// Are We Able To Release The DC	{		MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hDC=NULL;							// Set DC To NULL	}	if (hWnd && !DestroyWindow(hWnd))					// Are We Able To Destroy The Window?	{		MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hWnd=NULL;							// Set hWnd To NULL	}	if (!UnregisterClass("OpenGL",hInstance))			// Are We Able To Unregister Class	{		MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hInstance=NULL;									// Set hInstance To NULL	}}BOOL CreateGLWindow(char* title, int width, int height, int bits, BOOL fullscreenflag){	GLuint		PixelFormat;						// Holds The Results After Searching For A Match	WNDCLASS	wc;							// Windows Class Structure	DWORD		dwExStyle;						// Window Extended Style	DWORD		dwStyle;						// Window Style	RECT WindowRect;							// Grabs Rectangle Upper Left / Lower Right Values	WindowRect.left=(long)0;						// Set Left Value To 0	WindowRect.right=(long)width;						// Set Right Value To Requested Width	WindowRect.top=(long)0;							// Set Top Value To 0	WindowRect.bottom=(long)height;						// Set Bottom Value To Requested Height	fullscreen=fullscreenflag;						// Set The Global Fullscreen Flag	hInstance		= GetModuleHandle(NULL);			// Grab An Instance For Our Window	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		// Redraw On Move, And Own DC For Window	wc.lpfnWndProc		= (WNDPROC) WndProc;				// WndProc Handles Messages	wc.cbClsExtra		= 0;						// No Extra Window Data	wc.cbWndExtra		= 0;						// No Extra Window Data	wc.hInstance		= hInstance;					// Set The Instance	wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer	wc.hbrBackground	= NULL;						// No Background Required For GL	wc.lpszMenuName		= NULL;						// We Don't Want A Menu	wc.lpszClassName	= "OpenGL";					// Set The Class Name	if (!RegisterClass(&wc))						// Attempt To Register The Window Class	{		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Exit And Return FALSE	}	if (fullscreen)								// Attempt Fullscreen Mode?	{		DEVMODE dmScreenSettings;					// Device Mode		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));		// Makes Sure Memory's Cleared		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure		dmScreenSettings.dmPelsWidth	= width;			// Selected Screen Width		dmScreenSettings.dmPelsHeight	= height;			// Selected Screen Height		dmScreenSettings.dmBitsPerPel	= bits;				// Selected Bits Per Pixel		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)		{			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.			if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)			{				fullscreen=FALSE;				// Select Windowed Mode (Fullscreen=FALSE)			}			else			{				// Pop Up A Message Box Letting User Know The Program Is Closing.				MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);				return FALSE;					// Exit And Return FALSE			}		}	}	if (fullscreen)								// Are We Still In Fullscreen Mode?	{		dwExStyle=WS_EX_APPWINDOW;					// Window Extended Style		dwStyle=WS_POPUP;						// Windows Style		ShowCursor(FALSE);						// Hide Mouse Pointer	}	else	{		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows Style	}	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size	if (!(hWnd=CreateWindowEx(	dwExStyle,				// Extended Style For The Window					"OpenGL",				// Class Name					title,					// Window Title					WS_CLIPSIBLINGS |			// Required Window Style					WS_CLIPCHILDREN |			// Required Window Style					dwStyle,				// Selected Window Style					0, 0,					// Window Position					WindowRect.right-WindowRect.left,	// Calculate Adjusted Window Width					WindowRect.bottom-WindowRect.top,	// Calculate Adjusted Window Height					NULL,					// No Parent Window					NULL,					// No Menu					hInstance,				// Instance					NULL)))					// Don't Pass Anything To WM_CREATE	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be	{		sizeof(PIXELFORMATDESCRIPTOR),					// Size Of This Pixel Format Descriptor		1,								// Version Number		PFD_DRAW_TO_WINDOW |						// Format Must Support Window		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL		PFD_DOUBLEBUFFER,						// Must Support Double Buffering		PFD_TYPE_RGBA,							// Request An RGBA Format		bits,								// Select Our Color Depth		0, 0, 0, 0, 0, 0,						// Color Bits Ignored		0,								// No Alpha Buffer		0,								// Shift Bit Ignored		0,								// No Accumulation Buffer		0, 0, 0, 0,							// Accumulation Bits Ignored		16,								// 16Bit Z-Buffer (Depth Buffer)		0,								// No Stencil Buffer		0,								// No Auxiliary Buffer		PFD_MAIN_PLANE,							// Main Drawing Layer		0,								// Reserved		0, 0, 0								// Layer Masks Ignored	};	if (!(hDC=GetDC(hWnd)))							// Did We Get A Device Context?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))				// Did Windows Find A Matching Pixel Format?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if(!SetPixelFormat(hDC,PixelFormat,&pfd))				// Are We Able To Set The Pixel Format?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if (!(hRC=wglCreateContext(hDC)))					// Are We Able To Get A Rendering Context?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if(!wglMakeCurrent(hDC,hRC))						// Try To Activate The Rendering Context	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	ShowWindow(hWnd,SW_SHOW);						// Show The Window	SetForegroundWindow(hWnd);						// Slightly Higher Priority	SetFocus(hWnd);								// Sets Keyboard Focus To The Window	ReSizeGLScene(width, height);						// Set Up Our Perspective GL Screen	if (!InitGL())								// Initialize Our Newly Created GL Window	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	return TRUE;								// Success}LRESULT CALLBACK WndProc(	HWND	hWnd,					// Handle For This Window				UINT	uMsg,					// Message For This Window				WPARAM	wParam,					// Additional Message Information				LPARAM	lParam)					// Additional Message Information{	switch (uMsg)								// Check For Windows Messages	{		case WM_ACTIVATE:						// Watch For Window Activate Message		{			if (!HIWORD(wParam))					// Check Minimization State			{				active=TRUE;					// Program Is Active			}			else			{				active=FALSE;					// Program Is No Longer Active			}			return 0;						// Return To The Message Loop		}		case WM_SYSCOMMAND:						// Intercept System Commands		{			switch (wParam)						// Check System Calls			{				case SC_SCREENSAVE:				// Screensaver Trying To Start?				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?				return 0;					// Prevent From Happening			}			break;							// Exit		}		case WM_CLOSE:							// Did We Receive A Close Message?		{			PostQuitMessage(0);					// Send A Quit Message			return 0;						// Jump Back		}		case WM_KEYDOWN:						// Is A Key Being Held Down?		{			keys[wParam] = TRUE;					// If So, Mark It As TRUE			return 0;						// Jump Back		}		case WM_KEYUP:							// Has A Key Been Released?		{			keys[wParam] = FALSE;					// If So, Mark It As FALSE			return 0;						// Jump Back		}		case WM_SIZE:							// Resize The OpenGL Window		{			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));		// LoWord=Width, HiWord=Height			return 0;						// Jump Back		}	}	// Pass All Unhandled Messages To DefWindowProc	return DefWindowProc(hWnd,uMsg,wParam,lParam);}int WINAPI WinMain(	HINSTANCE	hInstance,				// Instance			HINSTANCE	hPrevInstance,				// Previous Instance			LPSTR		lpCmdLine,				// Command Line Parameters			int		nCmdShow)				// Window Show State{	MSG	msg;								// Windows Message Structure	BOOL	done=FALSE;							// Bool Variable To Exit Loop	// Ask The User Which Screen Mode They Prefer	if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)	{		fullscreen=FALSE;						// Windowed Mode	}	// Create Our OpenGL Window	if (!CreateGLWindow("Dan Carroll's Final Project",640,480,16,fullscreen))	{		return 0;							// Quit If Window Was Not Created	}	// Create cube objects	Cube room(6.0f,6.0f,15.0f);	Cube cube(1.0f,1.0f,1.0f);	// Modify cube parameters	room.SetColor(0.5f,0.5f,0.5f);	room.ShowDepth(TRUE);	room.SetPosition(0.0f,-1.0f,-7.0f);	cube.IsRotation(TRUE);	cube.SetColor(0.2f,0.1f,1.0f);	cube.SetPosition(0.0f,-1.0f,-5.0f);	cube.SetRotation(2.0f,1.0f,1.0f,0.0f);	apvector <Cube> cubes(2);	cubes[0] = room;	cubes[1] = cube;	while(!done)								// Loop That Runs Until done=TRUE	{		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))			// Is There A Message Waiting?		{			if (msg.message==WM_QUIT)				// Have We Received A Quit Message?			{				done=TRUE;					// If So done=TRUE			}			else							// If Not, Deal With Window Messages			{				TranslateMessage(&msg);				// Translate The Message				DispatchMessage(&msg);				// Dispatch The Message			}		}		else								// If There Are No Messages		{			// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()			if (active)						// Program Active?			{				if (keys[VK_ESCAPE])				// Was ESC Pressed?				{					done=TRUE;				// ESC Signalled A Quit				}				else						// Not Time To Quit, Update Screen				{					DrawGLScene(cubes);				// Draw The Scene					SwapBuffers(hDC);			// Swap Buffers (Double Buffering)				}			}			if (keys[VK_F1])					// Is F1 Being Pressed?			{				keys[VK_F1]=FALSE;				// If So Make Key FALSE				KillGLWindow();					// Kill Our Current Window				fullscreen=!fullscreen;				// Toggle Fullscreen / Windowed Mode				// Recreate Our OpenGL Window				if (!CreateGLWindow("Dan Carroll's Final Project",640,480,16,fullscreen))				{					return 0;				// Quit If Window Was Not Created				}			}		}	}	// Shutdown	KillGLWindow();								// Kill The Window	return (msg.wParam);							// Exit The Program}

Edit: Some of the formatting got messed up, but the code is all there. And for some reason it treats a large portion of the code as commented out, but trust me, it is not!

[edited by - Erunama on May 3, 2002 4:26:38 PM]

##### Share on other sites
I'll squeeze two header files into one here.

My Cube class header file (cube.h):

    #ifndef _CUBE_H#define _CUBE_H#include <windows.h>								// Header File For Windows#include <gl\gl.h>								// Header File For The OpenGL32 Library#include <gl\glu.h>								// Header File For The GLu32 Library#include <gl\glaux.h>								// Header File For The GLaux Library#include "apvector.h"class Cube{  public://///////////////////////////////////////////////////////////////////// constructors	Cube();	Cube(GLfloat length, GLfloat width, GLfloat height);/////////////////////////////////////////////////////////////////////// destructor	~Cube();/////////////////////////////////////////////////////////////////////// modifying functions	void SetDimensions(GLfloat length, GLfloat width, GLfloat height);	void SetColor(GLfloat red, GLfloat green, GLfloat blue);	void ShowDepth(BOOL depth);	void IsRotation(BOOL rotation);	void SetRotation(GLfloat change, GLfloat x, GLfloat y, GLfloat z);	void SetPosition(GLfloat x, GLfloat y, GLfloat z);		void Draw();	// uses private data members to draw cube on the screen  private:	// cube size variables	GLfloat myHeight;			// height of the cube (along y axis)	GLfloat myLength;			// length of the cube (along z axis)	GLfloat myWidth;			// width of the cube (along x axis)	// cube state variables	BOOL myDepth;				// shade the cube?	BOOL myRotate;				// rotate the cube?	BOOL amIDefined;			// draw the cube?	// rotation variables	apvector<GLfloat> myRot;	// vector holding the rotational axis	GLfloat myAngle;			// the cube's current angle	GLfloat myChange;			// the rate that the cube spins	apvector<GLfloat> myPosition;	// vector holding the position values	apvector<GLfloat> myColor;		// vector holding the color values (R,G,B)};#endif  And the apvector header file (apvector.h):      #ifndef _APVECTOR_H#define _APVECTOR_H// *******************************************************************// Last Revised: 8/14/98, abort changed to exit//// January 13,1998, added explicit to int constructor// APCS vector class template//// implements "safe" (range-checked) arrays// examples are given at the end of this file// *******************************************************************// If your compiler supports the keyword explicit, comment out the// #define explicit line below, leaving the #define means explicit// is ignored, but doesn't generate an error////   This will disallow a typically erroneous implicit type-conversion://   vector<int> v( 10 );//   v = 0; // Oops!! Allowed because of implicit type-con2lversion.#define explicittemplate <class itemType>class apvector{  public:  // constructors/destructor    apvector( );                        // default constructor (size==0)    explicit apvector( int size );      // initial size of vector is size    apvector( int size, const itemType & fillValue ); // all entries == fillValue    apvector( const apvector & vec );   // copy constructor    ~apvector( );                       // destructor  // assignment    const apvector & operator = ( const apvector & vec );  // accessors    int  length( ) const;                   // capacity of vector  // indexing    itemType &       operator [ ] ( int index );       // indexing with range checking    const itemType & operator [ ] ( int index ) const; // indexing with range checking  // modifiers    void resize( int newSize );             // change size dynamically;                                            // can result in losing values  private:    int  mySize;                            // # elements in array    itemType * myList;                      // array used for storage};// *******************************************************************//  Specifications for vector functions////  The template parameter itemType must satisfy the following two conditions://   (1) itemType has a 0-argument constructor//   (2) operator = is defined for itemType//  Any violation of these conditions may result in compilation failure.////  Any violation of a function's precondition will result in an error message//  followed by a call to exit.////  constructors/destructor////   apvector( )//     postcondition: vector has a capacity of 0 items, and therefore it will//                    need to be resized////   apvector( int size )//     precondition: size >= 0//     postcondition: vector has a capacity of size items////   apvector( int size, const itemType & fillValue )//     precondition: size >= 0//     postcondition: vector has a capacity of size items, all of which are set//                    by assignment to fillValue after default construction////   apvector( const apvector & vec )//     postcondition: vector is a copy of vec////   ~apvector( )//     postcondition: vector is destroyed////  assignment////   const apvector & operator = ( const apvector & rhs )//     postcondition: normal assignment via copying has been performed;//                    if vector and rhs were different sizes, vector//                    has been resized to  match the size of rhs////  accessor////   int  length( ) const//     postcondition: returns vector's size (number of memory cells//                    allocated for vector)////  indexing////   itemType &       operator [ ] ( int k )       -- index into nonconst vector//   const itemType & operator [ ] ( int k ) const -- index into const vector//     description: range-checked indexing, returning kth item//     precondition: 0 <= k < length()//     postcondition: returns the kth item////  modifier////   void resize( int newSize )//     description:  resizes the vector to newSize elements//     precondition: the current capacity of vector is length; newSize >= 0////     postcondition: the current capacity of vector is newSize; for each k//                    such that 0 <= k <= min(length, newSize), vector[k]//                    is a copy of the original; other elements of vector are//                    initialized using the 0-argument itemType constructor//                    Note: if newSize < length, elements may be lost////  examples of use//      apvector<int> v1;         // 0-element vector//      apvector<int> v2(4);      // 4-element vector//      apvector<int> v3(4, 22);  // 4-element vector, all elements == 22.#include "apvector.cpp"#endif

Edit: Some weird green font stuff going on here...

[edited by - Erunama on May 3, 2002 4:32:46 PM]

##### Share on other sites
And finally, my Cube class source code (cube.cpp):

        #include <windows.h>								// Header File For Windows#include <gl\gl.h>								// Header File For The OpenGL32 Library#include <gl\glu.h>								// Header File For The GLu32 Library#include <gl\glaux.h>								// Header File For The GLaux Library#include "cube.h"								// Header file for the Cube class#include "apvector.h"// constructorsCube::Cube()  : amIDefined(FALSE){}Cube::Cube(GLfloat x, GLfloat y, GLfloat z)  : amIDefined(TRUE),    myLength(z),	myHeight(y),	myWidth(x),	myDepth(FALSE),	myRotate(FALSE),	myAngle(0.0f),	myChange(0.0f),	myRot(3),	myPosition(3),	myColor(3){	// set default position to center of screen	myPosition[0] = 0.0f;	myPosition[1] = 0.0f;	myPosition[2] = 0.0f;	// set default color to white	myColor[0] = 1.0f;	myColor[1] = 1.0f;	myColor[2] = 1.0f;}Cube::~Cube(){}// modifying functionsvoid Cube::SetDimensions(GLfloat x, GLfloat y, GLfloat z){	myLength = z;	myWidth = x;	myHeight = y;}void Cube::SetColor(GLfloat red, GLfloat green, GLfloat blue){	myColor[0] = red;	myColor[1] = green;	myColor[2] = blue;}void Cube::ShowDepth(BOOL depth){	myDepth = depth;}void Cube::IsRotation(BOOL rotation){	myRotate = rotation;}void Cube::SetRotation(GLfloat change, GLfloat x, GLfloat y, GLfloat z){	myChange = change;	myRot[0] = x;	myRot[1] = y;	myRot[2] = z;}void Cube::SetPosition(GLfloat x, GLfloat y, GLfloat z){	myPosition[0] = x;	myPosition[1] = y;	myPosition[2] = z;}void Cube::Draw(){	if(amIDefined)	{		glTranslatef(myPosition[0],myPosition[1],myPosition[2]);		if(myRotate)		{			glRotatef(myAngle,myRot[0],myRot[1],myRot[2]);			myAngle += myChange;		}		//Start drawing the cube		glBegin(GL_QUADS);			glColor3f(myColor[0],myColor[1],myColor[2]);						// Draw the left side of the cube			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			if(myDepth)				glColor3f(myColor[0] - 0.15f,myColor[1] - 0.15f,myColor[2] - 0.15f);			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));			glColor3f(myColor[0],myColor[1],myColor[2]);			// Draw the right side of the cube			glVertex3f((myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			if(myDepth)				glColor3f(myColor[0] - 0.15f,myColor[1] - 0.15f,myColor[2] - 0.15f);			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));			glVertex3f((myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));					// Draw the back of the cube			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));			glVertex3f((myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));			glColor3f(myColor[0],myColor[1],myColor[2]);			// Draw the front of the cube			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			glVertex3f((myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			if(myDepth)				glColor3f(myColor[0] - 0.2f,myColor[1] - 0.2f,myColor[2] - 0.2f);			// Draw the top of the cube			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			glVertex3f((myWidth/2.0f),(myHeight/2.0f),(myLength/2.0f));			if(myDepth)				glColor3f(myColor[0] - 0.25f,myColor[1] - 0.25f,myColor[2] - 0.25f);			glVertex3f((myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),(myHeight/2.0f),-(myLength/2.0f));			// Draw the bottom of the cube			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),(myLength/2.0f));			if(myDepth)				glColor3f(myColor[0] - 0.25f,myColor[1] - 0.25f,myColor[2] - 0.25f);			glVertex3f((myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));			glVertex3f(-(myWidth/2.0f),-(myHeight/2.0f),-(myLength/2.0f));					glEnd();	}}  Feel free to use this class in your own projects.  The shading technique is really primitive, but I actually think it looks kind of decent.  It took me a long time to figure out how to do the Draw function by using just three variables, but it works great!Here is the apvector.cpp file:[source]// *******************************************************************//  Last Revised: 8/14/98//                changed abort to exit////  APCS vector class  IMPLEMENTATION////  see vector.h for complete documentation of functions////  vector class consistent with a subset of the standard C++ vector class//  as defined in the draft ANSI standard (part of standard template library)// *******************************************************************#include <stdlib.h>#include <assert.h>#include <iostream.h>#include "apvector.h"template <class itemType>apvector<itemType>::apvector()//postcondition: vector has a capacity of 0 items, and therefore it will//               need to be resized    : mySize(0),      myList(0){}template <class itemType>apvector<itemType>::apvector(int size)// precondition: size >= 0// postcondition: vector has a capacity of size items   : mySize(size),     myList(new itemType[size]){}template <class itemType>apvector<itemType>::apvector(int size, const itemType & fillValue)// precondition: size >= 0// postcondition: vector has a capacity of size items, all of which are set//                by assignment to fillValue after default construction    : mySize(size),      myList(new itemType[size]){    int k;    for(k = 0; k < size; k++)    {        myList[k] = fillValue;    }}template <class itemType>apvector<itemType>::apvector(const apvector<itemType> & vec)// postcondition: vector is a copy of vec    : mySize(vec.length()),      myList(new itemType[mySize]){    int k;        // copy elements    for(k = 0; k < mySize; k++){        myList[k] = vec.myList[k];    }}template <class itemType>apvector<itemType>::~apvector ()// postcondition: vector is destroyed{    delete [] myList;}template <class itemType>const apvector<itemType> &apvector<itemType>::operator = (const apvector<itemType> & rhs)// postcondition: normal assignment via copying has been performed;//                if vector and rhs were different sizes, vector//                has been resized to  match the size of rhs{    if (this != &rhs)                           // don't assign to self!    {        delete [] myList;                       // get rid of old storage        mySize = rhs.length();        myList = new itemType [mySize];         // allocate new storage            // copy rhs        int k;        for(k=0; k < mySize; k++)        {            myList[k] = rhs.myList[k];        }    }    return *this;                               // permit a = b = c = d}template <class itemType>int apvector<itemType>::length() const// postcondition: returns vector's size (number of memory cells//                allocated for vector){    return mySize;}template <class itemType>itemType & apvector<itemType>::operator [] (int k)// description: range-checked indexing, returning kth item// precondition: 0 <= k < length()// postcondition: returns the kth item{    if (k < 0 || mySize <= k)    {        cerr << "Illegal vector index: " << k << " max index = ";        cerr << (mySize-1) << endl;        exit(1);    }    return myList[k];}template <class itemType>const itemType & apvector<itemType>::operator [] (int k) const// safe indexing, returning const reference to avoid modification// precondition: 0 <= index < length// postcondition: return index-th item// exception: exits if index is out-of-bounds{    if (k < 0 || mySize <= k)    {        cerr << "Illegal vector index: " << k << " max index = ";        cerr << (mySize-1) << endl;        exit(1);    }    return myList[k];}template <class itemType>void apvector<itemType>::resize(int newSize)// description:  resizes the vector to newSize elements// precondition: the current capacity of vector is length(); newSize >= 0// postcondition: the current capacity of vector is newSize; for each k//                such that 0 <= k <= min(length, newSize), vector[k]//                is a copy of the original; other elements of vector are//                initialized using the 0-argument itemType constructor//                Note: if newSize < length, elements may be lost{    int k;    int numToCopy = newSize < mySize ? newSize : mySize;         // allocate new storage and copy element into new storage    itemType * newList = new itemType[newSize];    for(k=0; k < numToCopy; k++)    {        newList[k] = myList[k];    }    delete [] myList;                      // de-allocate old storage    mySize = newSize;                      // assign new storage/size    myList = newList;}

Ok! Now that there are no questions about exactly what my code is, can anyone figure out my problem?

Edit: Tried to fix some errors, but there seems to be a problem with the 'source' tags. Before you ask about missing header files or the like, make sure you scroll over because cut-and-paste seems to have screwed with things like the carriage returns

Edit #2: Hrmmmm, now the apvector.cpp code has disappeared. Hopefully, it will come back now. If not, I don't think you really need it to analyze my code.

[edited by - Erunama on May 3, 2002 4:42:42 PM]

[edited by - Erunama on May 3, 2002 4:44:51 PM]

##### Share on other sites
Cool i am taking AP computer science part AB

##### Share on other sites
Since you posted the code, can you do us all a favor and zip your whole project and put it up somewhere so that we won''t have to mess with files, project settings and the such?

##### Share on other sites
Enurama, the code above is not for you to use in your project. It was just to demonstrate the use of glPushMatrix() and glPopMatrix().

And, definatelly, you WILL NEED to use them, as you want some vertices to be rotated (the cube) and others to be static (the room).

The For loop just gives an increasing number... this way you could copy/past that code in a OpenGL basecode and see what I mean.

Definatelly, LEARN glPushMatrix() and glPopMatrix().

Bye!

##### Share on other sites
Ok, for anyone who wanted the project files, here you go:
http://opengl.0catch.com/final_project.zip

(I just registered for a ZeroCatch account... I am surprised that the opengl username was not taken). Just a note, I am using Microsoft Visual C++ version 4. I am not sure whether or not the project files will work on the newer versions, but at the very least, you''ll get the necessary source and header files (if the workspace does not work, just go in and link to the OGL libraries, then include apvector.cpp and cube.cpp to your workspace).

ChacaL: I will learn Push and Pop eventually, but I have no need for them yet. This program can work without them (I know because I did it without classes). I don''t see the reason of putting something in there that I do not need and do not fully understand. If you want proof that this scenario works without glPushMatrix and glPopMatrix, check out my old code:

  #include <windows.h>								// Header File For Windows#include <gl\gl.h>								// Header File For The OpenGL32 Library#include <gl\glu.h>								// Header File For The GLu32 Library#include <gl\glaux.h>								// Header File For The GLaux Library#include "cube.h"								// Header file for the Cube class#include "apvector.h"							// Header file for the AP vector classHGLRC		hRC=NULL;							// Permanent Rendering ContextHDC		hDC=NULL;							// Private GDI Device ContextHWND		hWnd=NULL;							// Holds Our Window HandleHINSTANCE	hInstance;							// Holds The Instance Of The ApplicationBOOL	keys[256];								// Array Used For The Keyboard RoutineBOOL	active=TRUE;								// Window Active Flag Set To TRUE By DefaultBOOL	fullscreen=TRUE;							// Fullscreen Flag Set To Fullscreen Mode By DefaultGLfloat cuberot;							// Rotation angle for the spinning cubeLRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);				// Declaration For WndProcGLvoid ReSizeGLScene(GLsizei width, GLsizei height)				// Resize And Initialize The GL Window{	if (height==0)								// Prevent A Divide By Zero By	{		height=1;							// Making Height Equal One	}	glViewport(0, 0, width, height);					// Reset The Current Viewport	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix	glLoadIdentity();							// Reset The Projection Matrix	// Calculate The Aspect Ratio Of The Window	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);	glMatrixMode(GL_MODELVIEW);						// Select The Modelview Matrix	glLoadIdentity();							// Reset The Modelview Matrix}int InitGL(GLvoid)								// All Setup For OpenGL Goes Here{	glShadeModel(GL_SMOOTH);						// Enables Smooth Shading	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);					// Black Background	glClearDepth(1.0f);							// Depth Buffer Setup	glEnable(GL_DEPTH_TEST);						// Enables Depth Testing	glDepthFunc(GL_LEQUAL);							// The Type Of Depth Test To Do	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations	return TRUE;								// Initialization Went OK}int DrawGLScene(GLvoid)								// Here''s Where We Do All The Drawing{	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			// Clear The Screen And The Depth Buffer	glLoadIdentity();							// Reset The Current Modelview Matrix	glTranslatef(0.0f,-3.0f,-10.0f);	// Move into the screen a down a little bit	// Draw the room	glBegin(GL_QUADS);		glColor3f(0.5f,0.5f,0.5f);		// Set color for walls (grey)		// Draw left wall first		glVertex3f(-3.0f,5.0f,6.0f);		glVertex3f(-3.0f,0.0f,6.0f);		glVertex3f(-3.0f,0.0f,-5.0f);		glVertex3f(-3.0f,5.0f,-5.0f);		// Draw right wall next		glVertex3f(3.0f,5.0f,6.0f);		glVertex3f(3.0f,0.0f,6.0f);		glVertex3f(3.0f,0.0f,-5.0f);		glVertex3f(3.0f,5.0f,-5.0f);		// Draw back wall next		glVertex3f(-3.0f,5.0f,-5.0f);		glVertex3f(-3.0f,0.0f,-5.0f);		glVertex3f(3.0f,0.0f,-5.0f);		glVertex3f(3.0f,5.0f,-5.0f);		// Fourth wall is not needed (behind screen)		glColor3f(0.3f,0.3f,0.3f);		// Set color for ceiling and floor (dark grey)		// Draw ceiling		glVertex3f(-3.0f,5.0f,6.0f);		glVertex3f(-3.0f,5.0f,-5.0f);		glVertex3f(3.0f,5.0f,-5.0f);		glVertex3f(3.0f,5.0f,6.0f);		// Draw floor		glVertex3f(-3.0f,0.0f,6.0f);		glVertex3f(-3.0f,0.0f,-5.0f);		glVertex3f(3.0f,0.0f,-5.0f);		glVertex3f(3.0f,0.0f,6.0f);	glEnd();	glLoadIdentity();		// Move to the center of the screen and reset the axis	glTranslatef(0.0f,-0.5f,-5.0f);		// Move to the center of the room	glRotatef(cuberot,1.0f,1.0f,0.0f);	// Rotate the cube along the X and Y axis	// After the room, draw the rotating cube	glBegin(GL_QUADS);		glColor3f(0.1f,0.1f,1.0f);		// Make the cube blue				// Draw the left side of the cube		glVertex3f(0.5f,0.5f,0.5f);		glVertex3f(0.5f,-0.5f,0.5f);		glVertex3f(0.5f,-0.5f,-0.5f);		glVertex3f(0.5f,0.5f,-0.5f);		// Draw the right side of the cube		glVertex3f(-0.5f,0.5f,0.5f);		glVertex3f(-0.5f,-0.5f,0.5f);		glVertex3f(-0.5f,-0.5f,-0.5f);		glVertex3f(-0.5f,0.5f,-0.5f);				// Draw the back of the cube		glVertex3f(0.5f,0.5f,-0.5f);		glVertex3f(0.5f,-0.5f,-0.5f);		glVertex3f(-0.5f,-0.5f,-0.5f);		glVertex3f(-0.5f,0.5f,-0.5f);		// Draw the front of the cube		glVertex3f(0.5f,0.5f,0.5f);		glVertex3f(0.5f,-0.5f,0.5f);		glVertex3f(-0.5f,-0.5f,0.5f);		glVertex3f(-0.5f,0.5f,0.5f);		// Draw the top of the cube		glVertex3f(0.5f,0.5f,0.5f);		glVertex3f(0.5f,0.5f,-0.5f);		glVertex3f(-0.5f,0.5f,-0.5f);		glVertex3f(-0.5f,0.5f,0.5f);		// Draw the bottom of the cube		glVertex3f(0.5f,-0.5f,0.5f);		glVertex3f(0.5f,-0.5f,-0.5f);		glVertex3f(-0.5f,-0.5f,-0.5f);		glVertex3f(-0.5f,-0.5f,0.5f);	glEnd();	cuberot += 0.2f;		// Change the angle of rotation (so that the cube actually rotates)	return TRUE;								// Everything Went OK}GLvoid KillGLWindow(GLvoid)							// Properly Kill The Window{	if (fullscreen)								// Are We In Fullscreen Mode?	{		ChangeDisplaySettings(NULL,0);					// If So Switch Back To The Desktop		ShowCursor(TRUE);						// Show Mouse Pointer	}	if (hRC)								// Do We Have A Rendering Context?	{		if (!wglMakeCurrent(NULL,NULL))					// Are We Able To Release The DC And RC Contexts?		{			MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		}		if (!wglDeleteContext(hRC))					// Are We Able To Delete The RC?		{			MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		}		hRC=NULL;							// Set RC To NULL	}	if (hDC && !ReleaseDC(hWnd,hDC))					// Are We Able To Release The DC	{		MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hDC=NULL;							// Set DC To NULL	}	if (hWnd && !DestroyWindow(hWnd))					// Are We Able To Destroy The Window?	{		MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hWnd=NULL;							// Set hWnd To NULL	}	if (!UnregisterClass("OpenGL",hInstance))			// Are We Able To Unregister Class	{		MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);		hInstance=NULL;									// Set hInstance To NULL	}}BOOL CreateGLWindow(char* title, int width, int height, int bits, BOOL fullscreenflag){	GLuint		PixelFormat;						// Holds The Results After Searching For A Match	WNDCLASS	wc;							// Windows Class Structure	DWORD		dwExStyle;						// Window Extended Style	DWORD		dwStyle;						// Window Style	RECT WindowRect;							// Grabs Rectangle Upper Left / Lower Right Values	WindowRect.left=(long)0;						// Set Left Value To 0	WindowRect.right=(long)width;						// Set Right Value To Requested Width	WindowRect.top=(long)0;							// Set Top Value To 0	WindowRect.bottom=(long)height;						// Set Bottom Value To Requested Height	fullscreen=fullscreenflag;						// Set The Global Fullscreen Flag	hInstance		= GetModuleHandle(NULL);			// Grab An Instance For Our Window	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		// Redraw On Move, And Own DC For Window	wc.lpfnWndProc		= (WNDPROC) WndProc;				// WndProc Handles Messages	wc.cbClsExtra		= 0;						// No Extra Window Data	wc.cbWndExtra		= 0;						// No Extra Window Data	wc.hInstance		= hInstance;					// Set The Instance	wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer	wc.hbrBackground	= NULL;						// No Background Required For GL	wc.lpszMenuName		= NULL;						// We Don''t Want A Menu	wc.lpszClassName	= "OpenGL";					// Set The Class Name	if (!RegisterClass(&wc))						// Attempt To Register The Window Class	{		MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Exit And Return FALSE	}	if (fullscreen)								// Attempt Fullscreen Mode?	{		DEVMODE dmScreenSettings;					// Device Mode		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));		// Makes Sure Memory''s Cleared		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure		dmScreenSettings.dmPelsWidth	= width;			// Selected Screen Width		dmScreenSettings.dmPelsHeight	= height;			// Selected Screen Height		dmScreenSettings.dmBitsPerPel	= bits;				// Selected Bits Per Pixel		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)		{			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.			if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)			{				fullscreen=FALSE;				// Select Windowed Mode (Fullscreen=FALSE)			}			else			{				// Pop Up A Message Box Letting User Know The Program Is Closing.				MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);				return FALSE;					// Exit And Return FALSE			}		}	}	if (fullscreen)								// Are We Still In Fullscreen Mode?	{		dwExStyle=WS_EX_APPWINDOW;					// Window Extended Style		dwStyle=WS_POPUP;						// Windows Style		ShowCursor(FALSE);						// Hide Mouse Pointer	}	else	{		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows Style	}	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requested Size	if (!(hWnd=CreateWindowEx(	dwExStyle,				// Extended Style For The Window					"OpenGL",				// Class Name					title,					// Window Title					WS_CLIPSIBLINGS |			// Required Window Style					WS_CLIPCHILDREN |			// Required Window Style					dwStyle,				// Selected Window Style					0, 0,					// Window Position					WindowRect.right-WindowRect.left,	// Calculate Adjusted Window Width					WindowRect.bottom-WindowRect.top,	// Calculate Adjusted Window Height					NULL,					// No Parent Window					NULL,					// No Menu					hInstance,				// Instance					NULL)))					// Don''t Pass Anything To WM_CREATE	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	static	PIXELFORMATDESCRIPTOR pfd=					// pfd Tells Windows How We Want Things To Be	{		sizeof(PIXELFORMATDESCRIPTOR),					// Size Of This Pixel Format Descriptor		1,								// Version Number		PFD_DRAW_TO_WINDOW |						// Format Must Support Window		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL		PFD_DOUBLEBUFFER,						// Must Support Double Buffering		PFD_TYPE_RGBA,							// Request An RGBA Format		bits,								// Select Our Color Depth		0, 0, 0, 0, 0, 0,						// Color Bits Ignored		0,								// No Alpha Buffer		0,								// Shift Bit Ignored		0,								// No Accumulation Buffer		0, 0, 0, 0,							// Accumulation Bits Ignored		16,								// 16Bit Z-Buffer (Depth Buffer)		0,								// No Stencil Buffer		0,								// No Auxiliary Buffer		PFD_MAIN_PLANE,							// Main Drawing Layer		0,								// Reserved		0, 0, 0								// Layer Masks Ignored	};	if (!(hDC=GetDC(hWnd)))							// Did We Get A Device Context?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can''t Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))				// Did Windows Find A Matching Pixel Format?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can''t Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if(!SetPixelFormat(hDC,PixelFormat,&pfd))				// Are We Able To Set The Pixel Format?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can''t Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if (!(hRC=wglCreateContext(hDC)))					// Are We Able To Get A Rendering Context?	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can''t Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	if(!wglMakeCurrent(hDC,hRC))						// Try To Activate The Rendering Context	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Can''t Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	ShowWindow(hWnd,SW_SHOW);						// Show The Window	SetForegroundWindow(hWnd);						// Slightly Higher Priority	SetFocus(hWnd);								// Sets Keyboard Focus To The Window	ReSizeGLScene(width, height);						// Set Up Our Perspective GL Screen	if (!InitGL())								// Initialize Our Newly Created GL Window	{		KillGLWindow();							// Reset The Display		MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);		return FALSE;							// Return FALSE	}	return TRUE;								// Success}LRESULT CALLBACK WndProc(	HWND	hWnd,					// Handle For This Window				UINT	uMsg,					// Message For This Window				WPARAM	wParam,					// Additional Message Information				LPARAM	lParam)					// Additional Message Information{	switch (uMsg)								// Check For Windows Messages	{		case WM_ACTIVATE:						// Watch For Window Activate Message		{			if (!HIWORD(wParam))					// Check Minimization State			{				active=TRUE;					// Program Is Active			}			else			{				active=FALSE;					// Program Is No Longer Active			}			return 0;						// Return To The Message Loop		}		case WM_SYSCOMMAND:						// Intercept System Commands		{			switch (wParam)						// Check System Calls			{				case SC_SCREENSAVE:				// Screensaver Trying To Start?				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?				return 0;					// Prevent From Happening			}			break;							// Exit		}		case WM_CLOSE:							// Did We Receive A Close Message?		{			PostQuitMessage(0);					// Send A Quit Message			return 0;						// Jump Back		}		case WM_KEYDOWN:						// Is A Key Being Held Down?		{			keys[wParam] = TRUE;					// If So, Mark It As TRUE			return 0;						// Jump Back		}		case WM_KEYUP:							// Has A Key Been Released?		{			keys[wParam] = FALSE;					// If So, Mark It As FALSE			return 0;						// Jump Back		}		case WM_SIZE:							// Resize The OpenGL Window		{			ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));		// LoWord=Width, HiWord=Height			return 0;						// Jump Back		}	}	// Pass All Unhandled Messages To DefWindowProc	return DefWindowProc(hWnd,uMsg,wParam,lParam);}int WINAPI WinMain(	HINSTANCE	hInstance,				// Instance			HINSTANCE	hPrevInstance,				// Previous Instance			LPSTR		lpCmdLine,				// Command Line Parameters			int		nCmdShow)				// Window Show State{	MSG	msg;								// Windows Message Structure	BOOL	done=FALSE;							// Bool Variable To Exit Loop	// Ask The User Which Screen Mode They Prefer	if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)	{		fullscreen=FALSE;						// Windowed Mode	}	// Create Our OpenGL Window	if (!CreateGLWindow("Dan Carroll''s Final Project",640,480,16,fullscreen))	{		return 0;							// Quit If Window Was Not Created	}	while(!done)								// Loop That Runs Until done=TRUE	{		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))			// Is There A Message Waiting?		{			if (msg.message==WM_QUIT)				// Have We Received A Quit Message?			{				done=TRUE;					// If So done=TRUE			}			else							// If Not, Deal With Window Messages			{				TranslateMessage(&msg);				// Translate The Message				DispatchMessage(&msg);				// Dispatch The Message			}		}		else								// If There Are No Messages		{			// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()			if (active)						// Program Active?			{				if (keys[VK_ESCAPE])				// Was ESC Pressed?				{					done=TRUE;				// ESC Signalled A Quit				}				else						// Not Time To Quit, Update Screen				{					DrawGLScene();				// Draw The Scene					SwapBuffers(hDC);			// Swap Buffers (Double Buffering)				}			}			if (keys[VK_F1])					// Is F1 Being Pressed?			{				keys[VK_F1]=FALSE;				// If So Make Key FALSE				KillGLWindow();					// Kill Our Current Window				fullscreen=!fullscreen;				// Toggle Fullscreen / Windowed Mode				// Recreate Our OpenGL Window				if (!CreateGLWindow("Dan Carroll''s Final Project",640,480,16,fullscreen))				{					return 0;				// Quit If Window Was Not Created				}			}		}	}	// Shutdown	KillGLWindow();								// Kill The Window	return (msg.wParam);							// Exit The Program}

##### Share on other sites
Well, I solved it for you. It turned out that myAngle in Cube::Draw was 0 on every iteration, indicating that something reset your data structures. After some tracing, the problem is in this line:

        int DrawGLScene(apvector <Cube> cubes)								// Here's Where We Do All The Drawing

You are passing cubes by value. Aside from performance penalty involved in copying the array, whatever your drawing function changed (myAngle, in this case) was changed in the local copy of the array. The "real" cubes array wasn't modified, and next time you drew it, you got the original array, instead of modified one. Changing the function declaration to

  int DrawGLScene(apvector <Cube>& cubes)								// Here's Where We Do All The Drawing

solves the problem.

How did I find this bug? I noticed that myAngle is zero. I got its address and set data breakpoint on (float *)0x1234, where 0x1234 is the address of myAngle. The breakpoint was hit from debug free memory routine that was overwriting the container, which was called from apvector destructor. Naturally, I didn't expect vector destructor to be called in your render loop, and after some looking around I noticed that you were passing it by value instead of by reference.

Edit: gl[Push|Pop]Matrix wouldn't help in this case, because geometry modifications made during drawing weren't saved. Heh.

[edited by - IndirectX on May 4, 2002 5:19:35 PM]

[edited by - IndirectX on May 5, 2002 9:01:06 PM]

##### Share on other sites
I knew it would be something simple! Thank you for finding the error, IndirectX. I knew all along it would be some little error like that, which is why I was annoyed with everyone suggesting glPush and PopMatrix, because I was sure I didn''t need them.

Thanks again! It works great know (just got to fool around with the rotation values to make it look good).

• ### Forum Statistics

• Total Topics
628394
• Total Posts
2982427

• 10
• 9
• 19
• 24
• 9