|
Notes for Tuesday March 24 class -- perspective and 3D objects
Note: I will be adding some diagrams to these notes in the coming days.
Perspective
Given a focal length f, we want to distort the scene
as though the point (0,0,f) is a camera viewpoint.
Objects that are in positive z will appear to be larger, and
objects that are in negative z will appear to be smaller.
The matrix that does this is:
We send this matrix down to the GPU as a uniform mat4 variable:
mat4 uFMat = [ 1,0,0,0, 0,1,0,0, 0,0,-1/f,0, 0,0,0,1 ]
We then use it in the vertex shader.
In the vertex shader, we multiply the vertex by
uFMat
after (that is, to the left of)
multiplying by the transformation matrix
uMat .
In particular, we replace this line in the vertex shader:
vec4 pos = uMatF * vec4(aPos, 1.);
by this line:
vec4 pos = uPMat * uMatF * vec4(aPos, 1.);
Phong function (parameters → matrix)
Instead of just writing out the 16 numbers of a matrix
to specify the parameters for the Phong algorithm,
we can define a function to do that for us:
phong(ambient,diffuse,specular,p)
The arguments are three color vectors ar,g,b, dr,g,b, sr,g,b, and a numerical power p.
They can be used to define the materials matrix as follows:
mat4 uM = [ a0,a1,a2,0, d0,d1,d2,0, s0,s1,s2,p, 0,0,0,1 ]
Various materials using Phong (eg: gold, plastic):
Using the phong function, we can define various convenient materials.
Here are two examples:
let gold = phong([.1,.03,0], [.12,.05,0], [1,.5,0], 10);
let red_plastic = phong([.1,0,0], [.5,0,0], [1,1,1], 20);
Matrix methods:
You have already implemented the Matrix class methods
identity(), translate(x,y,z), rotateX(θ), rotateY(θ), rotateZ(θ) and scale(x,y,z).
In class we talked about a few refinements to the Matrix class.
For example, if there ia only one argument to scale(x,y,z),
then we should assume uniform scaling.
In other words, if
y === undefined, then y = z = x.
You will want both a getValue() and setValue() method.
But be sure your getValue() method copies each value from an array.
In other words:
this.setValue = function(v) { // need to copy values
for (let i = 0 ; i < 16 ; i++)
value[i] = v[i];
}
Also, it is useful to multiply a matrix object by another
matrix object. In order to do thism we access the values of
both matrix objects, and use our internal multiply function:
this.multiply(matrix) = function(matrix) {
value = multiply(value, matrix.getValue());
}
3D Hierarchical Objects:
We went over in the class how a 3D renderable
object has the following members:
this.shape
this.phong
this.children[]
this.matrix
and the following methods:
this.add(shape, phong) // add a child
this.child(n) // get the nth child
this.draw() // draw the object and its children.
For convenience, we make all of the
matrix operations available as well:
this.identity = () => this.matrix.identity();
this.translate = (x,y,z) => this.matrix.translate(x,y,z);
etc.
The draw method recursively draws an object
and all of its children and their children, etc.
performing matrix multiplication recursively
as we descend the parent to child tree.
Here is my implementation of the draw method:
this.draw = isChild => {
if (! isChild)
matrix.identity();
matrix.multiply(this.matrix);
if (this.phong)
setUniform('Matrix4fv', 'uM', false, this.phong);
if (this.shape)
drawShape(this.shape);
let parentValue = matrix.getValue();
for (let n = 0 ; n < this.children.length ; n++) {
matrix.setValue(parentValue);
this.children[n].draw(true);
}
}
Glueing together two triangle meshes:
Given two triangle meshes a and b,
we can glue them together to create a single
mesh via the following four steps:
1) add the first mesh
2) add the last vertex of the first mesh
3) add the first vertex of the second mesh
4) add the second mesh
More parametric shapes:
We also discussed triangle meshes in the
form of sphere, torus, tube, square and disk.
We have already discussed the parametric definition of a sphere, torus and tube.
As we discussed in class, the parametric definition of a circular disk is:
position at u,v = [ cos(2 π u) v , sin(2 π u) v , 0]
normal at u,v = [ 0, 0, 1 ]
The parametric definition of a square is particularly simple:
position at u,v = [ 2u-1 , 2v-1 , 0]
normal at u,v = [ 0, 0, 1 ]
Glueing triangle meshes together:
We also discussed, at a high level, how you can make
a triangle mesh in the shape of a cylinder by glueing together three triangle meshes:
One for the back cap, one for the open tube, and one for the front cap.
To do that you need to call the glueMeshes function twice -- once for
each of the two glue operations -- since it only glues together two meshes at a time.
|
| |