/**
 * @file VCRA-SZCZERBACKI-splatting.h
 * @brief Point Based Rendering Tool.
 *                                                                    
 * Point Based Rendering Tool (using OpenGL and GLUT).                 \n
 *                                                                     \n
 * Using partially the splatting code implemented by Jussi Rasanen for \n
 * his Master Thesis "Surface Splatting: Theory, Extensions and        \n
 * Implementation", 2002, at Helsinki University of Technology         \n
 *                                                                     \n
 * Course:      Visao Computacional e Realidade Aumentada (PUC-RIO).   \n
 * Instructor:  Marcelo Gattass.                                       \n
 * Student:     Ricardo Szczerbacki.                                   \n
 * Version:     1.00.                                                  \n
 * 2006.2                                                  \n
 */

#ifndef __SPLATTING_H
#define __SPLATTING_H

#include "ssVector.hpp"
#include "ssMatrix.hpp"
#include "ssAdditional.hpp"
#include "Timer.h"
#include "Mesh.h"
#include "ABuffer.h"
#include <glut.h>   /* includes glut and OpenGL */
#include <fstream>

static char lwoFileName[200]; /**< lwo file name (LightWave format mesh) */

const int   maxResolution = 609; /*256*/
const int   maxSubpixels = 16;
const float maxPrefiltersize = 0.0f;	//1.0f

static int sizex = 609,sizey = 609; /*256*/
static int subpixels = 1;
static float prefiltersize = 0.0f;	//1.0f

const float  defaultWidth = 609;
const float  defaultHeight = 609;
static float pixelScale = defaultWidth/(float)sizex;
static float figsx,figsy;

const int  jitterPatterns = 64;
const int  gausssamples = 1024;/*256*/
static Vector2 *prefilterJitter = NULL;
static Vector2 *lensJitter = NULL;

const float F = 2.0f;

const float prefiltercutoff = 2.0f;	//2.0f

const float conditionThreshold = 100.0f;

const int subdivision = 3;

const float focus = 10.0f;
const float aperture = 2.8f;
const float imagePlane = 1.0f;	//do not change
const float focalLength = imagePlane*focus/(imagePlane+focus);
const float lensRadius = focalLength*0.5f/aperture;

static bool rasterization = true;
static bool pointvisualization = false;
static bool reconstructionvisualization = false;


struct Splat
{
	Vector3   m_position;
	Vector3   m_normal;
	Vector4   m_color;
	float     m_size;
};

class CameraControls
{
public:
	CameraControls( float rotationScale = 1.0f, float translationScale = 1.0f, float inertia = 0.0f, bool framerateDependent = true )
	{
		m_rotationScale = rotationScale;
		m_translationScale = translationScale;
		m_inertia = inertia;
		m_framerateDependent = framerateDependent;

		m_angles.set(0,0,0);
		m_angleAdds.set(0,0,0);
		m_position.set(0,0,0);
		m_positionAdd.set(0,0,0);
		m_objectAngles.set(0,0,0);
		m_cameraMatrix.ident();
	}
	~CameraControls()
	{
	}

	const Matrix4x4 &getCameraMatrix()
	{
		float s,r;
		m_timer.sample();
		float dt = m_timer.getDelta();

	//camera movement
		if( m_framerateDependent )
		{
			s = 5.0f * m_translationScale * dt;
			r = m_rotationScale * 3.1415f / 4.0f * dt;
		}
		else
		{
			s = 0.5f * m_translationScale;
			r = m_rotationScale * 3.1415f / 64.0f;
		}

		m_angles += m_angleAdds;
		m_position += m_positionAdd;
		if( m_framerateDependent )
		{
			m_angleAdds *= float(pow(m_inertia,dt*30.0f));
			m_positionAdd *= float(pow(m_inertia,dt*30.0f));
		}
		else
		{
			m_angleAdds *= m_inertia;
			m_positionAdd *= m_inertia;
		}


		m_cameraMatrix.ident();
		m_cameraMatrix *= MatrixFactory::rotateZ( -m_angles.z );
		m_cameraMatrix *= MatrixFactory::rotateX( -m_angles.x );
		m_cameraMatrix *= MatrixFactory::rotateY( -m_angles.y );
		m_cameraMatrix.setColumn(3,Vector4(m_position.x,m_position.y,m_position.z,1.0f));
		return m_cameraMatrix;
	}
private:
	bool			m_framerateDependent;
	float			m_inertia;
	float			m_rotationScale;
	float			m_translationScale;
	Vector3			m_angles;
	Vector3			m_angleAdds;
	Vector3			m_position;
	Vector3			m_positionAdd;
	Matrix4x4		m_cameraMatrix;
	Timer			m_timer;

	Vector3		m_objectAngles;
};


#define PROJECTION_PERSPECTIVE


void loadLwoFile(char *filename);

void makeJitter(int subpixels);

#endif