6. OpenGL Cube (Version 2.0)
Introduction
All is perfectly fine if we want to draw standard 2D shapes in OpenGL, but the next step up is 3D shapes, and it is these shapes that will really make your application look impressive. The best part about 3D shapes, is that they are made up of 2D shapes, just drawn in 3D space. While OpenGL provides methods for easily rendering 2D shapes, it doesn’t provide any methods for shapes such as cubes, spheres, pyramids, etc. But all is not lost, you have two choices. The first choice is to create the shapes yourself, work out the vertices, determine which vertices you want to use to make faces, and hand code it all in. The next choice, not including 3D modeling applications and model loaders, is to use GLUT for simple 3D shapes. GLUT comes with the ability to render some extremely basic 3D shapes such as a cube, sphere (without texture coordinates), cone, torus/donut and the all famous teapot. GLUT also lets us render this in both their wireframe version, or their regular filled version. GLUT also comes with several other shapes, but they are not all that common. Lets take a look at the code required to render these more common shapes:
Cube
glutWireCube(double size); glutSolidCube(double size);
This will create a cube with the same width, height and depth/length, each the length of the size parameter specified. This cube in GLUT also comes with surface normals but not texture coordinates.
Sphere
glutWireSphere(double radius, int slices, int stacks); glutSolidSphere(double radius, int slices, int stacks);
The calls to create a sphere in GLUT require you to give a radius, which determines the size of the sphere, and the number of stacks and slices. The stacks and slices determine the quality of the sphere, and are the number of divisions in vertical and horizontal directions. The sphere does come with surface normals, but does not come with texture coordinates.
Cone
glutWireCone(double radius, double height, int slices, int stacks); glutSolidCone(double radius, double height, int slices, int stacks);
If you want to create a cone, you would use the above GLUT calls. These calls are almost identical to that of the sphere code, we have a radius and the stacks and slices. But it also takes another parameter which defines the height of the cone. Also note that the radius of the cone, refers to the radius of the base of the cone. The cone will come with surface normals, but does not come with texture coordinates.
Torus
glutWireTorus(double inner_radius, double outer_radius, int sides, int rings); glutSolidTorus(double inner_radius, double outer_radius, int sides, int rings);
A torus looks exactly like a donut. It has an inner radius, which specifies the size of the hole in the middle, an outer radius, which specifies the outer side of the torus from the centre (not the inner radius onwards), the sides specifies the number of sides in each radial section and finally, the rings specify how many radial divisions are used for the torus.
Teapot
glutWireTeapot(double size); glutSolidTeapot(double size);
The all famous teapot was first created in 1975 by Martin Newell and is widely used for testing in computer graphics because it is round, has saddle points, can project a shadow onto itself and looks decent when it is untextured. All you have to do to create the teapot is specify the size for the teapot. The teapot comes with surface normals and texture coordinates which means it is perfect for testing bump mapping, environment mapping, and many other effects.
Code
As you can probably tell from the above calls to GLUT, these shapes are extremely easy to use in OpenGL. Find a section in your code and simply insert the call you want. So let’s remove our renderPrimitive method from the previous tutorial in our display method, we are going to replace the call to renderPrimitive with a call to create a cube.
void display (void) { … glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive glutWireCube(2.0f); // Render the primitive glFlush(); // Flush the OpenGL buffers to the window }
You should now have a nice 3D cube in your OpenGL application. If you have any questions, you can always contact me at swiftless@gmail.com
Tutorial Code
#include <GL/glew.h> // Include the GLEW header file #include <GL/glut.h> // Include the GLUT header file bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255) void keyOperations (void) { if (keyStates['a']) { // If the 'a' key has been pressed // Perform 'a' key operations } } void display (void) { keyOperations(); glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on) glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive glutWireCube(2.0f); // Render the primitive glFlush(); // Flush the OpenGL buffers to the window } void reshape (int width, int height) { glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up) gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly } void keyPressed (unsigned char key, int x, int y) { keyStates[key] = true; // Set the state of the current key to pressed } void keyUp (unsigned char key, int x, int y) { keyStates[key] = false; // Set the state of the current key to not pressed } int main (int argc, char **argv) { glutInit(&argc, argv); // Initialize GLUT glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now) glutInitWindowSize (500, 500); // Set the width and height of the window glutInitWindowPosition (100, 100); // Set the position of the window glutCreateWindow ("Your first OpenGL Window"); // Set the title for the window glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events glutMainLoop(); // Enter GLUT's main loop }
hello, i am not able to draw the cube if i omit the reshape function, only blank black screen appears, why is that?
How will I be able to draw the cube with a different clipping ranges say -1000 —- 1000
Thanks
Probably not the best way to do it but, you can create a new function that you will call in your display() function.
Like this:
void myCube()
{
glBegin(GL_QUADS);
glVertex3f(-1.0f, -1.0f, 0.0f); //corner 1
glVertex3f(-1.0f, 1.0f, 0.0f); //corner 2
glVertex3f(1.0f, 1.0f, 0.0f); //corner 3
glVertex3f(1.0f, -1.0f, 0.0f); //corner 4
glVertex3f(-1.0f, -1.0f, 1.0f);//corner 5
glVertex3f(-1.0f, 1.0f, 1.0f);//corner 6
glVertex3f(1.0f, 1.0f, 1.0f); //corner 7
glVertex3f(1.0f, -1.0f, 1.0f);//corner 8
glEnd();
}
//You call it in display() like this:
glTranslatef(0.0f, 0.0f, -5.0f); // Push everything 5 units back into the //scene, so you can see the cube
myCube();
OpenGL Version must be 2.0 or higher
Hi, I am wondering how to draw a line on the glutSolid object for example I wan to draw a cream on a donut which I use as glutSolidTorus. Is that a way to do this?
Thanks.
Hello, I just wanted to let you know that i like this site and the content you are providing. Tutorials are very nice and to the point. The one thing i dont like is the web design width. You have to make it wider so that the various codes in tutorials dont show up weird. A little more view window will be nice. i am pretty sure most people interested on this website are high resolution monitors if the concern was to satisfy 800×600 people…
Hi Dave,
I’ll take a look at it thanks. I’m using a theme I found on the web, but it shouldn’t take too much to modify.
Cheers,
Swiftless
Hello, i’m also using openGL and i’ve one problem:
i have to delete a cube that i’ve drawn with glSolidCube.
Thanks !
Hey Anna,
I’m confused as to why you are having trouble deleting shapes you have drawn. It is as simply as not calling the drawing code in your program.
You can use an if statement, so if something happens, draw the cube, or vice versa, if something happens, don’t draw the cube.
Or if you have a loop of shapes, skip the drawing for the specific cube you don’t want to draw.
Cheers,
Swiftless
l like this site
nice man…
good tutorial, all shapes being drawn seem to be centered at 0,0,0 I guess, how do we place them at required poistion? I`m sory I`m just following the tutoirals in order, wonder if this is covered later on
Hey Imrn,
You can use the glTranslate methods to move your objects around the scene. I know I cover the rotate method, but I’m not sure I actually cover the translate method.
Cheers,
Swiftless
Somethings wrong here afaik:
These GLUT routines do NOT generate texture coordinates. Only the Teapot one does.
So NO texturing with “glutSolidCube”.
I used this routine to make my cube and tried for hours to do the texturing. It’s just not possible, you need to build your own cube with 2D polygons.
Actually you might want to have a look at some GLU routines.
gluNewQuadric
gluQuadricTexture
gluQuadricNormals
gluQuadricOrientation
Then you just use
gluSphere
gluCylinder
gluDisk
gluPartialDisk
Hi MatMar,
Yes, these are nice, but it means you have to rely on another library for basic shapes. Personally I recommend learning how to create or use a model loader as soon as possible, as you can only do so much with these shapes.
Cheers,
Swiftless
Relying on libraries is a bad habit of mine 😉
Despite sounding somewhat knowledgeable in my last post, I’m only beginning with GL.
My habits are still formed by basic experience with STL, which is “if it’s provided in a header, then it’s good, saves space, saves time, and is optimised.” That is generally true for STL. I don’t know about GLU’s performance or, more importantly, availability on different platforms.