
function init(modelURL, textureURL)
{
	// Initialize
	 gl = initWebGL(
		// The id of the Canvas Element
		"vortex",
		// The ids of the vertex and fragment shaders
		"vshader", "fshader", 
		// The vertex attribute names used by the shaders.
		// The order they appear here corresponds to their index
		// used later.
		[ "vert", "normal", "texcoord"],
		// The clear color and depth values
		[ 0,0,0, 1 ], 10000);
		
	// save the initial shader
	g_shader_vortex = gl.program;

	// Set some uniform variables for the shaders
	gl.uniform1i(gl.getUniformLocation(gl.program, "basemap"), 0);
	
	// vortex shader variables / uniform locations
	u_baseRotation			= gl.getUniformLocation(gl.program, "baseRotation");
	u_corkscrewRotation		= gl.getUniformLocation(gl.program, "corkscrewRotation");
	u_corkscrewRange		= gl.getUniformLocation(gl.program, "corkscrewRange");
	u_taperEnd 				= gl.getUniformLocation(gl.program, "taperEnd");
	u_taperStart 			= gl.getUniformLocation(gl.program, "taperStart");
	u_lineColor 			= gl.getUniformLocation(gl.program, "lineColor");
	u_swapColor 			= gl.getUniformLocation(gl.program, "swapColor");
	u_swapTime 				= gl.getUniformLocation(gl.program, "swapTime");
	
	// only need to be set once
	gl.uniform1f(u_corkscrewRotation,	5.280);
	gl.uniform1f(u_corkscrewRange, 		80.265);
	gl.uniform1f(u_taperEnd, 			0.496);
	gl.uniform1f(u_taperStart, 			1.0);
	gl.uniform4f(u_lineColor, 			1.0, 1.0, 1.0, 1.0);
	gl.uniform4f(u_swapColor, 			1.0, 1.0, 1.0, 1.0);
	gl.uniform1f(u_swapTime, 			1.0);

	// Enable texturing
	gl.enable(gl.TEXTURE_2D);
	
	// Create a box. On return 'gl' contains a 'box' property with
	// the BufferObjects containing the arrays for vertices,
	// normals, texture coords, and indices.
	vortexCube 		= loadObj(gl, modelURL);

	// Load an image to use. Returns a WebGLTexture object
	vortexTexture 	= loadImageTexture(gl, textureURL);
	gl.bindTexture(gl.TEXTURE_2D, vortexTexture);

	// Create some matrices to use later and save their locations in the shaders
	gl.mvMatrix 					= new CanvasMatrix4();
	gl.u_normalMatrixLoc 			= gl.getUniformLocation(gl.program, "u_normalMatrix");
	gl.normalMatrix 				= new CanvasMatrix4();
	gl.u_modelViewProjMatrixLoc 	= gl.getUniformLocation(gl.program, "u_modelViewProjMatrix");
	gl.mvpMatrix 					= new CanvasMatrix4();

	// Enable all of the vertex attribute arrays.
	gl.enableVertexAttribArray(0);
	gl.enableVertexAttribArray(1);
	gl.enableVertexAttribArray(2);
	
	//add models to the scene
	sceneObjects.push(new model(gl, g_rotSpeed, 0, 1.2, vortexTexture, vortexCube, 0.0, g_shader_vortex));
	sceneObjects.push(new model(gl, g_rotSpeed, -g_zOffset, 1.2, vortexTexture, vortexCube, 0, g_shader_vortex));
	
	// used to save the starting values - used in effects.js
	startCorkSkrwRot = sceneObjects[0].corkscrewRotation;
	startCorkSkrwRng = sceneObjects[0].corkscrewRange;
	
	// initialize all the scene-objects (all two of them ;)
	for(var item in sceneObjects)
		sceneObjects[item].init();

	// start time
	startTime = new Date().getTime();
	
	// setup initialize lookat
	g_cam.setLookAt(new vec3(0, 0, 145), zeroVec(), upVec()); 
	
	//setup camera aniation controller
	g_camAnimProc = new camAnimProc(g_cam, camFrameList);
	
	g_camAnimCon.frameProc 		= g_camAnimProc;
	g_camAnimCon.timePerFrame	= 0.032;
	g_camAnimCon.totalFrames	= camFrameList.length;
	g_camAnimCon.loop 			= false;
	g_camAnimCon.begin();
	
	//start the state machine
	g_sceneStateMachine = new sceneAnimState(g_cam);
	
	// global references to the two scene states
	g_attractState 	= new attractMode(gl, g_cam, g_camAnimCon, sceneObjects[0], sceneObjects[1]);
	g_phoneState	= new phoneMode(gl, g_cam, g_camAnimCon, sceneObjects[0], sceneObjects[1], g_sceneStateMachine);
	
	// startup in "phone-mode" (looking down the barrel)
	g_sceneStateMachine.switchState(g_phoneState);
	
	return gl;
}

width = -1;
height = -1;

function reshape(gl)
{
	var canvas = document.getElementById('vortex');
	if (canvas.clientWidth == width && canvas.clientHeight == height)
		return;

	// clamp to one resolution
	width = g_width;
	height = g_height;

	// Set the viewport and projection matrix for the scene
	gl.viewport(0, 0, width, height);
	gl.perspectiveMatrix = new CanvasMatrix4();
	gl.perspectiveMatrix.perspective(90, width/height, 1, 10000);
}

doOnce = true; // weird logic due to the asynchronous nature of loading models with a GET request

function drawPicture(gl)
{
	// check if phone state should be on
	if(overlayIsOn)
	{
		overlayIsOn = false;
		g_sceneStateMachine.switchState(g_attractState);
	}

	// get elapsed time
	g_dt = new Date().getTime() - startTime;
	g_dt /= 1000.0;
	startTime = new Date().getTime();
	
	if(g_dt > 0.09)
		g_dt = 0.05;
		
	// Make sure the canvas is sized correctly.
	reshape(gl);

	// Clear the canvas
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

	 if(vortexCube != null && vortexCube.loaded == true)
	 {
		if(doOnce)
		{
			doOnce = false;
			// Set up all the vertex attributes for vertices, normals and texCoords
			gl.bindBuffer(gl.ARRAY_BUFFER, vortexCube.vertexObject);
			gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
	 
			gl.bindBuffer(gl.ARRAY_BUFFER, vortexCube.normalObject);
			gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0);
	 
			gl.bindBuffer(gl.ARRAY_BUFFER, vortexCube.texCoordObject);
			gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 0, 0);
			
			// Bind the index array
			gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, vortexCube.indexObject);
		}

		// Make a model/view matrix.
		gl.mvMatrix.makeIdentity(); // reset the camera
		
		// create the spin effect when flagged
		if(doEffect)
			spin();
			
		// update the states
		g_sceneStateMachine.update(g_dt);
		
		// udpate all the scene objects
		for( var item in sceneObjects)
			sceneObjects[item].update(g_dt);
 
		// dump the rotation speed of vortex models
		controller.xRot = controller.xRot*Math.max(g_dt*15, 0.9);
		controller.yRot = controller.yRot*Math.max(g_dt*15, 0.9);
		// clamp to zero
		if(Math.abs(controller.xRot) < 0.1)
			controller.xRot = 0.0;
		if(Math.abs(controller.yRot) < 0.1)
			controller.yRot = 0.0;
 
		// draw all the scene objects
		for( var item in sceneObjects)
			sceneObjects[item].draw();
	}
	
	gl.flush();

	// Show the framerate
	//framerate.snapshot();

	currentAngle += incAngle;
	if (currentAngle > 360)
		currentAngle -= 360;
}

