In this MP you will

  1. Generate an icosahedron
  2. Apply triangular subdivision to it a variable number of times

This MP is elective, with no core components. It assumes you have already completed the Terrain MP.

Warning

This MP is likely to take more effort and time than its point value suggests. It is intended to be a jumping-off point for students interested in geometry definition and refinement, which is not a topic given much attention in this course.

1 Overview

You will submit a webpage that has

  • One number entry field
  • One button
  • One canvas
  • A 3D view of dynamically-generated fractal terrain

Submit an HTML file and any number of js, glsl, css, and JSON files. No image files are permitted for this assignment.

You are welcome to use a JavaScript math library, such as the one used in in-class examples or others you might know.

2 Specification

2.1 HTML input setup

Have one input numeric field for entering how many rounds of subdivision to do.

HTML input elements, styling, and event handling are beyond the scope of this class. See the Terrain MP for example code for setting up inputs.

2.2 Initial icosahedron

The only geometry you may directly represent in your submission is an icosahedron.

The 12 vertices of an icosahedron are at (\pm 1, \pm \varphi, 0), (0, \pm 1, \pm \varphi), and (\pm \varphi, 0, \pm 1), where \varphi = (5^{0.5})(0.5)-0.5. The vertex (1, \varphi, 0) is connected to the five vertices (1, -\varphi, 0), (\varphi, 0, \pm 1), and (0, 1, \pm \varphi), for 30 edges and 20 triangles.

The normal of each point on this icosahedron is equal to (a scaled version of) its position.

If the rounds of subdivision is 0, render this icosahedron as-is.

2.3 Triangular subdivision

If the rounds of subdivision is greater than 0, repeatedly perform a pass of triangular subdivision, move all vertices to the same distance from the origin, and continue with the next round. Support at least subdivision levels 0 through 6.

An icosphere with n levels of subdivision has exactly 10(4^n)+2 vertices and 20(4^n) triangles.

Triangular subdivision is much more easily explained than it is implemented. The main challenge in implementation is keeping track of which vertices are connected to which others as the subdivision progresses. We offer two approaches for you to consider

2.3.1 The proper approach

Represent the geometry using an editable mesh format. The half-edge data structure is a good pick for this, and we have a guided to using it. We strongly recommend this approach.

It is likely you’ll want to use some kind of JavaScript class/object to work with the half-edges. JavaScript initially had very little support for classes, but it now has a class system you can use that should look familiar from C++ and Java.

You might start your half-edge data structure with something like this:

class HalfEdge {
    v
    next
    twin
    constructor(v, next, twin) {
        this.v = v;
        this.next = next;
        this.twin = twin;
    }
    sideCount() {
        let ans = 1
        for(let he=this.next; he!=this; he=he.next) ans += 1
        return ans
    }
}

and then use it like so:

let he1 = new HalfEdge([1,0,0],null,null)
let he2 = new HalfEdge([0,1,0],he1,null)
let he3 = new HalfEdge([0,0,1],he2,null)
he1.next = he3
console.log(he1.sideCount())

Note that this. is required, not optional, in class methods when accessing class members.

2.3.2 The special-case hack approach

Because we have a spherical arrangement for this MP, there is a hack that can work, though it won’t help you learn as much as the proper approach.

Initially we have an icosahedron, meaning every edge has the same length. In particular, a vertex is connected by an edge to every other vertex that is less than some threshold distance away.

Subdivision adds a new vertex in the center of every edge. Afterwards not all edges are exactly the same length, but they’re pretty close and all just a bit over half the size they were before. So again, a vertex is connected by an edge to every other vertex that is less than some (smaller) threshold distance away.

This hack can be continued for as many subdivisions as we want. But because it is operating in an essentially brute-force way it will likely experience quadratic runtime, making it painfully slow for higher levels of subdivision. Some points will be removed if subdivision slows in this way in your implementation.

2.4 Render and light

Render the geometry with both diffuse and specular lighting. Have the camera moving around the geometry.

3 Evaluating your results

On both your development machine and when submitted to the submission server and then viewed by clicking the HTML link, the resulting page should initially be blank. Once the button is pressed a (possibly-subdivided) icosahedron should appear, filling most of the screen with a moving camera. One example might be the following:

A video of an example result.