<!doctype html>
<html>
    <head>
        <style>
            html, body
            {
                margin:0;
            }
            canvas
            {
                position:absolute;
                top:0;
                left:0;
                display:block;
                width:100%;
                height:100%;
            }
        </style>
    </head>
    <body>
        <canvas></canvas>
<script type="module">
import { Scene, THREE } from './scene.js';
import { Region } from "./region.js";

let surfaceTest = () =>
{
    let voxels = [];
    voxels[Region.I(2, 2, 2)] = true;
    voxels[Region.I(2, 3, 2)] = true;
    voxels[Region.I(3, 2, 2)] = true;
    let surface = Region.Surface(voxels)
    console.log(surface);

    let surfaceGeometry = new THREE.BufferGeometry();
    surfaceGeometry.setAttribute('position', new THREE.BufferAttribute(surface.vert, 3) );
    surfaceGeometry.setIndex(surface.triPointVert);
    surfaceGeometry.computeVertexNormals();

    let surfaceObject = new THREE.Mesh(
        surfaceGeometry,
        new THREE.MeshBasicMaterial({color:0xaa9900, wireframe:true})
    );

    return {
        DOM:"canvas",
        Init(inScene)
        {
            inScene.add(surfaceObject);
            inScene.add(new THREE.GridHelper(10, 10));
        },
        Update(inScene, inDelta){}
    };

}

let smoothTest = () =>
{
    let average = (inArray, inPointInd, ...inOthersInd) =>
    {
        let sum = [0, 0, 0];
        for(let i=0; i<inOthersInd.length; i++)
        {
            let otherInd = inOthersInd[i]*3;
            sum[0] += inArray[otherInd+0];
            sum[1] += inArray[otherInd+1];
            sum[2] += inArray[otherInd+2];
        }
        
        let pointX = inPointInd*3 + 0;
        let pointY = inPointInd*3 + 1;
        let pointZ = inPointInd*3 + 2;
        let reducer = inOthersInd.length;
        let limit = (inCenter, inPoint) => 
        {
            var limit;
            limit = inCenter-0.49;
            if(inPoint <= limit)
            {
                return limit;
            }
            limit = inCenter + 0.49;
            if(inPoint >= limit)
            {
                return limit;
            }

            return inPoint;
        }
        inArray[pointX] = limit(Math.round(inArray[pointX]), sum[0]/reducer);
        inArray[pointY] = limit(Math.round(inArray[pointY]), sum[1]/reducer);
        inArray[pointZ] = limit(Math.round(inArray[pointZ]), sum[2]/reducer);
    };
    let smooth = (inArray, inTimes) =>
    {
        let count = inArray.length/3;
        for(let t=0; t<inTimes; t++)
        {
            for(let i=0; i<count; i++)
            {
                if(i==0)
                {
                    average(inArray,  i, count-1, i+1);
                }
                else
                {
                    if(i==count-1)
                    {
                        average(inArray,  i, i-1, 0);
                    }
                    else
                    {
                        average(inArray,  i, i-1, i+1);
                    }
                }
            }
        }
    }
    let path = (inPoints, inSmoothing, inColor) =>
    {
        let clone = [...inPoints];
        smooth(clone, inSmoothing);
        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.Float32BufferAttribute( clone, 3 ));
        const materialLine = new THREE.LineBasicMaterial( { color: inColor, linewidth: 3 } );
        const materialPoint = new THREE.PointsMaterial( { color:inColor, size: 0.05 } );
        const output = new THREE.Group();
        
        output.add( new THREE.Line( geometry, materialLine ) );
        output.add( new THREE.Points( geometry, materialPoint ) );
        return output;
    }
    const points =
    [
            4,  0,  0,
            3,  0,  0,
            2,  0,  0,
            1,  0,  0,
        //
            0,  0,  0,
            0,  1,  0,
            1,  1,  0,
            2,  1,  0,
            2,  2,  0,
            3,  2,  0,
            4,  2,  0,
            4,  3,  0,
            //
            5,  3,  0,
            5,  2,  0,
            5,  1,  0,
            5,  0,  0,
    ];

    return {
        DOM:"canvas",
        Init(inScene)
        {
            inScene.add(path(points, 0, 0xFF0000));
            inScene.add(path(points, 10, 0x00ff00));
        },
        Update(scene, delta)
        {

        }
    }
};

Scene(surfaceTest());

</script>

    </body>
</html>