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.
polydots
folder, run npm install
to download the dependencies, and run npm run start
to start up a web server.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>
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 nInput: HTMLInputElement;
let radiusInput: HTMLInputElement;
let nInput: HTMLInputElement; let radiusInput: HTMLInputElement;
initialize
:
// other getElementById calls...
nInput = document.getElementById('n-input') as HTMLInputElement;
radiusInput = document.getElementById('radius-input') as HTMLInputElement;
// ...
// other event listeners...
nInput.addEventListener('input', synchronize);
radiusInput.addEventListener('input', synchronize);
// other getElementById calls... nInput = document.getElementById('n-input') as HTMLInputElement; radiusInput = document.getElementById('radius-input') as HTMLInputElement; // ... // other event listeners... nInput.addEventListener('input', synchronize); radiusInput.addEventListener('input', synchronize);
synchronize
function, which will be called whenever a number in the text inputs changes:
function synchronize() {
// Release any previous VAO and VBOs.
vao?.destroy();
attributes?.destroy();
const n = parseInt(nInput.value);
const radius = parseFloat(radiusInput.value);
console.log(n, radius);
// TODO: regenerate circle and redraw.
}
function synchronize() { // Release any previous VAO and VBOs. vao?.destroy(); attributes?.destroy(); const n = parseInt(nInput.value); const radius = parseFloat(radiusInput.value); console.log(n, radius); // 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 a 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.
index.html
, style.css
, and main.ts
from the circle exercise to the lissadots
folder. Ensure that you can render a circle before moving on.lissadots
folder and start up a new server.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:
#lab-gallery
channel in Discord. Tag your group members.Only labs submitted on time will be granted credit. Late labs or forgot-to-submits are not accepted because Wednesday at noon is when your instructor has time to grade.