// http://threejs.org/examples/webgl_interactive_cubes_gpu.html

var pos = new THREE.Vector3();
var normal = new THREE.Vector3();

var FXBirdBuilder = function () {

	FRAME.Module.call( this );

	this.parameters.input = {
		phase: 0
	};

	var width = renderer.domElement.width;
	var height = renderer.domElement.height;

	var camera = new THREE.PerspectiveCamera( 60, width / height, 1, 5000 );

	var scene = new THREE.Scene;

  	var ambientLight = new THREE.AmbientLight( 0x22222222 );
    scene.add(ambientLight);

	var light1 = new THREE.PointLight( 0xffffff, 5, 300 );
	
	light1.position.set ( -20, 30, 250 );
	scene.add( light1 );

	this.numCubes = 400;
	this.radius = 200;

	this.cubeGeometry = new THREE.CubeGeometry(1,1,1);

	this.cubeMaterial = new THREE.ShaderMaterial( 
	{
		uniforms: 
		{
			texture:   { type: "t", value: resourceManager.getTexture("particle_steam") },
		},
		attributes:     
		{
			customVisible:	{ type: 'f',  value: [] },
			customSize:		{ type: 'f',  value: [] },
			customColor:	{ type: 'c',  value: new THREE.Color( 0xffffff ) },
			customOpacity:	{ type: 'f',  value: [] }
		},
		vertexShader: [

			"attribute float customSize;",
			"void main()",
			"{",
				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
				"gl_PointSize = customSize * ( 300.0 / length( mvPosition.xyz ) );",     // scale particles as objects in 3D space
				"gl_Position = projectionMatrix * mvPosition;",
			"}"
			].join("\n"),

		fragmentShader: [

			"uniform sampler2D texture;",
			"uniform float opacity;",
			"void main()", 
			"{",
				"gl_FragColor = texture2D( texture,  gl_PointCoord );",    
			"}"
			].join("\n"),

		transparent: true, 
		blending: THREE.NormalBlending, 
		depthTest: true,
		depthWrite: false
	});

    this.cubeMaterial = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: false
    });

	this.cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors	} );

	this.cubeMesh = new THREE.Mesh( this.cubeGeometry, this.cubeMaterial );

	this.randomizer = new THREE.Randomizer();

	this.cubes = [];

	camera.position.set( 0, 0, 10 );
	var type;

	this.init = function ( parameters ) {

		type = parameters.type;

		if ( type == 1 )
			camera.rotation.z = 0.7;
		
		this.lasttime = 0;

		var lerp = function(a,b,x)
		{
			return a + (b-a)*x;
		};

		var polyval4 = function(a,b,c,d,e,x) {
			return a*x*x*x*x + b*x*x*x + c*x*x + d*x + e;
		};

		var neck = 0.48;
		var radius = function(y) {
			if (y<0 || y>1)
				return 0;

			if (y<neck)
				return lerp(1.4,0.15,y/neck);

			return polyval4(-.85, 0, 0, 0, 1, 1-(y-neck)/(1-neck));
		};

		var randomizer = this.randomizer;
		var a = randomizer.randFloat(0,1);
		
		var rnd = function(a,b) {
			if (a===undefined && b===undefined)
				return randomizer.randFloat(-1,1);
			else if (b===undefined)
				return randomizer.randFloat(0,a);
			return randomizer.randFloat(a,b);
		};

		var cubesize = function() {
			return 0.2+rnd(0.1);
		};


		if (this.parameters.phase == 0)
		{
			for( var i = 0; i < this.numCubes; i++ )
			{
				var position = new THREE.Vector3();
				var y = rnd(1);
				var r = radius(y);
				position.y = 10*y-5;
				position.x = r*rnd()*2;
				position.z = r*rnd()*2;

				var rotation = new THREE.Euler();
				rotation.x = rnd() * Math.PI;
				rotation.y = rnd() * Math.PI;
				rotation.z = rnd() * Math.PI;

				var scale = new THREE.Vector3();
				scale.x = cubesize();
				scale.y = cubesize();
				scale.z = cubesize();

				var cube = this.cubeMesh.clone();
				cube.position = position;
				cube.rotation = rotation;
				cube.quaternion.setFromEuler( rotation );
				cube.scale = scale;

				this.cubes.push( cube );
				scene.add( cube );
			}
		}

	},

	this.animate = function (t, perc) 
	{
		var inc = t-this.lasttime;
		this.lasttime = t;

		if (this.parameters.phase == 0)
		{
			for(var i = 0; i < this.numCubes; i++)
			{
				var cube = this.cubes[i];

				var rotation = new THREE.Euler();
				rotation.copy(cube.rotation);
				rotation.y += t;
				cube.quaternion.setFromEuler( rotation );
			}
		}
	}

	this.update = function ( t, perc ) {

		this.animate( t, perc );

		if ( this.renderToTexture )
			renderer.render( scene, camera, this.fbo, this.clearBuffer );
		else
			renderer.render( scene, camera );

	};

};