objectives introduce simple data structures for building polygonal models -- vertex lists and edge...
TRANSCRIPT
Objectives Objectives
Introduce simple data structures for building Introduce simple data structures for building polygonal models -- Vertex lists and Edge listspolygonal models -- Vertex lists and Edge lists
OpenGL vertex arraysOpenGL vertex arrays Use transformations by an example of creating Use transformations by an example of creating
graphical (virtual) devices using OpenGLgraphical (virtual) devices using OpenGL Lead to reusable code that will be helpful laterLead to reusable code that will be helpful later
CSC461: Lecture 17CSC461: Lecture 17Modeling and Virtual TrackBallModeling and Virtual TrackBall
Representing a MeshRepresenting a Mesh Consider a meshConsider a mesh
There are 8 nodes and 12 edgesThere are 8 nodes and 12 edges 5 interior polygons5 interior polygons 6 interior (shared) edges6 interior (shared) edges
Each vertex has a location vEach vertex has a location vii = (x = (xii y yii z zii))
v1 v2
v7
v6
v8
v5
v4
v3
e1
e8
e3
e2
e11
e6
e7
e10
e5
e4
e9
e12
Simple RepresentationSimple Representation
List all polygons by their geometric locationsList all polygons by their geometric locations Leads to OpenGL code such asLeads to OpenGL code such as
glBegin(GL_POLYGON); glVertex3f(x1, y1, z1); glVertex3f(x6, y6, z6); glVertex3f(x7, y7, z7);glEnd();
Inefficient and unstructuredInefficient and unstructured Consider moving a vertex to a new locationsConsider moving a vertex to a new locations
Inward and Outward Facing PolygonsInward and Outward Facing Polygons
The order {vThe order {v11, v, v66, v, v77} and {v} and {v66, v, v77, v, v11} are equivalent in that } are equivalent in that
the same polygon will be rendered by OpenGL but the order the same polygon will be rendered by OpenGL but the order {v{v11, v, v77, v, v66} is different} is different
The first two describe The first two describe outwardly facingoutwardly facing polygons polygons Use the Use the right-hand ruleright-hand rule = =
counter-clockwise encirclement counter-clockwise encirclement
of outward-pointing normal of outward-pointing normal OpenGL treats inward and OpenGL treats inward and
outward facing polygons differentlyoutward facing polygons differently
Geometry vs TopologyGeometry vs Topology
Generally it is a good idea to look for data Generally it is a good idea to look for data structures that separate the geometry from the structures that separate the geometry from the topologytopology Geometry: locations of the verticesGeometry: locations of the vertices Topology: organization of the vertices and edgesTopology: organization of the vertices and edges Example: a polygon is an ordered list of vertices Example: a polygon is an ordered list of vertices
with an edge connecting successive pairs of with an edge connecting successive pairs of vertices and the last to the firstvertices and the last to the first
Topology holds even if geometry changesTopology holds even if geometry changes
Vertex ListsVertex Lists Put the geometry in an arrayPut the geometry in an array Use pointers from the vertices into this arrayUse pointers from the vertices into this array Introduce a polygon listIntroduce a polygon list
x1 y1 z1
x2 y2 z2
x3 y3 z3
x4 y4 z4
x5 y5 z5.
x6 y6 z6
x7 y7 z7
x8 y8 z8
P1P2P3P4P5
v1
v7
v6
v8
v5
v6topology geometry
Shared Edges and Edge ListShared Edges and Edge List Vertex lists will draw filled polygons correctly but if Vertex lists will draw filled polygons correctly but if
we draw the polygon by its edges, shared edges are we draw the polygon by its edges, shared edges are drawn twicedrawn twice
Can store mesh by Can store mesh by edge listedge list Edge ListEdge List
Note polygons arenot represented
v1 v2
v7
v6v8
v5
v4
v3
e1
e8
e3
e2
e11
e6
e7
e10
e5
e4
e9
e12
e1e2e3e4e5e6e7e8e9
x1 y1 z1
x2 y2 z2
x3 y3 z3
x4 y4 z4
x5 y5 z5.
x6 y6 z6
x7 y7 z7
x8 y8 z8
v1v6
Drawing a polygon Drawing a polygon from a list of indicesfrom a list of indices
Draw a quadrilateral Draw a quadrilateral from a list of indices into from a list of indices into the array the array verticesvertices and and use color corresponding use color corresponding to first indexto first index
void polygon(int a, int b, int c , int d)
{ glBegin(GL_POLYGON); glColor3fv(colors[a]); glVertex3fv(vertices[a]); glVertex3fv(vertices[b]); glVertex3fv(vertices[c]); glVertex3fv(vertices[d]); glEnd(); }
Modeling a CubeModeling a Cube
Model a color cube for Model a color cube for rotating cube programrotating cube program
Define global arrays for Define global arrays for vertices and colorsvertices and colors
GLfloat vertices[][3] = GLfloat vertices[][3] = {{-1.0,-1.0,-1.0}, { 1.0,-1.0,-1.0}, {{-1.0,-1.0,-1.0}, { 1.0,-1.0,-1.0},
{ 1.0, 1.0,-1.0}, {-1.0, 1.0,-1.0}, { 1.0, 1.0,-1.0}, {-1.0, 1.0,-1.0}, {-1.0,-1.0, 1.0}, { 1.0,-1.0, 1.0},{-1.0,-1.0, 1.0}, { 1.0,-1.0, 1.0}, { 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0}};{ 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0}};
GLfloat colors[][3] = {{0.0,0.0,0.0}, {1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}};
Draw cube from facesDraw cube from facesvoid colorcube( )void colorcube( ){ polygon(0,3,2,1);{ polygon(0,3,2,1); polygon(2,3,7,6);polygon(2,3,7,6); polygon(0,4,7,3);polygon(0,4,7,3); polygon(1,2,6,5);polygon(1,2,6,5); polygon(4,5,6,7);polygon(4,5,6,7); polygon(0,1,5,4);polygon(0,1,5,4);}} Note that vertices are ordered so that Note that vertices are ordered so that we obtain correct outward facing normalswe obtain correct outward facing normals EfficiencyEfficiency
The weakness of our approach is that we are building the model in The weakness of our approach is that we are building the model in the application and must do many function calls to draw the cubethe application and must do many function calls to draw the cube
Drawing a cube by its faces in the most straight forward way Drawing a cube by its faces in the most straight forward way requiresrequires
6 6 glBeginglBegin, 6 , 6 glEndglEnd 6 6 glColorglColor 24 24 glVertexglVertex More if we use texture and lightingMore if we use texture and lighting
0
5 6
2
4 7
1
3
Vertex ArraysVertex Arrays OpenGL provides a facility called OpenGL provides a facility called vertex arraysvertex arrays that that
allow us to store array data in the implementationallow us to store array data in the implementation Six types of arrays supportedSix types of arrays supported
VerticesVertices ColorsColors Color indicesColor indices NormalsNormals Texture coordinatesTexture coordinates Edge flagsEdge flags
We will need only colors and verticesWe will need only colors and vertices Initialization -- Using the same color and vertex Initialization -- Using the same color and vertex
data, first we enabledata, first we enable glEnableClientState(GL_COLOR_ARRAY);glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_VERTEX_ARRAY);
Using ArraysUsing Arrays Identify location of arraysIdentify location of arrays
glVertexPointer(3, GL_FLOAT, 0, vertices);glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);glColorPointer(3, GL_FLOAT, 0, colors);
Map indices to faces Map indices to faces Form an array of face indicesForm an array of face indices
GLubyte cubeIndices[24] = { 0,3,2,1, 2,3,7,6, 0,4,7,3,
1,2,6,5, 4,5,6,7, 0,1,5,4}; Each successive four indices describe a face of the cubeEach successive four indices describe a face of the cube
3d arrays stored as floats data contiguous
data array
Drawing the cubeDrawing the cube Draw through Draw through glDrawElementsglDrawElements which replaces all which replaces all glVertexglVertex and and glColorglColor calls in the display callback calls in the display callback
for(i=0; i<6; i++) glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_BYTE, &cubeIndices[4*i]);
format of index data start of index data
what to draw number of indices Method 1:Method 1:
Method 2:Method 2:
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cubeIndices);
Draws cube with 1 function call!!
Example: Virtual TrackballExample: Virtual Trackball Physical TrackballPhysical Trackball
The trackball is an “upside down” mouseThe trackball is an “upside down” mouse If there is little friction between the ball If there is little friction between the ball
and the rollers, we can give the ball a push and the rollers, we can give the ball a push and it will keep rolling yielding and it will keep rolling yielding continuous changescontinuous changes
Two possible modes of operationTwo possible modes of operation Continuous pushing or tracking hand motion; and SpinningContinuous pushing or tracking hand motion; and Spinning
A Trackball from a MouseA Trackball from a Mouse Problem: we want to get the two behavior modes from a mouseProblem: we want to get the two behavior modes from a mouse We would also like the mouse to emulate a frictionless (ideal) We would also like the mouse to emulate a frictionless (ideal)
trackballtrackball Solve in two stepsSolve in two steps
Map trackball position to mouse positionMap trackball position to mouse position Use GLUT to obtain the proper modesUse GLUT to obtain the proper modes
Trackball FrameTrackball Frame
origin at center of ballorigin at center of ball
Projection of Projection of Trackball PositionTrackball PositionWe can relate position on trackball to position on a normalized mouse pad by projecting orthogonally onto pad
Reversing ProjectionReversing Projection Because both the pad and the upper hemisphere of the Because both the pad and the upper hemisphere of the
ball are two-dimensional surfaces, we can reverse the ball are two-dimensional surfaces, we can reverse the projectionprojection
A point (x,z) on the mouse pad corresponds to the point A point (x,z) on the mouse pad corresponds to the point (x,y,z) on the upper hemisphere where(x,y,z) on the upper hemisphere where
Computing RotationsComputing Rotations Suppose that we have two points that were obtained from the Suppose that we have two points that were obtained from the
mouse. mouse. We can project them up to the hemisphere to points We can project them up to the hemisphere to points pp11 and and pp22 These points determine a great circle on the sphereThese points determine a great circle on the sphere We can rotate from We can rotate from pp11 to to pp by finding the proper axis of rotation and the angle between by finding the proper axis of rotation and the angle between
the pointsthe points
y = 222 zxr if r |x| 0, r |z| 0
Obtaining the angleObtaining the angle The axis of rotation is given by the normal to the plane The axis of rotation is given by the normal to the plane
determined by the origin, determined by the origin, pp1 1 , and , and pp2 2
The angle between The angle between pp1 1
and and pp2 2 is given byis given by
If we move the mouse slowly or sample its position If we move the mouse slowly or sample its position frequently, then frequently, then will be small and we can use the will be small and we can use the approximation approximation
n = p1 p1
| sin | = ||||
||
21 pp
n
sin
Implementing with GLUTImplementing with GLUT
We will use the idle, motion, and mouse callbacks to We will use the idle, motion, and mouse callbacks to implement the virtual trackballimplement the virtual trackball
Define actions in terms of three booleansDefine actions in terms of three booleans
trackingMousetrackingMouse: if true update trackball position: if true update trackball position
redrawContinueredrawContinue: if true, idle function posts a redisplay: if true, idle function posts a redisplay trackballMovetrackballMove: if true, update rotation matrix: if true, update rotation matrix In this example, we use the virtual trackball to rotate the In this example, we use the virtual trackball to rotate the
color cube we modeled earliercolor cube we modeled earlier The code for the colorcube function is omitted because The code for the colorcube function is omitted because
it is unchanged from the earlier examplesit is unchanged from the earlier examples
InitializationInitialization#define bool int /* if system does not support#define bool int /* if system does not support bool type */bool type */#define false 0#define false 0#define true 1#define true 1#define M_PI 3.14159 /* if not in math.h */#define M_PI 3.14159 /* if not in math.h */
int int winWidth, winHeight;winWidth, winHeight;
float angle = 0.0, axis[3], trans[3];float angle = 0.0, axis[3], trans[3];
bool bool trackingMouse = false;trackingMouse = false;bool bool redrawContinue = false;redrawContinue = false;bool trackballMove = false;bool trackballMove = false;
float lastPos[3] = {0.0, 0.0, 0.0};float lastPos[3] = {0.0, 0.0, 0.0};int curx, cury;int curx, cury;int startX, startY;int startX, startY;
The Projection StepThe Projection Stepvoidtrackball_ptov(int x, int y, int width, int height, voidtrackball_ptov(int x, int y, int width, int height,
float v[3])float v[3]){{ float d, a;float d, a; /* project x,y onto a hemisphere centered /* project x,y onto a hemisphere centered
within within width, height , note z is up here*/width, height , note z is up here*/ v[0] = (2.0*x - width) / width;v[0] = (2.0*x - width) / width; v[1] = (height - 2.0F*y) / height; v[1] = (height - 2.0F*y) / height; d = sqrt(v[0]*v[0] + v[1]*v[1]);d = sqrt(v[0]*v[0] + v[1]*v[1]); v[2] = cos((M_PI/2.0) * ((d < 1.0) ? d : 1.0));v[2] = cos((M_PI/2.0) * ((d < 1.0) ? d : 1.0)); a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] *= a; v[1] *= a; v[2] *= a;v[0] *= a; v[1] *= a; v[2] *= a;}}
glutMotionFuncglutMotionFunc void mouseMotion(int x, int y) void mouseMotion(int x, int y) { { float curPos[3],float curPos[3], dx, dy, dz;dx, dy, dz; // compute position on // compute position on
hemisphere hemisphere trackball_ptov(x, y, trackball_ptov(x, y,
winWidth, winWidth, winHeight, curPos);winHeight, curPos);
if (trackingMouse) if (trackingMouse) { {
/* compute the change of /* compute the change of position on the hemisphere */position on the hemisphere */
dx = curPos[0] - lastPos[0];dx = curPos[0] - lastPos[0]; dy = curPos[1] - lastPos[1];dy = curPos[1] - lastPos[1]; dz = curPos[2] - lastPos[2];dz = curPos[2] - lastPos[2];
}}
if (dx || dy || dz) {if (dx || dy || dz) { // compute theta and cross product// compute theta and cross product angle = 90.0 * angle = 90.0 *
sqrt(dx*dx + dy*dy + dz*dz);sqrt(dx*dx + dy*dy + dz*dz); axis[0] = lastPos[1]*curPos[2] – axis[0] = lastPos[1]*curPos[2] – lastPos[2]*curPos[1];lastPos[2]*curPos[1]; axis[1] = lastPos[2]*curPos[0] – axis[1] = lastPos[2]*curPos[0] – lastPos[0]*curPos[2];lastPos[0]*curPos[2]; axis[2] = lastPos[0]*curPos[1] – axis[2] = lastPos[0]*curPos[1] – lastPos[1]*curPos[0];lastPos[1]*curPos[0]; /* update position *//* update position */ lastPos[0] = curPos[0];lastPos[0] = curPos[0]; lastPos[1] = curPos[1];lastPos[1] = curPos[1]; lastPos[2] = curPos[2];lastPos[2] = curPos[2]; }} } } glutPostRedisplay();glutPostRedisplay();}}
Idle and Display CallbacksIdle and Display Callbacksvoid spinCube()void spinCube(){ { if (redrawContinue) glutPostRedisplay();if (redrawContinue) glutPostRedisplay();}}
void display()void display(){ glClear(GL_COLOR_BUFFER_BIT|{ glClear(GL_COLOR_BUFFER_BIT|
GL_DEPTH_BUFFER_BIT);GL_DEPTH_BUFFER_BIT); if (trackballMove) if (trackballMove) {{
glRotatef(angle, axis[0], axis[1], axis[2]);glRotatef(angle, axis[0], axis[1], axis[2]); }}
colorcube();colorcube(); glutSwapBuffers();glutSwapBuffers();}}
Mouse CallbackMouse Callback
void mouseButton(int button,int state,int x,int y)void mouseButton(int button,int state,int x,int y){{
if(button==GLUT_RIGHT_BUTTON) exit(0);if(button==GLUT_RIGHT_BUTTON) exit(0);
/* holding down left button /* holding down left button allows user to rotate cube */allows user to rotate cube */
if(button==GLUT_LEFT_BUTTON) switch(state)if(button==GLUT_LEFT_BUTTON) switch(state) {{ case GLUT_DOWN:case GLUT_DOWN:
y=winHeight-y;y=winHeight-y; startMotion( x,y);startMotion( x,y); break;break;
case GLUT_UP:case GLUT_UP: stopMotion( x,y);stopMotion( x,y); break;break;
}}}}
Start FunctionStart Functionvoid startMotion(int x, int y)void startMotion(int x, int y)
{{
trackingMouse = true;trackingMouse = true;
redrawContinue = false;redrawContinue = false;
startX = x;startX = x;
startY = y;startY = y;
curx = x;curx = x;
cury = y;cury = y;
trackball_ptov(x, y, trackball_ptov(x, y, winWidth, winHeight, winWidth, winHeight, lastPos);lastPos);
trackballMove=true;trackballMove=true;
}}
Stop FunctionStop Functionvoid stopMotion(int x, int y)void stopMotion(int x, int y){{ trackingMouse = false;trackingMouse = false; /* check if position has /* check if position has
changed */changed */ if(startX!=x || startY!=y)if(startX!=x || startY!=y)
redrawContinue = true;redrawContinue = true; else{else{
angle = 0.0;angle = 0.0; redrawContinue=false;redrawContinue=false; trackballMove=false;trackballMove=false;
}}}}
QuaternionsQuaternions
Because the rotations are on the surface of a Because the rotations are on the surface of a sphere, quaternions provide an interesting and sphere, quaternions provide an interesting and more efficient way to implement the trackballmore efficient way to implement the trackball
See code in some of the standard demos See code in some of the standard demos included with Mesaincluded with Mesa