CS307: Introduction to Three.js Programming
Plan
- (Very high-level) summary of reading
- I'll answer your quiz questions
- A simple scene with a box
- Use the orbiting camera interface
- Keyboard commands
- Add a sphere to the scene
- Use the JavaScript console for debugging
- (breakout exercise) Enhance the box scene
- Building a geometry from scratch
- Save and load a copy of the Barn demo
- Exercise: Local library files
- (breakout exercises) Changing width, two barns
Summary
We will use three APIs:
- WebGL, a subset of OpenGL (we won't actually see much of it)
- Three.js, a JavaScript library built on top of WebGL
- TW, a home-grown set of conveniences and shortcuts created by Scott Anderson
Graphics are drawn on a canvas on the webpage
As shown in the skeleton code below for the scene with a box, you need to create:
- a scene object
- stuff to look at, added to the scene object
- a renderer object
- a camera object
var scene = new THREE.Scene(); // scene object var boxGeom = new THREE.BoxGeometry(4,6,8); // stuff to look at var boxMesh = TW.createMesh(boxGeom); scene.add(boxMesh); var renderer = new THREE.WebGLRenderer(); // renderer object TW.mainInit(renderer,scene); var state = TW.cameraSetup(renderer, // camera object scene, {minx: -2.5, maxx: 2.5, miny: -3.5, maxy: 3.5, minz: -4.5, maxz: 4.5});
The "stuff to look at" are meshes that consist of geometry and material
- Geometry is comprised of vertices and faces (triangles in Three.js)
- Vertices of triangular faces are specified in counterclockwise order, as viewed from the front
Quiz Questions
I'll answer your quiz questions
So Let's Get Started...
- Visit this simple
scene with a box and save
the page to your Desktop as
box.html
. You can do this by selecting theFile>Save Page As...
menu item and specifying the file name asbox.html
and Format as "Webpage, HTML Only". - In a new tab, visit the local file from your browser:
File>Open File...
- Navigate to Desktop
- Choose
box.html
The URL will be something like file:///Users/youraccount/Desktop/box.html
Alternatively, you can start the local web server. This is not necessary at this point in the course, but it can't hurt. It will be necessary later when we want to dynamically load images for texture-mapping, so I decided to teach it right away. But you can do either one.
Using the Orbiting Camera Interface
The TW package creates a Three.js Orbiting Camera for the scene, which makes it easy to view your model.
- Clicking and dragging with the mouse left/right moves the camera around the model
(orbits it), keeping a constant distance from the center. You can also drag
up/down but that stops at the
poles
. - The arrow keys can be used to shift the camera to the left, right, up, or down — this also changes the center of the scene, so that dragging with the mouse then rotates the model around a different point. (Note: in the current version of the OrbitControls code, the up/down arrow keys do not work properly.)
- Scrolling your mouse lets you dolly in/out.
Keyboard Commands
TW also defines some keyboard commands:
- A "?" prints a list of single-letter commands to the terminal window
- The letter "a" toggles an
axis helper
that shows you the orientation of the model (where the X (red), Y (green) and Z (blue) axes are). The axes emanate from the origin of the coordinate system. - The letter "b" toggles a visualization of the scene bounding box. (This is the bounding box used to set up the camera, not the true bounding box of the scene.)
- The lowercase axis letters view the model from that direction: "x" "y" "z"
- The letter "o" (for "oblique") views the model from an oblique direction.
Code for the Simple Box
Open the box.html
code file in a text editor on your local machine
and view the code. These slides capture the
essential parts of the code, which we'll review in class.
Now let's add another object using the built-in geometry,
THREE.SphereGeometry
, with an input that specifies the
radius of the sphere:
var sphereGeom = new THREE.SphereGeometry(3); var sphereMesh = TW.createMesh(sphereGeom); scene.add(sphereMesh);
Save your modified code file and reload the webpage in your browser (you
may want to hold down the shift
key while reloading the page).
hmmmm.... where is our sphere?
Hint: Use your mouse to move the camera inside
the box!
Let's move the sphere outside the box so we can see it better:
sphereMesh.position.set(5,0,0); // x,y,z coordinates of the center
Use the JavaScript Console for Debugging
Our main debugging tool for JavaScript will be the JavaScript Console. To open the JS console in your browser (the process may be different on a PC):
- Chrome: Enter command-option-j or select
View>Developer>JavaScript Console
(enter control-shift-j on a PC) - Safari: If you do not see the
Develop
menu along the top of the browser window, first go toSafari>Preferences
. Select theAdvanced
tab, and then check theShow Develop menu in menu bar
item at the bottom. In theDevelop
menu, you can then selectShow JavaScript Console
(shortcut: command-option-c) (this may be control-shift-c on a PC) - Firefox: Enter command-option-k or select
Tools>Web Developer>Web Console
(control-shift-k on a PC)
Try introducing an error in your code file, reload your webpage, and view the error message(s) in the JS console.
Add a print statement to your code with
console.log()
— also handy for debugging!
var name = 'Scott'; var age = 29; console.log("Hi " + name + ", you're really only " + age + "??");
Breakout Exercise: Be Creative!
For this exercise, I'll divide you into breakout groups. Using the
box and sphere geometries, and the ability to position your meshes
anywhere in the scene, work together to build on the box.html
code file to create a new
scene of your own design. Be careful about the size of your objects and
coordinates — you might need to change the coordinates specified in
the bounding box in order to see everything (e.g. minx
,
maxx
, miny
, maxy
, minz
,
maxz
).
Imagine things like a lollipop, barbell, stack of blocks, toy, snowman, robot, ...
Pairs:
- 2 Annabel+Faith
- 4 Aizah+Ingrid
- 6 Lan+Martha
- 8 Ari+Hae Rin
- 10 Gabby+Genevieve
- 12 Anastacia+Elisha
- 14 Amy+UGyeong
- 16 Ailie+Emily
- 18 Joyce+Kate
- 20 Ariana+Lindsay
- 22 Claire+Rik
- 24 Heidi+Marilyn
- 26 Alo+Hana
- 28 Claire (ILL)
Building a Geometry From Scratch
Step 1: Create a new THREE.Geometry
object and
define its vertices:
var barnGeometry = new THREE.Geometry(); // add vertices to the barnGeometry.vertices array - // indices of this array correspond to the above labels barnGeometry.vertices.push(new THREE.Vector3(0, 0, 0)); barnGeometry.vertices.push(new THREE.Vector3(30, 0, 0)); barnGeometry.vertices.push(new THREE.Vector3(30, 40, 0)); ...
Step 2: Divide each object surface into triangular faces, and
define each face using three vertex labels (indices of the
barnGeometry.vertices
array).
Keep in mind:
- each triangular face has a front and back side
- by default, Three.js only renders the front side (the back side is invisible)
So how do you define which side is the front?
- imagine you're looking at the side you want to define as the front side...
- ... and list the three vertices in a counterclockwise order, as viewed from this side
- Three.js will interpret this side as the front side
// front side of each of these faces is outside the barn barnGeometry.faces.push(new THREE.Face3(0, 1, 2)); barnGeometry.faces.push(new THREE.Face3(0, 2, 3)); barnGeometry.faces.push(new THREE.Face3(3, 2, 4)); ...
How would you specify the face outlined in red, if you want the outside of the barn to be visible?
Let's look at the code to create the barn
In case you're wondering how faces look when the vertices are specified in the "wrong" order:
Here is the code that created this unfortunate barn, which also provides a sneak preview on how to create a mesh with desired colors, and how to control which side is rendered.
Set up the Barn Code
- Visit the barn and save
the page to your Desktop as
barn.html
. You can do this by selecting theFile>Save Page As...
menu item and specifying the file name asbarn.html
and Format as "Webpage, HTML Only". - In a new tab, visit the local file from your browser:
File>Open File...
- Navigate to Desktop
- Choose
barn.html
The URL will be something like file:///Users/youraccount/Desktop/barn.html
Working Without a Network
View the source of the file you downloaded to your Desktop. Note that it starts by loading three JavaScript files from the web, all from /~cs307/threejs/libs.
three-r95.all.js
, version 95 of the Three.js codeOrbitControls-r95.js
, which is the extra code for the orbiting cameratw-sp21.js
, which is the Spring 2021 version of our TW code. This file contains theTW.createBarn()
function.
What if you have a laptop, hiking in the White Mountains on a glorious fall day, far from any internet connection, and you have a sudden inspiration to do some graphics coding? What do you do then?
First, try sitting down to view the beauty of nature, wait for the feeling to pass, and remind yourself that there's more to life than work...
If that doesn't work, you can hope that you had the foresight to have a a local copy of those files. If they're on your laptop, you can make the appropriate changes to your program file, and load the local copies instead.
Exercise: Using Local Library Files
(Do this exercise individually, on your own computer.)
You can "manually" download the necessary library files to your local machine
and modify the source code to use the local files, but here we'll use a shortcut.
Again save the code for the barn using the File>Save Page As...
menu item, but this time save it as "Webpage, Complete" and use a different
name, like barnComplete
. You'll see both an HTML file and a folder
(barnComplete_files
) on your Desktop. Load the new HTML file into
your browser and view the source. What changed in the code statements that load
the library files?
Breakout Exercises: Modify the Barn
Exercise: Changing Width
This is a relatively quick exercise, to get you warmed up.
- Copy the original
barn.html
to another file, saywide-barn.html
. - Edit the new file to change the width of the barn (
barnWidth
), say to 50. - View the changed
wide-barn.html
file in your browser. Is this what you expected? - The variable name
barnWidth
is supplied in the call to theTW.createBarn()
function, and is also used to specifymaxx
for the bounding box in the later call toTW.cameraSetup()
. In both places, change the variable name (barnWidth
) to numeric constants. Use a larger value in the call toTW.createBarn()
relative to the value chosen formaxx
.What do you notice about the wide barn in this case?
- You might have something like
this wide-barn.html. In this sample
solution, the barn is wide (50) but
maxx
for the camera is only 20, so the camera setup is off. The original code allowed us to change the width of the barn in just one place and the camera setup changed automatically. This is a good reason to use variables instead of numeric constants!
- You might have something like
this wide-barn.html. In this sample
solution, the barn is wide (50) but
- Change the numeric constants back to the variable
barnWidth
. The bounding box for the original barn truncates some of the roof of the barn from view. Modify the value formaxy
in the bounding box, using an expression with variable names, so that the entire roof is visible. (Hint: In thecreateBarn()
function, how is the y coordinate of the roof of the barn defined?)- You might have something like this full-barn.html.
Earlier, you adjusted the position of meshes using position.set()
:
sphereMesh.position.set(5,0,0); // x,y,z coordinates of the center
In Three.js, an instance of Mesh
(actually, an instance of
Object3D
, which is the parent class of Mesh
) has a property
called position
that is a Vector3
, which has a method
set(x,y,z)
that can be used to set the components of the vector. This
will come in handy for the next exercise.
Exercise: Two Barns
Modify the code from the previous exercise to add a second barn that is
- half the size of the first barn
- shifted to the left of the first barn, leaving a gap between the two barns
Adjust the bounding box so that you can see the two barns in their entirety. Your result might look something like this:
Optional: Add more barns to your scene, with different sizes.
A possible solution: two-barns.html
General Coding Tips
- Build and test your code incrementally. Save often!
- Save versions by saving the file to a different filename
(
ex1.html
,ex2.html
, ...) It will be easier (emotionally) to experiment with things if you know you can go back to an earlier version. - Be willing to create a simple
test
program to see how something works without all the complexity of your larger program. - Be modular, and document as you go. It'll be easier to understand and debug your own code.
To Do for the Next Class
- Reading for Tuesday: Keyboard and GUI Controls