INSTITUTIONEN FÖR SYSTEMTEKNIK LULEÅ TEKNISKA UNIVERSITET 3D Graphics in OpenGL David Carr Fundamentals of Computer Graphics Spring 2004 Based on Slides by E. Angel 1 L Jan-22-04 SMD159, 3D Graphics in OpenGL Overview • 3D applications in OpenGL - A 3D example, Sierpinski gasket, a fractal • Introduction to hidden-surface removal 2 L Jan-22-04 SMD159, 3D Graphics in OpenGL INSTITUTIONEN FÖR SYSTEMTEKNIK LULEÅ TEKNISKA UNIVERSITET 3D Applications in OpenGL 3 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Three-Dimensional Applications • In OpenGL, two-dimensional applications are a special case of three-dimensional graphics - Not much changes - Use glVertex3*( ) - Have to worry about the order in which polygons are drawn or use hidden-surface removal - Polygons should be simple, convex, flat 4 L Jan-22-04 SMD159, 3D Graphics in OpenGL Sierpinski Gasket (2D) • Start with a triangle • Connect bisectors of sides and remove central triangle • Repeat 5 L Jan-22-04 SMD159, 3D Graphics in OpenGL Example • Five subdivisions 6 L Jan-22-04 SMD159, 3D Graphics in OpenGL
The Gasket as a Fractal • Consider: - The filled area (black) - The perimeter (the length of all the lines around the filled triangles) • As we continue subdividing - The area goes to zero - But the perimeter goes to infinity • This is not an ordinary geometric object - It is neither two- nor three-dimensional • It is a fractal (fractional dimension) object 7 L Jan-22-04 SMD159, 3D Graphics in OpenGL Gasket Program import java.awt.*; import java.awt.event.*; import net.java.games.jogl.*; public class Gasket2 { public static void main(String[] args) { Frame gasketFrame = new Frame("Sierpinski Gasket"); GLCanvas drawable = GLDrawableFactory.getFactory(). createGLCanvas(new GLCapabilities()); drawable.addGLEventListener(new GasketRenderer()); gasketFrame.add(drawable); gasketFrame.setSize(500, 500); gasketFrame.show(); } 8 L Jan-22-04 SMD159, 3D Graphics in OpenGL Triangle Subdivision (part of GasketRenderer ) private void divide_triangle(double[] a, double[] b, double[] c, int m) { // triangle subdivision using vertex numbers double [] v0 = new double[2], v1 = new double[2], v2 = new double[2]; int j; if(m>0) { for(j=0; j<2; j++) v0[j]=(a[j]+b[j])/2; for(j=0; j<2; j++) v1[j]=(a[j]+c[j])/2; for(j=0; j<2; j++) v2[j]=(b[j]+c[j])/2; divide_triangle(a, v0, v1, m-1); divide_triangle(c, v1, v2, m-1); divide_triangle(b, v2, v0, m-1); } else { // … 9 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Draw a Triangle ( divide_triangle Continued) else { // draw triangle at end of recursion gl.glBegin(GL.GL_TRIANGLES); gl.glVertex2dv(a); gl.glVertex2dv(b); gl.glVertex2dv(c); gl.glEnd(); } } 10 L Jan-22-04 SMD159, 3D Graphics in OpenGL GasketRenderer Class static class GasketRenderer implements GLEventListener { private GL gl; // interfaces, load in every method! private GLU glu; // initial triangle private static final double[] pt1 = {-1.0, -0.58}, pt2 = {1.0, -0.58}, pt3 = {0.0, 1.15}; private static final int RECURSION_LEVELS = 4; public void displayChanged(…) {} public void reshape(…) {} … 11 L Jan-22-04 SMD159, 3D Graphics in OpenGL Display() and init() Methods public void display(GLDrawable drawable) { gl = drawable.getGL(); glu = drawable.getGLU(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); divide_triangle(pt1, pt2, pt3, RECURSION_LEVELS); gl.glFlush(); } public void init(GLDrawable drawable) { gl = drawable.getGL(); glu = drawable.getGLU(); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); glu.gluOrtho2D(-2.0, 2.0, -2.0, 2.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glClearColor (1.0f, 1.0f, 1.0f, 1.0f); gl.glColor3f(0.0f,0.0f,0.0f); } 12 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Moving to 3D • We can easily make the program three-dimensional by using double point3 = new double[3]; glVertex3f glOrtho • But that would not be very interesting • Instead, we can start with a tetrahedron 13 L Jan-22-04 SMD159, 3D Graphics in OpenGL 3D Gasket • We can subdivide each of the four faces • Appears as if we remove a solid tetrahedron from the center leaving four smaller tetrahedtra 14 L Jan-22-04 SMD159, 3D Graphics in OpenGL Example after 5 interations 15 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Modifications to Declarations & Projection // initial tetrahedron private static final double[][] tetra = { {0., 0., 0.} , {250., 150., 100.} , {250., 500., 0.} , {500., 0., 0.} }; … public void init(GLDrawable drawable) { gl = drawable.getGL(); glu = drawable.getGLU(); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrtho(0.0, 500.0, 0.0, 500.0, -500.0, 500.0); gl.glMatrixMode(GL.GL_MODELVIEW); gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); } 16 L Jan-22-04 SMD159, 3D Graphics in OpenGL Triangle Code private void triangle(double[] a,double[] b,double[] c) { gl.glBegin(GL.GL_TRIANGLES); gl.glVertex3dv(a); gl.glVertex3dv(b); gl.glVertex3dv(c); gl.glEnd(); 17 L Jan-22-04 SMD159, 3D Graphics in OpenGL Subdivision Code private void divide_triangle(double[] a, double[] b, double[] c, int m) { // triangle subdivision using vertex numbers double [] v0 = new double[3], v1 = new double[3], v2 = new double[3]; int j; if(m>0) { for(j=0; j<3; j++) v0[j]=(a[j]+b[j])/2; for(j=0; j<3; j++) v1[j]=(a[j]+c[j])/2; for(j=0; j<3; j++) v2[j]=(b[j]+c[j])/2; divide_triangle(a, v0, v1, m-1); divide_triangle(c, v1, v2, m-1); divide_triangle(b, v2, v0, m-1); } else { triangle(a, b, c); } // draw tri. @end of recursion } 18 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Tetrahedron Code private void tetrahedron(int m) { gl.glColor3f(1.0f, 0.0f, 0.0f); divide_triangle(tetra[0], tetra[1], tetra[2], m); gl.glColor3f(0.0f, 1.0f, 0.0f); divide_triangle(tetra[0], tetra[3], tetra[2], m); gl.glColor3f(0.0f, 0.0f, 1.0f); divide_triangle(tetra[1], tetra[2], tetra[3], m); gl.glColor3f(0.0f, 0.0f, 0.0f); divide_triangle(tetra[0], tetra[1], tetra[3], m); } 19 L Jan-22-04 SMD159, 3D Graphics in OpenGL Almost Correct • Because the triangles are drawn in the order they are defined in the program, the front triangles are not always rendered in front of triangles behind them get this want this 20 L Jan-22-04 SMD159, 3D Graphics in OpenGL INSTITUTIONEN FÖR SYSTEMTEKNIK LULEÅ TEKNISKA UNIVERSITET Introduction to Hidden-Surface Removal 21 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Hidden-Surface Removal • We want to see only those surfaces in front of other surfaces • OpenGL uses a hidden-surface method called the z -buffer algorithm that saves depth information as objects are rendered so that only the front objects appear in the image 22 L Jan-22-04 SMD159, 3D Graphics in OpenGL Using the z -buffer algorithm • The algorithm uses an extra buffer, the z-buffer, to store depth information as geometry travels down the pipeline • Enabled in GasketRender.init() - gl.glEnable(GL.GL_DEPTH_TEST) • Cleared in GasketRender.display() - glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 23 L Jan-22-04 SMD159, 3D Graphics in OpenGL Questions? 24 L Jan-22-04 SMD159, 3D Graphics in OpenGL
Recommend
More recommend