Introduction to Modeling Transformations in OpenGL

boringtarpΛογισμικό & κατασκευή λογ/κού

13 Δεκ 2013 (πριν από 3 χρόνια και 7 μήνες)

76 εμφανίσεις

Introduction to Modeling Transformations in OpenGL
CS 442/542
August 30,2012
1.Modeling transformations
 When dening the geometry of an object,we typically use a coordinate system that is convenient
for describing its shape.This is often called the master or local coordinate system for that shape.
 Many times we want to reuse that shape by placing new instances of the object in dierent areas,
with possibly dierent sizes and orientation.
 The transformation that maps the object from its own local coordinates to world coordinates is
called a modeling transformation.
2.Example:Creating a\unit star"in its own local coordinate system.
(0,0)
x
y
0
1
2
3
4
5
6
7
8
9
unit circle
local coordinate
system
static GLfloat starVerts[10][2] = {
{-0.224513988,0.30901699},
{ 0.0,1.0},
{ 0.224513988,0.30901699},
{ 0.951056516,0.30901699},
{ 0.363271264,-0.118033989},
{ 0.587785252,-0.809016994},
{ 0.0,-0.381966011},
{-0.587785252,-0.809016994},
{-0.363271264,-0.118033989},
{-0.951056516,0.30901699}
};
GLushort starIndices[20] = {
0,1,2,//triangle 0
2,3,4,//triangle 1
4,5,6,//triangle 2
6,7,8,//triangle 3
8,9,0,//triangle 4
0,2,4,6,8//triangle fan
};
1
3.Transformation Matrices,Vertex Shader,Matrix Operations,and a Matrix Stack
 Client matrices
GLfloat ModelView[4*4];
GLfloat Projection[4*4];
 GL matrix
GLint ModelViewProjectionUniform;
 Vertex Shader
const GLchar *vertexShaderSource = {
"attribute vec2 vertexPosition;"
"uniform mat4 ModelViewProjection;\n"
"void main() {\n"
"gl_Position = ModelViewProjection*vec4(vertexPosition,0.0,1.0);\n"
"}\n"
};
 Loading GL matrix from client matrices
void loadUniforms() {
GLfloat ModelViewProjection[4*4];
matrixMultiply(ModelViewProjection,Projection,ModelView);
glUniformMatrix4fv(ModelViewProjectionUniform,1,GL_FALSE,
ModelViewProjection);
glUniform3fv(ColorUniform,1,Color);
}
 Client matrix operations
void matrixIdentity(GLfloat M[4*4]) {...}
matrixOrtho(GLfloat M[4*4],
GLfloat left,GLfloat right,
GLfloat bottom,GLfloat top,
GLfloat hither,GLfloat yon) {...}
matrixScale(GLfloat M[4*4],GLfloat sx,GLfloat sy,GLfloat sz) {...}
void matrixTranslate(GLfloat M[4*4],GLfloat dx,GLfloat dy,GLfloat dz) {...}
void matrixRotate(GLfloat M[4*4],
GLfloat angle_degrees,GLfloat x,GLfloat y,GLfloat z) {...}
 Matrix Stack
#define STACK_MAX 10
int matrixStackSize = 0;
GLfloat matrixStack[STACK_MAX][4*4];
void matrixPush(GLfloat M[4*4]) {
memcpy(matrixStack[matrixStackSize++],M,4*4*sizeof(GLfloat));
}
void matrixPop(GLfloat M[4*4]) {
memcpy(M,matrixStack[--matrixStackSize],4*4*sizeof(GLfloat));
}
2
4.OpenGL code to draw unit star
 We create buer objects for both the triangle vertices and vertex indices on the rst invocation.
 We use glDrawElements() to draw triangle tips and the triangle fan for the center pentagon.
void star(void) {
static GLuint vertBuffer;
static GLuint indexBuffer;
static GLboolean firstTime = GL_TRUE;
if (firstTime) {
glGenBuffers(1,&vertBuffer);
glBindBuffer(GL_ARRAY_BUFFER,vertBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(starVerts),
starVerts,GL_STATIC_DRAW);
glGenBuffers(1,&indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(starIndices),
starIndices,GL_STATIC_DRAW);
firstTime = GL_FALSE;
}
matrixPush(ModelView);
matrixRotate(ModelView,starAngle,0.0,0.0,1.0);
loadUniforms();
glEnableVertexAttribArray(vertexPositionAttr);
glBindBuffer(GL_ARRAY_BUFFER,vertBuffer);
glVertexAttribPointer(vertexPositionAttr,2,GL_FLOAT,
GL_FALSE,0,(GLvoid*) 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexBuffer);
glDrawElements(GL_TRIANGLES,15,
GL_UNSIGNED_SHORT,(GLvoid*) 0);
glDrawElements(GL_TRIANGLE_FAN,5,
GL_UNSIGNED_SHORT,(GLvoid*) (15*sizeof(GLushort)));
matrixPop(ModelView);
}
5.The Modeling Matrix
 Whenever we\send"a vertex to OpenGL,the vertex is transformed by the current Modeling
Matrix M:This matrix maps the vertex from its local coordinate system to the world coordinate
system.
M
modeling matrix
(x,y)
(x
w
,y
w
)
local
coordinates
world
coordinates
 There is another matrix,called the View Matrix V;which maps points from the world coordinate
system to the\eye"or\view"coordinate system.(We will cover this in detail later).
3
M
modeling matrix
(x,y)
(x
w
,y
w
)
local
coordinates
world
coordinates
V
(x
e
,y
e
)
eye
coordinates
view matrix
 We combine these two matrices into a single Model-View Matrix which is conceptually the product
V M:
VM
composite
model-view matrix
(x,y)
local
coordinates
(x
e
,y
e
)
eye
coordinates
 For now,just assume that the view-matrix is the identity matrix.
matrixIdentity(ModelView);
M I
 Subsequent calls to matrixRotate(),matrixTranslate(),matrixScale(),...concatenate
the specied matrix onto the specied matrix.For example,the following code snippet rst
concatenates a translation matrix onto the Model-View matrix and then concatenates a scale
matrix onto the result.
matrixTranslate(ModelView,0.0,0.75,0.0);
matrixScale(ModelView,0.15,0.15,1.0);
The concatenation replaces the current matrix with the product of the current matrix times the
specied matrix (i.e.,we multiply on the right).
M M  T
M M  S
 It is important to note that,since we multiply on the right,the last transformation specied has
the rst eect on the vertices being transformed.In the above example M = T  S;so the scale
occurs before the translation:
Mx = (TS)x = (T(Sx))
 We can preserve and restore the current matrix using a matrix stack via matrixPush() and
matrixPop():
matrixPush(ModelView);//save model-view matrix
matrixTranslate(ModelView,0.0,0.75,0.0);
matrixScale(ModelView,0.15,0.15,1.0);
/* draw some primitives here */
matrixPop(ModelView);//resore model-view matrix
This allows us to temporarily modify the Model-View matrix.
4
6.Example:Create ring of stars
(a) Create\pole star"by rst scaling the unit star by 0.1 in both x and y and then translating it in
the y direction by 0.75.The composite transformation becomes
M
0
= T
0;:75
 S
:1;:1
void poleStar(void) {
matrixPush(ModelView);
matrixTranslate(ModelView,0.0,0.75,0.0);
matrixScale(ModelView,0.15,0.15,1.0);
star();
matrixPop(ModelView);
}
(b) We then create our ring of 13 stars by continually rotating the pole star by  = 360=13:
M
1
= R

M
0
M
2
= R

R

M
0
.
.
.
M
12
= R

:::R

R

|
{z
}
12
M
0
void starRing(void) {
matrixPush(ModelView);
matrixRotate(ModelView,ringAngle,0.0,0.0,1.0);
poleStar();
for (int i = 0;i < 12;i++) {
matrixRotate(ModelView,360.0/13,0.0,0.0,1.0);
poleStar();
}
matrixPop(ModelView);
}
 The matrixTranslate(ModelMatrix,0.0,0.75,0.0) creates a new translation matrix T
0;:75
and concatenates it onto the right of the current modeling matrix:
M M  T
0;:75
5
 The call the matrixPush(ModelMatrix) preserves the state of the current modeling matrix.Later,
a symmetric call to matrixPop(ModelMatrix) restores the modeling matrix to its value at the
time of the corresponding push.
 How transformation matrices are composed in starRing() (M = current modeling matrix,T =
translation,S = scale,R = rotate):
M = I
push entering starRing()
push entering poleStar()
M = T
M = T  S
unit star
pop leaving poleStar()
M = I
M = R
push
M = R T
M = R T  S
unit star
pop
M = R
M = R R
push
M = R R T
M = R R T  S
unit star
pop
M = R R
.
.
.
pop leaving starRing()
M = I
6