WebGL Demo- Koch Tetrahedron

Uses WebGL to display and manipulate a 3D Koch Tetrahedron fractal

by Jason Tiscione

HTML

<title>Koch Tetrahedron</title>
    <script src="https://ajax.googleapis.com/ajax/libs/threejs/r67/three.js"></script>
    <script src="https://rawgithub.com/dataarts/dat.gui/master/build/dat.gui.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/stats.js/master/build/stats.min.js"></script>
    <script src="https://cdn.rawgit.com/jeromeetienne/threex.rendererstats/master/threex.rendererstats.js"></script>
    <script src="https://cdn.rawgit.com/jeromeetienne/threex.basiclighting/master/threex.basiclighting.js"></script>
    <script src="koch_tetrahedron.js"></script>
    <body>
        <div id="Stats-output"></div>
        <div id="RenderStats-output"></div>
        <div id="container"></div>
        <!-- info on screen display -->
        <div id="info">
            <div class="top">
                <p>
                  WebGL Demo- Koch Tetrahedron
                </p>
                <p class="footer">
                  Adjust the order and stellation settings to see the structure of this fractal.
                </p>
            </div>
        </div>
    </body>

CSS

body {
  overflow    : hidden;
  padding     : 0;
  margin      : 0;
  color       : white;
  font-family : Calibri;
}
#info .top {
  position    : absolute;
  top	        : 0;
  width       : 100%;
  padding	    : 5px;
  font-size   : 100%;
  text-align	: center;
}
.footer {
    position: fixed;
    bottom: 0;
    width: 100%;
}

JavaScript

/**
 * @author Jason Tiscione
 */
var KOCH3D = {};

KOCH3D.KochTetrahedronGeometry = function(order, // small non-negative integer
										  stellation) {		// range 0.0 to 1.0, default 1.0
	this.order = order;
	this.stellation = stellation;
	this.faces = [];
	this.vertices = [
		new THREE.Vector3(1, 1, 1),
		new THREE.Vector3(-1, -1, 1),
		new THREE.Vector3(-1, 1, -1),
		new THREE.Vector3(1, -1, -1)
	];
	this.recurse(2, 1, 0, 0, 1);
	this.recurse(0, 3, 2, 0, 1);
	this.recurse(1, 3, 0, 0, 1);
	this.recurse(2, 3, 1, 0, 1);
	// Alternate debug setup: one triangular face on xy plane, centered around origin
	// this.vertices = [new THREE.Vector3(1, 0, 0), new THREE.Vector3(-0.5,  Math.sqrt(0.75), 0), new THREE.Vector3(-0.5, -Math.sqrt(0.75), 0)];
	// this.recurse(0, 1, 2, 0, 1);
	this.computeFaceNormals();
	this.mergeVertices();
};

KOCH3D.KochTetrahedronGeometry.prototype = new THREE.Geometry();

KOCH3D.KochTetrahedronGeometry.prototype.recurse = function(a, b, c, face_value, depth) {

	if (depth > this.order) {
		this.faces.push(new THREE.Face3(a, b, c, null, null, face_value));
		return;
	}

	// counter-clockwise:
	var A = this.vertices[a], B = this.vertices[b], C = this.vertices[c];

	// define new base vertices at edge midpoints
	var AB = A.clone().add(B).multiplyScalar(0.5),
		BC = B.clone().add(C).multiplyScalar(0.5),
		CA = C.clone().add(A).multiplyScalar(0.5);

	var ab = this.vertices.push(AB) - 1;
	var bc = this.vertices.push(BC) - 1;
	var ca = this.vertices.push(CA) - 1;

	// Calculate the top vertex
	var ab2 = A.clone().sub(B).lengthSq();
	var bc2 = B.clone().sub(C).lengthSq();
	var ca2 = C.clone().sub(A).lengthSq();
	var elevation = this.stellation * Math.sqrt(2 * (ab2 + bc2 + ca2)) / 6;
	var ABC = new THREE.Triangle(AB, BC, CA);
	var TOP = ABC.midpoint().add(ABC.normal().multiplyScalar(elevation));
	var top = this.vertices.push(TOP) - 1;

	// Outer 3 base faces retain their previous material indices
	this.recurse(a, ab, ca, face_value, depth +...