// samsung gearvr browser doesnt have webgl enabled yet
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20151201/samsungbrowser
        // https://zproxy.wordpress.com/2015/07/04/gearvr-ovrmycubeworldndk/


        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IDefault page = null)
        {
            // X:\jsc.svn\examples\java\android\vr\OVRMyCubeWorldNDK\OVRMyCubeWorldNDK\VrCubeWorld.Renderer.cs

            // works for IE11
            //DiagnosticsConsole.ApplicationContent.BindKeyboardToDiagnosticsConsole();


            //if (Native.window.parent != Native.window.self)
            //{
            //    // why stop there. negotiate our own title bar!
            //    Native.document.body.style.backgroundColor = JSColor.Transparent;
            //}
            //else
            //{
            Native.window.document.body.style.backgroundColor = JSColor.Black;
            Native.window.document.body.style.color = JSColor.Yellow;
            //}

            //page.PageContainer.style.color = Color.Blue;

            var size = 600;


            var gl = new WebGLRenderingContext();


            var canvas = gl.canvas.AttachToDocument();

            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;
            canvas.style.SetLocation(0, 0, size, size);

            canvas.width = size;
            canvas.height = size;



            var gl_viewportWidth = size;
            var gl_viewportHeight = size;

            #region AtResize
            Action AtResize =
                delegate
                {
                    gl_viewportWidth = Native.window.Width;
                    gl_viewportHeight = Native.window.Height;

                    canvas.style.SetLocation(0, 0, gl_viewportWidth, gl_viewportHeight);

                    canvas.width = gl_viewportWidth;
                    canvas.height = gl_viewportHeight;
                };

            Native.window.onresize +=
                e =>
                {
                    AtResize();
                };
            AtResize();
            #endregion


            var shaderProgram = gl.createProgram(
                new GeometryVertexShader(),
                new GeometryFragmentShader()
            );



            gl.linkProgram(shaderProgram);
            gl.useProgram(shaderProgram);

            var shaderProgram_vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");

            gl.enableVertexAttribArray((uint)shaderProgram_vertexPositionAttribute);

            // new in lesson 02
            var shaderProgram_vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
            gl.enableVertexAttribArray((uint)shaderProgram_vertexColorAttribute);

            var shaderProgram_pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
            var shaderProgram_mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");


            // X:\jsc.svn\examples\java\android\vr\OVRMyCubeWorldNDK\OVRMyCubeWorldNDK\References\VrApi.ovrMatrix4f.cs
            // exports.mat4 = require("./gl-matrix/mat4.js");
            // https://github.com/toji/gl-matrix/blob/master/src/gl-matrix.js
            // https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat4.js
            // new glMatrix.ARRAY_TYPE(16);
            // https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/common.js
            //  Float32Array : Array



            var __mat4 = new
            {
                // X:\jsc.svn\examples\javascript\Test\TestFloatArray\TestFloatArray\Application.cs
                // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150706/20150708
                create = new Func<float[]>(
                    () => new float[]
                    {
                        1, 0, 0, 0,
                        0, 1, 0, 0,
                        0, 0, 1, 0,
                        0, 0, 0, 1,
                    }
                )
            };

            // should jsc default to Float32Array  ?
            //var __mvMatrix = new float[]
            //{
            //    1, 0, 0, 0,
            //    0, 1, 0, 0,
            //    0, 0, 1, 0,
            //    0, 0, 0, 1,
            //};

            //var mvMatrix = glMatrix.mat4.create();
            var mvMatrix = __mat4.create();
            // for js we erased the generic type..
            var mvMatrixStack = new Stack<float[]>();

            // X:\jsc.svn\examples\javascript\WebGL\WebGLSpadeWarrior\WebGLSpadeWarrior\Shaders\GeometryVertexShader.cs
            var pMatrix = __mat4.create();
            //var pMatrix = new ScriptCoreLib.GLSL.mat4(1);
            //var pMatrix = glMatrix.mat4.create();


            #region mvMatrixScope
            Action mvPushMatrix = delegate
            {
                var copy = __mat4.create();
                glMatrix.mat4.set(mvMatrix, copy);
                mvMatrixStack.Push(copy);
            };

            Action mvPopMatrix = delegate
            {
                mvMatrix = mvMatrixStack.Pop();
            };

            Action<Action> mvMatrixScope =
                h =>
                {
                    mvPushMatrix();
                    h();
                    mvPopMatrix();
                };
            #endregion

            #region setMatrixUniforms
            Action setMatrixUniforms =
                delegate
                {
                    gl.uniformMatrix4fv(shaderProgram_pMatrixUniform, false, pMatrix);
                    gl.uniformMatrix4fv(shaderProgram_mvMatrixUniform, false, mvMatrix);
                };
            #endregion




            #region init buffers


            #region cube
            var cubeVertexPositionBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
            var cubesize = 1.0f * 0.02f;
            var vertices = new[]{
                // Front face
                -cubesize, -cubesize,  cubesize,
                 cubesize, -cubesize,  cubesize,
                 cubesize,  cubesize,  cubesize,
                -cubesize,  cubesize,  cubesize,

                // Back face
                -cubesize, -cubesize, -cubesize,
                -cubesize,  cubesize, -cubesize,
                 cubesize,  cubesize, -cubesize,
                 cubesize, -cubesize, -cubesize,

                // Top face
                -cubesize,  cubesize, -cubesize,
                -cubesize,  cubesize,  cubesize,
                 cubesize,  cubesize,  cubesize,
                 cubesize,  cubesize, -cubesize,

                // Bottom face
                -cubesize, -cubesize, -cubesize,
                 cubesize, -cubesize, -cubesize,
                 cubesize, -cubesize,  cubesize,
                -cubesize, -cubesize,  cubesize,

                // Right face
                 cubesize, -cubesize, -cubesize,
                 cubesize,  cubesize, -cubesize,
                 cubesize,  cubesize,  cubesize,
                 cubesize, -cubesize,  cubesize,

                // Left face
                -cubesize, -cubesize, -cubesize,
                -cubesize, -cubesize,  cubesize,
                -cubesize,  cubesize,  cubesize,
                -cubesize,  cubesize, -cubesize
            };
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

            var cubeVertexPositionBuffer_itemSize = 3;
            var cubeVertexPositionBuffer_numItems = 36;


            // 216, 191, 18
            #region colors1
            var colors_orange = new[]{
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face

                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face

                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face

                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face


                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face

                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f  // Left face
            };


            var cubeVertexColorBuffer_orange = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors_orange), gl.STATIC_DRAW);
            #endregion

            #region colors2
            var colors2 = new[]{
                0.0f, 0.6f, 1.0f, 1.0f, // Front face
                0.0f, 0.6f, 1.0f, 1.0f, // Front face
                0.0f, 0.6f, 1.0f, 1.0f, // Front face
                0.0f, 0.6f, 1.0f, 1.0f, // Front face

                0.0f, 0.4f, 0.8f, 1.0f, // Back face
                0.0f, 0.4f, 0.8f, 1.0f, // Back face
                0.0f, 0.4f, 0.8f, 1.0f, // Back face
                0.0f, 0.4f, 0.8f, 1.0f, // Back face

                0.0f, 0.5f, 0.9f, 1.0f, // Top face
                0.0f, 0.5f, 0.9f, 1.0f, // Top face
                0.0f, 0.5f, 0.9f, 1.0f, // Top face
                0.0f, 0.5f, 0.9f, 1.0f, // Top face

                0.0f, 0.5f, 1.0f, 1.0f, // Bottom face
                0.0f, 0.5f, 1.0f, 1.0f, // Bottom face
                0.0f, 0.5f, 1.0f, 1.0f, // Bottom face
                0.0f, 0.5f, 1.0f, 1.0f, // Bottom face


                0.0f, 0.8f, 1.0f, 1.0f, // Right face
                0.0f, 0.8f, 1.0f, 1.0f, // Right face
                0.0f, 0.8f, 1.0f, 1.0f, // Right face
                0.0f, 0.8f, 1.0f, 1.0f, // Right face

                0.0f, 0.8f, 1.0f, 1.0f,  // Left face
                0.0f, 0.8f, 1.0f, 1.0f,  // Left face
                0.0f, 0.8f, 1.0f, 1.0f,  // Left face
                0.0f, 0.8f, 1.0f, 1.0f  // Left face
            };


            var cubeVertexColorBuffer2 = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors2), gl.STATIC_DRAW);
            #endregion

            #region colors3
            var colors_green = new[]{
                0.0f, 1.0f, 0.0f, 1.0f, // Front face
                0.0f, 1.0f, 0.0f, 1.0f, // Front face
                0.0f, 1.0f, 0.0f, 1.0f, // Front face
                0.0f, 1.0f, 0.0f, 1.0f, // Front face

                0.0f, 0.4f, 0.0f, 1.0f, // Back face
                0.0f, 0.4f, 0.0f, 1.0f, // Back face
                0.0f, 0.4f, 0.0f, 1.0f, // Back face
                0.0f, 0.4f, 0.0f, 1.0f, // Back face

                0.0f, 0.5f, 0.0f, 1.0f, // Top face
                0.0f, 0.5f, 0.0f, 1.0f, // Top face
                0.0f, 0.5f, 0.0f, 1.0f, // Top face
                0.0f, 0.5f, 0.0f, 1.0f, // Top face

                0.0f, 0.7f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.7f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.7f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.7f, 0.0f, 1.0f, // Bottom face


                0.0f, 0.8f, 0.0f, 1.0f, // Right face
                0.0f, 0.8f, 0.0f, 1.0f, // Right face
                0.0f, 0.8f, 0.0f, 1.0f, // Right face
                0.0f, 0.8f, 0.0f, 1.0f, // Right face

                0.0f, 0.9f, 0.0f, 1.0f,  // Left face
                0.0f, 0.9f, 0.0f, 1.0f,  // Left face
                0.0f, 0.9f, 0.0f, 1.0f,  // Left face
                0.0f, 0.9f, 0.0f, 1.0f  // Left face
            };


            var cubeVertexColorBuffer_green = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_green);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors_green), gl.STATIC_DRAW);
            #endregion

            #region colors_black
            var colors_black = new[]{
                0.0f, 0.0f, 0.0f, 1.0f, // Front face
                0.0f, 0.0f, 0.0f, 1.0f, // Front face
                0.0f, 0.0f, 0.0f, 1.0f, // Front face
                0.0f, 0.0f, 0.0f, 1.0f, // Front face
                0.0f, 0.0f, 0.0f, 1.0f, // Back face
                0.0f, 0.0f, 0.0f, 1.0f, // Back face
                0.0f, 0.0f, 0.0f, 1.0f, // Back face
                0.0f, 0.0f, 0.0f, 1.0f, // Back face
                0.0f, 0.0f, 0.0f, 1.0f, // Top face
                0.0f, 0.0f, 0.0f, 1.0f, // Top face
                0.0f, 0.0f, 0.0f, 1.0f, // Top face
                0.0f, 0.0f, 0.0f, 1.0f, // Top face
                0.0f, 0.0f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.0f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.0f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.0f, 0.0f, 1.0f, // Bottom face
                0.0f, 0.0f, 0.0f, 1.0f, // Right face
                0.0f, 0.0f, 0.0f, 1.0f, // Right face
                0.0f, 0.0f, 0.0f, 1.0f, // Right face
                0.0f, 0.0f, 0.0f, 1.0f, // Right face
                0.0f, 0.0f, 0.0f, 1.0f,  // Left face
                0.0f, 0.0f, 0.0f, 1.0f,  // Left face
                0.0f, 0.0f, 0.0f, 1.0f,  // Left face
                0.0f, 0.0f, 0.0f, 1.0f  // Left face
            };


            var cubeVertexColorBuffer_black = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_black);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors_black), gl.STATIC_DRAW);
            #endregion


            var cubeVertexColorBuffer_itemSize = 4;
            var cubeVertexColorBuffer_numItems = 24;

            var cubeVertexIndexBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
            var cubeVertexIndices = new UInt16[]{
                0, 1, 2,      0, 2, 3,    // Front face
                4, 5, 6,      4, 6, 7,    // Back face
                8, 9, 10,     8, 10, 11,  // Top face
                12, 13, 14,   12, 14, 15, // Bottom face
                16, 17, 18,   16, 18, 19, // Right face
                20, 21, 22,   20, 22, 23  // Left face
            };

            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
            var cubeVertexIndexBuffer_itemSize = 1;
            var cubeVertexIndexBuffer_numItems = 36;

            #endregion

            #endregion




            //gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
            gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
            gl.enable(gl.DEPTH_TEST);

            var IsWalking = false;
            var WalkMultiplier = 0.0f;


            var ego_x = 0f;
            var ego_y = 0f;
            var ego_z = 0f;
            var ego_za = 0f;

            var rCube = 0f;
            var raCube = 0f;

            var lastTime = 0L;
            Action animate = delegate
            {
                var timeNow = new IDate().getTime();
                if (lastTime != 0)
                {
                    var elapsed = timeNow - lastTime;

                    var u = ego_z + ego_za * (elapsed) / 1000.0f;


                    if (u < 0)
                        ego_z = (float)Math.Min(ego_z, 0);
                    else
                        ego_z = u;


                    ego_za -= 3.2f * (elapsed) / 1000.0f;


                    raCube += (75 * elapsed) / 1000.0f;
                }
                lastTime = timeNow;
            };

            Func<float, float> degToRad = (degrees) =>
            {
                return degrees * (f)Math.PI / 180f;
            };


            var c = 0;

            #region drawScene
            Action drawScene = delegate
            {
                if (ego_x < 0)
                    ego_x = 0;

                if (ego_y > 0)
                    ego_y = 0;

                gl.viewport(0, 0, gl_viewportWidth, gl_viewportHeight);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);


                glMatrix.mat4.perspective(45f, (float)gl_viewportWidth / (float)gl_viewportHeight, 0.1f, 100.0f, pMatrix);

                glMatrix.mat4.identity(mvMatrix);




                #region vertex
                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0);
                #endregion


                //__glMatrix.mat4.rotate(mvMatrix, degToRad(-33), new float[] { 0f, 1f, 0f });
                //__glMatrix.mat4.rotate(mvMatrix, rCube, new float[] { 1f, 0f, 0f });



                #region OriginalCubeAt
                Action<float, float, float> OriginalCubeAt =
                    (x, y, z) =>
                    {
                        mvMatrixScope(
                            delegate
                            {
                                glMatrix.mat4.translate(mvMatrix, new float[] { x, y, z });
                                glMatrix.mat4.rotate(mvMatrix, degToRad(raCube), new float[] { 1f, 1f, 1f });

                                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                                setMatrixUniforms();
                                gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0);
                            }
                        );
                    };
                #endregion

                mvMatrixScope(
                    delegate
                    {
                        glMatrix.mat4.translate(mvMatrix, new float[] {
                            - 1.5f,
                            0,
                             - 7f});
                        glMatrix.mat4.rotate(mvMatrix, degToRad(-80), new float[] { 1f, 0f, 0f });


                        #region grid

                        #region color
                        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_green);
                        gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                        #endregion



                        var GridZoom = 0.3f;

                        Action<float> WriteYLine =
                            x =>
                            {
                                for (int i = -12; i < -1; i++)
                                {
                                    OriginalCubeAt(x * GridZoom, (i) * GridZoom, 0);


                                }
                            };

                        for (int i = 1; i < 12; i++)
                            WriteYLine(i);


                        #region color
                        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
                        gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                        #endregion

                        for (int i = 1; i < 12; i++)
                            OriginalCubeAt(i * GridZoom, 0, 0);

                        for (int i = -12; i < 0; i++)
                            OriginalCubeAt(0, (i) * GridZoom, 0);


                        #endregion

                        #region color
                        gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
                        gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                        #endregion

                        {
                            var _y = (float)Math.Cos(raCube * 0.05f) * 0.1f;
                            var _x = (float)Math.Sin(raCube * 0.05f) * 0.1f;

                            OriginalCubeAt(_x, _y, 0);
                        }

                        {
                            var _y = (float)Math.Sin(rCube) * 0.2f;
                            var _x = (float)Math.Cos(rCube) * 0.2f;

                            OriginalCubeAt(_x, _y, 0);
                        }


                        mvMatrixScope(
                          delegate
                          {
                              // where are we
                              glMatrix.mat4.translate(mvMatrix, new float[] { ego_x, ego_y, ego_z });


                              // rotate all of it
                              //__glMatrix.mat4.rotate(mvMatrix, degToRad(-45), new float[] { 1f, 0f, 0f });

                              // which way are we looking at?
                              glMatrix.mat4.rotate(mvMatrix, rCube, new float[] { 0f, 0f, 1f });


                              #region cube
                              Action<float, float, float> cube =
                                  (x, y, z) =>
                                  {
                                      mvPushMatrix();
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * x,
                                        2 * cubesize * y,
                                        2 * cubesize  * z});

                                      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                                      setMatrixUniforms();
                                      gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0);
                                      mvPopMatrix();
                                  };
                              #endregion cube

                              #region draw

                              Action<int, int, int> rect =
                                  (ix, iy, z) =>
                                  {
                                      for (int y = 0; y < ix; y++)
                                      {
                                          for (int x = 0; x < iy; x++)
                                          {
                                              cube(x, y, z);
                                          }
                                      }
                                  };
                              #endregion draw

                              #region leg
                              Action<int, float, float> leg =
                                  (y, hiprotation, kneerotation) =>
                                  {
                                      mvPushMatrix();

                                      #region hiprotation
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 2,
                                        2 * cubesize * 0,
                                        2 * cubesize * 11});

                                      glMatrix.mat4.rotate(mvMatrix, degToRad(hiprotation), new float[] { 0f, 1f, 0f });
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * -2,
                                        2 * cubesize * 0,
                                        2 * cubesize * -11});
                                      #endregion



                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 1,
                                        2 * cubesize * y,
                                        2 * cubesize  * 0});


                                      mvPushMatrix();

                                      #region kneerotation
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 1,
                                        2 * cubesize * 0,
                                        2 * cubesize * 6f});

                                      glMatrix.mat4.rotate(mvMatrix, degToRad(kneerotation), new float[] { 0f, 1f, 0f });
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * -1,
                                        2 * cubesize * 0,
                                        2 * cubesize * -6f});
                                      #endregion

                                      #region color
                                      gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
                                      gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                      #endregion


                                      #region lower leg
                                      rect(3, 5, 0);
                                      rect(3, 5, 1);
                                      rect(3, 5, 2);
                                      rect(3, 3, 3);
                                      #endregion



                                      #region color
                                      gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
                                      gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                      #endregion

                                      rect(3, 3, 4);
                                      rect(3, 3, 5);
                                      rect(3, 3, 6);

                                      mvPopMatrix();


                                      #region upper leg
                                      mvPushMatrix();
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 1,
                                        2 * cubesize * 0,
                                        2 * cubesize  * 0});

                                      rect(3, 3, 7);
                                      rect(3, 3, 8);
                                      rect(3, 3, 9);


                                      mvPopMatrix();
                                      #endregion

                                      #region hips
                                      rect(3, 4, 10);
                                      //rect(3, 4, 11);
                                      #endregion

                                      mvPopMatrix();



                                  };
                              #endregion

                              var seed = (raCube * WalkMultiplier * 16);

                              #region animated_leg
                              Action<int, int> animated_leg = (seed_offset, x) =>
                              {
                                  var seed_180 = (float)((seed + seed_offset) % 180f);

                                  var left_hip = 30f;
                                  var left_knee = 0f;


                                  if (ego_z < 0)
                                  {
                                      // crouch
                                      left_hip = -66;
                                      left_knee = left_hip * -2;
                                  }
                                  else if (ego_z > 0)
                                  {
                                      // crouch
                                      left_hip = 10;
                                      left_knee = 10;
                                  }
                                  else if (!IsWalking)
                                  {
                                      left_hip = 0;
                                      left_knee = 0;
                                  }
                                  else
                                  {
                                      left_hip = seed_180;

                                      if (left_hip > 90)
                                      {
                                          left_hip = 180 - left_hip;
                                          // -60 should be 0 -  front
                                          // 0 should be 60
                                          // 30 should be 0 - back


                                          var v = (90 - left_hip) - 70;



                                          if (v < 0)
                                              left_knee = 70 + v;
                                          else if (v == 0)
                                              left_knee = 70;
                                          else if (v > 0)
                                              left_knee = (20 - v) * (70 / 20);



                                          //page.Data1.innerText = "" + new { left_hip, v, left_knee };
                                      }
                                      else
                                      {
                                      }

                                      left_hip -= 45;
                                  }

                                  leg(x, left_hip, left_knee);
                              };
                              #endregion

                              animated_leg(0, -2);
                              animated_leg(90, 3);





                              #region body
                              mvMatrixScope(
                                  delegate
                                  {
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 1,
                                        2 * cubesize * -2,
                                        2 * cubesize  * 11});

                                      rect(8, 4, 0);
                                      rect(8, 4, 1);
                                      rect(8, 4, 2);
                                      rect(8, 4, 3);
                                      rect(8, 4, 4);
                                      rect(8, 4, 5);
                                      rect(8, 4, 6);
                                      rect(8, 4, 7);
                                      rect(8, 4, 8);

                                      mvMatrixScope(
                                         delegate
                                         {
                                             glMatrix.mat4.translate(mvMatrix, new float[] {
                                                2 * cubesize * 0,
                                                2 * cubesize * -2,
                                                2 * cubesize  * 7});

                                             rect(2, 10, 0);
                                             rect(2, 10, 1);
                                         }
                                     );


                                      mvMatrixScope(
                                          delegate
                                          {
                                              #region color
                                              gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
                                              gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                              #endregion

                                              glMatrix.mat4.translate(mvMatrix, new float[] {
                                                    2 * cubesize * 10,
                                                    2 * cubesize * -2,
                                                    2 * cubesize  * 7});

                                              rect(2, 2, 0);
                                              rect(2, 2, 1);

                                              #region color
                                              gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
                                              gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                              #endregion
                                          }
                                      );

                                      mvMatrixScope(
                                          delegate
                                          {
                                              #region color
                                              gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
                                              gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                              #endregion

                                              glMatrix.mat4.translate(mvMatrix, new float[] {
                                                    2 * cubesize * 10,
                                                    2 * cubesize * 8,
                                                    2 * cubesize  * 7});

                                              rect(2, 2, 0);
                                              rect(2, 2, 1);

                                              #region color
                                              gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
                                              gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                              #endregion
                                          }
                                      );

                                      mvMatrixScope(
                                      delegate
                                      {

                                          glMatrix.mat4.translate(mvMatrix, new float[] {
                                                2 * cubesize * 0,
                                                2 * cubesize * 8,
                                                2 * cubesize  * 7});

                                          rect(2, 10, 0);
                                          rect(2, 10, 1);
                                      }
                                    );



                                  }
                              );
                              #endregion

                              #region head


                              mvMatrixScope(
                                  delegate
                                  {
                                      glMatrix.mat4.translate(mvMatrix, new float[] {
                                        2 * cubesize * 0,
                                        2 * cubesize * -1,
                                        2 * cubesize  * 20});

                                      #region color
                                      gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_black);
                                      gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                      #endregion


                                      cube(5, 4, 2);
                                      cube(5, 1, 2);

                                      cube(3, 0, 0);
                                      cube(3, 0, 1);
                                      cube(3, 0, 2);
                                      cube(3, 5, 0);
                                      cube(3, 5, 1);
                                      cube(3, 5, 2);

                                      #region color
                                      gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer_orange);
                                      gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                      #endregion




                                      rect(6, 3, 0);
                                      rect(6, 3, 1);

                                      cube(4, 0, 2);
                                      cube(5, 0, 2);
                                      cube(5, 2, 2);
                                      cube(5, 3, 2);
                                      cube(5, 5, 2);
                                      cube(4, 5, 2);

                                      cube(4, 0, 1);
                                      cube(5, 0, 1);
                                      cube(5, 1, 1);
                                      cube(5, 2, 1);
                                      cube(5, 3, 1);
                                      cube(5, 4, 1);
                                      cube(5, 5, 1);
                                      cube(4, 5, 1);

                                      cube(4, 0, 0);
                                      cube(5, 0, 0);
                                      cube(5, 1, 0);
                                      cube(5, 2, 0);
                                      cube(5, 3, 0);
                                      cube(5, 4, 0);
                                      cube(5, 5, 0);
                                      cube(4, 5, 0);

                                      //rect(6, 2, 2);

                                      #region color
                                      gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer2);
                                      gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);
                                      #endregion


                                      // 3 or 3?? :)
                                      rect(6, 3, 2);

                                      rect(6, 6, 3);
                                      rect(6, 6, 4);
                                      rect(6, 6, 5);


                                  }
                              );
                              #endregion



                          }
                      );
                    }
                );

            };
            drawScene();
            #endregion







            Native.window.onframe += delegate
            {
                c++;


                Native.document.title = "" + c + " " + (rCube) + " " + ego_z + " " + ego_za;

                drawScene();
                animate();

            };



            #region onkeyup
            Native.document.onkeyup +=
                (e) =>
                {
                    //Native.Document.title = "" + new { e.KeyCode };


                    if (e.KeyCode == 17)
                    {
                        ego_z = 0;
                    }

                    if (e.KeyCode == 32)
                    {
                        ego_z = 0;
                        ego_za = 2;
                    }

                    if (e.KeyCode == 38)
                    {
                        IsWalking = false;
                    }



                    if (e.KeyCode == 40)
                    {
                        IsWalking = false;
                    }
                };
            #endregion

            #region onkeydown
            Native.document.onkeydown +=
                (e) =>
                {
                    // see also: http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes

                    e.preventDefault();

                    #region turnspeed
                    var turnspeed = 0.05f;

                    if (e.KeyCode == 37)
                    {
                        // left
                        rCube += turnspeed;
                    }

                    if (e.KeyCode == 65)
                    {
                        // left
                        rCube += turnspeed;
                    }


                    if (e.KeyCode == 39)
                    {
                        rCube -= turnspeed;

                        // right
                    }

                    if (e.KeyCode == 68)
                    {
                        rCube -= turnspeed;

                        // right
                    }
                    #endregion

                    if (e.KeyCode == 17)
                    {
                        ego_z = -cubesize * 6;
                    }

                    if (e.KeyCode == 32)
                    {
                        ego_z = -cubesize * 6;
                    }

                    if (ego_z > 0)
                    {
                        // not on ground. cant walk :)
                    }
                    else
                    {
                        if (e.KeyCode == 38)
                        {
                            IsWalking = true;

                            // mat aint working ..


                            if (!e.shiftKey)
                            {
                                WalkMultiplier = 0.04f;
                            }
                            else
                            {
                                WalkMultiplier = 0.02f;



                            }

                            ego_y += (float)Math.Sin(rCube) * WalkMultiplier;
                            ego_x += (float)Math.Cos(rCube) * WalkMultiplier;
                        }



                        if (e.KeyCode == 40)
                        {
                            IsWalking = true;
                            WalkMultiplier = 0.02f;

                            ego_y -= (float)Math.Sin(rCube) * WalkMultiplier;
                            ego_x -= (float)Math.Cos(rCube) * WalkMultiplier;

                        }

                    }
                };
            #endregion

            //#region requestFullscreen
            //Native.document.body.ondblclick +=
            //    delegate
            //    {
            //        if (IsDisposed)
            //            return;

            //        // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/

            //        Native.document.body.requestFullscreen();


            //    };
            //#endregion



            //new IHTMLAnchor { "drag me to my.jsc-solutions.net" }.AttachToDocument().With(
            //    dragme =>
            //    {
            //        dragme.style.position = [email protected];
            //        dragme.style.left = "1em";
            //        dragme.style.bottom = "1em";
            //        dragme.style.color = "yellow";

            //        dragme.AllowToDragAsApplicationPackage();
            //    }
            //);
        }
        /// <summary>
        /// This is a javascript application.
        /// </summary>
        /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param>
        public Application(IDefault page = null)
        {
            var size = 600;
            var gl = new WebGLRenderingContext();

            var canvas = gl.canvas.AttachToDocument();

            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;
            canvas.style.SetLocation(0, 0, size, size);

            canvas.width = size;
            canvas.height = size;


            var gl_viewportWidth = size;
            var gl_viewportHeight = size;


            // can AssetLibrary create a special type
            // and define the variables
            // for it we need to parse glsl?

            // Geometry
            var shaderProgram = gl.createProgram(
                new GeometryVertexShader(),
                new GeometryFragmentShader()
           );



            gl.linkProgram(shaderProgram);
            gl.useProgram(shaderProgram);

            var shaderProgram_vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");

            gl.enableVertexAttribArray((uint)shaderProgram_vertexPositionAttribute);

            // new in lesson 02
            var shaderProgram_vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
            gl.enableVertexAttribArray((uint)shaderProgram_vertexColorAttribute);

            var shaderProgram_pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
            var shaderProgram_mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");

            // https://hacks.mozilla.org/2014/10/introducing-simd-js/
            // https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat4.js
            // http://www.i-programmer.info/news/167-javascript/8578-chrome-to-support-simdjs.html

            // https://code.google.com/p/v8/issues/detail?id=2228
            var SIMD_mat4 = new System.Numerics.Matrix4x4();
            var SIMD_mat4s = new  Stack<System.Numerics.Matrix4x4>();
            

            // can we convert this code to NDK friendly non GC library?
            // for gearVR 90FOV and cardboard wearality 150FOV
            #region __mat4
            var __mat4 = new
            {
                // X:\jsc.svn\examples\javascript\Test\TestFloatArray\TestFloatArray\Application.cs
                // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150706/20150708

                // generic in the sens of caller choosing is the return type a new struct or out ref?
                perspective = new Func<float[], float, float, float, float, float[]>(
                    (that, fovy, aspect, near, far) =>
                    {
                        var f = 1.0f / (float)Math.Tan(fovy / 2f);
                        var nf = 1f / (near - far);

                        that[0] = f / aspect;
                        that[1] = 0;
                        that[2] = 0;
                        that[3] = 0;
                        that[4] = 0;
                        that[5] = f;
                        that[6] = 0;
                        that[7] = 0;
                        that[8] = 0;
                        that[9] = 0;
                        that[10] = (far + near) * nf;
                        that[11] = -1;
                        that[12] = 0;
                        that[13] = 0;
                        that[14] = (2 * far * near) * nf;
                        that[15] = 0;

                        return that;
                    }),

                // reset content of mat4
                identity = new Func<float[], float[]>(
                    that =>
                    {
                        //Array.Copy()

                        //var xx =&that;
                        var x = new float[]
                        {
                            1, 0, 0, 0,
                            0, 1, 0, 0,
                            0, 0, 1, 0,
                            0, 0, 0, 1,
                        };

                        //is this the best way to update array contents?
                        x.CopyTo(that, 0);

                        return x;
                    }
                ),

                create = new Func<float[]>(
                    () =>
                    //new mat4()
                    new float[]
                    {
                        1, 0, 0, 0,
                        0, 1, 0, 0,
                        0, 0, 1, 0,
                        0, 0, 0, 1,
                    }
                ),

                #region not used?
                clone = new Func<float[], float[]>(
                    smat4 =>
                    //new mat4()
                    new float[]
                    {
                        smat4[0], smat4[1], smat4[2], smat4[3],
                        smat4[4], smat4[5], smat4[6], smat4[7],
                        smat4[8], smat4[9], smat4[10], smat4[11],
                        smat4[12], smat4[13], smat4[14], smat4[15],
                    }
                )
                #endregion

                ,
                // X:\jsc.svn\examples\java\android\vr\OVRWindWheelNDK\OVRWindWheelNDK\References\VrApi.ovrMatrix4f.cs
                translate = new Func<float[], float[], float[], float[]>(
                    (float[] that, float[] output, float[]  xyz) =>
                    {
                        float x = xyz[0], y = xyz[1], z = xyz[2];

                        if (output == that)
                        {
                            that[12] = output[0] * x + output[4] * y + output[8] * z + output[12];
                            that[13] = output[1] * x + output[5] * y + output[9] * z + output[13];
                            that[14] = output[2] * x + output[6] * y + output[10] * z + output[14];
                            that[15] = output[3] * x + output[7] * y + output[11] * z + output[15];

                            return that;
                        }

                        float a00, a01, a02, a03,
                            a10, a11, a12, a13,
                            a20, a21, a22, a23;


                        a00 = output[0]; a01 = output[1]; a02 = output[2]; a03 = output[3];
                        a10 = output[4]; a11 = output[5]; a12 = output[6]; a13 = output[7];
                        a20 = output[8]; a21 = output[9]; a22 = output[10]; a23 = output[11];

                        that[0] = a00; that[1] = a01; that[2] = a02; that[3] = a03;
                        that[4] = a10; that[5] = a11; that[6] = a12; that[7] = a13;
                        that[8] = a20; that[9] = a21; that[10] = a22; that[11] = a23;

                        that[12] = a00 * x + a10 * y + a20 * z + output[12];
                        that[13] = a01 * x + a11 * y + a21 * z + output[13];
                        that[14] = a02 * x + a12 * y + a22 * z + output[14];
                        that[15] = a03 * x + a13 * y + a23 * z + output[15];


                        return that;
                    }
                ),

                rotate = new Func<float[], float[], float, float[], float[]>(
                    (that, a, rad, axis) =>
                    {
                        float x = axis[0], y = axis[1], z = axis[2];
                        float len = (float)Math.Sqrt(x * x + y * y + z * z),
                        s, c, t,
                        a00, a01, a02, a03,
                        a10, a11, a12, a13,
                        a20, a21, a22, a23,
                        b00, b01, b02,
                        b10, b11, b12,
                        b20, b21, b22;


                        if (Math.Abs(len) < float.Epsilon)
                            return that;

                        len = 1f / len;
                        x *= len;
                        y *= len;
                        z *= len;

                        s = (float)Math.Sin(rad);
                        c = (float)Math.Cos(rad);
                        t = 1 - c;

                        a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
                        a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
                        a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];

                        // Construct the elements of the rotation matrix
                        b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
                        b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
                        b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;

                        // Perform rotation-specific matrix multiplication
                        that[0] = a00 * b00 + a10 * b01 + a20 * b02;
                        that[1] = a01 * b00 + a11 * b01 + a21 * b02;
                        that[2] = a02 * b00 + a12 * b01 + a22 * b02;
                        that[3] = a03 * b00 + a13 * b01 + a23 * b02;
                        that[4] = a00 * b10 + a10 * b11 + a20 * b12;
                        that[5] = a01 * b10 + a11 * b11 + a21 * b12;
                        that[6] = a02 * b10 + a12 * b11 + a22 * b12;
                        that[7] = a03 * b10 + a13 * b11 + a23 * b12;
                        that[8] = a00 * b20 + a10 * b21 + a20 * b22;
                        that[9] = a01 * b20 + a11 * b21 + a21 * b22;
                        that[10] = a02 * b20 + a12 * b21 + a22 * b22;
                        that[11] = a03 * b20 + a13 * b21 + a23 * b22;

                        if (a != that)
                        { // If the source and destination differ, copy the unchanged last row
                            that[12] = a[12];
                            that[13] = a[13];
                            that[14] = a[14];
                            that[15] = a[15];
                        }


                        return that;
                    }
                )
            };
            #endregion



            // set to identity
            var mvMatrix = __mat4.create();
            var mvMatrixStack = new Stack<float[]>();

            // set to perspective
            var pMatrix = __mat4.create();

            #region new in lesson 03
            // how would this translate to non GC, NDK?
            Action mvPushMatrix = delegate
            {
                var copy = __mat4.create();

                mvMatrix.CopyTo(copy, 0);

                //glMatrix.mat4.set(mvMatrix, copy);
                mvMatrixStack.Push(copy);
            };

            Action mvPopMatrix = delegate
            {
                mvMatrix = mvMatrixStack.Pop();
            };
            #endregion


            #region setMatrixUniforms
            Action setMatrixUniforms =
                delegate
                {
                    gl.uniformMatrix4fv(shaderProgram_pMatrixUniform, false, pMatrix);
                    gl.uniformMatrix4fv(shaderProgram_mvMatrixUniform, false, mvMatrix);
                };
            #endregion




            #region init buffers


            #region cube
            var cubeVertexPositionBuffer = new WebGLBuffer(gl);
            gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);

            var cubesize = 1.0f * 0.05f;
            var vertices = new[]{
                // Front face
                -cubesize, -cubesize,  cubesize,
                 cubesize, -cubesize,  cubesize,
                 cubesize,  cubesize,  cubesize,
                -cubesize,  cubesize,  cubesize,

                // Back face
                -cubesize, -cubesize, -cubesize,
                -cubesize,  cubesize, -cubesize,
                 cubesize,  cubesize, -cubesize,
                 cubesize, -cubesize, -cubesize,

                // Top face
                -cubesize,  cubesize, -cubesize,
                -cubesize,  cubesize,  cubesize,
                 cubesize,  cubesize,  cubesize,
                 cubesize,  cubesize, -cubesize,

                // Bottom face
                -cubesize, -cubesize, -cubesize,
                 cubesize, -cubesize, -cubesize,
                 cubesize, -cubesize,  cubesize,
                -cubesize, -cubesize,  cubesize,

                // Right face
                cubesize, -cubesize, -cubesize,
                 cubesize,  cubesize, -cubesize,
                 cubesize,  cubesize,  cubesize,
                 cubesize, -cubesize,  cubesize,

                // Left face
                -cubesize, -cubesize, -cubesize,
                -cubesize, -cubesize,  cubesize,
                -cubesize,  cubesize,  cubesize,
                -cubesize,  cubesize, -cubesize
            };


            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

            var cubeVertexPositionBuffer_itemSize = 3;
            var cubeVertexPositionBuffer_numItems = 6 * 6;

            var squareVertexColorBuffer = new WebGLBuffer(gl);
            gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);

            // 216, 191, 18
            var colors = new[]{
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face
                1.0f, 0.6f, 0.0f, 1.0f, // Front face

                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face
                0.8f, 0.4f, 0.0f, 1.0f, // Back face

                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face
                0.9f, 0.5f, 0.0f, 1.0f, // Top face

                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face
                1.0f, 0.5f, 0.0f, 1.0f, // Bottom face


                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face
                1.0f, 0.8f, 0.0f, 1.0f, // Right face

                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f,  // Left face
                1.0f, 0.8f, 0.0f, 1.0f  // Left face
            };



            gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
            var cubeVertexColorBuffer_itemSize = 4;
            var cubeVertexColorBuffer_numItems = 24;

            // ELEMENT_ARRAY_BUFFER : WebGLBuffer?
            // drawElements
            var cubeVertexIndexBuffer = new WebGLBuffer(gl);
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
            //var cubeVertexIndices = new UInt16[]{
            var cubeVertexIndices = new byte[]{
                0, 1, 2,      0, 2, 3,    // Front face
                4, 5, 6,      4, 6, 7,    // Back face
                8, 9, 10,     8, 10, 11,  // Top face
                12, 13, 14,   12, 14, 15, // Bottom face
                16, 17, 18,   16, 18, 19, // Right face
                20, 21, 22,   20, 22, 23  // Left face
            };

            // ushort[]?
            //gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndices, gl.STATIC_DRAW);
            var cubeVertexIndexBuffer_itemSize = 1;
            var cubeVertexIndexBuffer_numItems = 36;

            #endregion

            #endregion




            gl.clearColor(0.0f, 0.0f, 0.0f, alpha: 1.0f);
            gl.enable(gl.DEPTH_TEST);


            var rWindDelta = 0.0f;
            var rCubeDelta = 1.0f;

            if (page != null)
            {

                #region WindLeft
                page.WindLeft.onmousedown +=
                    delegate
                    {
                        rWindDelta = -2.0f;
                    };
                page.WindLeft.onmouseup +=
                 delegate
                 {
                     rWindDelta = 0.0f;
                 };
                #endregion

                #region WindRight
                page.WindRight.onmousedown +=
                    delegate
                    {
                        rWindDelta = 2.0f;
                    };
                page.WindRight.onmouseup +=
                 delegate
                 {
                     rWindDelta = 0.0f;
                 };
                #endregion


                #region SpeedSlow
                page.SpeedSlow.onmousedown +=
                    delegate
                    {
                        rCubeDelta = 0.1f;
                    };
                page.SpeedSlow.onmouseup +=
                 delegate
                 {
                     rCubeDelta = 1.0f;
                 };
                #endregion

                #region SpeedFast
                page.SpeedFast.onmousedown +=
                  delegate
                  {
                      rCubeDelta = 4.0f;
                  };
                page.SpeedFast.onmouseup +=
                 delegate
                 {
                     rCubeDelta = 1.0f;
                 };
                #endregion
            }


            #region animate
            var rCube = 0f;
            var rWind = 0f;

            var lastTime = 0L;
            Action animate = delegate
            {
                var timeNow = new IDate().getTime();
                if (lastTime != 0)
                {
                    var elapsed = timeNow - lastTime;

                    rCube -= ((75 * elapsed) / 1000.0f) * rCubeDelta;
                    rWind -= ((75 * elapsed) / 1000.0f) * rWindDelta;
                }
                lastTime = timeNow;
            };
            #endregion

            #region degToRad
            Func<float, float> degToRad = (degrees) =>
            {
                return degrees * (f)Math.PI / 180f;
            };
            #endregion


            #region drawScene
            Action drawScene = delegate
            {
                gl.viewport(0, 0, gl_viewportWidth, gl_viewportHeight);
                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

                // glMatrix.mat4.perspective(
                //     45f,
                //     (float)gl_viewportWidth / (float)gl_viewportHeight,
                //     0.1f,
                //     100.0f,
                //     pMatrix
                //);

                __mat4.perspective(
                    pMatrix,

                    45f,
                    (float)gl_viewportWidth / (float)gl_viewportHeight,
                    0.1f,
                    100.0f
                    );

                __mat4.identity(mvMatrix);
                //glMatrix.mat4.identity(mvMatrix);

                __mat4.translate(mvMatrix, mvMatrix, new float[] { -1.5f, 0.0f, -7.0f });
                //glMatrix.mat4.translate(mvMatrix, new float[] { -1.5f, 0.0f, -7.0f });

                mvPushMatrix();
                //glMatrix.mat4.rotate(mvMatrix, degToRad(rWind), new float[] { 0f, 1f, 0f });
                __mat4.rotate(mvMatrix, mvMatrix, degToRad(rWind), new float[] { 0, 1f, 0f });


                #region DrawFrameworkWingAtX
                Action<float, float> DrawFrameworkWingAtX =
            (WingX, WingY) =>
            {
                #region draw center cube
                mvPushMatrix();

                __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, cubesize * WingY, 0 });
                //glMatrix.mat4.translate(mvMatrix, new float[] { cubesize * WingX, cubesize * WingY, 0 });

                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                setMatrixUniforms();
                //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0);
                gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0);

                mvPopMatrix();
                #endregion
            };
                #endregion

                #region DrawWingAtX
                Action<int, int, float, float> DrawWingAtX =
            (WingX, WingSize, WingRotationMultiplier, WingRotationOffset) =>
            {
                mvPushMatrix();

                __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, 0, 0 });
                //glMatrix.mat4.translate(mvMatrix, new float[] { cubesize * WingX, 0, 0 });

                if (WingRotationOffset == 0)
                {
                    DrawFrameworkWingAtX(0, 0);
                }

                #region DrawWingPart
                Action<float> DrawWingPart =
            PartIndex =>
            {
                mvPushMatrix();
                //glMatrix.mat4.rotate(mvMatrix, degToRad(WingRotationOffset + (rCube * WingRotationMultiplier)), new float[] { 1f, 0f, 0f });
                __mat4.rotate(mvMatrix, mvMatrix, degToRad(WingRotationOffset + (rCube * WingRotationMultiplier)), new float[] { 1f, 0f, 0f });
                //glMatrix.mat4.translate(mvMatrix, new float[] { 0f, cubesize * PartIndex * 2, 0 });
                __mat4.translate(mvMatrix, mvMatrix, new float[] { 0f, cubesize * PartIndex * 2, 0 });

                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                setMatrixUniforms();
                //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0);
                gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0);

                mvPopMatrix();
            };
                #endregion

                #region DrawWingWithSize
                Action<int> DrawWingWithSize =
            length =>
            {
                for (int i = 4; i < length; i++)
                {
                    DrawWingPart(i * 1.0f);
                    DrawWingPart(-i * 1.0f);

                }
            };
                #endregion

                DrawWingWithSize(WingSize);

                mvPopMatrix();

            };
                #endregion

                var x = 8;

                DrawFrameworkWingAtX(x - 8, 0);

                for (int i = 0; i < 24; i++)
                {
                    DrawFrameworkWingAtX(x - 8, -2.0f * i);

                }

                DrawWingAtX(x - 6, 0, 1f, 0);
                DrawWingAtX(x - 4, 0, 1f, 0);
                DrawWingAtX(x - 2, 0, 1f, 0);

                DrawWingAtX(x + 0, 16, 1f, 0);
                DrawWingAtX(x + 0, 16, 1f, 30);
                DrawWingAtX(x + 0, 16, 1f, 60);
                DrawWingAtX(x + 0, 16, 1f, 90);
                DrawWingAtX(x + 0, 16, 1f, 120);
                DrawWingAtX(x + 0, 16, 1f, 150);

                DrawWingAtX(x + 2, 0, 1f, 0);
                DrawWingAtX(x + 4, 0, 1f, 0);
                DrawWingAtX(x + 6, 0, 1f, 0);

                DrawWingAtX(x + 8, 12, 0.4f, 0);
                DrawWingAtX(x + 8, 12, 0.4f, 60);
                DrawWingAtX(x + 8, 12, 0.4f, 120);


                DrawWingAtX(x + 8 + 2, 0, 1f, 0);
                DrawWingAtX(x + 8 + 4, 0, 1f, 0);
                DrawWingAtX(x + 8 + 6, 0, 1f, 0);

                DrawWingAtX(x + 16, 8, 0.3f, 0);
                DrawWingAtX(x + 16, 8, 0.3f, 90);




                mvPopMatrix();


                #region draw cube on the right to remind where we started
                //glMatrix.mat4.translate(mvMatrix, new float[] { 3.0f, 2.0f, 0.0f });
                __mat4.translate(mvMatrix, mvMatrix, new float[] { 3.0f, 2.0f, 0.0f });

                mvPushMatrix();
                //glMatrix.mat4.rotate(mvMatrix, degToRad(rCube), new float[] { 1f, 1f, 1f });
                __mat4.rotate(mvMatrix, mvMatrix, degToRad(rCube), new float[] { 1f, 1f, 1f });



                gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
                gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0);

                gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
                setMatrixUniforms();
                //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0);
                gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0);

                mvPopMatrix();
                #endregion

            };
            drawScene();
            #endregion



            #region AtResize
            Action AtResize =
                delegate
                {
                    gl_viewportWidth = Native.window.Width;
                    gl_viewportHeight = Native.window.Height;

                    canvas.style.SetLocation(0, 0, gl_viewportWidth, gl_viewportHeight);

                    canvas.width = gl_viewportWidth;
                    canvas.height = gl_viewportHeight;
                };

            Native.window.onresize +=
                            e =>
                            {
                                AtResize();
                            };
            AtResize();
            #endregion

            #region IsDisposed
            var IsDisposed = false;

            this.Dispose = delegate
            {
                if (IsDisposed)
                    return;

                IsDisposed = true;

                canvas.Orphanize();
            };
            #endregion

            #region requestFullscreen
            Native.document.body.ondblclick +=
                delegate
                {
                    if (IsDisposed)
                        return;

                    // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/

                    Native.document.body.requestFullscreen();


                };
            #endregion




            //var c = 0;

            #region tick

            Native.window.onframe += e =>
                        {
                            if (IsDisposed)
                                return;

                            //c++;

                            // frameID
                            Native.document.title = "" + e.counter;

                            drawScene();
                            animate();

                        };

            #endregion

            if (page != null)
                page.Mission.Orphanize().AttachToDocument().style.SetLocation(left: size - 56, top: 16);
        }
Example #3
0
        // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150720

        // "X:\jsc.svn\examples\java\android\vr\OVRWindWheelNDK\UDPWindWheel.sln"
        static void drawElements(Action<float[]> uniformMatrix4fv)
        {
            //Matrix4x4
            // 15680 udp

            var rWind = sw.ElapsedMilliseconds * 0.01f;
            var rCube = sw.ElapsedMilliseconds * 0.09f;



            #region __mat4
            var __mat4 = new
            {
                // X:\jsc.svn\examples\javascript\Test\TestFloatArray\TestFloatArray\Application.cs
                // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150706/20150708

                // generic in the sens of caller choosing is the return type a new struct or out ref?
                perspective = new Func<float[], float, float, float, float, float[]>(
                    (that, fovy, aspect, near, far) =>
                    {
                        var f = 1.0f / (float)Math.Tan(fovy / 2f);
                        var nf = 1f / (near - far);

                        that[0] = f / aspect;
                        that[1] = 0;
                        that[2] = 0;
                        that[3] = 0;
                        that[4] = 0;
                        that[5] = f;
                        that[6] = 0;
                        that[7] = 0;
                        that[8] = 0;
                        that[9] = 0;
                        that[10] = (far + near) * nf;
                        that[11] = -1;
                        that[12] = 0;
                        that[13] = 0;
                        that[14] = (2 * far * near) * nf;
                        that[15] = 0;

                        return that;
                    }),

                // reset content of mat4
                identity = new Func<float[], float[]>(
                    that =>
                    {
                        //Array.Copy()

                        //var xx =&that;
                        var xx = new float[]
                        {
                            1, 0, 0, 0,
                            0, 1, 0, 0,
                            0, 0, 1, 0,
                            0, 0, 0, 1,
                        };

                        //is this the best way to update array contents?
                        xx.CopyTo(that, 0);

                        return xx;
                    }
                ),

                create = new Func<float[]>(
                    () =>
                    //new mat4()
                    new float[]
                    {
                        1, 0, 0, 0,
                        0, 1, 0, 0,
                        0, 0, 1, 0,
                        0, 0, 0, 1,
                    }
                ),

                #region not used?
                clone = new Func<float[], float[]>(
                    smat4 =>
                    //new mat4()
                    new float[]
                    {
                        smat4[0], smat4[1], smat4[2], smat4[3],
                        smat4[4], smat4[5], smat4[6], smat4[7],
                        smat4[8], smat4[9], smat4[10], smat4[11],
                        smat4[12], smat4[13], smat4[14], smat4[15],
                    }
                )
                #endregion

                ,
                // X:\jsc.svn\examples\java\android\vr\OVRWindWheelNDK\OVRWindWheelNDK\References\VrApi.ovrMatrix4f.cs
                translate = new Func<float[], float[], float[], float[]>(
                    (float[] that, float[] output, float[] xyz) =>
                    {
                        float xx = xyz[0], y = xyz[1], z = xyz[2];

                        if (output == that)
                        {
                            that[12] = output[0] * xx + output[4] * y + output[8] * z + output[12];
                            that[13] = output[1] * xx + output[5] * y + output[9] * z + output[13];
                            that[14] = output[2] * xx + output[6] * y + output[10] * z + output[14];
                            that[15] = output[3] * xx + output[7] * y + output[11] * z + output[15];

                            return that;
                        }

                        float a00, a01, a02, a03,
                            a10, a11, a12, a13,
                            a20, a21, a22, a23;


                        a00 = output[0]; a01 = output[1]; a02 = output[2]; a03 = output[3];
                        a10 = output[4]; a11 = output[5]; a12 = output[6]; a13 = output[7];
                        a20 = output[8]; a21 = output[9]; a22 = output[10]; a23 = output[11];

                        that[0] = a00; that[1] = a01; that[2] = a02; that[3] = a03;
                        that[4] = a10; that[5] = a11; that[6] = a12; that[7] = a13;
                        that[8] = a20; that[9] = a21; that[10] = a22; that[11] = a23;

                        that[12] = a00 * xx + a10 * y + a20 * z + output[12];
                        that[13] = a01 * xx + a11 * y + a21 * z + output[13];
                        that[14] = a02 * xx + a12 * y + a22 * z + output[14];
                        that[15] = a03 * xx + a13 * y + a23 * z + output[15];


                        return that;
                    }
                ),

                rotate = new Func<float[], float[], float, float[], float[]>(
                    (that, a, rad, axis) =>
                    {
                        float x = axis[0], y = axis[1], z = axis[2];
                        float len = (float)Math.Sqrt(x * x + y * y + z * z),
                        s, c, t,
                        a00, a01, a02, a03,
                        a10, a11, a12, a13,
                        a20, a21, a22, a23,
                        b00, b01, b02,
                        b10, b11, b12,
                        b20, b21, b22;


                        if (Math.Abs(len) < float.Epsilon)
                            return that;

                        len = 1f / len;
                        x *= len;
                        y *= len;
                        z *= len;

                        s = (float)Math.Sin(rad);
                        c = (float)Math.Cos(rad);
                        t = 1 - c;

                        a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
                        a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
                        a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];

                        // Construct the elements of the rotation matrix
                        b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
                        b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
                        b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;

                        // Perform rotation-specific matrix multiplication
                        that[0] = a00 * b00 + a10 * b01 + a20 * b02;
                        that[1] = a01 * b00 + a11 * b01 + a21 * b02;
                        that[2] = a02 * b00 + a12 * b01 + a22 * b02;
                        that[3] = a03 * b00 + a13 * b01 + a23 * b02;
                        that[4] = a00 * b10 + a10 * b11 + a20 * b12;
                        that[5] = a01 * b10 + a11 * b11 + a21 * b12;
                        that[6] = a02 * b10 + a12 * b11 + a22 * b12;
                        that[7] = a03 * b10 + a13 * b11 + a23 * b12;
                        that[8] = a00 * b20 + a10 * b21 + a20 * b22;
                        that[9] = a01 * b20 + a11 * b21 + a21 * b22;
                        that[10] = a02 * b20 + a12 * b21 + a22 * b22;
                        that[11] = a03 * b20 + a13 * b21 + a23 * b22;

                        if (a != that)
                        { // If the source and destination differ, copy the unchanged last row
                            that[12] = a[12];
                            that[13] = a[13];
                            that[14] = a[14];
                            that[15] = a[15];
                        }


                        return that;
                    }
                )
            };
            #endregion

            var mvMatrix = __mat4.create();
            var mvMatrixStack = new Stack<float[]>();

            // set to perspective
            var pMatrix = __mat4.create();

            #region new in lesson 03
            // how would this translate to non GC, NDK?
            Action mvPushMatrix = delegate
            {
                var copy = __mat4.create();

                mvMatrix.CopyTo(copy, 0);

                //glMatrix.mat4.set(mvMatrix, copy);
                mvMatrixStack.Push(copy);
            };

            Action mvPopMatrix = delegate
            {
                mvMatrix = mvMatrixStack.Pop();
            };
            #endregion



            #region degToRad
            Func<float, float> degToRad = (degrees) =>
            {
                return degrees * (float)Math.PI / 180f;
            };
            #endregion




            //var cubesize = 8;
            // X:\jsc.svn\examples\java\android\vr\OVRWindWheelNDK\OVRWindWheelNDK\VrCubeWorld.Geometry.cs
            //var cubesize = 0.125f;


            var cubesize = 16 / 128f;

            __mat4.identity(mvMatrix);
            __mat4.translate(mvMatrix, mvMatrix, new float[] {
                // left 
                1.0f,
                // up?
                3.0f,
                // distance
                -6.0f });

            #region windwheel
            mvPushMatrix();
            __mat4.rotate(mvMatrix, mvMatrix, degToRad(rWind), new float[] { 0, 1f, 0f });

            #region DrawFrameworkWingAtX
            Action<float, float> DrawFrameworkWingAtX = (WingX, WingY) =>
            {
                mvPushMatrix();

                __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, cubesize * WingY, 0 });

                uniformMatrix4fv(mvMatrix);

                mvPopMatrix();
            };
            #endregion

            #region DrawWingAtX
            Action<int, int, float, float> DrawWingAtX = (WingX, WingSize, WingRotationMultiplier, WingRotationOffset) =>
            {
                mvPushMatrix();
                __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, 0, 0 });

                if (WingRotationOffset == 0)
                {
                    DrawFrameworkWingAtX(0, 0);
                }

                #region DrawWingPart
                Action<float> DrawWingPart = PartIndex =>
                {
                    mvPushMatrix();
                    __mat4.rotate(mvMatrix, mvMatrix, degToRad(WingRotationOffset + (rCube * WingRotationMultiplier)), new float[] { 1f, 0f, 0f });
                    __mat4.translate(mvMatrix, mvMatrix, new float[] { 0f, cubesize * PartIndex * 2, 0 });

                    uniformMatrix4fv(mvMatrix);


                    mvPopMatrix();
                };
                #endregion

                #region DrawWingWithSize
                Action<int> DrawWingWithSize =
                    length =>
                    {
                        for (int i = 4; i < length; i++)
                        {
                            DrawWingPart(i * 1.0f);
                            DrawWingPart(-i * 1.0f);

                        }
                    };
                #endregion

                DrawWingWithSize(WingSize);

                mvPopMatrix();

            };
            #endregion

            {
                var x = 8;

                DrawFrameworkWingAtX(x - 8, 0);

                for (int i = 0; i < 24; i++)
                {
                    DrawFrameworkWingAtX(x - 8, -2.0f * i);

                }

                DrawWingAtX(x - 6, 0, 1f, 0);
                DrawWingAtX(x - 4, 0, 1f, 0);
                DrawWingAtX(x - 2, 0, 1f, 0);

                DrawWingAtX(x + 0, 16, 1f, 0);
                DrawWingAtX(x + 0, 16, 1f, 30);
                DrawWingAtX(x + 0, 16, 1f, 60);
                DrawWingAtX(x + 0, 16, 1f, 90);
                DrawWingAtX(x + 0, 16, 1f, 120);
                DrawWingAtX(x + 0, 16, 1f, 150);

                DrawWingAtX(x + 2, 0, 1f, 0);
                DrawWingAtX(x + 4, 0, 1f, 0);
                DrawWingAtX(x + 6, 0, 1f, 0);

                DrawWingAtX(x + 8, 12, 0.4f, 0);
                DrawWingAtX(x + 8, 12, 0.4f, 60);
                DrawWingAtX(x + 8, 12, 0.4f, 120);


                DrawWingAtX(x + 8 + 2, 0, 1f, 0);
                DrawWingAtX(x + 8 + 4, 0, 1f, 0);
                DrawWingAtX(x + 8 + 6, 0, 1f, 0);

                DrawWingAtX(x + 16, 8, 0.3f, 0);
                DrawWingAtX(x + 16, 8, 0.3f, 90);
            }

            mvPopMatrix();
            #endregion




        }
		private void showQuitDialog()
		{
			runOnUiThread(() =>
			{
				AlertDialog.Builder alertbox = new AlertDialog.Builder(FileTransferReceiverActivity.this);
				alertbox = new AlertDialog.Builder(FileTransferReceiverActivity.this);
				alertbox.Message = "Receiving file : [" + mFilePath + "] QUIT?";
				alertbox.setNegativeButton("OK", new OnClickListenerAnonymousInnerClassHelper3(this));
				alertbox.Cancelable = false;
				mAlert = alertbox.create();
				mAlert.show();
			});
		}