\( \newcommand{\vecIII}[3]{\left[\begin{array}{c} #1\\#2\\#3 \end{array}\right]} \newcommand{\vecIV}[4]{\left[\begin{array}{c} #1\\#2\\#3\\#4 \end{array}\right]} \newcommand{\Choose}[2]{ { { #1 }\choose{ #2 } } } \newcommand{\vecII}[2]{\left[\begin{array}{c} #1\\#2 \end{array}\right]} \newcommand{\vecIII}[3]{\left[\begin{array}{c} #1\\#2\\#3 \end{array}\right]} \newcommand{\vecIV}[4]{\left[\begin{array}{c} #1\\#2\\#3\\#4 \end{array}\right]} \newcommand{\matIIxII}[4]{\left[ \begin{array}{cc} #1 & #2 \\ #3 & #4 \end{array}\right]} \newcommand{\matIIIxIII}[9]{\left[ \begin{array}{ccc} #1 & #2 & #3 \\ #4 & #5 & #6 \\ #7 & #8 & #9 \end{array}\right]} \)

CS307: Synthetic Cameras

Plan

  • Review solution to the Scale-of-Justice exercise
  • Recap and questions: synthetic camera and perspective projection
  • (paper/pencil) Exercise on perspective projection
  • Recap and questions: Projection matrices
  • Recap and questions: Three.js Camera API and camera tutor demo
  • Exercises on setting up a camera

Pinhole and Synthetic Cameras

Pinhole camera, aka camera obscura:

pinhole camera camera obscura

Pinhole camera with object and its projection:

pinhole camera with tree

Pinhole camera showing similar triangles:

pinhole camera showing similar triangles

The synthetic camera moves the image plane in front of the center of projection to eliminate negatives:

synthetic camera and tree      perspective projection

We'll use $(X,Y,Z)$ to refer to the 3D coordinates of a point in space, and $(x,y,z)$ to refer to the projected image coordinates. In the above diagram, the negative $z$ axis points to the right, so $z=-d$.

Consider the $y$ coordinate in the above pictures. Using similar triangles, $Y/Z = y/d$, so $y = d(Y/Z)$, which can be written as $y = Y/(Z/d)$

We can derive an expression for $x$ in a similar way: $x = X/(Z/d)$

Exercise: Perspective Projection

Assume a synthetic camera with the image plane (near plane) at a distance d from the center of projection (COP). Suppose the scene contains a tree of height H at a distance D from the COP. What is the height of the projected tree?

d*(H/D)   or   H*(d/D)

Perspective: projections shrink with distance. This also gives us vanishing points — think about railroad tracks.

Example: With the standard camera (COP at the origin, looking down the negative Z axis) and the image plane at Z=-3, find the projection of (7,8,-9).

Bird's eye view:

point projection

For X:

X/x = Z/z
7/x = -9/-3
7/(-9/-3) = x
x = 7/3

For Y:

Y/y = Z/z
8/y = -9/-3
8/(-9/-3) = y
y = 8/3

For the entire point, P:

projection of P
= (7/3, 8/3, -3)
= (1/3) * P

and 1/3 is just 1/near, where "near" is the distance from the COP to the image plane

Projection Matrices

We've been focusing on perspective projection, which was used to generate the drawing below:

The following two images illustrate orthographic projection:

    

For orthographic projection, $(x,y,z) = (X,Y,0)$

Both projections can be implemented with matrix multiplication.

Orthographic Projection

\[ \left[ \begin{array}{rrrr} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right] \vecIV{X}{Y}{Z}{1} \]

What does this do to a point $(X, Y, Z)$?

Perspective Projection

\[ \vecIV{X}{Y}{Z}{Z/d} = \left[ \begin{array}{rrrr} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 1/d & 0 \end{array} \right] \vecIV{X}{Y}{Z}{1} \]

To obtain the projected image coordinates, $(x, y, z)$, we divide the result on the left by $Z/d$ (the perspective division step), yielding the following:

\[ \vecIV{x}{y}{z}{w} = \vecIV{X/(Z/d)}{Y/(Z/d)}{d}{1} \]

Note that \(d\) is the near distance: the distance from the COP (center of projection) to the image plane. (We'll think of $d$ as a positive quantity here)

Camera Setup in Three.js


The diagram below summarizes the key elements of the camera setup:

In the above code example, the camera parameters (adjusted in the GUI) are stored in an object named cameraParams:

var cameraParams = {
    near: 5,
    far: 30,
    fov: 75,                  // degrees
    aspectRatio: 400.0/300.0, // from canvas dimensions, see CSS
    atX: 0,
    atY: 0,
    atZ: 0,
    eyeX: 0,
    eyeY: 0,
    eyeZ: 25,
    upX: 0,
    upY: 1,
    upZ: 0
};

The following code defines a function named setupCamera() that creates a camera with the desired parameters, and then invokes the function and adds the camera to a scene:

function setupCamera (cameraParameters) {
    // set up an abbreviation 
    var cp = cameraParameters;
    // create an initial camera with the desired shape
    var camera = new THREE.PerspectiveCamera(cp.fov,
                                             cp.aspectRatio,
                                             cp.near,
                                             cp.far);
    // set the camera location and orientation
    camera.position.set(cp.eyeX, cp.eyeY, cp.eyeZ);
    camera.up.set(cp.upX, cp.upY, cp.upZ);
    camera.lookAt(new THREE.Vector3(cp.atX, cp.atY, cp.atZ));
    return camera;
}
var camera = setupCamera(cameraParams);
scene.add(camera);

Note that you also need to do something like this at the end of your code:

function render() {
    // assume global variables scene, renderer, and camera
    renderer.render(scene,camera);
}
render();

TW's camera setup did this for us automatically. With this code, though, we can cut the TW apron strings.

Question: Can we set up multiple cameras in the same scene? Not really, but see this example from the Three.js site

Exercises: Creating Desired Camera Views

Exercise: Setting up a Camera

Using this town-view-before.html, set up a camera to view the snowman from above and to the right. Something like this:

snowman with placed camera

  • You might find it helpful to use the following town-view-gui.html .
  • Define a function to set up the camera the way you want.
  • Replace TW.cameraSetup() with your new camera.

Your result might look like town-view.html

Exercise: Zooming vs. Dollying

Is there any difference between

  • zooming in, keeping the eye point the same and reducing the FOV
  • dollying in, keeping the FOV the same and moving the camera closer

Let's try to experience the effects of these changes to the camera setup.

To begin, add a wireframe box to the scene that fits snuggly around the head of the snowman. Then try to set the camera parameters so that the scene appears like this:

initial snowman view

Hints: the camera is positioned 5 units in front of the center of the snowman's head (at the same x and y coordinates as this center point) and is looking at this center point. Set the fov to achieve the above appearance.

Then try to set the camera parameters to reproduce each of the following views, dollying in to create one of the views and zooming in to create the other:

snowman from up close snowman zoomed in

Which figure was created by zooming, and which by dollying?

Your solutions might be like snowman-close.html and snowman-zoom.html.

Vup

Most of the time, Vup is very simple: we have \[ V_\mathrm{up} = (0, 1, 0) \]

The minute we want something different, though, Vup can be confusing. Try to imagine it this way:

  • Visualize the Vup vector in 3D space, along with the image plane.
  • Project the Vup vector onto the image plane
  • The frustum spins around the VPN (view plane normal) so that the Vup vector is parallel to the left/right edges.
  • When the top of the frustum is mapped onto the canvas, the Vup vector is parallel to the left/right edge of the canvas.

There are two important consequences of the way Vup works:

  • The Vup vector can't project to a point, which means it can't be parallel or anti-parallel to the VPN.
  • Any change to the Vup vector that doesn't change the direction of its projection on the image plane doesn't affect anything. The image is still oriented the same way.

Exercise: Changing Vup

Let's try to experiment with changing Vup

Try to reproduce both of the following:

snowman at an angle snowman from overhead

  • Think about what Vup might be.
  • Set up the camera for each scene.

Your solutions might be like snowman-close-angled.html and snowman-close-overhead.html.

Exercise: Viewing the Barn

The goal of this exercise is to mimic a set of views of a wireframe barn, shown in the following code (you won't be able to see the actual solution code here): barnviews-solution.html

When viewing this page, type any of the keys numbered 1 to 5, and a new view of the barn will appear. In this exercise, you'll try to duplicate my camera location and orientation as closely as possible, by analyzing how things are projecting to see if you can reverse-engineer to set up a similar camera. This will help you when you are trying to achieve a particular look in your own scenes.

The starting point for this exercise is this barnviews-start.html code file

Carefully examine the starter code to understand the dimensions of the barn and initial camera information that's provided. For each of the 5 views, add two code statements to set the position and the up vector for the camera, to create a view that is as close as possible to the solution.

Here's a solution with JS code that you can view: barnviews.html

Preparation for Next Time

Next time, we'll look at how we create surface with different material properties, such as dull or shiny surfaces, and how we add light sources to a graphical scene. To prepare:

  • Reading for Monday: Material and Lighting
  • Submit Sakai Quiz by Sunday evening at 9:00 pm EST — you'll have an hour to complete the quiz, which is "open book/notes"

Due on Friday at 11:00 pm EST: HWK2: Clown