(function(){
    
    var img_earth     = null;
    
    //var img_sky     = new Image();
	//img_sky.src = 'sky3.png';
    
    var tex_earth;
    var tex_sky;
    
    var canvas;
    var context3d;
    var rotationX = 90;
    var rotationY = 0;
    var rotationZ = 270;
    
    
    var earth;
    var sky;
    
    var zoom = 2.2;
    
    window.addEventListener('load', function(){
	
	canvas = document.getElementById("canvas");
	
	try {
	    context3d = canvas.getContext("opera-3d");
	    
	    if (!context3d)
	    {
		throw new Error();
	    }
	}
	catch (e)
	{
	    notSupported();
	    return;
	}
	
	img_earth = new Image();
	img_earth.onload = dependenciesLoaded;
	img_earth.src = 'earth.jpg';
	
    }, false);
	
    function dependenciesLoaded()
    {
	supported();
	
	tex_earth = context3d.createTexture(img_earth);
	//tex_sky   = context3d.createTexture(img_sky);
	
	canvas.addEventListener('mousedown', function(e)
	{
	    var x = e.clientX;
	    var y = e.clientY;
	    
	    document.addEventListener('mousemove', mousemove, false);
            document.addEventListener('mouseup', mouseup, false);
	    
	    function mousemove(e)
	    {
		rotationX -= (y-e.clientY)/5;            
		rotationZ += (x-e.clientX)/5;
		
		rotationX = Math.min(180, Math.max(0, rotationX));
		
		x = e.clientX;
		y = e.clientY;
		
		render();
	    };
	    
	    function mouseup()
	    {
		document.removeEventListener('mousemove', mousemove, false);
		document.removeEventListener('mouseup', mousemove, false);
	    }
	    
	}, false);
	
	canvas.addEventListener('mousewheel', function(e)
	{
	    zoom += e.detail/20;
	    if (zoom > 5) zoom = 5;
	    if (zoom < 1) zoom = 1;
	    render();
	    
	    e.preventDefault && e.preventDefault();
	    
	}, false);
	
	if (!context3d)
	{
	  alert("3d canvas not supported");
	  return;
	}
    
	sky = createSky();
	earth = createEarth();
	
	render();
	
    }
    
    function supported()
    {
	var ele = document.createElement('p');
	ele.textContent = 'Click and drag to navigate around the 3D Model. Use your mouse wheel to zoom.';
	
	canvas.parentNode.insertBefore(ele, canvas);
	canvas.style.display = 'block';
    }
    
    function notSupported()
    {
	var ele = document.createElement('p');
	ele.textContent = 'The demo was not able to run because your browser does not support Canvas 3D.';
	
	canvas.parentNode.insertBefore(ele, canvas);
	canvas.parentNode.removeChild(canvas);
    }
    
    function render(){
	
	context3d.beginScene();   
	
	context3d.translate(0,0,-zoom);
	
	context3d.translate(0,0,-zoom);
	
	context3d.rotateX(rotationX);
	context3d.rotateY(rotationY);
	context3d.rotateZ(rotationZ);
	
	var scale = zoom*20;
	
	context3d.farPlane = 200;
	
	context3d.scale(scale,scale,scale);
	/*
	context3d.texture = tex_sky;
	context3d.draw3DModel(sky);
	*/
	context3d.scale(1/scale,1/scale,1/scale);
	
	context3d.texture = tex_earth;
	context3d.draw3DModel(earth);
	
	context3d.endScene();
    }
    
    
    function createSky()
    {
	var model = context3d.create3DModel();
	
	model.addVertex(-1, 1, -1, 0, 0);
	model.addVertex(-1, -1, -1, 0, 0.5);
	model.addVertex(1, 1, -1, 0.25, 0);
	model.addVertex(1, -1, -1, 0.25, 0.5);
	model.addVertex(1, 1, 1, 0.5, 0);
	model.addVertex(1, -1, 1, 0.5, 0.5);
	model.addVertex(-1, 1, 1, 0.75, 0);
	model.addVertex(-1, -1, 1, 0.75, 0.5);
	model.addVertex(-1, 1, -1, 1, 0);
	model.addVertex(-1, -1, -1, 1, 0.5);
      
	// the caps
	model.addVertex(-1, 1, -1, 0, 0.5);
	model.addVertex(-1, 1, 1, 0.25, 0.5);
	model.addVertex(1, 1, -1, 0, 1);
	model.addVertex(1, 1, 1, 0, 0.5);
	
	model.addVertex(-1, -1, -1, 0.5, 1);
	model.addVertex(-1, -1, 1, 0.5, 0.5);
	model.addVertex(1, -1, -1, 0.25, 1);
	model.addVertex(1, -1, 1, 0.25, 0.5);
	
	model.addTriangle(0,1,2);
	model.addTriangle(1,2,3);
	model.addTriangle(2,3,4);
	model.addTriangle(3,4,5);
	model.addTriangle(4,5,6);
	model.addTriangle(5,6,7);
	model.addTriangle(6,7,8);
	model.addTriangle(7,8,9);
	
	model.addTriangle(10,11,12);
	model.addTriangle(11,12,13);
	
	model.addTriangle(14,15,16);
	model.addTriangle(15,16,17);
	
	return model;
    }
    
    function createEarth()
    {
	var model = context3d.create3DModel();
	
	var x,y;
	
	for (y=-10; y<=10; y++)
	{
	    for (x = (y%2 ? 0 : 0.5); x<40; x++)
	    {
		model.addVertex(
		    Math.sin(x/39*Math.PI*2) * Math.cos(y/10*Math.PI/2),
		    Math.cos(x/39*Math.PI*2) * Math.cos(y/10*Math.PI/2),
		    Math.sin(y/10*Math.PI/2),
		    (x/39),
		    (y+10)/20
		);
		
	    }
    
	}
	
	for (var n=0; n<20*40; n++)
	{
	    
	    model.addTriangle(
		n,
		n+40,
		n%40==39 ? n-39 : n+1
	    );
    
	    model.addTriangle(
		n,
		n+40,
		n+39+(n%40==0 ? 40 : 0)
	    );
	}
	
	return model;
	
    }
    
})();