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

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 #include #include #include #include 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

 ``` [ 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