JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://npmcdn.com/gl-matrix@2.3.2/dist/gl-matrix.js"></script>
<div id="container">
<div id="stage">
</div>
<div id="circle"></div>
</div>
CSS
#container {
width: 400px;
height: 400px;
background-color: #eee;
margin: auto;
}
#stage {
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transform: translate3d(0px, 0px, 0px);
-webkit-transform: translate3d(0px, 0px, 0px);
}
.line {
display: block; position: absolute;
width: 300px; height: 0px;
border-radius: 1px;
border: 1px solid #444;
transform-origin: 1px 1px;
-webkit-transform-origin: 1px 1px;
pointer-events: none;
}
#circle {
width: 200px;
height: 200px;
border: 1px solid #ccc;
border-radius: 50%;
position: absolute;
top: 211px;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
.line.thick {
transform-origin: 1px 2px;
border-top-color: black;
border-top: 2px solid black;
}
.line.back {
-webkit-transform-origin: 1px 0.5px;
border-top-width: 0;
border-color: rgba(0,0,0,0.15);
border-style: dotted;
}
JavaScript
var PHI = 1.61803398875;
var requestAnimationFrame = window.requestAnimationFrame || webkitRequestAnimationFrame;
var stage = makeIcosahedron( new Stage() );
var worldSpacePoints = createArray( stage.points.length, vec3.create );
var screenSpacePoints = createArray( stage.points.length, vec2.create );
var stageElem = document.getElementById("stage");
var lineElems = createArray( stage.lines.length, function() {
var line = document.createElement("div");
line.className = "line";
stageElem.appendChild( line );
return line;
} );
var renderTime = 0;
var worldMatrix = mat4.create();
var normal1 = vec4.create(),
normal2 = vec4.create(),
screenPosition = vec3.create();
var shapePosition = vec3.fromValues( 0, 0, 70 );
var shapeQuaternion = quat.create( );
var shapeRotationVelocity = vec3.create();
var screenDist = 1 / Math.tan( 30 * Math.PI / 180 );
var previousTime = Date.now();
setupTrackballControls( document.getElementById("container"), shapeQuaternion, shapePosition );
run();
function run() {
var time = Date.now();
renderTime += 0.0004 * (time - previousTime > 50 ? 0 : time - previousTime);
previousTime = time;
mat4.fromRotationTranslation( worldMatrix, shapeQuaternion, shapePosition );
mat4.scale( worldMatrix, worldMatrix, [ 10, 10, 10 ] );
for ( var i = 0; i < stage.points.length; i++ ) {
var worldSpace = worldSpacePoints[ i ];
vec3.transformMat4( worldSpace, stage.points[ i ], worldMatrix );
var screenSpace = vec2.set( screenSpacePoints[ i ], worldSpace[ 0 ], worldSpace[ 1 ] );
vec2.scale( screenSpace, screenSpace, screenDist / worldSpace[ 2 ] );
vec2.multiply( screenSpace, screenSpace, [ 200, 200 ] );
vec2.add( screenSpace, screenSpace, [ 200, 200 ] );
}
for ( var i = 0; i < stage.lines.length; i++ ) {
var point1 = screenSpacePoints[ stage.lines[ i ][ 0 ] ];
var point2 = screenSpacePoints[ stage.lines[ i ][ 1 ] ];
var rot = vec2angle( point1, point2 );
var len...