Syllabus   Blank Homework   Quizzes  
Notes   Labs   Scores   Blank

Lecture Notes
Dr. Tong Lai Yu, 2010
    1. Introduction
    2. OpenGL Shading Language ( GLSL ) I
    3. GLSL II
    4. Curve and Surface Design
    5. Modeling Shapes with Polygonal Meshes
    6. Texture Mapping
    7. Casting Shadows
    8. Tools for Raster Display
    9. Parsing External Objects

    Modeling Shapes with Polygon Mesh

      Polygon mesh ( or mesh ) is a collection of polygons that share vertices and edges.

    1. Properties of Meshes

    2. Solidity: A mesh represents a solid object if its faces together enclose a finite amount of space.
    3. Connectedness: A mesh is connected if every face shares at least one edge with some other face.
    4. Simplicity: A mesh is simple if the object it represents is solid and has no holes through it.
    5. Planarity: A mesh is planar if every face is a planar polygon.
    6. Convexity: A mesh is convex if the line connecting any two points within the object lies wholly inside the mesh object.
    7. Mesh examples:

       


      Elements of Polygonal mesh modeling:

      Objects created with polygon meshes must store different types of elements, including vertices, edges, faces, polygons and surfaces.

    8. Mesh Representations

      see http://en.wikipedia.org/wiki/Polygon_mesh


        Normal nx ny nz
        0 -1 0 0
        1 -0.7071 0.7071 0
        2 0.7071 0.7071 0
        3 1 0 0
        4 0 -1 0
        5 0 0 1
        6 0 0 -1
         
        Face Vertices Associated
        Normal
        0 (left) 0,5,9,4 0,0,0,0
        1 (roof left) 3, 4, 9, 8 1, 1, 1, 1
        2 (roof right) 2, 3, 8, 7 2, 2, 2, 2
        3 (right) 1, 2, 7, 6 3, 3, 3, 3
        4 (bottom) 0, 1, 6, 5 4, 4, 4, 4
        5 (front) 5, 6, 7, 8, 9 5, 5, 5, 5, 5
        6 (back) 0, 4, 3, 2, 1 6, 6, 6, 6, 6

    9. Extruding Shapes

      A large class of 3D shapes can be generated by extruding or sweeping a 2D shape through space.

      Creating Prisms

      e.g. An ARROW prism

    10. 7 rectangular sides
    11. bottom base P
    12. top cap

    13. base: N vertices ( xi, yi ): 0, ..., N-1
    14. cap: vertices N, ..., 2N - 1
    15. an edge joins vertices i and i + N
    16. vertex list:
        (xi, yi, 0)
        (xi, yi, H)     i = 0, 1, ..., N - 1
    17. face list:
      • cap, base
      • A wall ( side face ) has 4 vertices.
        j-th wall ( j = 0, ..., N-1 ) vertices: j, j+N, next(j)+N, and next(j)
        if ( j == N - 1 )
          next = 0;
        else
          next = j + 1;
        
    18. Normals to each face can be found by Newell method.
    19. Extrusions with a "Twist"

    20. Base polygon P with vertices: {p0, p1, ...pN-1 }
    21. Cap polygon P': MP

      e.g. scaling factor = 0.7, translation = H along z

      e.g. the cap has been rotated through an angle θ about z-axis before translation.

    22. Building Segmented Extrusions -- Tubes and Snakes

    23. Tubes can be built by using a sequence of extrusions, each with its own transformations, and laying them end to end to form a tube.
    24. The various transformed polygons are called the "waists" of the tube.
    25. A snake can be built from successive extrusions of a polygon by extruding a polygon in different directions.
    26. Example:
      • Vertex list contains 16 vertices:
        M0P0, M0P1, M0P2, M0P3, M1P0, M1P1, M1P2, M1P3, M2P0, ...., M3P3

      • The "snake" used the matrices Mi to grow and shrink the tube to
        represent the body and head of a snake.

    27. Designing Tubes using 3D Curves

    28. A tube can be naturally thought of as a 3D shape wrapping around a curve C, the spine of the extrusion.
    29. The curve can be represented parametrically by C(t) = (x(t), y(t), z(t) ).
      e.g. A helix:
      • We get the curve values at various points ti and then build a polygon perpendicular to the curve at C(ti) using a Frenet frame.
      • We create the Frenet frame at each point along the curve: at each value ti a normalized vector T(ti) tangent to the curve is computed. It is given by C'(ti), the derivative of C(ti).

      • Then two normalized vectors, N(ti) and B(ti), which are perpendicular to T(ti) and to each other, are computed. These three vectors constitute the Frenet frame at ti.

      • The transformation matrix M that transforms the base polygon of the tube to its position and orientation in this frame is the transformation that carries the world coordinate system ( i, j, k ) into this new coordinate system ( N(ti), B(ti), T(ti) ), and the origin of the world into the spine point C(ti).

      • Thus, in homogeneous coordinates,
          M = ( N(ti), B(ti), T(ti), C(ti) )

      • For example, helix curve:
        • C(t) = ( cos(t), sin(t), bt, 1 )T
        • Tangent vector to C(t) is
        • Normalized tangent vector T at t is
      • x(t) = cos ( t )
        y(t) = sin ( t )
        z(t) = b*t
        i.e. C(t) = ( cos(t), sin(t), b*t )     for some constant b


        Tangents to the helix.

        Frenet frames for the helix.

      • The derivative of T gives us approximately a normal which is perpendicular to T. Normalizing gives us the unit normal,

      • The unit binormal is given by: The three unit vectors T(t), N(t), B(t) form an orthonormal basis.

      • If the derivatives of C(t) are difficult to evaluate, we can approximate them numerically:

    30. Examples:

      • A tube wrapped along a helix:

        A decagon (10 sides) is wrapped around a helix.

        See programs in /pool/u/class/cs520/labs/lab4

        cse520-4b.avi (3D Objects by Extrusion)

      • Tubes based on toroidal spirals:

        C(t) = (a + b cos(qt)cos(pt), (a + b cos(qt)) sin(pt), c sin(qt)).

        a) p = 2, q = 5; b) p = 1, q = 7

      • A sea shell -- Helix with t-dependent scaling:

        Matrix Mi is multiplied by a matrix which provides t-dependent scaling (here, g(t) = t) along the local x and y.
         
        It is also possible to add a rotation to the matrix, so that the tube appears to twist more vigorously as one looks along the spine.

      • Roller Coaster

      • Another application for Frenet frames is analyzing the motion of a car moving along a roller coaster.
      • If we assume a motor within the car is able to control its speed at any instant, then knowing the shape of the car's path is enough to specify C(t).
      • Now if suitable derivatives of C(t) can be taken, the normal and binormal vectors for the car's motion can be found and a Frenet frame for the car can be constructed for each relevant value of t.
      • This allows us to find the forces operating on the wheels of each car and the passengers.

    31. some demos ...

    32. Surfaces of Revolution

      Produce 3D objects by

      1. drawing a profile
      2. rotating the profile about an axis in discrete steps

      A surface can be obtained by

    33. rotating a plane curve in space about an axis coplanar to the curve
    34.    

      Details:

    35. Determining points defining the curve in the (x, y) plane say (xi, yi , 0) for i=1 to N.
    36. Then, for each two points, they are rotated about the y axis by a small angle theta.
    37. This rotation forms a polygon consisting of four points – the original two points and the points after they have been rotated.
    38. Next, the normal to the polygon is found by using cross products.
    39. The polygon is then drawn.
    40. Rotate the two new points about the y-axis by the same amount to create two newer points.
    41. Form the polygon between the new points and the newer points, determine the normal and draw it.
    42. Continue this process until a rotation of 360 degrees has been achieved.
    43. Go to the next two points in the 2D curve and repeat the steps above until all of the points have been used
    44. Example

      /*  sweep1.cpp
      *  Construct surfaces of revolution using wireframe but have not considered lighting.
      *  Surface is generated by revolving a curve around x-axis.			
      *  A curve f(x) is generated by polynomial interpolation from some control points
      *  or by some interested functions.
      *
      *  @Author: T.L. Yu, Fall 2008 
      */
      #include <GL/glut.h>
      #include <stdlib.h>
      #include <stdio.h>
      #include <math.h>
      #include <stdlib.h>
      
      using namespace std;
      
      const double PI = 3.14159265389;
      
      int anglex= 0, angley = 0, anglez = 0;          //rotation angles
      int window;
      
      //control points
      GLfloat ctrlpoints[4][3] = {
      	{ 0.0, 0.0, 0.0}, { 1.0, 0.5, 0.0}, 
      	{2.0, 1.2, 0.0}, {3.0, 3, 0.0}};
      
      
      void init(void)
      {
         glClearColor(1.0, 1.0, 1.0, 1.0);
         glPolygonMode( GL_FRONT, GL_LINE ) ;
         glPolygonMode( GL_BACK,  GL_LINE ) ;
         glShadeModel(GL_FLAT);
      }
      
      
      //polynomial interpretation for N points
      float polyint ( float  points[][3], float x, int N )
      {
        float y;
      
        float num = 1.0, den = 1.0;
        float sum = 0.0;
      
        for ( int i = 0; i < N; ++i ) {
          num = den = 1.0;
          for ( int j = 0; j < N; ++j ) {
            if ( j == i ) continue;
      
            num = num * ( x - points[j][0] );		 	//x - xj
          }
          for ( int j = 0; j < N; ++j ) {
            if ( j == i ) continue;
            den = den * ( points[i][0] - points[j][0] );	//xi - xj
          }
          sum += num / den * points[i][1];
        }
        y = sum;
      
        return y;
      }
      
      float aLine ( float x )
      {
        return x + 2.5;
      }
      
      void display(void)
      {
         int i, j;
         float x, y, z, r;				//current coordinates
         float x1, y1, z1, r1;			//next coordinates
         float theta;
      
         glClear(GL_COLOR_BUFFER_BIT);
         glColor3f(0.0, 1.0, 1.0);
         const float startx = 0, endx = 3;
         const int nx = 20;				//number of slices along x-direction
         const int ntheta = 20;			//number of angular slices
         const float dx = (endx - startx) / nx;	//x step size
         const float dtheta = 2*PI / ntheta;		//angular step size
      
         x = startx;
         //r = aLine ( x );
         r = polyint( ctrlpoints, x, 4);
         glPushMatrix();
         glRotatef( anglex, 1.0, 0.0, 0.0);       	//rotate the object about x-axis
         glRotatef( angley, 0.0, 1.0, 0.0);         	//rotate about y-axis   
         glRotatef( anglez, 0.0, 0.0, 1.0);		//rotate about z-axis
        
         for ( i = 0; i < nx; ++i ) {			//step through x
            theta = 0;
            x1 = x + dx;				//next x
            //r1 = aLine ( x1 );			//next f(x)
            r1 = polyint( ctrlpoints, x1, 4);		//next f(x)
            //draw the surface composed of quadrilaterals by sweeping theta
            glBegin( GL_QUAD_STRIP );
      	for ( j = 0; j <= ntheta; ++j ) {
      	  theta += dtheta;
      	  double cosa = cos( theta );
      	  double sina = sin ( theta );
      	  y = r * cosa;  y1 = r1 * cosa;	//current and next y
      	  z = r * sina;	 z1 = r1 * sina;	//current and next z
      	 
      	  //edge from point at x to point at next x
      	  glVertex3f (x, y, z);
      	  glVertex3f (x1, y1, z1);
      	  
      	  //forms quad with next pair of points with incremented theta value	
      	}			  	
            glEnd();
            x = x1;
            r = r1;	
         } //for i
      
         /* The following code displays the control points as dots. */
         glPointSize(5.0);
         glColor3f(1.0, 0.0, 1.0);
         glBegin(GL_POINTS);
            for (i = 0; i < 4; i++) 
               glVertex3fv(&ctrlpoints[i][0]);
         glEnd();
         glPopMatrix();
         glFlush();
      }
      
      
      void reshape(int w, int h)
      {
         glViewport(0, 0, (GLsizei) w, (GLsizei) h);
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         if (w <= h)
            glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 
                     5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
         else
            glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 
                     5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
      }
      
      
      void keyboard(unsigned char key, int x, int y)
      {
        switch(key) {
          case 'x':
            anglex = ( anglex + 3 ) % 360;
            break;
          case 'X':
            anglex = ( anglex - 3 ) % 360;
            break;
          case 'y':
            angley = ( angley + 3 ) % 360;
            break;
          case 'Y':
            angley = ( angley - 3 ) % 360;
            break;
          case 'z':
            anglez = ( anglez + 3 ) % 360;
            break;
          case 'Z':
            anglez = ( anglez - 3 ) % 360;
            break;
          case 'r':					//reset
            anglez = angley = anglex = 0;
            glLoadIdentity();
            break;
          case 27: /* escape */
              glutDestroyWindow(window);
              exit(0);
        }
        glutPostRedisplay();
      }
      
      int main(int argc, char** argv)
      {
         glutInit(&argc, argv);
         glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
         glutInitWindowSize (500, 500);
         glutInitWindowPosition (100, 100);
         glutCreateWindow (argv[0]);
         init ();
         glutDisplayFunc(display);
         glutReshapeFunc(reshape);
         glutKeyboardFunc (keyboard);
         glutMainLoop();
         return 0;
      }
          

      Area of a Surface of Revolution

      If y = f(x) and its second derivative exists for a ≤ x ≤ b, then the area of the surface generated by revolving the curve about the x-axis is

      e.g. f(x) = √x     1 ≤ x ≤ 4

        S = π/6 ( 17√(17) - 5√5 )

      Volume of a Surface of Revolution

      V ~ πf(x)2 dx

      e.g.

    45. 3ds File Fromat

    46. File format of 3ds Max ( formerly 3D Studio Max ), a full-featured 3D graphics animation package developed by Autodesk Media and Entertainment.


      Version 2008 interface with a dark theme
       
      3ds max living room rendered with V-Ray

      In addition to its modeling and animation tools, the latest version of 3ds Max also features advanced shaders (such as ambient occlusion and subsurface scattering), dynamic simulation, particle systems, radiosity, normal map creation and rendering, and global illumination.

    47. Organized into chunks, each contains 2-byte chunkname, 4-byte length, can have subchunks:

      MAIN3DS

        0x4D4D - The main chunk in the .3ds file, containing all other chunks

      EDIT3DS

        0x3D3D - Most interested, containing EDIT_OBJECT chunks, which define the objects in the .3ds scene (lights, geometry, etc...)

      EDIT_OBJECT

        0x4000 - Containing data and OBJ_TRIMESH; immediately followed by an object name, which is a NULL terminated string

      OBJ_TRIMESH

        0x4100 - Containing the geometric information about the object: the vertices, triangles, and texture coordinate chunks.

      TRI_VERTEXL

        0x4110 - Containing a list of vertices, a 2-byte unsigned integer vertex count followed by vertex count float triplets that define the x, y, z coordinates.

      TRI_FACEL1

        0x4120 - Defining the triangles of the model, similar to the vertex list, starting out with a 2-byte unsigned integer that gives a count of how many triangles there are, followed by sets of four 2-byte unsigned integers, the first three indixing to one of the vertices in the vertex list, the last containing a few bit-flags; a triagnle consists of three vertices in counter-clockwise order

      TRI_TEXCOORD

        0x4140 - Giving a series texture coordinates, starting out with a 2-byte unsigned integer like the last couple lists which defines how many entries are in this list.

    48. Example

      Header of "knot.3ds"

            [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  0123456789012345]
      00000: 4D 4D 29 D2 00 00 02 00 0A 00 00 00 03 00 00 00 |MM).............|
      00016: 3D 3D 39 D1 00 00 3E 3D 0A 00 00 00 03 00 00 00 |==9...>=........|
      00032: 00 01 0A 00 00 00 00 00 80 3F 00 40 1F D1 00 00 |.........?.@....|
      00048: 54 6F 72 75 73 20 4B 6E 6F 74 00 00 41 0E D1 00 |Torus Knot..A...|
      00064: 00 10 41 C4 49 00 00 25 06 3D 09 61 42 40 3E 05 |..A.I..%.=.aB@>.|
      00080: C0 E7 75 01 42 6A 93 6D 42 F2 1F 0E C1 38 E3 1C |..u.Bj.mB....8..|
      00096: 42 C5 E3 67 42 40 BC 5D C1 D5 D4 3F 42 59 80 51 |B..gB@.]...?BY.Q|
      00112: 42 97 CF 7A C1 C6 ED 60 42 DF 68 30 42 87 8F 5D |B..z...`B.h0B..]|
      00128: C1 BA 4F 77 42 46 7B 0D 42 7C D2 0D C1 5C FB 7C |..OwBF{.B|...\.||
      00144: 42 E2 26 E4 41 81 D8 03 C0 B3 6B 70 42 88 12 CB |B.&.A.....kpB...|
      00160: 41 81 B4 97 40 64 FE 54 42 D0 71 D6 41 8F 76 1B |A...@d.TB.q.A.v.|
      00176: 41 C7 0C 32 42 53 9C 01 42 E9 89 38 41 D6 F3 10 |A..2BS..B..8A...|
      00192: 42 CC B3 22 42 DD 49 1B 41 C1 23 F5 41 66 A1 45 |B.."B.I.A.#.Af.E|
      00208: 42 AC 19 97 40 7C CC E9 41 3B 09 61 42 13 3E 05 |B...@|..A;.aB.>.|
      00224: C0 E5 75 01 42 AD 0E 6E 42 04 51 AA 3F 38 97 0D |..u.B..nB.Q.?8..|
      00240: 42 BA 90 7B 42 F4 63 84 C0 C9 08 2D 42 A6 99 76 |B..{B.c....-B..v|
            [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  0123456789012345] 
      	

      00000: 	4D 4D 29 D2 00 00 		|MAIN3DS chunk length
      	02 00 0A 00 00 00 		|BOTTOM subchunk length
      	03 00 00 00 			|LEFT 
      00016: 	3D 3D 39 D1 00 00 3E 3D	 	|EDIT3DS sibling chunk length
       	0A 00 00 00 03 00 00 00 
      
      00032: 00 01 0A 00 00 00 00 00 80 3F 00 40 1F D1 00 00 |.........?.@....|
      00048: 54 6F 72 75 73 20 4B 6E 6F 74 00 00 41 0E D1 00 |Torus Knot..A...|
      00064: 00 10 41 C4 49 00 00 25 06 3D 09 61 42 40 3E 05 |..A.I..%.=.aB@>.|
      00080: C0 E7 75 01 42 6A 93 6D 42 F2 1F 0E C1 38 E3 1C |..u.Bj.mB....8..|
      00096: 42 C5 E3 67 42 40 BC 5D C1 D5 D4 3F 42 59 80 51 |B..gB@.]...?BY.Q|
      00112: 42 97 CF 7A C1 C6 ED 60 42 DF 68 30 42 87 8F 5D |B..z...`B.h0B..]|
      00128: C1 BA 4F 77 42 46 7B 0D 42 7C D2 0D C1 5C FB 7C |..OwBF{.B|...\.||
      00144: 42 E2 26 E4 41 81 D8 03 C0 B3 6B 70 42 88 12 CB |B.&.A.....kpB...|
      00160: 41 81 B4 97 40 64 FE 54 42 D0 71 D6 41 8F 76 1B |A...@d.TB.q.A.v.|
      00176: 41 C7 0C 32 42 53 9C 01 42 E9 89 38 41 D6 F3 10 |A..2BS..B..8A...|
      00192: 42 CC B3 22 42 DD 49 1B 41 C1 23 F5 41 66 A1 45 |B.."B.I.A.#.Af.E|
      00208: 42 AC 19 97 40 7C CC E9 41 3B 09 61 42 13 3E 05 |B...@|..A;.aB.>.|
      00224: C0 E5 75 01 42 AD 0E 6E 42 04 51 AA 3F 38 97 0D |..u.B..nB.Q.?8..|
      00240: 42 BA 90 7B 42 F4 63 84 C0 C9 08 2D 42 A6 99 76 |B..{B.c....-B..v|
            [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  0123456789012345] 
      
      
      • Chunk name = "MAIN3DS" ( 0x4D4D )
      • Length of main chunk = 0x0000D229 = 53801 bytes (also equals length of file )
      • Subchunk name = "BOTTOM" ( 0x0002 )
      • Length of subchunk = 0x00000A = 10 ( bytes )
      • Sibling subchunk = "LEFT" ( 0x0003 ) ?
      • Sibling subchunk = "3DSEDIT" ( 0x3D3D )
      • Length of "3DSEDIT" = 0x3D3E0000 = 15678 ( bytes )

      ....

      For details, see sepcifications.

      Open-source library: http://www.lib3ds.org/

        struct Vertex {
          float x, y, z;
        };
        
        void display_meshes (  Lib3dsFile *f )
        { 
          struct Vertex *vs, v;
          Lib3dsMesh *mesh;
        
          Lib3dsMaterial *mat=0;    //mesh materials
          init_texture();           //initialize texture features
        
          glEnable( GL_CULL_FACE );
          glCullFace ( GL_BACK );
          Lib3dsNode *node;	    //3DS node
          
          for ( int k = 0; k < f->nmeshes; ++k ) {
            mesh = f->meshes[k];
            vs = getVertices(f->meshes[k]);//get a vertice of mesh
        
            //calculate normal
            float  (*normals)[3] = (float (*)[3])  
              malloc (3*3*sizeof(float) * mesh->nfaces);
            lib3ds_mesh_calculate_face_normals ( mesh, normals );
            for ( int i = 0; i < mesh->nfaces; ++i ) {
              if (mat) {            //set material properties
                float s;
                glMaterialfv(GL_FRONT, GL_AMBIENT, mat->ambient );
                glMaterialfv(GL_FRONT, GL_DIFFUSE, mat->diffuse);
                glMaterialfv(GL_FRONT, GL_SPECULAR, mat->specular);
                s = pow(2, 10.0*mat->shininess);
                if (s>128.0)
                 s=128.0;       
                glMaterialf(GL_FRONT, GL_SHININESS, s);
             }  //if ( mat )
             //display the mesh 
             glBegin ( GL_TRIANGLES );
             for ( int j = 0; j < 3; ++ j ) {
               glNormal3fv(normals[3*i+j]);
               int ii = mesh->faces[i].index[j];
               v = vs[ii];
               if ( mesh->texcos )    //texture coordinates
                 glTexCoord2f(mesh->texcos[ii][0],
                                 mesh->texcos[ii][1]);
               glVertex3fv( ( float*)&v );	
             }
             glEnd();
           } //for i
           free ( normals );
          }  //for k
          free ( vs );
        }
        
        void display()
        {
          Lib3dsCamera *camera;
          Lib3dsFile *f = get3dsFile ( (char *) filename );
        
          if ( f->ncameras > 0 ) {
            camera = f->cameras[0];
            glMatrixMode ( GL_PROJECTION );
            glLoadIdentity();
            gluPerspective ( camera->fov, 1.0, 
                camera->near_range, camera->far_range );
            glMatrixMode ( GL_MODELVIEW );
            glLoadIdentity();
            gluLookAt(camera->position[0], camera->position[1], 
              camera->position[2], camera->target[0], 
              camera->target[1], camera->target[2], 0, 1, 0 );
          } 
          display_meshes (  f );
          glFlush();
          glutSwapBuffers();
        }
        

      Open-source software: Blender
      Blender Tutorial