3d Tree with sliders

by jcubed111

HTML

<canvas width=1000 height=800 id='canvas'></canvas>

<div id='sliders'>
	<input type="range" id="drn0" min="-5" max="5" step="0.01" value="0" data-index="0" data-type="drn">
	<input type="range" id="drn1" min="-5" max="5" step="0.01" value="0" data-index="1" data-type="drn">
	<input type="range" id="drn2" min="-5" max="5" step="0.01" value="0" data-index="2" data-type="drn">
	<input type="range" id="drn3" min="-5" max="5" step="0.01" value="0" data-index="3" data-type="drn">
	<input type="range" id="drn4" min="-5" max="5" step="0.01" value="0" data-index="4" data-type="drn">
	<input type="range" id="drn5" min="-5" max="5" step="0.01" value="0" data-index="5" data-type="drn">
	<input type="range" id="drn6" min="-5" max="5" step="0.01" value="0" data-index="6" data-type="drn">
	<input type="range" id="drn7" min="-5" max="5" step="0.01" value="0" data-index="7" data-type="drn">
	<input type="range" id="drn8" min="-5" max="5" step="0.01" value="0" data-index="8" data-type="drn">
	<input type="range" id="drn9" min="-5" max="5" step="0.01" value="0" data-index="9" data-type="drn">
	<input type="range" id="drn10" min="-5" max="5" step="0.01" value="0" data-index="10" data-type="drn">
	<input type="range" id="drn11" min="-5" max="5" step="0.01" value="0" data-index="11" data-type="drn">
	<input type="range" id="drn12" min="-5" max="5" step="0.01" value="0" data-index="12" data-type="drn">
	<input type="range" id="drn13" min="-5" max="5" step="0.01" value="0" data-index="13" data-type="drn">
	<input type="range" id="drn14" min="-5" max="5" step="0.01" value="0" data-index="14" data-type="drn">
	<input type="range" id="drn15" min="-5" max="5" step="0.01" value="0" data-index="15" data-type="drn">
	<input type="range" id="drn16" min="-5" max="5" step="0.01" value="0" data-index="16" data-type="drn">
<br/>
	<input type="range" id="drz0" min="-5" max="5" step="0.01" value="0" data-index="0" data-type="drz">
	<input type="range" id="drz1" min="-5" max="5" step="0.01" value="0"...

SCSS

canvas{
	background: #fff;
}

#sliders{
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	padding: 10px;
	background: transparent;
	
	input{
		display: block;
		width: 150px;
	}
}

JavaScript

"use strict";
var ctx = document.getElementById('canvas').getContext('2d');
ctx.transform(1, 0, 0, -1, 0, document.getElementById('canvas').height)
ctx.scale(100, 100);

class Vector{
	constructor(x, y, z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	dot(b) {
		return this.x*b.x + this.y*b.y + this.z*b.z;
	}
	
	cross(b) {
		return new Vector(
            this.y * b.z - this.z * b.y,
            this.z * b.x - this.x * b.z,
            this.x * b.y - this.y * b.x
        );
	}
	
	times(factor) {
		return new Vector(this.x*factor, this.y*factor, this.z*factor);
	}
	
	sub(b) {
		return new Vector(this.x - b.x, this.y - b.y, this.z - b.z);
	}
	
	plus(b) {
		return new Vector(this.x + b.x, this.y + b.y, this.z + b.z);
	}
	
	mag() {
		return Math.sqrt(this.dot(this));
	}
	
	projectionOn(b) {
		return b.times(this.dot(b)/b.dot(b));
	}
	
	rejectionFrom(b) {
		return this.sub(this.projectionOn(b));
	}
	
	rotatedAbout(rotVector, theta) {
		let parallel = this.projectionOn(rotVector);
		let perp = this.sub(parallel);
		let w = rotVector.cross(perp).times(1/rotVector.mag());
		
		let sTheta = Math.sin(theta);
		let cTheta = Math.cos(theta);
		
		let newPerp = perp.times(Math.cos(theta)).plus( w.times(Math.sin(theta)) );
		
		return newPerp.plus(parallel);
	}
	
	toString() {
		return "<" +
			Math.round(this.x * 1000) / 1000 + ', ' +
			Math.round(this.y * 1000) / 1000 + ', ' +
			Math.round(this.z * 1000) / 1000 + '>';
	}
}

var drnValues = [];
var drzValues = [];

$('input[data-type=drn]').on('input', function(event) {
	drnValues[+event.target.dataset.index-1] = +event.target.value;
	draw();
});
$('input[data-type=drn]').each(i => drnValues[i] = 0);

$('input[data-type=drz]').on('input', function(event) {
	drzValues[+event.target.dataset.index-1] = +event.target.value;
	draw();
});
$('input[data-type=drz]').each(i => drzValues[i] = 0);

function drnAtTime(t) {
    t *= 2;
	var a = drnValues[~~t];
	var b = drnValues[~~t+1] - a;
	t %= 1;
	return a + b*(3*t*t -...