public override void Init()
        {
            var width = Width;
            var height = Height;

            var info = Document.CreateElement("div");
            info.InnerHTML = "Drag to change the view";
            Container.AppendChild(info);

            camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
            camera.position.y = 150;
            camera.position.z = 500;

            controls = new THREE.TrackballControls(camera);

            scene = new THREE.Scene();

            THREE.PointLight light = new THREE.PointLight(0xffffff);
            light.position.set(500, 500, 500);
            scene.add(light);

            THREE.MeshLambertMaterial mat = new THREE.MeshLambertMaterial();

            mat.shading = THREE.ShadingType.FlatShading;

            sphere = new THREE.Mesh(new THREE.SphereGeometry(200, 20, 10), mat);
            scene.add(sphere);

            THREE.MeshBasicMaterial mat2 = new THREE.MeshBasicMaterial();
            mat2.color = 0xe0e0e0;

            THREE.Mesh plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(400, 400), mat2);
            plane.position.y = -200;
            plane.rotation.x = -Math.PI / 2;
            scene.add(plane);

            renderer = new THREE.CanvasRenderer();
            renderer.setClearColor(0xf0f0f0);
            renderer.setSize(width, height);

            effect = new THREE.AsciiEffect(renderer, " +-Hgxyz");
            effect.setSize(width, height);
            Container.AppendChild(effect.domElement);
        }
        /// <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(IApp page)
        {
            Native.body.Clear();
            Native.body.style.margin = "0px";

            // http://www.highlander.co.uk/blog/2011/09/23/learning-three-js/

            //this sets the canvas size.
            var WIDTH = Native.window.Width;
            var HEIGHT = Native.window.Height;

            // camera attributes
            var VIEW_ANGLE = 45;
            var ASPECT = WIDTH / HEIGHT;
            var NEAR = 0.1;
            var FAR = 10000;

            var renderer = new THREE.WebGLRenderer();
            //I am choosing the WebGL renderer here, but you have others to choose from
            var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
            //these variables have been set at the top of  our script
            var scene = new THREE.Scene(); //create a new scene
            // the camera starts at 0,0,0 so we need to pull back
            camera.position.z = 200;
            // start the renderer
            renderer.setSize(WIDTH, HEIGHT);

            // http://www.highlander.co.uk/blog/2011/09/23/learning-three-js/



            //create materials
            var material = new THREE.MeshLambertMaterial(new { color = 0xCC0000 });
            //var material = new THREE.MeshBasicMaterial({color: 0xCC0000});  //gives you just a flat colour – ugly

            // create a new mesh with sphere geometry
            var radius = 50;
            var segments = 16;
            var rings = 16;
            var mesh = new THREE.Mesh(new THREE.SphereGeometry(radius, segments, rings), material).AttachTo(scene);
            //scene.addChild(mesh);
            scene.add(mesh);


            renderer.domElement.AttachToDocument();

            var pointLight = new THREE.PointLight(0xFFFFFF);
            // set its position
            pointLight.position.x = 50;
            pointLight.position.y = 50;
            pointLight.position.z = 130;
            // add to the scene
            scene.add(pointLight);
            //scene.addLight(pointLight);
            // render our scene

            Native.window.onframe +=
                delegate
                {
                    renderer.render(scene, camera);
                };
        }
        void InitializeContent()
        {

            #region make sure we atleast have our invisible DOM
            var page_song = new nyanlooped { loop = true };
            var page_song2 = new nyanslow { loop = true };


            #endregion

            #region container
            Native.document.body.style.overflow = IStyle.OverflowEnum.hidden;
            var container = new IHTMLDiv();

            container.AttachToDocument();
            container.style.backgroundColor = "#003366";
            container.style.SetLocation(0, 0, Native.window.Width, Native.window.Height);
            #endregion

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(Native.window.Width, Native.window.Height);
            renderer.domElement.AttachTo(container);

            var numStars = 10;
            var numRainChunks = 30;
            var mouseX = 0;
            var mouseY = 0;

            var clock = new Stopwatch();
            clock.Start();

            var deltaSum = 0f;
            //tick=0, 
            var frame = 0;

            var running = true;


            #region onmousemove
            Native.document.onmousemove +=
                e =>
                {
                    if (IsDisposed)
                        return;

                    var windowHalfX = Native.window.Width / 2;
                    var windowHalfY = Native.window.Height / 2;

                    mouseX = (e.CursorX - windowHalfX);
                    mouseY = (e.CursorY - windowHalfY);
                };

            #endregion

            Action PlaySomething =
                delegate
                {
                    if (running)
                    {
                        page_song.play();
                        page_song2.pause();
                    }
                    else
                    {
                        page_song.pause();
                        page_song2.play();
                    }
                };
            #region onmousedown
            Native.document.onmousedown +=
                e =>
                {
                    if (IsDisposed)
                        return;


                    running = !running;
                    PlaySomething();
                };
            #endregion

            #region HasFocus
            var HasFocus = false;

            Native.window.onblur +=
               delegate
               {
                   HasFocus = false;

                   page_song.pause();
                   page_song2.pause();
               };

            Native.window.onfocus +=
                delegate
                {
                    HasFocus = true;
                    PlaySomething();
                };
            Native.Document.onmousemove +=
          delegate
          {
              if (HasFocus)
                  return;
              PlaySomething();
          };

            Native.Document.onmouseout +=
              delegate
              {
                  if (HasFocus)
                      return;

                  page_song.pause();
                  page_song2.pause();
              };
            #endregion


            #region helper
            Action<THREE.Object3D, f, f, f, f, f, f, int> helper =
                (o, x, y, z, w, h, d, c) =>
                {
                    //            function helper(o, x, y, z, w, h, d, c){
                    var material = new THREE.MeshLambertMaterial(new { color = c });
                    var geometry = new THREE.CubeGeometry(w, h, d, 1, 1, 1);
                    var mesh = new THREE.Mesh(geometry, material);
                    mesh.position.x = x + (w / 2);
                    mesh.position.y = y - (h / 2);
                    mesh.position.z = z + (d / 2);
                    o.add(mesh);
                };
            #endregion

            #region buildStar
            Action<THREE.Object3D, int> buildStar =
                (star, state) =>
                {
                    #region  dear JSC, please start supporting switch!
                    if (state == 0)
                    {
                        helper(star, 0, 0, 0, 1, 1, 1, 0xffffff);
                    }
                    else if (state == 1)
                    {
                        helper(star, 1, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, -1, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, 0, 1, 0, 1, 1, 1, 0xffffff);
                        helper(star, 0, -1, 0, 1, 1, 1, 0xffffff);
                    }
                    else if (state == 2)
                    {
                        helper(star, 1, 0, 0, 2, 1, 1, 0xffffff);
                        helper(star, -2, 0, 0, 2, 1, 1, 0xffffff);
                        helper(star, 0, 2, 0, 1, 2, 1, 0xffffff);
                        helper(star, 0, -1, 0, 1, 2, 1, 0xffffff);
                    }
                    else if (state == 3)
                    {
                        helper(star, 0, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, 2, 0, 0, 2, 1, 1, 0xffffff);
                        helper(star, -3, 0, 0, 2, 1, 1, 0xffffff);
                        helper(star, 0, 3, 0, 1, 2, 1, 0xffffff);
                        helper(star, 0, -2, 0, 1, 2, 1, 0xffffff);
                    }
                    else if (state == 4)
                    {
                        helper(star, 0, 3, 0, 1, 1, 1, 0xffffff);
                        helper(star, 2, 2, 0, 1, 1, 1, 0xffffff);
                        helper(star, 3, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, 2, -2, 0, 1, 1, 1, 0xffffff);
                        helper(star, 0, -3, 0, 1, 1, 1, 0xffffff);
                        helper(star, -2, -2, 0, 1, 1, 1, 0xffffff);
                        helper(star, -3, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, -2, 2, 0, 1, 1, 1, 0xffffff);
                    }
                    else if (state == 4)
                    {
                        helper(star, 2, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, -2, 0, 0, 1, 1, 1, 0xffffff);
                        helper(star, 0, 2, 0, 1, 1, 1, 0xffffff);
                        helper(star, 0, -2, 0, 1, 1, 1, 0xffffff);
                    }
                    #endregion
                };
            #endregion

            var r = new Random();
            Func<f> Math_random = () => r.NextFloat();

            var stars = new List<List<THREE.Object3D>>();


            #region  init
            var camera = new THREE.PerspectiveCamera(45,
            Native.window.Width / Native.window.Height, .1f, 10000);

            camera.position.z = 30;
            camera.position.x = 0;
            camera.position.y = 0;

            var scene = new THREE.Scene();
            scene.fog = new THREE.FogExp2(0x003366, 0.0095f);

            #region POPTART
            var poptart = new THREE.Object3D();

            //		object	   x    y    z    w    h    d	  color
            helper(poptart, 0, -2, -1, 21, 14, 3, 0x222222);
            helper(poptart, 1, -1, -1, 19, 16, 3, 0x222222);
            helper(poptart, 2, 0, -1, 17, 18, 3, 0x222222);

            helper(poptart, 1, -2, -1.5f, 19, 14, 4, 0xffcc99);
            helper(poptart, 2, -1, -1.5f, 17, 16, 4, 0xffcc99);

            helper(poptart, 2, -4, 2, 17, 10, .6f, 0xff99ff);
            helper(poptart, 3, -3, 2, 15, 12, .6f, 0xff99ff);
            helper(poptart, 4, -2, 2, 13, 14, .6f, 0xff99ff);

            helper(poptart, 4, -4, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 9, -3, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 12, -3, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 16, -5, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 8, -7, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 5, -9, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 9, -10, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 3, -11, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 7, -13, 2, 1, 1, .7f, 0xff3399);
            helper(poptart, 4, -14, 2, 1, 1, .7f, 0xff3399);

            poptart.position.x = -10.5f;
            poptart.position.y = 9;
            scene.add(poptart);
            #endregion

            #region FEET
            var feet = new THREE.Object3D();
            helper(feet, 0, -2, .49f, 3, 3, 1, 0x222222);
            helper(feet, 1, -1, .49f, 3, 3, 1, 0x222222);
            helper(feet, 1, -2, -.01f, 2, 2, 2, 0x999999);
            helper(feet, 2, -1, -.01f, 2, 2, 2, 0x999999);

            helper(feet, 6, -2, -.5f, 3, 3, 1, 0x222222);
            helper(feet, 6, -2, -.5f, 4, 2, 1, 0x222222);
            helper(feet, 7, -2, -.99f, 2, 2, 2, 0x999999);

            helper(feet, 16, -3, .49f, 3, 2, 1, 0x222222);
            helper(feet, 15, -2, .49f, 3, 2, 1, 0x222222);
            helper(feet, 15, -2, -.01f, 2, 1, 2, 0x999999);
            helper(feet, 16, -3, -.01f, 2, 1, 2, 0x999999);

            helper(feet, 21, -3, -.5f, 3, 2, 1, 0x222222);
            helper(feet, 20, -2, -.5f, 3, 2, 1, 0x222222);
            helper(feet, 20, -2, -.99f, 2, 1, 2, 0x999999);
            helper(feet, 21, -3, -.99f, 2, 1, 2, 0x999999);

            feet.position.x = -12.5f;
            feet.position.y = -6;
            scene.add(feet);
            #endregion


            #region TAIL
            var tail = new THREE.Object3D();
            helper(tail, 0, 0, -.25f, 4, 3, 1.5f, 0x222222);
            helper(tail, 1, -1, -.25f, 4, 3, 1.5f, 0x222222);
            helper(tail, 2, -2, -.25f, 4, 3, 1.5f, 0x222222);
            helper(tail, 3, -3, -.25f, 4, 3, 1.5f, 0x222222);
            helper(tail, 1, -1, -.5f, 2, 1, 2, 0x999999);
            helper(tail, 2, -2, -.5f, 2, 1, 2, 0x999999);
            helper(tail, 3, -3, -.5f, 2, 1, 2, 0x999999);
            helper(tail, 4, -4, -.5f, 2, 1, 2, 0x999999);

            tail.position.x = -16.5f;
            tail.position.y = 2;
            scene.add(tail);
            #endregion


            #region FACE
            var face = new THREE.Object3D();
            helper(face, 2, -3, -3, 12, 9, 4, 0x222222);
            helper(face, 0, -5, 0, 16, 5, 1, 0x222222);
            helper(face, 1, -1, 0, 4, 10, 1, 0x222222);
            helper(face, 11, -1, 0, 4, 10, 1, 0x222222);
            helper(face, 3, -11, 0, 10, 2, 1, 0x222222);
            helper(face, 2, 0, 0, 2, 2, 1, 0x222222);
            helper(face, 4, -2, 0, 2, 2, 1, 0x222222);
            helper(face, 12, 0, 0, 2, 2, 1, 0x222222);
            helper(face, 10, -2, 0, 2, 2, 1, 0x222222);

            helper(face, 1, -5, .5f, 14, 5, 1, 0x999999);
            helper(face, 3, -4, .5f, 10, 8, 1, 0x999999);
            helper(face, 2, -1, .5f, 2, 10, 1, 0x999999);
            helper(face, 12, -1, .5f, 2, 10, 1, 0x999999);
            helper(face, 4, -2, .5f, 1, 2, 1, 0x999999);
            helper(face, 5, -3, .5f, 1, 1, 1, 0x999999);
            helper(face, 11, -2, .5f, 1, 2, 1, 0x999999);
            helper(face, 10, -3, .5f, 1, 1, 1, 0x999999);
            //Eyes
            helper(face, 4, -6, .6f, 2, 2, 1, 0x222222);
            helper(face, 11, -6, .6f, 2, 2, 1, 0x222222);
            helper(face, 3.99f, -5.99f, .6f, 1.01f, 1.01f, 1.01f, 0xffffff);
            helper(face, 10.99f, -5.99f, .6f, 1.01f, 1.01f, 1.01f, 0xffffff);
            //MOUTH
            helper(face, 5, -10, .6f, 7, 1, 1, 0x222222);
            helper(face, 5, -9, .6f, 1, 2, 1, 0x222222);
            helper(face, 8, -9, .6f, 1, 2, 1, 0x222222);
            helper(face, 11, -9, .6f, 1, 2, 1, 0x222222);
            //CHEEKS
            helper(face, 2, -8, .6f, 2, 2, .91f, 0xff9999);
            helper(face, 13, -8, .6f, 2, 2, .91f, 0xff9999);

            face.position.x = -.5f;
            face.position.y = 4;
            face.position.z = 4;
            scene.add(face);
            #endregion

            #region RAINBOW
            var rainbow = new THREE.Object3D();
            for (var c = 0; c < numRainChunks - 1; c++)
            {
                var yOffset = 8;
                if (c % 2 == 1) yOffset = 7;
                var xOffset = (-c * 8) - 16.5f;
                helper(rainbow, xOffset, yOffset, 0, 8, 3, 1, 0xff0000);
                helper(rainbow, xOffset, yOffset - 3, 0, 8, 3, 1, 0xff9900);
                helper(rainbow, xOffset, yOffset - 6, 0, 8, 3, 1, 0xffff00);
                helper(rainbow, xOffset, yOffset - 9, 0, 8, 3, 1, 0x33ff00);
                helper(rainbow, xOffset, yOffset - 12, 0, 8, 3, 1, 0x0099ff);
                helper(rainbow, xOffset, yOffset - 15, 0, 8, 3, 1, 0x6633ff);
            }
            scene.add(rainbow);
            #endregion


            #region rainChunk
            var rainChunk = new THREE.Object3D();
            helper(rainChunk, -16.5f, 7, 0, 8, 3, 1, 0xff0000);
            helper(rainChunk, -16.5f, 4, 0, 8, 3, 1, 0xff9900);
            helper(rainChunk, -16.5f, 1, 0, 8, 3, 1, 0xffff00);
            helper(rainChunk, -16.5f, -2, 0, 8, 3, 1, 0x33ff00);
            helper(rainChunk, -16.5f, -5, 0, 8, 3, 1, 0x0099ff);
            helper(rainChunk, -16.5f, -8, 0, 8, 3, 1, 0x6633ff);
            rainChunk.position.x -= (8 * (numRainChunks - 1));
            scene.add(rainChunk);
            #endregion

            #region stars



            for (var state = 0; state < 6; state++)
            {

                stars.Add(new List<THREE.Object3D>());

                for (var c = 0; c < numStars; c++)
                {
                    var star = new THREE.Object3D();
                    star.position.x = Math_random() * 200 - 100;
                    star.position.y = Math_random() * 200 - 100;
                    star.position.z = Math_random() * 200 - 100;
                    buildStar(star, state);
                    scene.add(star);
                    stars[state].Add(star);
                }
            }
            #endregion


            var pointLight = new THREE.PointLight(0xFFFFFF);
            pointLight.position.z = 1000;
            scene.add(pointLight);



            #endregion




            #region IsDisposed

            Dispose = delegate
            {
                if (IsDisposed)
                    return;

                IsDisposed = true;

                page_song.pause();
                page_song2.pause();

                container.Orphanize();
            };
            #endregion




            Native.window.onframe +=
                delegate
                {
                    f delta = clock.ElapsedMilliseconds * 0.001f;
                    clock.Restart();

                    if (running) deltaSum += delta;

                    if (deltaSum > .07)
                    {
                        deltaSum = deltaSum % .07f;
                        frame = (frame + 1) % 12;
                        for (var c = 0; c < numStars; c++)
                        {
                            var tempX = stars[5][c].position.x;
                            var tempY = stars[5][c].position.y;
                            var tempZ = stars[5][c].position.z;
                            for (var state = 5; state > 0; state--)
                            {
                                var star = stars[state][c];
                                var star2 = stars[state - 1][c];
                                star.position.x = star2.position.x - 8;
                                star.position.y = star2.position.y;
                                star.position.z = star2.position.z;

                                if (star.position.x < -100)
                                {
                                    star.position.x += 200;
                                    star.position.y = Math_random() * 200 - 100;
                                    star.position.z = Math_random() * 200 - 100;
                                }
                            }
                            stars[0][c].position.x = tempX;
                            stars[0][c].position.y = tempY;
                            stars[0][c].position.z = tempZ;
                        }

                        #region  dear JSC, please start supporting switch!

                        if (frame == 0)
                        {
                            face.position.x++;
                            feet.position.x++;
                        }
                        else if (frame == 1)
                        {
                            face.position.y--;
                            feet.position.x++;
                            feet.position.y--;
                            poptart.position.y--;
                            rainbow.position.x -= 9;
                            rainChunk.position.x += (8 * (numRainChunks - 1)) - 1;
                        }
                        else if (frame == 2)
                        {
                            feet.position.x--;
                        }
                        else if (frame == 3)
                        {
                            face.position.x--;
                            feet.position.x--;
                            rainbow.position.x += 9;
                            rainChunk.position.x -= (8 * (numRainChunks - 1)) - 1;

                        }
                        else if (frame == 4)
                        {
                            face.position.y++;
                        }
                        else if (frame == 5)
                        {
                            poptart.position.y++;
                            feet.position.y++;
                            rainbow.position.x -= 9;
                            rainChunk.position.x += (8 * (numRainChunks - 1)) - 1;
                        }
                        else if (frame == 6)
                        {

                            face.position.x++;
                            feet.position.x++;
                        }
                        else if (frame == 7)
                        {
                            poptart.position.y--;
                            face.position.y--;
                            feet.position.x++;
                            feet.position.y--;
                            rainbow.position.x += 9;
                            rainChunk.position.x -= (8 * (numRainChunks - 1)) - 1;
                        }
                        else if (frame == 8)
                        {
                            feet.position.x--;
                        }
                        else if (frame == 9)
                        {
                            face.position.x--;
                            feet.position.x--;
                            rainbow.position.x -= 9;
                            rainChunk.position.x += (8 * (numRainChunks - 1)) - 1;
                        }
                        else if (frame == 10)
                        {
                            face.position.y++;
                        }
                        else if (frame == 11)
                        {
                            poptart.position.y++;
                            feet.position.y++;
                            rainbow.position.x += 9;
                            rainChunk.position.x -= (8 * (numRainChunks - 1)) - 1;
                        }
                        #endregion

                    }
                    camera.position.x += (mouseX - camera.position.x) * .005f;
                    camera.position.y += (-mouseY - camera.position.y) * .005f;
                    camera.lookAt(scene.position);
                    renderer.render(scene, camera);
                };





            #region AtResize
            Action AtResize = delegate
            {
                container.style.SetLocation(0, 0, Native.window.Width, Native.window.Height);

                camera.aspect = Native.window.aspect;
                camera.updateProjectionMatrix();

                renderer.setSize(Native.window.Width, Native.window.Height);
            };

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

            AtResize();
            #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


        }
        // no animation no more?

        /// <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(IApp page = null)
        {
            // 20150527  i see a red blob. broken?

            var sw = Stopwatch.StartNew();

            // X:\jsc.svn\examples\javascript\synergy\webgl\WebGLMD2MorphtargetExample\WebGLMD2MorphtargetExample\Application.cs

            Console.WriteLine("before three");

            // fails with gallery? why?
            //Action Toggle = DiagnosticsConsole.ApplicationContent.BindKeyboardToDiagnosticsConsole();


            Console.WriteLine("InitializeContent");
            // http://oos.moxiecode.com/js_webgl/md5_test/


            var oldTime = 0L;

            var cameraTarget = new THREE.Vector3 { x = 0, y = 300, z = 0 };

            var positionVector = new THREE.Vector3();
            var lookVector = new THREE.Vector3();

            var lastframe = 0;

            var scene = new THREE.Scene();
            scene.fog = new THREE.Fog(0x000000, 1000, 5000);

            var camera = new THREE.PerspectiveCamera(50, Native.window.aspect, 1, 10000);
            camera.position.z = 800;
            camera.position.y = 100;

            camera.lookAt(scene.position);
            scene.add(camera);

            // floor
            var plane = new THREE.PlaneGeometry(10000, 10000, 50, 50);
            var floorMaterial = new THREE.MeshBasicMaterial(new { wireframe = true, color = 0x333333 });
            var floor = new THREE.Mesh(plane, floorMaterial);
            floor.rotation.x = -Math.PI / 2;
            scene.add(floor);

            // renderer
            var renderer = new THREE.WebGLRenderer(new { antialias = true });
            //renderer.setClearColorHex(0x000000);

            renderer.domElement.AttachToDocument();


            //           0200001f WebGLBossHarvesterByOutsideOfSociety.Application +<> c__DisplayClass2
            //           script: error JSC1000: unsupported flow detected, try to simplify.
            //Assembly V:\WebGLBossHarvesterByOutsideOfSociety.Application.exe
            //DeclaringType WebGLBossHarvesterByOutsideOfSociety.Application +<> c__DisplayClass2,
            //OwnerMethod <.ctor > b__5
            //Offset 005b
            // did the problem just dissapear?


            var controls = new THREE.OrbitControls(camera, renderer.domElement);


            #region harvester_md5mesh
            new THREE.JSONLoader().load(
                new WebGLBossHarvesterByOutsideOfSociety.Models.harvester_md5mesh().Content.src,
                (Action<dynamic>)
                    (geometry =>
                    {
                        Console.WriteLine("geometry ready!");

                        //console.log("Number of bones: "+geometry.bones.length);

                        var material = new THREE.MeshBasicMaterial(new
                        {
                            color = 0xffffff,
                            wireframe = true,
                            opacity = 0.25,
                            transparent = true,
                            skinning = true
                        });

                        object geometry_object = geometry;
                        var skin = new THREE.SkinnedMesh(geometry_object, material);
                        scene.add(skin);


                        object geometry_animation = geometry.animation;
                        //THREE.AnimationHandler.add(geometry_animation);

                        //var animation = new THREE.Animation(skin, "walk1");
                        //animation.play();

                        skin.rotation.x = -Math.PI / 2;
                        skin.rotation.z = -Math.PI / 2;

                        // view-source:http://threejs.org/examples/webgl_animation_skinning_morph.html
                        var boneArray = new Dictionary<int, THREE.Mesh>();


                        var boneContainer = new THREE.Object3D();

                        boneContainer.rotation.x = -Math.PI / 2;
                        boneContainer.rotation.z = -Math.PI / 2;

                        scene.add(boneContainer);

                        var index = 0;
                        var pmaterial = new THREE.MeshPhongMaterial(new { color = 0xff0000 });

                        //for (var b = 1; b != skin.bones.Length; b++)
                        //{

                        //    var bone = skin.bones[b];

                        //    var nc = bone.children.Length;

                        //    for (var c = 0; c != nc; c++)
                        //    {
                        //        var child = bone.children[c];

                        //        var size = Math.Min(child.position.length() * 0.05, 8);

                        //        var cylinder = new THREE.CylinderGeometry(size, 0.1, child.position.length(), 6);

                        //        // ERROR: Matrix's .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.  Please update your code.
                        //        cylinder.applyMatrix(
                        //            new THREE.Matrix4().makeRotationFromEuler(
                        //               new THREE.Euler(Math.PI / 2, 0, 0)
                        //            )
                        //        );

                        //        cylinder.applyMatrix(new THREE.Matrix4().setPosition(new THREE.Vector3(0, 0, 0.5 * child.position.length())));
                        //        var mesh = new THREE.Mesh(cylinder, pmaterial);

                        //        boneArray[child.id] = mesh;
                        //        boneContainer.add(mesh);
                        //    }

                        //}




                        #region render


                        Native.window.onframe += delegate
                        {
                            Func<long> Date_now = () => (long)new IFunction("return Date.now();").apply(null);

                            var time = Date_now();
                            double delta = time - oldTime;


                            if (oldTime == 0)
                            {
                                delta = 1000 / 60.0;
                            }

                            oldTime = time;




                            THREE.AnimationHandler.update(delta / 1000.0);



                            // does not exist?
                            //for (var b = 1; b != skin.bones.Length; b++)
                            //{

                            //    var bone = skin.bones[b];
                            //    var nc = bone.children.Length;

                            //    for (var c = 0; c != nc; c++)
                            //    {

                            //        var child = bone.children[c];
                            //        var child_bone = (THREE.Bone)(object)child;
                            //        var id = child.id;
                            //        var mesh = boneArray[id];

                            //        positionVector.getPositionFromMatrix(child_bone.skinMatrix);
                            //        mesh.position.copy(positionVector);

                            //        var child_parent_bone = (THREE.Bone)(object)child.parent;
                            //        lookVector.getPositionFromMatrix(child_parent_bone.skinMatrix);
                            //        mesh.lookAt(lookVector);

                            //    }

                            //}


                            boneContainer.position.z = skin.position.z;

                            //var frame = (int)Math.Floor(animation.currentTime * 24.0);
                            var frame = (int)Math.Floor(sw.ElapsedMilliseconds * 24.0);

                            if (frame >= 0 && lastframe > frame)
                            {
                                skin.position.z += 304.799987793; // got that from the root bone, total movement of one walk cycle
                            }
                            lastframe = frame;

                            var speed = delta * 0.131;

                            cameraTarget.z += speed;

                            if (skin.position.z > floor.position.z + 1000.0)
                            {
                                floor.position.z += 1000.0;
                            };


                            //camera.position.x = 800.0 * Math.Sin(time / 3000.0);
                            //camera.position.z = cameraTarget.z + 800.0 * Math.Cos(time / 3000.0);

                            //camera.lookAt(cameraTarget);

                            controls.update();
                            camera.position = controls.center.clone();



                            renderer.render(scene, camera);

                        };
                        #endregion

                    }
               )
           );
            #endregion

            //var harvester_src = new WebGLBossHarvesterByOutsideOfSociety.Models.harvester().Content.src;

            //Console.WriteLine("before harvester " + new { harvester_src });
            //loader.load(harvester_src, harvesterLoaded);

            // lights
            var pointLight = new THREE.PointLight(0xffffff, 1.0, 0);


            pointLight.AttachTo(camera);



            #region AtResize
            Action AtResize = delegate
            {
                camera.aspect = Native.window.aspect;
                camera.updateProjectionMatrix();

                renderer.setSize(Native.window.Width, Native.window.Height);
            };
            Native.window.onresize +=
              delegate
            {
                AtResize();
            };

            AtResize();
            #endregion

            Console.WriteLine("renderer ready!");


            //#region onmousedown
            //Native.document.onmousedown +=
            //     e =>
            //     {
            //         if (e.MouseButton == IEvent.MouseButtonEnum.Middle)
            //         {
            //             if (Native.document.pointerLockElement == Native.document.body)
            //             {
            //                 // cant requestFullscreen while pointerLockElement
            //                 Console.WriteLine("exitPointerLock");
            //                 Native.document.exitPointerLock();
            //                 //Native.document.exitFullscreen();
            //                 return;
            //             }

            //             Console.WriteLine("requestFullscreen");
            //             //Native.document.body.requestFullscreen();
            //             Native.document.body.requestPointerLock();
            //             return;
            //         }
            //     };
            //#endregion


            #region ZeProperties
            var ze = new ZeProperties();

            ze.Show();
            ze.treeView1.Nodes.Clear();

            ze.Add(() => renderer);
            ze.Add(() => controls);
            ze.Add(() => scene);
            ze.Left = 0;
            #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(IApp page)
        {

           // SCENE
	         scene = new THREE.Scene();
	        // CAMERA
	        var SCREEN_WIDTH = Native.window.Width;
            var SCREEN_HEIGHT = Native.window.Height;
	        var VIEW_ANGLE = 45;
            var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
            var NEAR = 0.1;
            var FAR = 20000;

	        // perspective cameras
	        perspectiveCamera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
	        perspectiveCamera.position.set(0,200,550);
	        perspectiveCamera.lookAt(scene.position);
	        scene.add(perspectiveCamera);

	        // orthographic cameras
	        mapCamera = new THREE.OrthographicCamera(
            Native.window.Width / -2,		// Left
            Native.window.Width / 2,		// Right
            Native.window.Height / 2,		// Top
            Native.window.Height / -2,	// Bottom
            -5000,            			// Near 
            10000 );           			// Far 
	        mapCamera.up = new THREE.Vector3(0,0,-1);
	        mapCamera.lookAt( new THREE.Vector3(0,-1,0) );
	        scene.add(mapCamera);

            renderer = new THREE.WebGLRenderer(
                   new
                   {
                       antialias = true
                   }
                );
            

	        // RENDERER
	        renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
            this.container = (IHTMLCanvas)renderer.domElement;
            this.container.AttachToDocument();
            this.container.style.SetLocation(0, 0);
	
	        // EVENTS
            //THREEx.WindowResize(renderer, mapCamera);
            //THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });

	        // STATS
            //stats = new Stats();
            //stats.domElement.style.position = 'absolute';
            //stats.domElement.style.bottom = '0px';
            //stats.domElement.style.zIndex = 100;
            //container.appendChild( stats.domElement );
	        // LIGHT
	        var light = new THREE.PointLight(0xffffff);
	        light.position.set(0,250,0);
	        scene.add(light);
	        // FLOOR
            var img = new uvgrid01();
            var floorTexture = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await img;
                                    s.needsUpdate = true;
                                });
            floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; 
            floorTexture.repeat.set( 10, 10 );
	        var floorMaterial = new THREE.MeshBasicMaterial( new { map = floorTexture, side = THREE.DoubleSide } );
	        var floorGeometry = new THREE.PlaneGeometry(2000, 2000, 10, 10);
	        var floor = new THREE.Mesh(floorGeometry, floorMaterial);
	        floor.position.y = -0.5;
	        floor.rotation.x = Math.PI / 2;
	        scene.add(floor);
	
	        ////////////
	        // CUSTOM //
	        ////////////
	

    //        materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/xpos.png' ) }));
    //materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/xneg.png' ) }));
    //materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/ypos.png' ) }));
    //materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/yneg.png' ) }));
    //materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/zpos.png' ) }));
    //materialArray.push(new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'images/zneg.png' ) }));
	        // create an array with six textures for cube
	        var materialArray = new THREE.MeshBasicMaterial[6];
	        materialArray[0] = (new THREE.MeshBasicMaterial( new { map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new xpos();
                                    s.needsUpdate = true;
                                }) 
            }));
	        materialArray[1] = (new THREE.MeshBasicMaterial( new {  map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new xneg();
                                    s.needsUpdate = true;
                                }) 
            }));
	        materialArray[2] = (new THREE.MeshBasicMaterial( new { map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new ypos();
                                    s.needsUpdate = true;
                                }) 
            }));
	        materialArray[3] = (new THREE.MeshBasicMaterial( new { map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new yneg();
                                    s.needsUpdate = true;
                                }) 
            }));
	        materialArray[4] = (new THREE.MeshBasicMaterial( new {map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new zpos();
                                    s.needsUpdate = true;
                                }) 
            }));
	        materialArray[5] = (new THREE.MeshBasicMaterial( new { 
            map = new THREE.Texture().With(
                                async s =>
                                {
                                    s.image = await new zneg();
                                    s.needsUpdate = true;
                                }) 
            }));

            //var MovingCubeMat = new THREE.MeshFaceMaterial(new { material = materialArray });

            var MovingCubeGeom = new THREE.CubeGeometry(50, 50, 50, 1, 1, 1);
            var MovingCube = new THREE.Mesh(MovingCubeGeom, new THREE.MeshBasicMaterial(new
                                            {
                                                color = new THREE.Color(0xFFFFFF)
                                            }));
            MovingCube.position.set(0, 25.1, 0);
            scene.add(MovingCube);	
	
	        // a little bit of scenery...

	        var ambientlight = new THREE.AmbientLight(0x111111);
	        scene.add( ambientlight );

            // torus knot
            var colorMaterial = new THREE.MeshLambertMaterial(new { color = new THREE.Color(0xff3333) });
            var shape = new THREE.Mesh(new THREE.TorusKnotGeometry(30, 6, 160, 10, 2, 5, 4), colorMaterial);
            shape.position.set(-200, 50, -200);
            scene.add(shape);
            // torus knot
            var colorMaterial2 = new THREE.MeshLambertMaterial(new { color = new THREE.Color(0x33ff33) });
            var shape2 = new THREE.Mesh(new THREE.TorusKnotGeometry(30, 6, 160, 10, 3, 2, 4), colorMaterial2);
            shape2.position.set(200, 50, -200);
            scene.add(shape2);
            // torus knot
            var colorMaterial3 = new THREE.MeshLambertMaterial(new { color = new THREE.Color(0xffff33) });
            var shape3 = new THREE.Mesh(new THREE.TorusKnotGeometry(30, 6, 160, 10, 4, 3, 4), colorMaterial3);
            shape3.position.set(200, 50, 200);
            scene.add(shape3);
            // torus knot
            var colorMaterial4 = new THREE.MeshLambertMaterial(new { color = new THREE.Color(0x3333ff) });
            var shape4 = new THREE.Mesh(new THREE.TorusKnotGeometry(30, 6, 160, 10, 3, 4, 4), colorMaterial4);
            shape4.position.set(-200, 50, 200);
            scene.add(shape4);

            renderer.setSize(Native.window.Width, Native.window.Height);
	        renderer.setClearColor( 0x000000, 1 );
	        renderer.autoClear = false;

            Native.window.onframe +=
                e =>
                {
                    perspectiveCamera.updateProjectionMatrix();

                    render();
                };
            var isPushed = false;

            this.container.onkeydown +=
                     m =>
                     {
                         isPushed = true;

                         if (isPushed)
                         {
                             //var delta = clock.getDelta(); // seconds.
                             var moveDistance = 200 * 2; // 200 pixels per second
                             var rotateAngle = Math.PI / 2 * 2;   // pi/2 radians (90 degrees) per second

                             // local transformations

                             // move forwards/backwards/left/right
                             if (m.KeyCode == 87)
                                 MovingCube.translateZ(-moveDistance);
                             if (m.KeyCode == 83)
                                 MovingCube.translateZ(moveDistance);
                             if (m.KeyCode == 81)
                                 MovingCube.translateX(-moveDistance);
                             if (m.KeyCode == 69)
                                 MovingCube.translateX(moveDistance);

                             //// rotate left/right/up/down
                             //var rotation_matrix = new THREE.Matrix4().identity();
                             //if (m.KeyCode == 65)
                             //    MovingCube.rotateOnAxis(new THREE.Vector3(0, 1, 0), rotateAngle);
                             //if (m.KeyCode == 68)
                             //    MovingCube.rotateOnAxis(new THREE.Vector3(0, 1, 0), -rotateAngle);

                             //if (m.KeyCode == 90)
                             //{
                             //    MovingCube.position.set(0, 25.1, 0);
                             //    MovingCube.rotation.set(0, 0, 0);
                             //}
                         }
             };

            this.container.onkeyup += e =>
            {
                isPushed = false;
            };

            Native.window.onresize +=
                delegate
                {


                    //if (canvas.parentNode == Native.document.body)

                    // are we embedded?
                    if (page != null)
                        renderer.setSize();
                };

          
        }