Tackling three.js

I want to learn to use the JavaScript library three.js to get WebGL to render things like this:

The trouble is, I don’t know anything about JavaScript, three.js, or WebGL. Are you in the same boat? If so, then we might as well paddle together. I’m building an online “Wisdom Collector” that organizes all the resources, videos, online courses, books, and articles that are helping me to learn three.js. It’s a work in progress, so hit reload often to see what’s new. Press this button!

three_collector_logo

I managed to make the spinny graphic above after many days of scrutinizing this code from diale.org, meaning that I actually old-school printed it out and read it on the subway every day trying to figure out what it meant. The code itself wasn’t so bad in the end; what was difficult was getting everything set up and configured so that I could use three.js on my own computer, and then figuring out how to make all that work on WordPress for this blog. I’ll write about that in a separate post later, and/or put it in the three.js Collector, but for now I’ll just show you the code.

The HTML code I used in WordPress to display the spinny graphic is:

<div align="center">
<iframe 
    src="http://www.geekhaus.com/hacktastic_files/viewer/3viewer.js.html"
    width="300" height="300" 
    frameborder="0" scrolling="no">
</iframe></div>

The 3D model being displayed is the instellated* Disdyakis Dodecahedron ornament model from the previous two posts.  Of course the short burst of HTML above is just a container for a much larger code file that is loaded from our geekhaus.com server:

<html>
<head>
<script src="./js/three.min.js"></script>
<script src="./js/STLLoader.js"></script>
</head>
<body>

<script>
var container, camera, scene, renderer;

init();
animate();

function init(){
    container=document.createElement('div');
    document.body.appendChild(container);

    camera=new THREE.PerspectiveCamera(
         20, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(3, 0.5, 3);

    scene=new THREE.Scene();

    // object
    var loader=new THREE.STLLoader();
    loader.addEventListener('load', function (event){
        var geometry=event.content;
        var material=new THREE.MeshLambertMaterial({ 
             ambient: 0xFBB917,color: 0xfdd017 });
        var mesh=new THREE.Mesh(geometry, material);
        scene.add(mesh);});

    // STL file to be loaded
    loader.load('stl/DisdyakisDodecahedron_instellated.stl');

    // lights
    scene.add(new THREE.AmbientLight(0x736F6E));

    var directionalLight=new THREE.DirectionalLight(0xffffff, .8);
    directionalLight.position=camera.position;
    scene.add(directionalLight);

    // renderer

    renderer=new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);

    container.appendChild(renderer.domElement);

    window.addEventListener('resize', onWindowResize, false);
}

function addLight(x, y, z, color, intensity){
    var directionalLight=new THREE.DirectionalLight(color, intensity);
    directionalLight.position.set(x, y, z)
    scene.add(directionalLight);
}
  
addLight(0,-100,0,0xffffff,.3);

function onWindowResize(){
    camera.aspect=window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate(){
    requestAnimationFrame(animate);
    render();
}

function render(){
    var timer=Date.now() * 0.0002;
    r=150;
    camera.position.x = -r*Math.sqrt(1-.125*Math.cos(2*timer)
        *Math.cos(2*timer))*Math.cos(timer);
    camera.position.y = .25*r*Math.cos(2*timer);
    camera.position.z = r*Math.sqrt(1-.125*Math.cos(2*timer)
        *Math.cos(2*timer))*Math.sin(timer);
    camera.lookAt(scene.position);
    renderer.render(scene, camera);
    renderer.setClearColor(0xffffff, 1);
}

</script>

</body>
</html>

That’s a lot of code to read at once, and there’s also some interesting math hiding in the “camera.position” coordinates; it’s your turn to look like a dork on the subway. And if you want to start at the very beginning, get in the boat at the three.js Wisdom Collector.

* It turns out that “instellated” is actually a word. However, it is a premium word.  At the Merriam-Webster online dictionary, they state:

This word doesn’t usually appear in our free dictionary, but the definition from our premium Unabridged Dictionary is offered here on a limited basis.