<commit_before>﻿/**
 * @file Icosahedron class. Part of the "Age of Space" project.
 * @author github.com/azziliz
 * @author github.com/thyshimrod
 * {@link https://github.com/The-game-craftmen/age-of-space/ Project page}
 * @license MIT
 */

'use strict';
var aos = aos || {};
//debugger;

/**
 * This class is used to render a planet with an icosahedron.
 *
 * @class
 */
aos.Icosahedron = function () {
    this.vertices = [];
    this.triangles = [];
    this.modelMatrix = null;
    this.frustumMatrix = null;
    this.cameraMatrix = null;
    this.rotateY1 = null;
};


aos.Icosahedron.prototype = {

    initialize: function () {
        //identity
        this.modelMatrix = new Float32Array([
                1, 0, 0, 0,
                0, 1, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1
        ]);

        // http://www.songho.ca/opengl/gl_projectionmatrix.html
        const right = 0.268;
        const top = 0.268;
        const near = 1;
        const far = 100;
        const nf = 1 / (near - far);
        this.frustumMatrix = new Float32Array([
            near / right, 0, 0, 0,
            0, near / top, 0, 0,
            0, 0, (far + near) * nf, -1,
            0, 0, 2 * far * near * nf, 0
        ]);

        // http://www.songho.ca/opengl/gl_camera.html#lookat
        // translate (0, 0, 5)
        const tx = 0;
        const ty = 0;
        const tz = 5;
        this.cameraMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            tx, ty, tz, 1
        ]);

        const cos1 = Math.cos(Math.PI / 180);
        const sin1 = Math.sin(Math.PI / 180);
        this.rotateY1 = new Float32Array([
            cos1, 0, -sin1, 0,
            0, 1, 0, 0,
            sin1, 0, cos1, 0,
            0, 0, 0, 1
        ]);

        const invphi = 2 / (1 + Math.sqrt(5));

        // Vertices coordinates: [Xworld, Yworld, Zworld, Zmodel]
        this.vertices.push(new Float32Array([1, invphi, 0, 0]));    // 0
        this.vertices.push(new Float32Array([1, -invphi, 0, 0]));    // 1
        this.vertices.push(new Float32Array([-1, invphi, 0, 0]));    // 2
        this.vertices.push(new Float32Array([-1, -invphi, 0, 0]));    // 3
        this.vertices.push(new Float32Array([0, 1, invphi, 0]));    // 4
        this.vertices.push(new Float32Array([0, 1, -invphi, 0]));    // 5
        this.vertices.push(new Float32Array([0, -1, invphi, 0]));    // 6
        this.vertices.push(new Float32Array([0, -1, -invphi, 0]));    // 7
        this.vertices.push(new Float32Array([invphi, 0, 1, 0]));    // 8
        this.vertices.push(new Float32Array([-invphi, 0, 1, 0]));    // 9
        this.vertices.push(new Float32Array([invphi, 0, -1, 0]));    // 10
        this.vertices.push(new Float32Array([-invphi, 0, -1, 0]));    // 11

        // Triangles arrays: [vertex1, vertex2, vertex3, average Zmodel]
        this.triangles.push([4, 5, 0, 0]);
        this.triangles.push([4, 5, 2, 0]);
        this.triangles.push([6, 7, 1, 0]);
        this.triangles.push([6, 7, 3, 0]);
        this.triangles.push([0, 1, 8, 0]);
        this.triangles.push([0, 1, 10, 0]);
        this.triangles.push([2, 3, 9, 0]);
        this.triangles.push([2, 3, 11, 0]);
        this.triangles.push([8, 9, 4, 0]);
        this.triangles.push([8, 9, 6, 0]);
        this.triangles.push([10, 11, 5, 0]);
        this.triangles.push([10, 11, 7, 0]);
        this.triangles.push([0, 4, 8, 0]); // +++
        this.triangles.push([0, 5, 10, 0]); // ++-
        this.triangles.push([1, 6, 8, 0]); // +-+
        this.triangles.push([1, 7, 10, 0]); // +--
        this.triangles.push([2, 4, 9, 0]); // -++
        this.triangles.push([2, 5, 11, 0]); // -+-
        this.triangles.push([3, 6, 9, 0]); // --+
        this.triangles.push([3, 7, 11, 0]); // ---


        window.addEventListener('animationTick', function (e) {
            const canvas = document.getElementById('planetTestCanvas');
            const ctx = canvas.getContext("2d");

            const newModel = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
            this.modelMatrix = newModel;
            const vm = aos.Math.multiply4x4(this.cameraMatrix, this.modelMatrix);
            const pvm = aos.Math.multiply4x4(this.frustumMatrix, vm);

            const halfWidth = canvas.clientWidth / 2;
            const halfHeight = canvas.clientHeight / 2;

            ctx.fillStyle = "#000";
            ctx.fillRect(0, 0, canvas.clientWidth, canvas.clientHeight);

            const screenPoints = [];
            this.vertices.forEach(function (vec3) {
                const screenPoint = aos.Math.transformVector3(vec3, pvm);
                screenPoints.push(screenPoint);
                ctx.fillStyle = "#fff";
                ctx.fillRect(screenPoint[0] * halfWidth + halfWidth, screenPoint[1] * halfHeight + halfHeight, 1, 1);
                const modelPoint = aos.Math.transformVector3(vec3, this.modelMatrix);
                vec3[3] = modelPoint[2];
            }, this);
            this.triangles.forEach(function (tri) {
                tri[3] = this.vertices[tri[0]][3] + this.vertices[tri[1]][3] + this.vertices[tri[2]][3];
            }, this);
            this.triangles.sort(function (a, b) {
                return b[3] - a[3];
            });
            this.triangles.forEach(function (tri) {
                ctx.beginPath();
                ctx.fillStyle = 'rgb(' + (tri[0] * 20) + ', ' + (tri[1] * 20) + ', ' + (tri[2] * 20) + ')';
                ctx.moveTo(screenPoints[tri[0]][0] * halfWidth + halfWidth, screenPoints[tri[0]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.fill();
                ctx.strokeStyle = 'white';
                ctx.lineTo(screenPoints[tri[1]][0] * halfWidth + halfWidth, screenPoints[tri[1]][1] * halfHeight + halfHeight);
                ctx.lineTo(screenPoints[tri[2]][0] * halfWidth + halfWidth, screenPoints[tri[2]][1] * halfHeight + halfHeight);
                ctx.closePath();
                ctx.stroke();
            }, this);
        }.bind(this), false);
    },<commit_msg>rotate with mouse, identify mouseover<commit_after>﻿/**
 * @file Icosahedron class. Part of the "Age of Space" project.
 * @author github.com/azziliz
 * @author github.com/thyshimrod
 * {@link https://github.com/The-game-craftmen/age-of-space/ Project page}
 * @license MIT
 */

'use strict';
var aos = aos || {};
//debugger;

/**
 * This class is used to render a planet with an icosahedron.
 *
 * @class
 */
aos.Icosahedron = function () {
    this.vertices = [];
    this.triangles = [];
    this.modelMatrix = null;
    this.frustumMatrix = null;
    this.cameraMatrix = null;
    this.rotateY1 = null;
    this.rotateY1r = null;
    this.rotates = true;
    this.hoveredTriangle = -1;
    this.mousePosition = [0, 0];
};


aos.Icosahedron.prototype = {

    initialize: function () {
        //identity
        this.modelMatrix = new Float32Array([
                1, 0, 0, 0,
                0, 1, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1
        ]);

        // http://www.songho.ca/opengl/gl_projectionmatrix.html
        const right = 0.268;
        const top = 0.268;
        const near = 1;
        const far = 100;
        const nf = 1 / (near - far);
        this.frustumMatrix = new Float32Array([
            near / right, 0, 0, 0,
            0, near / top, 0, 0,
            0, 0, (far + near) * nf, -1,
            0, 0, 2 * far * near * nf, 0
        ]);

        // http://www.songho.ca/opengl/gl_camera.html#lookat
        // translate (0, 0, 5)
        const tx = 0;
        const ty = 0;
        const tz = 5;
        this.cameraMatrix = new Float32Array([
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            tx, ty, tz, 1
        ]);

        const cos1 = Math.cos(Math.PI / 500);
        const sin1 = Math.sin(Math.PI / 500);
        this.rotateY1 = new Float32Array([
            cos1, 0, -sin1, 0,
            0, 1, 0, 0,
            sin1, 0, cos1, 0,
            0, 0, 0, 1
        ]);
        this.rotateY1r = new Float32Array([
            cos1, 0, sin1, 0,
            0, 1, 0, 0,
            -sin1, 0, cos1, 0,
            0, 0, 0, 1
        ]);

        const invphi = 2 / (1 + Math.sqrt(5));

        // Vertices coordinates: [Xworld, Yworld, Zworld, Zmodel]
        this.vertices.push(new Float32Array([1, invphi, 0, 0]));    // 0
        this.vertices.push(new Float32Array([1, -invphi, 0, 0]));    // 1
        this.vertices.push(new Float32Array([-1, invphi, 0, 0]));    // 2
        this.vertices.push(new Float32Array([-1, -invphi, 0, 0]));    // 3
        this.vertices.push(new Float32Array([0, 1, invphi, 0]));    // 4
        this.vertices.push(new Float32Array([0, 1, -invphi, 0]));    // 5
        this.vertices.push(new Float32Array([0, -1, invphi, 0]));    // 6
        this.vertices.push(new Float32Array([0, -1, -invphi, 0]));    // 7
        this.vertices.push(new Float32Array([invphi, 0, 1, 0]));    // 8
        this.vertices.push(new Float32Array([-invphi, 0, 1, 0]));    // 9
        this.vertices.push(new Float32Array([invphi, 0, -1, 0]));    // 10
        this.vertices.push(new Float32Array([-invphi, 0, -1, 0]));    // 11

        // Triangles arrays: [vertex1, vertex2, vertex3, average Zmodel]
        this.triangles.push([4, 5, 0, 0]);
        this.triangles.push([4, 5, 2, 0]);
        this.triangles.push([6, 7, 1, 0]);
        this.triangles.push([6, 7, 3, 0]);
        this.triangles.push([0, 1, 8, 0]);
        this.triangles.push([0, 1, 10, 0]);
        this.triangles.push([2, 3, 9, 0]);
        this.triangles.push([2, 3, 11, 0]);
        this.triangles.push([8, 9, 4, 0]);
        this.triangles.push([8, 9, 6, 0]);
        this.triangles.push([10, 11, 5, 0]);
        this.triangles.push([10, 11, 7, 0]);
        this.triangles.push([0, 4, 8, 0]); // +++
        this.triangles.push([0, 5, 10, 0]); // ++-
        this.triangles.push([1, 6, 8, 0]); // +-+
        this.triangles.push([1, 7, 10, 0]); // +--
        this.triangles.push([2, 4, 9, 0]); // -++
        this.triangles.push([2, 5, 11, 0]); // -+-
        this.triangles.push([3, 6, 9, 0]); // --+
        this.triangles.push([3, 7, 11, 0]); // ---


        window.addEventListener('animationTick', function (e) {
            const canvas = document.getElementById('planetTestCanvas');
            const halfWidth = canvas.clientWidth / 2;
            const halfHeight = canvas.clientHeight / 2;
            const ctx = canvas.getContext("2d");

            ctx.save();
            ctx.translate(halfWidth, halfHeight);
            ctx.scale(halfWidth, halfHeight);

            if (this.rotates) {
                const newModel = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
                this.modelMatrix = newModel;
            }
            else {
                if (this.mousePosition[0] < 50) {
                    const newModel1 = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
                    const newModel2 = aos.Math.multiply4x4(this.rotateY1, newModel1);
                    const newModel3 = aos.Math.multiply4x4(this.rotateY1, newModel2);
                    const newModel4 = aos.Math.multiply4x4(this.rotateY1, newModel3);
                    this.modelMatrix = newModel4;
                } else if (this.mousePosition[0] < 150) {
                    const newModel1 = aos.Math.multiply4x4(this.rotateY1, this.modelMatrix);
                    const newModel2 = aos.Math.multiply4x4(this.rotateY1, newModel1);
                    this.modelMatrix = newModel2;
                } else if (this.mousePosition[0] < 350) {
                    // No rotation
                } else if (this.mousePosition[0] < 450) {
                    const newModel1 = aos.Math.multiply4x4(this.rotateY1r, this.modelMatrix);
                    const newModel2 = aos.Math.multiply4x4(this.rotateY1r, newModel1);
                    this.modelMatrix = newModel2;
                } else {
                    const newModel1 = aos.Math.multiply4x4(this.rotateY1r, this.modelMatrix);
                    const newModel2 = aos.Math.multiply4x4(this.rotateY1r, newModel1);
                    const newModel3 = aos.Math.multiply4x4(this.rotateY1r, newModel2);
                    const newModel4 = aos.Math.multiply4x4(this.rotateY1r, newModel3);
                    this.modelMatrix = newModel4;
                }
            }
            const vm = aos.Math.multiply4x4(this.cameraMatrix, this.modelMatrix);
            const pvm = aos.Math.multiply4x4(this.frustumMatrix, vm);

            ctx.fillStyle = "#000";
            ctx.fillRect(-1, -1, 2, 2);

            const screenPoints = [];
            this.vertices.forEach(function (vec3) {
                const screenPoint = aos.Math.transformVector3(vec3, pvm);
                screenPoints.push(screenPoint);
                const modelPoint = aos.Math.transformVector3(vec3, this.modelMatrix);
                vec3[3] = modelPoint[2];
            }, this);
            this.triangles.forEach(function (tri) {
                tri[3] = this.vertices[tri[0]][3] + this.vertices[tri[1]][3] + this.vertices[tri[2]][3];
            }, this);
            this.triangles.sort(function (a, b) {
                return b[3] - a[3];
            });
            this.triangles.forEach(function (tri) {
                ctx.beginPath();
                ctx.fillStyle = 'rgb(' + (tri[0] * 20) + ', ' + (tri[1] * 20) + ', ' + (tri[2] * 20) + ')';
                ctx.moveTo(screenPoints[tri[0]][0], screenPoints[tri[0]][1]);
                ctx.lineTo(screenPoints[tri[1]][0], screenPoints[tri[1]][1]);
                ctx.lineTo(screenPoints[tri[2]][0], screenPoints[tri[2]][1]);
                ctx.closePath();
                if (!this.rotates && ctx.isPointInPath(this.mousePosition[0], this.mousePosition[1])) {
                    ctx.fillStyle = 'red';
                }
                ctx.fill();
                ctx.lineWidth = 0.004; // 1/250 space units = 1 px on screen
                ctx.strokeStyle = 'white';
                ctx.lineTo(screenPoints[tri[1]][0], screenPoints[tri[1]][1]);
                ctx.lineTo(screenPoints[tri[2]][0], screenPoints[tri[2]][1]);
                ctx.closePath();
                ctx.stroke();
            }, this);

            ctx.restore();
        }.bind(this), false);

        document.getElementById('planetTestCanvas').addEventListener('mouseover', function (e) {
            this.rotates = false;
        }.bind(this), false);
        document.getElementById('planetTestCanvas').addEventListener('mouseout', function (e) {
            this.rotates = true;
        }.bind(this), false);

        document.getElementById('planetTestCanvas').addEventListener('mousemove', function (e) {
            e.preventDefault(); // usually, keeping the left mouse button down triggers a text selection or a drag & drop.
            const x = e.offsetX * 500 / document.getElementById('planetTestCanvas').offsetWidth;
            const y = e.offsetY * 500 / document.getElementById('planetTestCanvas').offsetWidth;
            this.mousePosition = [x, y];
            //console.log('m' + x + ',' + y);
        }.bind(this), false);
    },
{'fraction_non_alphanumeric': 0.15988653213848236, 'fraction_numerical': 0.04983560054155116, 'mean_word_length': 1.8055706275999277, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1438701', 'n_tokens_mistral': 5592, 'n_tokens_neox': 5004, 'n_words': 1099}