JSFiddle - React, Tailwind, and code Playground

by paldepind

HTML

<canvas id="canvas" width="400" height="400"></canvas>

JavaScript

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var hW = canvas.width / 2;
var hH = canvas.height / 2;
var startTime = window.performance.now();

var cameraPlaneDist = 1.5;
var planeZ = -1.8;

var vertices = [[0.5, 0.5, -0.5],
                [0.5, -0.5, -0.5],
                [-0.5, -0.5, -0.5],
                [-0.5, 0.5, -0.5],
                [0.5, 0.5, 0.5],
                [0.5, -0.5, 0.5],
                [-0.5, -0.5, 0.5],
                [-0.5, 0.5, 0.5]];

var edges = [[0, 1], [0, 3], [0, 4],
             [2, 3], [2, 1], [2, 6],
             [5, 6], [5, 4], [5, 1],
             [7, 6], [7, 4], [7, 3]];

var rotateAroundYAxis = function(v, a) {
   return [v[2]*Math.sin(a) + v[0]*Math.cos(a),
           v[1],
           v[2]*Math.cos(a) - v[0]*Math.sin(a)];
};


var rotateAroundXAxis = function(v, a) {
   return [v[0],
           v[1]*Math.cos(a) - v[2]*Math.sin(a),
           v[1]*Math.sin(a) + v[2]*Math.cos(a)];
};

var project = function(v) {
    var w = (v[2] - planeZ) / cameraPlaneDist;
    return [v[0] / w, v[1] / w, v[2]];
};

var toScreenCoordinates = function(v) {
    return [v[0] * hW + hW, v[1] * hH + hH];
};

var renderEdges = function(vertices, edges) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
    edges.forEach(function(edge) {
        ctx.moveTo(vertices[edge[0]][0], vertices[edge[0]][1]);
        ctx.lineTo(vertices[edge[1]][0], vertices[edge[1]][1]);
    });
    ctx.stroke();
};

function mainLoop() {
    var transformedVertices = vertices.map(function (vertice) {
        var dt = window.performance.now() - startTime;
        var v = rotateAroundYAxis(vertice, dt * 0.0005);
        v = rotateAroundXAxis(v, dt * 0.0003);
        v = project(v);
        v = toScreenCoordinates(v);
        return v;
    });
    renderEdges(transformedVertices, edges);
    requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);