Introduction to Computer Graphics, Midterm Cheat Sheet
Lecture 2: Linear Transformation
Point p̃, non-numerical
Vector ⃗v , non-numerical
Coordinate system f⃗t , bold means column vector, t means transposed
basis for vector; frame for point, non-numerical object
Coordinate vector c, numerical object
Vector space
h i c1
ci⃗bi = ⃗b1 ⃗b2 ⃗b3 c2 = b⃗t c
X
⃗v =
i c3
Linear transformation is notated by arrow.
X X
⃗v ⇒ L(⃗v ) = L( ci⃗bi ) = ci L(⃗bi )
i i
h i c1 h i c1
⃗b1 ⃗b2 ⃗b3 c2 ⇒ L(⃗b1 ) L(⃗b2 ) L(⃗b3 ) c2
c3 c3
h i M11 M12 M13 c1
= ⃗b1 ⃗b2 ⃗b3 M21 M22 M23 c2
M31 M32 M33 c3
Therefore, a vector undergoes a linear transformation as:
⃗v = b⃗t c ⇒ b⃗t M c
Where the matrix M depends on the linear transformation.
Lecture 3: Affine Transformation
Linear transformation
l t i t l 0
A= =
0 1 0 1 0 1
= TL
Rigid body transformation A = T R, where R is a rotation matrix.
RBT preserves dot product, handedness, and distance, i.e. geometric topology is maintained.
If we RBT’d a vector, then the fourth column becomes irrelevant; a vector cannot be translated.
A normal vector ⃗n is defined ⃗n · (p̃1 − p̃2 ) = 0.
When affine transformed, ⃗nt A−1 A(p̃1 − p̃2 ) = 0.
hence, transposing the expression, we get ⃗n′ = A−t⃗n = L−t⃗n
We need to normalize the vector after applying the inverse transpose linear transform.
1
Lecture 5: Respect
Left-of rule: Point is transformed w.r.t. the frame that appears immediately to the left of the
transform matrix.
f⃗t ⇒ f⃗t S
f⃗t is transformed by S with respect to f⃗t .
f⃗t = a⃗t A−1 ⇒ a⃗t SA−1 :
f⃗t is transformed by S with respect to a⃗t .
p̃ = f⃗t c ⇒ f⃗t Sc:
p̃ is transformed by S with respect to f⃗t .
p̃ = f⃗t c = a⃗t A−1 c ⇒ a⃗t SA−1 c = f⃗t ASA−1 c:
p̃ is transformed by S with respect to a⃗t .
Lecture 6: Frames in Graphics
⃗t
World frame w
Object frame o⃗t = w
⃗ tO
Eye frame e⃗t = w
⃗ tE
Eye matrix is specified by eye point p̃, view point q̃, and up vector ⃗u.
z = normalize(p − q), x = normalize(u × z), y = z × x
p̃ = o⃗t c = w
⃗ t Oc = e⃗t E −1 Oc
Lecture 8: Arcball
This is black magic
Lecture 9: Quaternion 2
ω
Quaternion , where ω is scalar and ĉ is 3D coordinate vector
ĉ
ω αω
α =
ĉ αĉ
ω1 ω2 ω1 ω2 − ĉ1 · ĉ2
=
ĉ2 ĉ2 ω1 ĉ2 + ω2 ĉ1 + ĉ1 × ĉ2
cos( θ2 )
: rotation of angle θ about unit length axis k̂
sin( θ2 )k̂
−1
cos( θ2 ) cos( θ2 )
0
Rotation:
sin( θ2 )k̂ ĉ sin( θ2 )k̂
−1
cos( θ2 ) cos( θ2 ) cos( −θ
2 )
where = =
sin( θ2 )k̂ −sin( θ2 )k̂ sin( −θ
2 )k̂
LERP and SLERP
cos( θ20 ) cos( θ21 )
LERP: (1 − α) + α , followed by normalization
sin( θ20 )k̂0 sin( θ21 )k̂1
2
1−α α
cos( θ20 ) cos( θ21 )
SLERP: +
sin( θ20 )k̂0 sin( θ21 )k̂1
α
cos( θ2 ) cos( αθ
2 )
where =
sin( θ2 )k̂ sin( αθ
2 )k̂
cos( θ20 ) cos( θ21 )
Sphere-based SLERP: sin[(1−α)Ω] + sin(αΩ)
sin(Ω) sin( θ20 )k̂0 sin(Ω) sin( θ21 )k̂1
Lecture 10: Bezier Curves / Polar Forms
Polar form: n-affine, symmetric, and correspondence identity; f (t, · · · , t) = F (t)
1
there is unique polar form tk = n C
Q
k
ui1 · · · uik
You can get Bezier points using polar form.
n
Bernstein basis polynomials: Bi,n (t) = (1 − t)n−i ti
i
nonnegative, symmetric, partition of unity, resursion; Bi,n (t) = (1 − t)Bi,n−1 (t) + tBi−1,n−1 (t).
P
Bezier curve F (t) = Pi Bi,n (t)
Bezier control polygon has
Convex hull property: the curve lies within the convex hull
Variation diminishing property: number of intersection...
Affine invariance
Lecture 11: Splines
Cubic Hermite splines:
1 0 0 0 c0
3 0
−1 0 0 ⃗v0
t2
F (t) = 1 t t
−3 −2 3 −1 c1
2 1 −2 1 ⃗v1
Catmull-Rom splines: since c′ (i) = 3(di − ci ) and c′ (i + 1) = 3(ci+1 − ei ), we set
di = 61 (ci+1 − ci−1 ) + ci , ei = 61 (ci+2 − ci ) + ci+1
1 0 0 0 c−1
−τ 0 τ 0
c0
F (t) = 1 t t2 t3
2τ τ − 3 −2τ + 3 −τ c1
−τ −τ + 2 τ −2 τ c2
Catmull-Rom splines: since c′ (i) = 3(di − ci ) and c′ (i + 1) = 3(ci+1 − ei ), we set
di = 61 (ci+1 − ci−1 ) + ci , ei = 61 (ci+2 − ci ) + ci+1 , and more generally:
0 1 0 0 c−1
−τ 0 τ 0
c0
F (t) = 1 t t2 t3
2τ τ − 3 −2τ + 3 −τ c1
−τ −τ + 2 τ −2 τ c2
B-splines:
1 4 1 0 c−1
3 −3 0 3 0
c0
t2
F (t) = 1 t t
3 6 3 0 c1
−1 3 −3 1 c2
3
Lecture 12: Geometric Modeling
Implicit surface - torus: (x2 + y 2 + z 2 − R2 − a2 )2 − 4R2 (x2 + y 2 ) = 0
Catmull-Clark subdivision surface
a new vertex for each vertex, edge, and face in existing mesh, resulting in all faces are quads.
vf = m1f j vj , ve = 14 (v1 + v2 + vf 1 + vf 2 ), vv = nvn−2 v + n12 j vj + n12 j vf j
P P P
v v v
This is proven to converge to a G1 continuous surface.
OpenGL Example
struct Geometry {
GlBufferObject vbo, ibo;
int vboLen, iboLen;
Geometry(VertexPN *vtx, unsigned short *idx, int vboLen, int iboLen) {
this->vboLen = vboLen;
this->iboLen = iboLen;
// Now create the VBO and IBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexPN) * vboLen, vtx, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * iboLen, idx, GL_STATIC_DRAW);
}
void draw(const ShaderState& curSS) {
// Enable the attributes used by our shader
safe_glEnableVertexAttribArray(curSS.h_aPosition);
safe_glEnableVertexAttribArray(curSS.h_aNormal);
// bind vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);
safe_glVertexAttribPointer(curSS.h_aPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPN), FIELD_OFFSET(VertexPN, p));
safe_glVertexAttribPointer(curSS.h_aNormal, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPN), FIELD_OFFSET(VertexPN, n));
// bind ibo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
// draw!
glDrawElements(GL_TRIANGLES, iboLen, GL_UNSIGNED_SHORT, 0);
// Disable the attributes used by our shader
safe_glDisableVertexAttribArray(curSS.h_aPosition);
safe_glDisableVertexAttribArray(curSS.h_aNormal);
}
};
static void drawStuff() {
// short hand for current shader state
const ShaderState& curSS = *g_shaderStates[g_activeShader];
// build & send proj. matrix to vshader
const Matrix4 projmat = makeProjectionMatrix();
sendProjectionMatrix(curSS, projmat);
// use the skyRbt as the eyeRbt
const Matrix4 eyeRbt = g_skyRbt;
const Matrix4 invEyeRbt = inv(eyeRbt);
4
const Cvec3 eyeLight1 = Cvec3(invEyeRbt * Cvec4(g_light1, 1)); // g_light1 position in eye coordinates
const Cvec3 eyeLight2 = Cvec3(invEyeRbt * Cvec4(g_light2, 1)); // g_light2 position in eye coordinates
safe_glUniform3f(curSS.h_uLight, eyeLight1[0], eyeLight1[1], eyeLight1[2]);
safe_glUniform3f(curSS.h_uLight2, eyeLight2[0], eyeLight2[1], eyeLight2[2]);
// draw ground
// ===========
//
const Matrix4 groundRbt = Matrix4(); // identity
Matrix4 MVM = invEyeRbt * groundRbt;
Matrix4 NMVM = normalMatrix(MVM);
sendModelViewNormalMatrix(curSS, MVM, NMVM);
safe_glUniform3f(curSS.h_uColor, 0.1, 0.95, 0.1); // set color
g_ground->draw(curSS);
// draw cubes
// ==========
MVM = invEyeRbt * g_objectRbt[0];
NMVM = normalMatrix(MVM);
sendModelViewNormalMatrix(curSS, MVM, NMVM);
safe_glUniform3f(curSS.h_uColor, g_objectColors[0][0], g_objectColors[0][1], g_objectColors[0][2]);
g_cube->draw(curSS);
}
static void display() {
glUseProgram(g_shaderStates[g_activeShader]->program);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear framebuffer color&depth
drawStuff();
glutSwapBuffers(); // show the back buffer (where we rendered stuff)
checkGlErrors();
}