Lab: Dotplots
In this chapter, you've been learning how to model objects as a collection of points and lines. Let's apply this knowledge by writing two renderers, one to plot a circle and one to plot a more interesting curve.
Circle
Your first challenge is to plot a circle. WebGL doesn't have a circle primitive, so the best you can do is plot a regular polygon with many sides. Follow these steps to create a circle regular polygon renderer.
npm run dev to start up a web server.circle. Put a new li and a in the index page and make a copy of your hello-cornflower directory named circle.generateCircle. You are going to factor out the vertex buffer and VAO creation to this separate function so that you can regenerate the circle without reinitializing the whole renderer.initialize that deals with positions, attributes, and vao to generateCircle. Leave the shader code in initialize because it won't change.initialize, call generateCircle. You should see the two dots as before.generateCircle accept parameters named n and radius.positions array so that it contains n evenly spaced vertices on the perimeter of a circle of the given radius. You'll need to loop through the angles around the circle. A vertex's location can be computed by turning its angle and radius into Cartesian coordinates:
generateCircle with various parameters. Ensure that you can see circles of various sizes and roughnesses.body tag in index.html to give the user an interface for changing the sample rate and radius:
<div class="controls">
<label for="n-input">n</label>
<input id="n-input" type="text">
<label for="radius-input">radius</label>
<input id="radius-input" type="text">
</div>
<div class="controls"> <label for="n-input">n</label> <input id="n-input" type="text"> <label for="radius-input">radius</label> <input id="radius-input" type="text"> </div>
public/style.css to position the controls atop the canvas:
.controls {
position: absolute;
top: 5px;
right: 5px;
display: grid;
grid-template-columns: auto auto;
grid-gap: 2px 5px;
justify-items: end;
z-index: 1;
}
.controls {
position: absolute;
top: 5px;
right: 5px;
display: grid;
grid-template-columns: auto auto;
grid-gap: 2px 5px;
justify-items: end;
z-index: 1;
}src/main.ts:
let n = 6;
let radius = 0.9;
let n = 6; let radius = 0.9;
n by adding this code at the end of initialize:
const nInput = document.getElementById('n-input') as HTMLInputElement;
nInput.addEventListener('input', () => {
n = parseInt(nInput.value);
synchronize();
});
const nInput = document.getElementById('n-input') as HTMLInputElement;
nInput.addEventListener('input', () => {
n = parseInt(nInput.value);
synchronize();
});attributes a global variable instead of a local one. We need it to be global so we can destroy the old attributes when a new circle is generated. Keep its assignment statement where it is, but move its declaration to the global scope.synchronize function, which will be called whenever a number in the text inputs changes:
function synchronize() {
// Release previous VAO and VBOs.
vao.destroy();
attributes.destroy();
// TODO: regenerate circle and redraw.
}
function synchronize() {
// Release previous VAO and VBOs.
vao.destroy();
attributes.destroy();
// TODO: regenerate circle and redraw.
}Lissajous Curve
Your second challenge is to render Lissajous curves. Just like circles, they can be modeled through a set of parametric equations. Their coordinates are computed as functions of variable \(t\):
The domain of \(t\) is \([0, 2\pi]\). The position of the first vertex is \(\begin{bmatrix}x(0)&y(0)&z(0)\end{bmatrix}\). Complete the following steps to build a Lissajous renderer.
circle directory to a new directory named lissadots.generateCircle to generateLissajous.n, a, b, ratio, and shift.getElementById.synchronize whenever these inputs are modified.synchronize. Only parameter n is an integer. The others are reals.generateLissajous and its calls to generate Lissajous curves instead of a circle. The code will have a very similar structure to your circle generator. It just generates a different shape and relies on different free variables.Submission
To receive credit for your lab work, follow these steps:
circle and lissadots folders before the host closes the session.#lab channel in Discord. Tag your partner in the message with @. No voiceover is necessary.Only labs submitted on time will be granted credit. Late labs or forgot-to-submits are not accepted because Monday at noon is when your instructor has time to grade.