Source: webgl.js

/** A WebGL implementation of grid.base.BaseHexagonalGrid using three.js
 * @module grid.webgl
 */

var base = require('./base.js')

import {
    OrthographicCamera, Scene, Camera,
    BoxGeometry, MeshNormalMaterial, Mesh,
    Shape, ExtrudeGeometry,
    WebGLRenderer, Vector3
} from "three";

function makeHexagonShape(radius) {
    var shape = new Shape();
    shape.moveTo(radius, 0);
    for(var i=1; i<6; i++) {
        shape.lineTo(radius * Math.cos(i * Math.PI / 3.0),
                     radius * Math.sin(i * Math.PI / 3.0));
    }
    return shape;
}

function makeHexoid(radius, height) {
    var shape = makeHexagonShape(radius * 0.8);
    return new ExtrudeGeometry(shape, {
        depth: height,
        bevelEnabled: true,
        bevelSize: radius * 0.2,
        bevelThickness: height 
    });
}

class WebGLHexagonalGrid extends base.BaseHexagonalGrid {
   constructor(options={}) {
        super(options);
        this.last_update_time = 0;

        if(this.autoResize) {
            var this_ = this;
            this.resizeListener = window.addEventListener('resize', () => {
                this_.resize();
            });
            this.resize();
        }
    }

    render() {
        this.renderer.render(this.scene, this.camera);
    }

    resize() {
        var rect = this.canvas.getBoundingClientRect();
        var size = this.calculateGridWidth(this.nodeRadius);
        var ratio = rect.width / rect.height;
        var w = Math.max(size.width, size.height);
        var h = w * ratio; 

        this.canvas.width = rect.width;
        this.canvas.height = rect.height;
        this.camera.aspect = rect.width / rect.height;

        this.camera.left = -w/2.0;
        this.camera.right = w/2.0;
        this.camera.top = -h/2.0;
        this.camera.bottom = h/2.0;

        this.camera.updateProjectionMatrix();
        this.renderer.setSize(rect.width, rect.height, false);
        this.render();
    }

    preInitialise() {
        super.preInitialise();
        this.camera = new OrthographicCamera(-1, 1, -1, 1, 0.01, 6);
        this.camera.position.z = 1;
        this.camera.lookAt(this.focusPoint);

        this.scene = new Scene();
        this.renderer = new WebGLRenderer({canvas: this.canvas, antialias: true});

        this.hexagonMaterial = new MeshNormalMaterial();
        this.hexagonGeometry = makeHexoid(this.nodeRadius * 0.8,
                                          this.nodeRadius / 5.0);


    }

    initialiseNode(node, data) {
        var position = node.to_cartesian(this.nodeRadius);
        data.mesh = new Mesh(this.hexagonGeometry, this.hexagonMaterial);
        data.mesh.position.x = position.x;
        data.mesh.position.y = position.y;
        this.scene.add(data.mesh);
    }

    updateNode(node, data) {
        data.mesh.rotation.x = performance.now() * node.q / 2000.0;
        data.mesh.rotation.y = performance.now() * node.r / 2000.0;
        data.mesh.rotation.z = performance.now() * node.s / 2000.0;
    }
}

WebGLHexagonalGrid.prototype.default_options = Object.assign(
    {},
    base.BaseHexagonalGrid.prototype.default_options,
    {
        'canvas': undefined,
        'focusPoint': new Vector3(0, 0, 0),
        'canvasPadding': {x: 0, y: 0},
        'autoResize': true,
        'nodeRadius': 0.2,
    }
)

export default {
    WebGLHexagonalGrid: WebGLHexagonalGrid,
    makeHexagonShape: makeHexagonShape,
    makeHexoid: makeHexoid
}