Time to go 3D.
You now learn how to represent a 3D object (with hidden surface removal) using first principles. There exist more elegant ways to implement hidden surface removal, as you will discover in future tutorials.
Next, you will discover how to look at the object from different sides. In effect, the object will remain fixed and the camera (viewing the object) will revolve around the object in a circular orbit.
Finally, you find out how to make GLFW detect keyboard events. We will begin using the ESC key to stop the animations.
#include <GLFW/glfw3.h> // GLFW
#include <OpenGL/glu.h> // for using gluLookAt( ... )
// the usual gang of C++ headers
#include <iostream>
#include <cmath>
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
// draw a cube using OpenGL primitives
void drawCube()
{
glColor3f(1, 0, 0);
glBegin(GL_POLYGON);
{
glVertex3f( -0.75, -0.75, -0.5); // 0
glVertex3f( 0.75, -0.75, -0.5); // 1
glVertex3f( 0.75, 0.75, -0.5); // 2
glVertex3f( -0.75, 0.75, -0.5); // 3
}
glEnd();
// draw the coordinate axes
glBegin(GL_LINES);
{
glColor3f(1, 1, 1);
glVertex3f( 0., 0., 0.); // x axis
glVertex3f( 2., 0., 0.);
glVertex3f( 2., 0., 0.);
glVertex3f( 1.8, 0.1, 0.);
glVertex3f( 2., 0., 0.);
glVertex3f( 1.8, -0.1, 0.);
glVertex3f( 0., 0., 0.); // y axis
glVertex3f( 0., 2., 0.);
}
glEnd();
glBegin(GL_LINES);
{
glVertex3f( -0.75, -0.75, -0.5); // 0
glVertex3f( -0.75, -0.75, 0.5); // 4
glVertex3f( 0.75, -0.75, -0.5); // 1
glVertex3f( 0.75, -0.75, 0.5); // 5
glVertex3f( 0.75, 0.75, -0.5); // 2
glVertex3f( 0.75, 0.75, 0.5); // 6
glVertex3f( -0.75, 0.75, -0.5); // 3
glVertex3f( -0.75, 0.75, 0.5); // 7
}
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_POLYGON);
{
glVertex3f( -0.75, -0.75, 0.5); // 4
glVertex3f( 0.75, -0.75, 0.5); // 5
glVertex3f( 0.75, 0.75, 0.5); // 6
glVertex3f( -0.75, 0.75, 0.5); // 7
}
glEnd();
glBegin(GL_LINES);
{
glColor3f(0, 0, 1);
glVertex3f( 0., 0., 0.5); // z axis
glVertex3f( 0., 0., 2.);
}
glEnd();
}
// calculate pixel colors for the current graphics window
void display(float scale, int time)
{
// select background color to be black
float R = 0, G = 0, B = 0, alpha = 0;
glClearColor(R, G, B, alpha);
// replace current transformation matrix with the identity matrix
glLoadIdentity();
// set clipping planes in the X-Y-Z coordinate system
float xmin = -scale, xmax = scale;
float ymin = -scale, ymax = scale;
float zmin = -20*scale, zmax = 20*scale;
glOrtho(xmin, xmax, ymin, ymax, zmin, zmax);
// new screen coordinates in OpenGL
//
// (xmin, ymax) (xmax, ymax)
// +-----------+-----------+
// | | |
// | | |
// | | |
// | | |
// | | (0,0) |
// +-----------+-----------+
// | | |
// | | |
// | | |
// | | |
// | | |
// +-----------+-----------+
// (xmin, ymin) (xmax, ymin)
// position the camera at a certain point and check how the view looks
float angle = time*0.001;
gluLookAt (cos(angle), sin(angle), 1.0, // camera position at (x,y,z)
0.0, 0.0, 0.0, // camera looks towards point (x,y,z)
0.0, 0.0, 1.0); // the "up" vector
// std::cout << "Viewing from point (" << cos(angle) << ", " << sin(angle) << ", " << 1.0 << ")\n";
// clear all pixels in the window with the current color
glClear(GL_COLOR_BUFFER_BIT);
// draw a cube using OpenGL primitives
drawCube();
}
int main(int argc, char* argv[])
{
//--------------------------------
// Create a WINDOW using GLFW
//--------------------------------
GLFWwindow *window;
// initialize the library
if(!glfwInit())
return -1;
// window size for displaying graphics
int WIDTH = 600; //atoi(argv[1]);
int HEIGHT = 600; //atoi(argv[2]);
// set the window's display mode
window = glfwCreateWindow(WIDTH, HEIGHT, "Triangle", NULL, NULL);
if(!window)
{
glfwTerminate();
return -1;
}
// make the windows context current
glfwMakeContextCurrent(window);
// enable quitting the graphics by pressing ESC
glfwSetKeyCallback(window, key_callback);
//---------------------------------------
// Loop until the user closes the window
//---------------------------------------
float scale = 3, delta = 0.01;
int time = 0;
while(!glfwWindowShouldClose(window))
{
// this is where you draw something
display(scale, time);
// swap front and back buffers
glfwSwapBuffers(window);
// poll for and processs events
glfwPollEvents();
// adjust scale
scale += delta;
if ( (scale > 4) || (scale < 2) ) delta = -delta;
// increment time
time += 3;
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
To compile this code, use the following Makefile:
NAME = movingCamera
all:
g++ -I /usr/local/include/ -L /usr/local/lib ${NAME}.cpp -o cpp.x -framework OpenGL -framework Cocoa -framework IOKit -lglfw
clean:
rm *.x