|
Transformation in OpenGL
with Examples |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
glMatrixMode(GL_MODELVIEW);
glMatrixMode(GL_PROJECTION);
gluLookAt()
glTranslate*(),
glScale*(), glRotate*()
glOrtho(left, right, bottom, top, near, far)
glFrustum(fovy, aspect, zNear, zFar)
fovy is the field of view (in degrees)
in the \(y\) direction, aspect is
the aspect ration that determines the FOV in the
\(x\) direction, zNear is the positive
distance from the viewer to the near clipping plane, and
zFar is the positive
distance from the viewer to the far clipping plane
glPushMatrix() and glPopMatrix())
is important and requires careful thought
/**
* The display callback
*/
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
// Draw the Sun at the origin with a radius of 2, 16 lines of latitude,
// and 16 lines of longitude
//
// Use a wireframe so we can see the orientation
glColor3f(1.0, 1.0, 0.0);
glutWireSphere(1.0, 16, 16);
// Rotate the local coordinate system
// around the z-axis based on the day of the year
//
// Note: After drawing the sphere we are at the origin. So, we
// are rotating around a ray from [0 0 0] to [0 0 1].
glRotatef(((GLfloat) day) / 365.0f * 360.0f, 0.0, 0.0, 1.0);
// Translate the local coordinate system along the x-axis the
// radius of the Earth's orbit
//
// Note: The x-axis has already been rotated.
glTranslatef(4.0, 0.0, 0.0);
// To rotate the Moon around the center of the Earth we need
// a different local coordinate system. Save the current
// local coordinate system first
glPushMatrix();
// Rotate the new local coordinate system around the z-axis
// based on the day of month
glRotatef(((GLfloat) dom) / 28.0f * 360.0f, 0.0, 0.0, 1.0);
// Translate the new local coordinate along the x-axis the
// radius of the Moon's orbit
glTranslatef(1.0, 0.0, 0.0);
// Draw the Moon
glColor3f(1.0, 1.0, 1.0);
glutWireSphere(0.1, 4, 4);
// Pop the previous local coordinate system
glPopMatrix();
// Rotate the local coordinate system around the z-axis based on
// the hour of the day
//
// Note: The origin is now at the appropriate point on the orbit.
glRotatef(((GLfloat) hour) / 24.0f * 360.0f, 0.0, 0.0, 1.0);
// Draw the Earth
//
// Use a wireframe so we can see it revolve
glColor3f(0.0, 0.0, 1.0);
glutWireSphere(0.5, 16, 16);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
/**
* The display callback
*/
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
// Translate the local coordinate system to the hinge
// of the first block
glTranslatef(-1.0, 0.0, 0.0);
// Rotate the local coordinate system around the z-axis
//
// Note: We are rotating around a ray to [0 0 1].
glRotatef((GLfloat) alpha, 0.0, 0.0, 1.0);
// Translate the local coordinate system back to the center
glTranslatef(1.0, 0.0, 0.0);
// Draw the first block
glutWireCube(2.0);
// Translate the local coordinate system to the hinge
// of the second block
glTranslatef(1.0, 0.0, 0.0);
// Rotate the local coordinate system around the z-axis
//
// Note: We are rotating around a ray to [0 0 1].
glRotatef((GLfloat) beta, 0.0, 0.0, 1.0);
// Translate the local coordinate system to the center of the
// second block
glTranslatef(1.0, 0.0, 0.0);
// Draw the second block
glutWireCube(2.0);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/glut.h>
/**
* \file
* An application that displays a first person view of a simple world.
*
* On Linux, compile with:
* g++ -o firstperson -Wall firstperson.c -lglut -lGL -lGLU
*
* NOTE: The camera/viewer starts in the middle of the world. So, you should
* probably move back several times to see everything.
*
* @author Prof. David Bernstein, James Madison University
*/
static GLfloat x = 0.0, z = 0.0, angle = 0.0;
/**
* Convert degrees to radians.
*
* @param degrees The angle in degrees
* @return The angle in radians
*/
inline GLfloat deg2rad(GLfloat degrees) {
return degrees * M_PI / 180.0;
}
/**
* Convert radians to degrees
*
* @param radians The angle in radians
* @return The angle in degrees
*/
inline GLfloat rad2deg(GLfloat radians) {
return radians * (180.0 / M_PI);
}
/**
* Draw the objects in the world.
*/
void drawWorld() {
glColor3f(1.0f, 1.0f, 1.0f);
// The "near" side of the world
glPushMatrix();
glTranslatef(0.0, 0.0, 5.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glutSolidCone(1.0, 1.0, 10, 10);
glPopMatrix();
// The "right" side of the world
glPushMatrix();
glTranslatef(5.0, 0.0, 0.0);
glutSolidTorus(0.5, 1.0, 10, 10);
glPopMatrix();
// The "left" side of the world
glPushMatrix();
glTranslatef(-5.0, 0.0, 0.0);
glutSolidSphere(1.0, 10, 10);
glPopMatrix();
// The "far" side of the world
glPushMatrix();
glTranslatef(0.0, 0.0, -5.0);
glutSolidTeapot(1.0);
glPopMatrix();
}
/**
* The display callback.
*/
void display() {
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset the local coordinate system
glLoadIdentity();
// Rotate around the y-axis
glRotatef(angle, 0.0, 1.0, 0.0);
// Translate the local coordinate system "backwards" an
// appropriate amount (based on the rotation angle)
glTranslatef(-x, 0.0, -z);
// Draw the world
drawWorld();
glFlush();
glutSwapBuffers();
}
/**
* Initialize GLUT and OpenGL.
*/
void init() {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("First Person");
glClearColor(0.0, 0.0, 0.0, 1.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // Use the default light
}
/**
* Handle keyboard events.
*/
void keyboard(unsigned char key, int xMouse, int yMouse) {
GLfloat deltaX, deltaZ;
// Move forward or backward
if ((key == 'f') || (key == 'b')) {
// Calculate the change in x and z necessary for a 1-unit
// move in the direction I am facing
deltaX = sin(deg2rad(angle));
deltaZ = cos(deg2rad(angle));
if (key == 'f') {
x += deltaX;
z -= deltaZ;
} else if (key == 'b') {
x -= deltaX;
z += deltaZ;
}
}
// Rotate right (clockwise) or left (counter-clockwise)
else if (key == 'r') {
angle += 10.0;
if (angle > 360)
angle -= 360;
} else if (key == 'l') {
angle -= 10.0;
if (angle < 0)
angle += 360;
}
// Reset
else if (key == ' ') {
angle = 0.0;
x = 0.0;
z = 0.0;
}
glutPostRedisplay();
}
/**
* The reshape callback (i.e., the function that is called
* each time the window is re-sized).
*
* @param width The new width
* @param height The new height
*/
void reshape(int width, int height) {
GLfloat aspect;
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
// Setup the projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
aspect = (GLfloat) width / (GLfloat) height;
gluPerspective(60.0, aspect, 1.0, 1000.0);
}
/**
* The entry point of the application.
*
* @param argc The number of command line arguments
* @param argv The array of command line arguments
* @return A status code
*/
int main(int argc, char **argv) {
// Initialize
glutInit(&argc, argv);
init();
// Callbacks
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
// Start the event loop
glutMainLoop();
return 0;
}