Notes for Wednesday March 17-24 -- vertex normals + splines 1

Vertex normals

In class we added the aNor attribute to each vertex for all of our mesh types. We showed that transforming a normal is different from transforming a point, because when we transform a normal, we need to preserve the value of (normal • point).

We do that as follows: normal • point == (normal • M-1) • (M • point)

So rather than left-multiplying by the transformation matrix, as in:

   uMatrix * vec4(aPos,1.)
we need to right-multiply by the inverse matrix, as in:
   vec4(aNor,0.) * uInvMatrix
We also added perspective as follows: Given a focal length fl, we can make it appear as though we looking through a camera lens fl at units in positive z. To do this, we left-multiply by the following matrix:
    1   0   0   0
    0   1   0   0
    0   0  -1   0
    0   0 -1/fl 1

Different material properties

We discussed, but did not finish implementing, having different material properties for each object. One way to implement this would be to set up a table of material properties. When it is time to draw a mesh, you can pass to drawMesh() an index into that table.

Inside the implementation of drawMesh() in your library, you can pass the Ambient, Diffuse and Specular data (which you have stored in your material properties table) into the corresponding uniform variables within your fragment shader, before rendering the mesh.

Intro to cubic splines

One way to create smooth curves is to use cubic splines. For example, a smooth path of motion can be defined by three functions:

   X(t) = axt3 + bxt2 + cxt + dx
   Y(t) = ayt3 + byt2 + cyt + dy
   Z(t) = azt3 + bzt2 + czt + dz
where all of the a,b,c,d are constant coefficients. By stringing together cubic curves end to end, you can then make arbitrarily complex smooth curves.

Although this is a very general solution, it is not easy to work with, because the values of a,b,c,d tend to be non-intuitive. For this reason, people don't usually specify splines in the set of cubic basis functions:

   t3, t2, t, 1
but instead they work with a different set of basis functions, for which coefficients are more intuitive and easier to understand and to specify.

Hermite splines

One such alternate function space is the Hermite basis, in which for each component cubic curve, the user specifies a value at t==0, a value at t==1, a rate of change at t==0, and a rate of change at t==1. These four values can be described as a column vector:

   P0
   P1
   R0
   R1
The corresponding basis functions are 2t3-3t2+1, -2t3+3t2, t3-2t2+t and t3-t2.

To transform from this basis to the cubic basis, we therefore multiply by the Hermite matrix:

a
b
c
d
  ←    2 -2  1  1
-3  3 -2 -1
 0  0  1  0
 1  0  0  0 
  •   P0
P1
R0
R1

Bezier splines

Another alternate function basis is the Bezier basis, in which the cubic curve is defined as three successive linear interpolations beginning at point A, through two successive guide points B and C, and ending at point D:

   P = mix ( mix( mix(A, B, t), mix(B, C, t), t),
             mix( mix(B, C, t), mix(C, D, t), t), t)

     = (1-t)3A + 3(1-t)2tB + 3(1-t)t2C + t3D

     = (-t3 + 3t2 - 3t + 1)A + (3t3 - 6t2 + 3t)B + (-3t3 + 3t2)C + t3D
where: mix(A,B,t) = (1-t)*A + t*B

The Bezier matrix which transforms from points A,B,C,D to the corresponding cubic coefficients a,b,c,d is:

a
b
c
d
  ←   -1  3 -3  1
 3 -6  3  0
-3  3  0  0
 1  0  0  0 
  •   A
B
C
D
Whether each point A,B,C,d is in two or three dimensions, the Bezier matrix needs to be applied once for each dimension, so coefficients a,b,c,d is actually ax,bx,cx,dx in the x dimension, ay,by,cy,dy in the y dimension, and so forth.

Homework -- due before class on Wednesday March 31

  • Starting with the code we implemented in class, which is in hw6.zip, animate an object by translating it along a Hermite or Bezier parametric spline.

    Hint 1: Use the time variable to create your t parameter. For example, if you want to create an animation that loops every three seconds, you could do the following in your animate() function:

       let t = (time / 3) % 1;
    

    Hint 2: If you want to string together multiple successive splines to create a longer and move intricate animation, then you need to divide time into successive segments, and apply a different spline for each of those segments. For example, to string together three splines S1(t), S2(t) and S3(t) for two seconds each (for a total animation time of six seconds), you might compute:

       t0 = time / 2,
       t1 = (time-2) / 2,
       t2 = (time-4) / 2.
    
    Then:
       for 0 ≤ time < 2: use S0(t0)
       for 2 ≤ time < 4: use S1(t1)
       for 4 ≤ time < 6: use S2(t2)
    

    Hint 3: The Hermite or Bezier matrix has nothing to do with m[top]. What you need to do with the [a,b,c,d] for each of your dimensions (x,y and z) is form the cubic equation a*t^3 + b*t^2 + c*t + d, and then march along successive values of t between 0.0 and 1.0 at successive animation frames, evaluating that cubic equation to get a particular value for that dimension at that animation frame. You have one set of [a,b,c,d] for X, another for Y, and a third for Z. Evaluating those three equations at a given value of t (that is, for a particular frame of your animation) gives you three numerical values x,y,z which you can then use in a call to m.translate(x,y,z) to move your object into position for that animation frame.

    Typo (now fixed): I originally had a typo in the notes for the Hermite matrix, now fixed. The correct value for the second Hermite equation is -2t3+3t2. The notes now state that correctly.

For extra credit:

  • Translate along a path that consists of multiple end-to-end cubic splines, so that each spline transitions smoothly to the next, with two adjacent splines going in the same direction where the two splines meet.

  • In addition to translation, use parametric splines to animate other kinds of movement, such as rotation and/or scaling of mesh objects.

  • Implement both Hermite and Bezier splines.

  • Implement different Phong material properties for different meshes, as described in the notes above.

As usual, see if you can do something really fun and interesting. Impress me. :-)