/// <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 gl_viewportWidth = 500;
            var gl_viewportHeight = 500;


            var gl = new WebGLRenderingContext();





            #region canvas
            var canvas = gl.canvas.AttachToDocument();

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

            canvas.width = gl_viewportWidth;
            canvas.height = gl_viewportHeight;
            #endregion




            var h = 1f;
            var r1 = .5f;
            var r2 = .2f;
            var nPhi = 500;


            var prog = gl.createProgram();


            #region createShader
            Func<ScriptCoreLib.GLSL.Shader, WebGLShader> createShader = (src) =>
            {
                var shader = gl.createShader(src);

                // verify
                if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == null)
                {
                    Native.window.alert("error in SHADER:\n" + gl.getShaderInfoLog(shader));
                    throw new InvalidOperationException("shader failed");
                }

                return shader;
            };
            #endregion

            var vs = createShader(new GeometryVertexShader());
            var fs = createShader(new GeometryFragmentShader());


            gl.attachShader(prog, vs);
            gl.attachShader(prog, fs);


            gl.linkProgram(prog);
            gl.useProgram(prog);



            var pt = new IArray<float>();
            var nt = new IArray<float>();
            var Phi = 0.0;
            var dPhi = 2 * Math.PI / (nPhi - 1);

            var Nx = r1 - r2;
            var Ny = h;
            var N = (float)Math.Sqrt(Nx * Nx + Ny * Ny);

            Nx /= N;
            Ny /= N;

            for (var i = 0; i < nPhi; i++)
            {
                var cosPhi = Math.Cos(Phi);
                var sinPhi = Math.Sin(Phi);
                var cosPhi2 = Math.Cos(Phi + dPhi / 2);
                var sinPhi2 = Math.Sin(Phi + dPhi / 2);

                pt.push(-h / 2);
                pt.push((float)(cosPhi * r1));
                pt.push((float)(sinPhi * r1));   // points

                nt.push(Nx);
                nt.push((float)(Ny * cosPhi));
                nt.push((float)(Ny * sinPhi));         // normals

                pt.push(h / 2);
                pt.push((float)(cosPhi2 * r2));
                pt.push((float)(sinPhi2 * r2));  // points

                nt.push(Nx);
                nt.push((float)(Ny * cosPhi2));
                nt.push((float)(Ny * sinPhi2));       // normals

                Phi += dPhi;
            }

            var posLoc = gl.getAttribLocation(prog, "aPos");
            gl.enableVertexAttribArray((uint)posLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt.ToArray()), gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)posLoc, 3, gl.FLOAT, false, 0, 0);

            var normLoc = gl.getAttribLocation(prog, "aNorm");
            gl.enableVertexAttribArray((uint)normLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(nt), gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)normLoc, 3, gl.FLOAT, false, 0, 0);

            var prMatrix = new CanvasMatrix4();

            gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
               false, new Float32Array(prMatrix.getAsArray()));

            var mvMatrix = new CanvasMatrix4();
            var rotMat = new CanvasMatrix4();
            rotMat.makeIdentity();
            rotMat.rotate(-40, 0, 1, 0);
            var mvMatLoc = gl.getUniformLocation(prog, "mvMatrix");

            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
            gl.clearDepth(1.0f);
            gl.clearColor(0, 0, .5f, 1);

            var xOffs = 0;
            var yOffs = 0;
            var drag = 0;
            var xRot = 0;
            var yRot = 0;
            var transl = -1.5f;

            Action drawScene = delegate
            {

                gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
   false, new Float32Array(prMatrix.getAsArray()));


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


                rotMat.rotate(xRot / 5, 1, 0, 0);
                rotMat.rotate(yRot / 5, 0, 1, 0);

                yRot = 0;
                xRot = 0;

                mvMatrix.load(rotMat);
                mvMatrix.translate(0, 0, transl);

                gl.uniformMatrix4fv(mvMatLoc, false,
                  new Float32Array(mvMatrix.getAsArray()));
                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2 * nPhi);
                gl.flush();
            };



            #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;





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

                c++;

                xRot += 2;
                yRot += 3;

                Native.document.title = "" + c;

                drawScene();
                //animate();

            };




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

                    prMatrix = new CanvasMatrix4();
                    prMatrix.perspective(45f, (f)gl_viewportWidth / (f)gl_viewportHeight, 1f, 100f);


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

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

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



        }
        /// <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 gl_viewportWidth = Native.window.Width;
            var gl_viewportHeight = Native.window.Height;




            var gl = new WebGLRenderingContext();


            var canvas = gl.canvas.AttachToDocument();

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


            gl.viewport(0, 0, gl_viewportWidth, gl_viewportWidth);


            var prog = gl.createProgram(
                new CubicVertexShader(),
                new CubicFragmentShader()
                );


            var posLoc = 0U;
            gl.bindAttribLocation(prog, posLoc, "aPos");
            var normLoc = 1U;
            gl.bindAttribLocation(prog, normLoc, "aNorm");
            gl.linkProgram(prog);
            gl.useProgram(prog);

            #region data
            var a = 1.0f; // where is it used? what shall be the type?
            var pt0 = new float[] {-a,-a,a, a,-a,a, -a,a,a, a,a,a,  // cubic
                 -a,a,a, a,a,a, -a,a,-a, a,a,-a,
                 -a,a,-a, a,a,-a, -a,-a,-a, a,-a,-a,  -a,-a,-a, a,-a,-a, -a,-a,a, a,-a,a,
                 a,a,a, a,a,-a, a,-a,a, a,-a,-a,  -a,a,a, -a,a,-a, -a,-a,a, -a,-a,-a};
            var nt = new float[] {0,0,1, 0,0,1, 0,0,1, 0,0,1,  0,1,0, 0,1,0, 0,1,0, 0,1,0,
                 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,  0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0,
                 1,0,0, 1,0,0, 1,0,0, 1,0,0,  -1,0,0, -1,0,0, -1,0,0, -1,0,0};
            var ind = new ushort[] {0,1,2,1,2,3, 4,5,6,5,6,7, 8,9,10,9,10,11,
                 12,13,14,13,14,15, 16,17,18,17,18,19, 20,21,22,21,22,23};

            var nPhi = 25;
            var nTheta = 12;
            var r = .15;
            var dPhi = 2.0 * Math.PI / nPhi;
            var dTheta = Math.PI / nTheta;

            for (var j = 0; j <= nTheta; j++)
            {
                var Theta = j * dTheta;
                var cosTheta = Math.Cos(Theta);
                var sinTheta = Math.Sin(Theta);
                for (var i = 0; i <= nPhi; i++)
                {
                    var Phi = i * dPhi;
                    var cosPhi = Math.Cos(Phi);
                    var sinPhi = Math.Sin(Phi);


                    ((IArray<float>)(object)pt0).push((float)(r * cosPhi * sinTheta));
                    ((IArray<float>)(object)pt0).push((float)(-r * sinPhi * sinTheta));
                    ((IArray<float>)(object)pt0).push((float)(r * cosTheta));

                    ((IArray<float>)(object)nt).push((float)(cosPhi * sinTheta));
                    ((IArray<float>)(object)nt).push((float)(-sinPhi * sinTheta));
                    ((IArray<float>)(object)nt).push((float)(cosTheta));
                }
            }
            var n1 = nPhi + 1;
            var off = 24;
            for (var i = 0; i < nTheta; i++)
                for (var j = 0; j < nPhi; j++)
                {
                    ((IArray<int>)(object)ind).push(i * n1 + j + off);
                    ((IArray<int>)(object)ind).push((i + 1) * n1 + j + 1 + off);
                    ((IArray<int>)(object)ind).push(i * n1 + j + 1 + off);
                    ((IArray<int>)(object)ind).push(i * n1 + j + off);
                    ((IArray<int>)(object)ind).push((i + 1) * n1 + j + off);
                    ((IArray<int>)(object)ind).push((i + 1) * n1 + j + 1 + off);
                }
            #endregion

            gl.enableVertexAttribArray(posLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt0), gl.STATIC_DRAW);
            gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 0, 0);

            gl.enableVertexAttribArray(normLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(nt), gl.STATIC_DRAW);
            gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, false, 0, 0);

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(ind),
              gl.STATIC_DRAW);

            var prMatrix = new CanvasMatrix4();
            prMatrix.perspective(45f, 1f, .1f, 100f);

            gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
                  false, new Float32Array(prMatrix.getAsArray()));

            var mvMatrix = new CanvasMatrix4();
            var rotMat = new CanvasMatrix4();
            rotMat.makeIdentity();
            rotMat.rotate(25, 1, 1, 0);

            var mvMatLoc = gl.getUniformLocation(prog, "mvMatrix");
            var colorLoc = gl.getUniformLocation(prog, "u_color");

            var line_prog = gl.createProgram(
                new LineVertexShader(),
                new LineFragmentShader()
                );


            var lineLoc = 2U;
            gl.bindAttribLocation(line_prog, lineLoc, "aPos");

            gl.linkProgram(line_prog);
            gl.useProgram(line_prog);
            gl.uniformMatrix4fv(gl.getUniformLocation(line_prog, "prMatrix"),
               false, new Float32Array(prMatrix.getAsArray()));
            var mvMatLineLoc = gl.getUniformLocation(line_prog, "mvMatrix");

            var pt1 = new float[]{2,1,1, -2,1,1, 2,-1,1, -2,-1,1, 2,1,-1, -2,1,-1, 2,-1,-1, -2,-1,-1,
                1,2,1, 1,-2,1, 1,2,-1, 1,-2,-1, -1,2,1, -1,-2,1, -1,2,-1, -1,-2,-1, 
                1,1,2, 1,1,-2, -1,1,2, -1,1,-2, 1,-1,2, 1,-1,-2, -1,-1,2, -1,-1,-2
            };

            gl.enableVertexAttribArray(lineLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt1), gl.STATIC_DRAW);
            gl.vertexAttribPointer(lineLoc, 3, gl.FLOAT, false, 0, 0);

            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
            gl.clearDepth(1.0f);
            gl.clearColor(.5f, 1f, .5f, 1f);
            gl.lineWidth(2);

            var xOffs = 0;
            var yOffs = 0;
            var drag = 0;
            var xRot = 0f;
            var yRot = 0f;
            var transl = -6.0f;


            #region drawBall
            Action<f, f, f> drawBall = (x, y, z) =>
            {
                mvMatrix.makeIdentity();
                mvMatrix.translate(x, y, z);
                mvMatrix.multRight(rotMat);
                mvMatrix.translate(0, 0, transl);
                gl.uniformMatrix4fv(mvMatLoc, false,
                  new Float32Array(mvMatrix.getAsArray()));

                gl.drawElements(gl.TRIANGLES, 6 * nPhi * nTheta, gl.UNSIGNED_SHORT, 72);
            };
            #endregion

            #region drawScene
            Action drawScene = delegate
            {


                gl.viewport(0, 0, gl_viewportWidth, gl_viewportWidth);
                gl.useProgram(prog);


                gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
   false, new Float32Array(prMatrix.getAsArray()));

                rotMat.rotate(xRot / 5, 1, 0, 0);
                rotMat.rotate(yRot / 5, 0, 1, 0);

                yRot = 0;
                xRot = 0;

                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

                gl.uniform4f(colorLoc, 1, 1, 0, 1);

                drawBall(1, 1, 1); drawBall(-1, 1, 1); drawBall(1, -1, 1);
                drawBall(1, 1, -1); drawBall(-1, -1, 1); drawBall(-1, 1, -1);
                drawBall(1, -1, -1); drawBall(-1, -1, -1);

                mvMatrix.load(rotMat);
                mvMatrix.translate(0, 0, transl);

                gl.uniformMatrix4fv(mvMatLoc, false,
                  new Float32Array(mvMatrix.getAsArray()));

                gl.enable(gl.BLEND);
                gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
                gl.uniform4f(colorLoc, .0f, .0f, .9f, .7f);
                gl.depthMask(false);
                gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
                gl.depthMask(true);
                gl.disable(gl.BLEND);



                gl.useProgram(line_prog);

                gl.uniformMatrix4fv(gl.getUniformLocation(line_prog, "prMatrix"),
   false, new Float32Array(prMatrix.getAsArray()));

                gl.uniformMatrix4fv(mvMatLineLoc, false,
                  new Float32Array(mvMatrix.getAsArray()));
                gl.drawArrays(gl.LINES, 0, 24);

                gl.flush();
            };
            #endregion


            drawScene();



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

                prMatrix = new CanvasMatrix4();

                //var aspect = (f)gl_viewportWidth / (f)gl_viewportHeight;
                var aspect = Native.window.aspect;

                Console.WriteLine(
                    new { gl_viewportWidth, gl_viewportHeight, aspect }
                    );
                //Native.document.title = new { aspect }.ToString();

                prMatrix.perspective(45f, (f)aspect, 1f, 100f);


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

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

                drawScene();
            };

            AtResize();

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


            #region mouse
            canvas.onmousedown += ev =>
            {
                ev.PreventDefault();

                drag = 1;
                xOffs = ev.CursorX;
                yOffs = ev.CursorY;

                canvas.requestPointerLock();
            };

            canvas.onmouseup += ev =>
            {
                ev.PreventDefault();


                drag = 0;
                xOffs = ev.CursorX;
                yOffs = ev.CursorY;

                Native.Document.exitPointerLock();
            };

            canvas.onmousemove += ev =>
            {
                if (drag == 0)
                    return;

                if (Native.Document.pointerLockElement == canvas)
                {
                    xRot += ev.movementY;
                    yRot += ev.movementX;
                    drawScene();

                    return;
                }

                ev.PreventDefault();

                if (ev.shiftKey)
                {
                    transl *= 1 + (ev.CursorY - yOffs) / 1000;
                    yRot = -xOffs + ev.CursorX;
                }
                else
                {
                    yRot = -xOffs + ev.CursorX;
                    xRot = -yOffs + ev.CursorY;
                }

                xOffs = ev.CursorX;
                yOffs = ev.CursorY;
                drawScene();
            };
            #endregion

            #region onmousewheel
            canvas.onmousewheel +=
                ev =>
                {
                    var del = 1.1f;

                    if (ev.shiftKey)
                        del = 1.01f;

                    if (ev.WheelDirection > 0)
                        transl *= del;
                    else
                        transl *= (1 / del);

                    drawScene();



                    ev.PreventDefault();
                };
            #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/

                    canvas.requestFullscreen();


                };
            #endregion

            #region tick

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

                if (drag == 0)
                {
                    xRot += 2;
                    yRot += 3;
                }

                drawScene();
                //animate();

            };

            #endregion



            //Native.Document.body.style.backgroundColor = Color.FromRGB(0x80, 0xFF, 0x80);
        }
Example #3
0
        /// <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 gl_viewportWidth  = 500;
            var gl_viewportHeight = 500;


            var gl = new WebGLRenderingContext();



            #region canvas
            var canvas = gl.canvas.AttachToDocument();

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

            canvas.width  = gl_viewportWidth;
            canvas.height = gl_viewportHeight;
            #endregion



            var h    = 1f;
            var r1   = .5f;
            var r2   = .2f;
            var nPhi = 500;


            var prog = gl.createProgram();


            #region createShader
            Func <ScriptCoreLib.GLSL.Shader, WebGLShader> createShader = (src) =>
            {
                var shader = gl.createShader(src);

                // verify
                if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == null)
                {
                    Native.window.alert("error in SHADER:\n" + gl.getShaderInfoLog(shader));
                    throw new InvalidOperationException("shader failed");
                }

                return(shader);
            };
            #endregion

            var vs = createShader(new GeometryVertexShader());
            var fs = createShader(new GeometryFragmentShader());


            gl.attachShader(prog, vs);
            gl.attachShader(prog, fs);


            gl.linkProgram(prog);
            gl.useProgram(prog);



            var pt   = new IArray <float>();
            var nt   = new IArray <float>();
            var Phi  = 0.0;
            var dPhi = 2 * Math.PI / (nPhi - 1);

            var Nx = r1 - r2;
            var Ny = h;
            var N  = (float)Math.Sqrt(Nx * Nx + Ny * Ny);

            Nx /= N;
            Ny /= N;

            for (var i = 0; i < nPhi; i++)
            {
                var cosPhi  = Math.Cos(Phi);
                var sinPhi  = Math.Sin(Phi);
                var cosPhi2 = Math.Cos(Phi + dPhi / 2);
                var sinPhi2 = Math.Sin(Phi + dPhi / 2);

                pt.push(-h / 2);
                pt.push((float)(cosPhi * r1));
                pt.push((float)(sinPhi * r1));   // points

                nt.push(Nx);
                nt.push((float)(Ny * cosPhi));
                nt.push((float)(Ny * sinPhi));         // normals

                pt.push(h / 2);
                pt.push((float)(cosPhi2 * r2));
                pt.push((float)(sinPhi2 * r2));  // points

                nt.push(Nx);
                nt.push((float)(Ny * cosPhi2));
                nt.push((float)(Ny * sinPhi2));       // normals

                Phi += dPhi;
            }

            var posLoc = gl.getAttribLocation(prog, "aPos");
            gl.enableVertexAttribArray((uint)posLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt.ToArray()), gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)posLoc, 3, gl.FLOAT, false, 0, 0);

            var normLoc = gl.getAttribLocation(prog, "aNorm");
            gl.enableVertexAttribArray((uint)normLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(nt), gl.STATIC_DRAW);
            gl.vertexAttribPointer((uint)normLoc, 3, gl.FLOAT, false, 0, 0);

            var prMatrix = new CanvasMatrix4();

            gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
                                false, new Float32Array(prMatrix.getAsArray()));

            var mvMatrix = new CanvasMatrix4();
            var rotMat   = new CanvasMatrix4();
            rotMat.makeIdentity();
            rotMat.rotate(-40, 0, 1, 0);
            var mvMatLoc = gl.getUniformLocation(prog, "mvMatrix");

            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
            gl.clearDepth(1.0f);
            gl.clearColor(0, 0, .5f, 1);

            var xOffs  = 0;
            var yOffs  = 0;
            var drag   = 0;
            var xRot   = 0;
            var yRot   = 0;
            var transl = -1.5f;

            Action drawScene = delegate
            {
                gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
                                    false, new Float32Array(prMatrix.getAsArray()));


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


                rotMat.rotate(xRot / 5, 1, 0, 0);
                rotMat.rotate(yRot / 5, 0, 1, 0);

                yRot = 0;
                xRot = 0;

                mvMatrix.load(rotMat);
                mvMatrix.translate(0, 0, transl);

                gl.uniformMatrix4fv(mvMatLoc, false,
                                    new Float32Array(mvMatrix.getAsArray()));
                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 2 * nPhi);
                gl.flush();
            };



            #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;



            Native.window.onframe += delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                c++;

                xRot += 2;
                yRot += 3;

                Native.document.title = "" + c;

                drawScene();
                //animate();
            };



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

                prMatrix = new CanvasMatrix4();
                prMatrix.perspective(45f, (f)gl_viewportWidth / (f)gl_viewportHeight, 1f, 100f);


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

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

            Native.window.onresize +=
                e =>
            {
                AtResize();
            };
            AtResize();
            #endregion
        }
Example #4
0
        /// <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 gl_viewportWidth  = Native.window.Width;
            var gl_viewportHeight = Native.window.Height;



            var gl = new WebGLRenderingContext();


            var canvas = gl.canvas.AttachToDocument();

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


            gl.viewport(0, 0, gl_viewportWidth, gl_viewportWidth);


            var prog = gl.createProgram(
                new CubicVertexShader(),
                new CubicFragmentShader()
                );


            var posLoc = 0U;

            gl.bindAttribLocation(prog, posLoc, "aPos");
            var normLoc = 1U;

            gl.bindAttribLocation(prog, normLoc, "aNorm");
            gl.linkProgram(prog);
            gl.useProgram(prog);

            #region data
            var a   = 1.0f;                                                 // where is it used? what shall be the type?
            var pt0 = new float[] { -a, -a, a, a, -a, a, -a, a, a, a, a, a, // cubic
                                    -a, a, a, a, a, a, -a, a, -a, a, a, -a,
                                    -a, a, -a, a, a, -a, -a, -a, -a, a, -a, -a, -a, -a, -a, a, -a, -a, -a, -a, a, a, -a, a,
                                    a, a, a, a, a, -a, a, -a, a, a, -a, -a, -a, a, a, -a, a, -a, -a, -a, a, -a, -a, -a };
            var nt = new float[] { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
                                   0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
                                   1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0 };
            var ind = new ushort[] { 0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7, 8, 9, 10, 9, 10, 11,
                                     12, 13, 14, 13, 14, 15, 16, 17, 18, 17, 18, 19, 20, 21, 22, 21, 22, 23 };

            var nPhi   = 25;
            var nTheta = 12;
            var r      = .15;
            var dPhi   = 2.0 * Math.PI / nPhi;
            var dTheta = Math.PI / nTheta;

            for (var j = 0; j <= nTheta; j++)
            {
                var Theta    = j * dTheta;
                var cosTheta = Math.Cos(Theta);
                var sinTheta = Math.Sin(Theta);
                for (var i = 0; i <= nPhi; i++)
                {
                    var Phi    = i * dPhi;
                    var cosPhi = Math.Cos(Phi);
                    var sinPhi = Math.Sin(Phi);


                    ((IArray <float>)(object) pt0).push((float)(r * cosPhi * sinTheta));
                    ((IArray <float>)(object) pt0).push((float)(-r * sinPhi * sinTheta));
                    ((IArray <float>)(object) pt0).push((float)(r * cosTheta));

                    ((IArray <float>)(object) nt).push((float)(cosPhi * sinTheta));
                    ((IArray <float>)(object) nt).push((float)(-sinPhi * sinTheta));
                    ((IArray <float>)(object) nt).push((float)(cosTheta));
                }
            }
            var n1  = nPhi + 1;
            var off = 24;
            for (var i = 0; i < nTheta; i++)
            {
                for (var j = 0; j < nPhi; j++)
                {
                    ((IArray <int>)(object) ind).push(i * n1 + j + off);
                    ((IArray <int>)(object) ind).push((i + 1) * n1 + j + 1 + off);
                    ((IArray <int>)(object) ind).push(i * n1 + j + 1 + off);
                    ((IArray <int>)(object) ind).push(i * n1 + j + off);
                    ((IArray <int>)(object) ind).push((i + 1) * n1 + j + off);
                    ((IArray <int>)(object) ind).push((i + 1) * n1 + j + 1 + off);
                }
            }
            #endregion

            gl.enableVertexAttribArray(posLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt0), gl.STATIC_DRAW);
            gl.vertexAttribPointer(posLoc, 3, gl.FLOAT, false, 0, 0);

            gl.enableVertexAttribArray(normLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(nt), gl.STATIC_DRAW);
            gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, false, 0, 0);

            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(ind),
                          gl.STATIC_DRAW);

            var prMatrix = new CanvasMatrix4();
            prMatrix.perspective(45f, 1f, .1f, 100f);

            gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
                                false, new Float32Array(prMatrix.getAsArray()));

            var mvMatrix = new CanvasMatrix4();
            var rotMat   = new CanvasMatrix4();
            rotMat.makeIdentity();
            rotMat.rotate(25, 1, 1, 0);

            var mvMatLoc = gl.getUniformLocation(prog, "mvMatrix");
            var colorLoc = gl.getUniformLocation(prog, "u_color");

            var line_prog = gl.createProgram(
                new LineVertexShader(),
                new LineFragmentShader()
                );


            var lineLoc = 2U;
            gl.bindAttribLocation(line_prog, lineLoc, "aPos");

            gl.linkProgram(line_prog);
            gl.useProgram(line_prog);
            gl.uniformMatrix4fv(gl.getUniformLocation(line_prog, "prMatrix"),
                                false, new Float32Array(prMatrix.getAsArray()));
            var mvMatLineLoc = gl.getUniformLocation(line_prog, "mvMatrix");

            var pt1 = new float[] { 2, 1, 1, -2, 1, 1, 2, -1, 1, -2, -1, 1, 2, 1, -1, -2, 1, -1, 2, -1, -1, -2, -1, -1,
                                    1, 2, 1, 1, -2, 1, 1, 2, -1, 1, -2, -1, -1, 2, 1, -1, -2, 1, -1, 2, -1, -1, -2, -1,
                                    1, 1, 2, 1, 1, -2, -1, 1, 2, -1, 1, -2, 1, -1, 2, 1, -1, -2, -1, -1, 2, -1, -1, -2 };

            gl.enableVertexAttribArray(lineLoc);
            gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pt1), gl.STATIC_DRAW);
            gl.vertexAttribPointer(lineLoc, 3, gl.FLOAT, false, 0, 0);

            gl.enable(gl.DEPTH_TEST);
            gl.depthFunc(gl.LEQUAL);
            gl.clearDepth(1.0f);
            gl.clearColor(.5f, 1f, .5f, 1f);
            gl.lineWidth(2);

            var xOffs  = 0;
            var yOffs  = 0;
            var drag   = 0;
            var xRot   = 0f;
            var yRot   = 0f;
            var transl = -6.0f;


            #region drawBall
            Action <f, f, f> drawBall = (x, y, z) =>
            {
                mvMatrix.makeIdentity();
                mvMatrix.translate(x, y, z);
                mvMatrix.multRight(rotMat);
                mvMatrix.translate(0, 0, transl);
                gl.uniformMatrix4fv(mvMatLoc, false,
                                    new Float32Array(mvMatrix.getAsArray()));

                gl.drawElements(gl.TRIANGLES, 6 * nPhi * nTheta, gl.UNSIGNED_SHORT, 72);
            };
            #endregion

            #region drawScene
            Action drawScene = delegate
            {
                gl.viewport(0, 0, gl_viewportWidth, gl_viewportWidth);
                gl.useProgram(prog);


                gl.uniformMatrix4fv(gl.getUniformLocation(prog, "prMatrix"),
                                    false, new Float32Array(prMatrix.getAsArray()));

                rotMat.rotate(xRot / 5, 1, 0, 0);
                rotMat.rotate(yRot / 5, 0, 1, 0);

                yRot = 0;
                xRot = 0;

                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

                gl.uniform4f(colorLoc, 1, 1, 0, 1);

                drawBall(1, 1, 1); drawBall(-1, 1, 1); drawBall(1, -1, 1);
                drawBall(1, 1, -1); drawBall(-1, -1, 1); drawBall(-1, 1, -1);
                drawBall(1, -1, -1); drawBall(-1, -1, -1);

                mvMatrix.load(rotMat);
                mvMatrix.translate(0, 0, transl);

                gl.uniformMatrix4fv(mvMatLoc, false,
                                    new Float32Array(mvMatrix.getAsArray()));

                gl.enable(gl.BLEND);
                gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
                gl.uniform4f(colorLoc, .0f, .0f, .9f, .7f);
                gl.depthMask(false);
                gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
                gl.depthMask(true);
                gl.disable(gl.BLEND);



                gl.useProgram(line_prog);

                gl.uniformMatrix4fv(gl.getUniformLocation(line_prog, "prMatrix"),
                                    false, new Float32Array(prMatrix.getAsArray()));

                gl.uniformMatrix4fv(mvMatLineLoc, false,
                                    new Float32Array(mvMatrix.getAsArray()));
                gl.drawArrays(gl.LINES, 0, 24);

                gl.flush();
            };
            #endregion


            drawScene();



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

                prMatrix = new CanvasMatrix4();

                //var aspect = (f)gl_viewportWidth / (f)gl_viewportHeight;
                var aspect = Native.window.aspect;

                Console.WriteLine(
                    new { gl_viewportWidth, gl_viewportHeight, aspect }
                    );
                //Native.document.title = new { aspect }.ToString();

                prMatrix.perspective(45f, (f)aspect, 1f, 100f);


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

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

                drawScene();
            };

            AtResize();

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


            #region mouse
            canvas.onmousedown += ev =>
            {
                ev.PreventDefault();

                drag  = 1;
                xOffs = ev.CursorX;
                yOffs = ev.CursorY;

                canvas.requestPointerLock();
            };

            canvas.onmouseup += ev =>
            {
                ev.PreventDefault();


                drag  = 0;
                xOffs = ev.CursorX;
                yOffs = ev.CursorY;

                Native.Document.exitPointerLock();
            };

            canvas.onmousemove += ev =>
            {
                if (drag == 0)
                {
                    return;
                }

                if (Native.Document.pointerLockElement == canvas)
                {
                    xRot += ev.movementY;
                    yRot += ev.movementX;
                    drawScene();

                    return;
                }

                ev.PreventDefault();

                if (ev.shiftKey)
                {
                    transl *= 1 + (ev.CursorY - yOffs) / 1000;
                    yRot    = -xOffs + ev.CursorX;
                }
                else
                {
                    yRot = -xOffs + ev.CursorX;
                    xRot = -yOffs + ev.CursorY;
                }

                xOffs = ev.CursorX;
                yOffs = ev.CursorY;
                drawScene();
            };
            #endregion

            #region onmousewheel
            canvas.onmousewheel +=
                ev =>
            {
                var del = 1.1f;

                if (ev.shiftKey)
                {
                    del = 1.01f;
                }

                if (ev.WheelDirection > 0)
                {
                    transl *= del;
                }
                else
                {
                    transl *= (1 / del);
                }

                drawScene();



                ev.PreventDefault();
            };
            #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/

                canvas.requestFullscreen();
            };
            #endregion

            #region tick

            Native.window.onframe += delegate
            {
                if (IsDisposed)
                {
                    return;
                }

                if (drag == 0)
                {
                    xRot += 2;
                    yRot += 3;
                }

                drawScene();
                //animate();
            };

            #endregion



            //Native.Document.body.style.backgroundColor = Color.FromRGB(0x80, 0xFF, 0x80);
        }