0% found this document useful (0 votes)
44 views

Viewing and Camera Control in Opengl

The document discusses viewing and camera control in OpenGL. It begins by explaining basic OpenGL transformations like scaling, translation, and rotation. It then discusses OpenGL's transformation stacks, including the modelview stack which specifies the camera position and orientation, and the projection stack which defines how points are mapped from 3D to 2D. It provides details on the projection and modelview transformations, and how they relate to specifying the camera in OpenGL. It concludes with examples of how to set up the camera by setting the projection and modelview matrices, and how to render objects using the transformation stacks.

Uploaded by

Wooden Pencil
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views

Viewing and Camera Control in Opengl

The document discusses viewing and camera control in OpenGL. It begins by explaining basic OpenGL transformations like scaling, translation, and rotation. It then discusses OpenGL's transformation stacks, including the modelview stack which specifies the camera position and orientation, and the projection stack which defines how points are mapped from 3D to 2D. It provides details on the projection and modelview transformations, and how they relate to specifying the camera in OpenGL. It concludes with examples of how to set up the camera by setting the projection and modelview matrices, and how to render objects using the transformation stacks.

Uploaded by

Wooden Pencil
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Viewing and Camera Control in OpenGL

Niels Joubert & James Andrews 2008-10-28

Basic OpenGL Transformations

Whenever we work in OpenGL, we have access to its API that denes functions for basic transformations. We use the following functions to create a transform matrix and push it onto the current transform stack1 : glScalef(x, y, z) glTranslatef(x, y, z) glRotatef(x, y, z, angle); - scale object by x,y,z scalars along the current axes - move an object by x,y,z along the current axes. - rotate an object by angle around vector [x,y,z]

Using techniques from linear algebra, any transform can be decomposed into a combination of these simple transforms. Luckily, we do not have to resort to always using only these transforms - OpenGL denes an interface to intuitively work with the cameras orientation and perspective, or we can dene arbitrary transforms and load this into OpenGL.

OpenGL Transformation Stacks

We think of viewing in OpenGL as specifying properties about a hypothetical camera inside our scene. To do this, we will be specifying transformations that must be applied to our world during the rendering process. OpenGL supports this by storing transformations in a user-controllable stack. OpenGL has 3 dierent transformation stacks which are applied at dierent times of the rendering pipeline. We are concerned with two of these stacks: the Modelview stack and the Projection stack.2 We will explore the relation between our hypothetical camera and these transformations stacks. Each of these OpenGL transformation stacks specify the following information about the camera: GL MODELVIEW - The position and orientation of the camera and the world. GL PROJECTION - How the camera sees the world

Projection transformation

The projection transform denes how a point (or vertex) is transformed from world space to the 2D plane of the screen (screen space). This is part of what we studied when we discussed perspective transforms. OpenGL gives you functions to dene an orthographic or a perspective projection relative to the camera: glFustrum (left, right, bottom, top, near, far); gluPerspective(fovy, aspect, near, far); glOrtho(left, right, bottom, top, near, far); The following sketches should explain each of these functions:
Much 1 See

of this handout was adapted from Stu Pomerantz at the Pittsburgh Supercomputing Center. http://www.psc.edu/ section 2 2 There is also a Texture transform stack.

(a) glOrtho given left, right, bottom, top, near and far

(b) glFustrum give left, right, bottom, top, near and far

(c) glPerspective given eld-of-view, aspect-ratio, near and far

Figure 1: OpenGL perspective functions

Modelview transformation

The Modelview transformation species both the position and orientation of the camera and the objects in the world. Why dont we have a model transform and a view transform? Because translating the world and translating the camera has exactly the same eect - thus we combine it into one Modelview transform. We tend to specify a viewing transform to place the camera, followed by transformations on the objects. Note that placing the camera using the viewing transform is exactly the same as applying the rotations and translations to place your camera using OpenGLs transformation functions. Define the viewing transform: void gluLookAt(eyeX,eyeY,eyeZ, centerX,centerY,centerZ, upX,upY,upZ) PARAMETERS eyeX,eyeY, eyeZ - Specifies the position of the eye point. centerX, centerY, centerZ - Specifies the position of the reference point. upX, upY, upZ - Specifies the direction of the up vector. Since the default transformation on any stack is the identity, this translates into a default camera with eye at (0, 0, 1) and center at (0, 0, 0) with an up direction of (0, 1, 0) along the y axis. In other words, gluLookAt(0,0,1,0,0,0,0,1,0) is the default view.

Managing the Transformation Stacks

Todays graphics programs demand complex scenes with many objects, each rendered under its own transform. To facilitate this, as mentioned, OpenGL stores transformations in a stack. We control this stack through the following four methods: glMatrixMode(STACK ) - Selects the stack to aect. glLoadIdentity() - Resets the selected stack to the Identity transform. glPushMatrix() - Duplicates the top transform of the current stack. glPopMatrix() - Deletes the top transform of the current stack. We tend to initialize the ModelView stack to the identity, then apply our viewing transform (positioning the camera). Once this has occurred, for each object we want to render, we push a duplicate matrix onto the modelview stack, apply the transformations for the given object, draw the object, and pop the top matrix o the stack, thereby returning to the original view transform, ready to draw the next object.

Putting it all together - Specify the Camera


Set the viewport Set the projection transformation Set the modelview transformation

In order to specify the view in OpenGL:

If you specify your viewport and projection on initialization, you need to specify only your modelview transformation every time you render. OpenGLs stack-based approach then allows you to apply dierent transformations to each object. Thus, a possible Reshape callback function (also called on initialization) would look like the following: 3

Listing 1: Specifying the view void r e s h a p e ( int w, int h ) { // S e t t h e v i e w p o r t g l V i e w p o r t ( 0 , 0 ,w, h ) ; // S e t t h e p r o j e c t i o n t r a n s f o r m glMatrixMode (GL PROJECTION ) ; glLoadIdentity ( ) ; gluPerspective (45 ,1 ,5 ,100); } And a possible display function would look like the following: Listing 2: Rendering the scene f l o a t zoom , rotx , roty , tx , ty ; void d i s p l a y ( ) { g l C l e a r (GL COLOR BUFFER BIT | GL DEPTH BUFFER BIT ) ; // C l e a r ZB u f f e r // S e t t h e camera o r i e n t a t i o n : glMatrixMode (GL MODELVIEW) ; glLoadIdentity ( ) ; gluLookAt (0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 ) ; // R o t a t e and zoom t h e camera . This o r d e r g i v e s you mayal i k e c o n t r o l . g l T r a n s l a t e f (0 ,0 , zoom ) ; g l T r a n s l a t e f ( tx , ty , 0 ) ; g l R o t a t e f ( rotx , 1 , 0 , 0 ) ; g l R o t a t e f ( roty , 0 , 1 , 0 ) ; //FOR EACH OBJECT: glPushMatrix ( ) ; // Save t h e c u r r e n t v i e w m a t r i x . //HERE YOU CAN APPLY TRANSFORMATIONS TO EACH OBJECT BEFORE DRAWING IT //AND HERE YOU CAN DRAW IT ! glPopMatrix ( ) ; // R e s t o r e t o t h e v i e w m a t r i x glutSwapBuffers ( ) ; } For more information, consult either the Red Book, or the following sites: http://www.newcyber3d.com/selfstudy/tips/camera_analogy.htm http://www.robthebloke.org/opengl_programming.html#4 http://www.morrowland.com/apron/tut_gl.php

Assorted OpenGL notes - OpenGL 101

We highly recommend a copy of the so-called Blue3 and Red4 books for all graphics programmers. OpenGL is your friend. The cake is not a lie. NOTE: We suggest googling for the MAN pages of the functions we mention here!

7.1

Drawing Objects

You already know how to do this, but as a brief overview, objects are drawn by issuing glVertex() and glNormal() calls between glBegin(TYPE) and glEnd() commands. For the normals to matter, you also want to enable lighting and dene both material properties and lights, as covered in section 7.6. If you scale your objects, you need to have OpenGL renormalize your normals. You can enable this behavior with glEnable(GL_NORMALIZE).

7.2

Shading

OpenGL supports at and smooth (gouraud) shading as part of the hardware pipeline. This is toggled between with glShadeModel(GL_SMOOTH) and glShadeModel(GL_FLAT). The shading model uses colors at vertices which are either computed by the lighting model or, if lighting is not enabled, specied directly with glColor().

7.3

Wireframes

OpenGL can draw polygons in one of several modes, controlled through the glPolygonMode() function. You can switch between lled polygons and outlined polygons with glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) and glPolygonMode(GL_FRONT_AND_BACK, GL_LINE). Keep in mind that lighting and shading occurs in the same fashion for both of these, so it is often wise to disable lighting when drawing in GL_LINE mode, which you can do with glDisable(GL_LIGHTING).

7.4

The Z-Buer and Depth Tests

OpenGL implements a Z-Buering algorithm to calculate the visibility of polygons. The Z-Buer is initialized by passing the GLUT_DEPTH ag to glutInitDisplayMode(), and enabled with glEnable(GL_DEPTH_TEST). Once the Z-Buer has been enabled, you can clear it by calling glClear(GL_DEPTH_BUFFER_BIT), something you normally want to do at the start of each frames rendering cycle. If you want greater control of how the depth test is performed, you can use glDepthFunc(FUNC). By default, a pixel is compared with the current Z-Buer value using GL_LESS. 7.4.1 Hidden Line Removal

We can use a trick to draw wireframes but remove hidden lines by employing a two-pass scheme. Render the scene with lled polygons without populating your color buer (call glColorMask() with all GL_FALSE) to calculate the depth buer values. Then rerender the scene with wireframed polygons without clearing the depth buer, but switching the depth test from GL_LESS to GL_LEQUAL.

7.5

Display Lists

Display lists provide an easy way to speed things up, by letting OpenGL remember a list of rendering instructions. It can optimize the instructions for rendering, and store them so you dont constantly need to send them to the card yourself. See http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=12
3 http://www.opengl.org/documentation/blue 4 http://www.opengl.org/documentation/red

book/ book/

7.6

Lighting Example
Listing 3: Lighting Example

void i n i t L i g h t s ( ) { g l E n a b l e (GL LIGHTING ) ; g l L i g h t M o d e l i (GL LIGHT MODEL TWO SIDE, GL TRUE ) ; GLfloat global ambient [ ] = { . 1 f , . 1 f , . 1 f } ; g l L i g h t M o d e l f v (GL LIGHT MODEL AMBIENT, g l o b a l a m b i e n t ) ; // d e f i n e and e n a b l e l i g h t 0 . You have 8 l i g h t s i n t o t a l . G L f l o a t ambient [ ] = { . 1 f , . 1 f , . 1 f } ; GLfloat d i f f u s e [ ] = { . 6 f , . 5 f , . 5 f } ; GLfloat s p e c u l a r [ ] = { 0 . 0 , 0 . 0 , 0 . 0 , 1 . 0 } ; G L f l o a t pos [ ] = { 3, 0 , 2 , 1 } ; g l L i g h t f v (GL LIGHT0 , GL AMBIENT, ambient ) ; g l L i g h t f v (GL LIGHT0 , GL DIFFUSE , d i f f u s e ) ; g l L i g h t f v (GL LIGHT0 , GL SPECULAR, s p e c u l a r ) ; g l L i g h t f v (GL LIGHT0 , GL POSITION , pos ) ; g l E n a b l e (GL LIGHT0 ) ; // d e f i n e m a t e r i a l p r o p e r t i e s : //You p r o b a b l y don t want t o use t h e e m i s s i o n term f o r t h i s c l a s s . GLfloat mat specular [ ] = { 1 . 0 , 0 . 0 , 0 . 0 , 1 . 0 } ; GLfloat m a t d i f f u s e [ ] = { 0 . 0 , 1 . 0 , 0 . 0 , 1 . 0 } ; G L f l o a t mat ambient [ ] = { 0 . 0 , 0 . 1 , 0 . 1 , 1 . 0 } ; GLfloat mat emission [ ] = { 0 . 2 , 0 . 0 , 0 . 0 , 1 . 0 } ; GLfloat m a t s h i n i n e s s ={10.0}; g l M a t e r i a l f v (GL FRONT AND BACK, GL SPECULAR, m a t s p e c u l a r ) ; g l M a t e r i a l f v (GL FRONT AND BACK, GL AMBIENT, mat ambient ) ; g l M a t e r i a l f v (GL FRONT AND BACK, GL DIFFUSE , m a t d i f f u s e ) ; g l M a t e r i a l f v (GL FRONT AND BACK, GL EMISSION , m a t e m i s s i o n ) ; g l M a t e r i a l f (GL FRONT AND BACK, GL SHININESS , m a t s h i n i n e s s ) ; glShadeModel (GL SMOOTH) ; // GL FLAT g i v e s f l a t s h a d i n g // A l l o w s you t o s c a l e o b j e c t s a t t h e c o s t o f some performance . g l E n a b l e (GL NORMALIZE ) ; } int main ( int argc , char argv ) { g l u t I n i t (& argc , argv ) ; g l u t I n i t D i s p l a y M o d e (GLUT DOUBLE|GLUT RGBA|GLUT DEPTH ) ; glutInitWindowSize (640 ,480); glutCreateWindow ( L i g h t i n g Test ) ; ... initLights (); g l E n a b l e (GL DEPTH TEST ) ; glutMainLoop ( ) ; }

You might also like