There are benefits to working on your local machine. You aren’t impacted by a slow network connection or service hiccups. There are also costs. You are on your own for troubleshooting your machine; your instructor is not going to help with your individual setup. Sharing your project with your instructor is a bit more work. If you willing to accept these costs and use your own computer, follow these instructions to install Visual Studio Code.
index.html.<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SLAI 2021: Geometric Modeling</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/TrackballControls.js"></script>
</head>
<body>
🥨
</body>
</html>
index.html. Return to the Explorer by way of View / Explorer. Right-click on the file and select Open with Live Server. A page with a pretzel in it should open in your web browser.Below are a few ideas for research projects that will build off of the 3D thinking that you’ve been doing. The descriptions are intentionally vague, as the projects are meant to be owned by you. Feel free to tailor the ideas below or ignore them altogether.
Triangulation Investigate algorithms for turning an arbitrary polygon into triangles. Implement a program that allows the user to draw a polygon, triangulate it, and then extrude or revolve it into a solid model.
Ramer–Douglas–Peucker algorithm Implement a program that allows the user to draw a cross section freehand, simplify the drawing using the RDP algorithm, and then extrude or revolve it. Or allow the user to draw multiple cross sections and then stitch them together.
Geometric Nets Develop an algorithm for unfolding a 3D model so that it lies flat. Flat meshes are easier to print on or cut from paper. Then they can reassembled into their 3D form.
Boolean Composition Investigate constructive solid geometry. Develop a program that allows the user to subtract, intersect, or union models.
Perlin Noise Investigate “organic” noise and use it to produce 3D models in some way.
Superquadrics Investigate the superquadric family of shapes. Develop a program that allows the user to explore their parameter space.
Octasphere Investigate the octasphere family of shapes. Develop a program that allows the user to explore their parameter space. See Philip Rideout’s overview.
Bézier Interface Investigate Bézier curves. Implement a program that allows the user to draw curved cross sections of models, convert them into polylines, and then revolve or extrude them.
Bézier Surfaces Investigate Bézier curves. Implement a program that allows the user to draw a grid of curves and convert it to a 3D mesh. See Scratch-a-pixel for an example.
Parametric Design Investigate direct manipulation. Implement a program that displays a parametric shape and allows the user to drag on it to change its parameters and regenerate the mesh.
Chaikin’s Algorithm Investigate Bézier curves. Implement a program that allows the user the draw a shape’s cross section as a polygon, converts the drawing to curves, and then samples the curves to produce a polyline that is extruded or revolved to produce a solid shape.
]]>As you have time, create other flat shape generators. Here are a few ideas:
Feed their return values into your extrude function to produce solid models.
All of our shape generators center the shapes around the origin. As we carve out new shapes using boolean operations, we want to be able to transform parts so that they have different sizes, locations, or orientations. In this exercise, you add a couple of utility functions to translate and scale your meshes.
Write a function named translate. Translation moves an object along the three axes, but does not rotate or resize the object. Have it accept these parameters:
mesh to shift around.offset by which to shift the mesh. It is an array of three numbers. Element 0 is the x-offset, element 1 is the y-offset, and element 2 is the z-offset.Inside the function, reassign every position in the mesh so that it is offset from its original position. Follow this pseudocode:
for each position apply offset to position
Test out your implementation of this method in render.js by adding a call like this:
const mesh = generateCube();
translate(mesh, [2, 0, 0]);
You should see the cube shifted right 2 units.
Write a function named scale. Have it accept these parameters:
mesh to shift around.factors by which to scale the mesh. It is an array of three numbers. Element 0 is the x-factor, element 1 is the y-factor, and element 2 is the z-factor.Inside the function, reassign every position in the mesh so that it is scaled from its original position. Follow this pseudocode:
for each position apply scale to position
Test out your implementation of this method in render.js by adding a call like this:
const mesh = generateCube();
scale(mesh, [1, 2, 1]);
You should see the cube scaled to be twice as tall as it is wide and deep.
Another common operation is rotation. The math behind rotation is more involved. If you find yourself needing to rotate a part or wanting to understand how rotation is done, let me know and we can talk through its implementation.
]]>Here’s an unsung hero whose worth isn’t recognized until it’s gone:

Just in case you lose one and need to print a replacement, you should have a 3D model of a button available.
Write a function named generateButton to generate the kind of shape you see in the image above. Have it accept these parameters:
nlongitudes that specifies the number of lines of longitude that the cylinder has. Higher numbers won’t have much of an effect on the appearance.height of the button, which measures the cylindrical height.majorRadius of the button, which marks the distance from the y-axis to the outer rim.minorRadius of the button, which marks the distance from the y-axis to the inner rim.holeRadius of the button, which measures the size of a thread hole.holeGap of the button, which measures the distance between thread holes.Use boolean operations to create your button.
]]>Future archaeologists will someday dig up our modern-day homes, and they will find many of these artifacts:

This is a six-sided die, known as a D6 to gamers who must distinguish it from D12s, D20s, and so on.
Write a function named generateD6 to generate this shape. Have it accept no parameters. Use boolean operations.
Every archaeological dig seems to turn up a bowl. Our species has been making them for millenia, so it only seems right to make one out of code.

Write a function named generateBowl to generate this kind of shape. Have it accept these parameters:
majorRadius of the bowl, which marks the distance from the y-axis to the outer rim.minorRadius of the bowl, which marks the distance from the y-axis to the inner rim.Use boolean operations to create your bowl.
]]>Consider the square pot below, which is just asking you to fill it with soil and plants. Or maybe pens and pencils. Or maybe ice and lemonade.

Write a function named generateSquarePot that creates square pots of all sizes and thicknesses. Have it accept these parameters:
side length of the pot.height of the pot.wall thickness of the pot.Use boolean operations to create your square pot.
]]>With these next few exercises, you are given only an image of a target shape and function specification. It’s up to you to deduce what boolean operations are happening to produce the shape. Here’s your first challenge, which we’ll call a chain for lack of a more specific term:

Create your shape in a function named generateChain. Have it accept these parameters:
nlatitudes that specifies the number of lines of latitude that each torus has.nlongitudes that specifies the number of lines of longitude that each torus has.majorRadius of each torus.minorRadius of each torus.Use boolean operations to weld together the three torii. Rendering three separate torii is cheating.
]]>Earlier you made a cylinder. That was fun, but now you will do something tubular. You will make a tube, which is a thin cylinder taken away from a thick cylinder.
On your paper, draw a tube around the y-axis. Angle the view so that one of the tube’s ends is visible. Label the distance between the y-axis and the outer perimeter as the major radius. Label the distance between the y-axis and the inner perimeter as the minor radius.
Write a function named generateTube. Have it accept these parameters:
nlatitudes that specifies the number of lines of latitude that the tube has. The higher the number, the more circular it will be.nlongitudes that specifies the number of lines of longitude that the tube has. Higher numbers won’t have much of an effect on the appearance.majorRadius of the tube.minorRadius of the tube.height of the tube.Unlike your earlier shapes, you don’t need any loops to fill the positions and triangles arrays. Instead, you will compose the tube out of shapes you already know how to make. Generate two cylinders using the major and minor radii, convert them to CSG objects, call the appropriate boolean method, convert the result back to a mesh, and then render the result.