

/***********************************************************************************/
/*																				   */
/*	  Copyright 2003 University of Texas at Austin                                 */
/*	  Authors: Dr C Bajaj bajaj@cs.utexas.edu,                                     */
/*             S K Vinay  skvinay@cs.utexas.edu                                    */
/*             Anthony Thane thanea@ices.utexas.edu                                */
/*																				   */
/*    This program is free software; you can redistribute it and/or modify         */
/*    it under the terms of the GNU General Public License as published by         */
/*    the Free Software Foundation; either version 2 of the License, or            */
/*    (at your option) any later version.                                          */
/*																				   */
/*    This program is distributed in the hope that it will be useful,              */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of               */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
/*    GNU General Public License for more details.                                 */
/*																				   */
/*    You should have received a copy of the GNU General Public License			   */
/*    along with this program; if not, write to the Free Software                  */
/*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    */
/*                                                                                 */
/***********************************************************************************/
// FunctionSphereRenderer.cpp: implementation of the FunctionSphereRenderer class.
//
//////////////////////////////////////////////////////////////////////

#include "FunctionSphereRenderer.h"
#include "Texture.h"
#include "GlobalCGContext.h"
#include "cgGLVertexFunctionShader.h"
#include "cgGLFragmentFunctionShader.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

using CCVImposterRenderer::FunctionSphereRenderer;

FunctionSphereRenderer::FunctionSphereRenderer()
{
	m_VertexProgram = 0;
	m_FragmentProgram = 0;
	m_Data = 0;
	m_minx = 0.0;
	m_miny = 0.0;
	m_minz = 0.0;
	m_maxx = 1.0;
	m_maxy = 1.0;
	m_maxz = 1.0;
	m_Width = 10;
	m_Height = 10;
	m_Depth = 10;
}

FunctionSphereRenderer::~FunctionSphereRenderer()
{
	if( m_FragmentProgram ) cgDestroyProgram(m_FragmentProgram);
	if( m_VertexProgram ) cgDestroyProgram(m_VertexProgram);
	delete [] m_Data; m_Data = 0;
}

bool FunctionSphereRenderer::bindProgramAndParams()
{
	// Set up for ball rendering
	cgGLEnableProfile(m_VertexProfile);
	cgGLBindProgram(m_VertexProgram);

	cgGLEnableProfile(m_FragmentProfile);
	cgGLBindProgram(m_FragmentProgram);

	cgGLEnableTextureParameter(m_NormalMapParam);
	cgGLEnableTextureParameter(m_DepthMapParam);
	cgGLEnableTextureParameter(m_FunctionMapParam);

	cgGLSetParameter4f(m_MainColorParam, 1.0, 0.0, 0.0, 1.0); // red
	cgGLSetParameter3f(m_MinExtentParam, (float)m_minx, (float)m_miny, (float)m_minz );
	cgGLSetParameter3f(m_MaxExtentParam, (float)m_maxx, (float)m_maxy, (float)m_maxz );

	return true;
}

void FunctionSphereRenderer::bindMatrices()
{
	cgGLSetStateMatrixParameter(m_ModelViewITParam, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE_TRANSPOSE);
	cgGLSetStateMatrixParameter(m_ModelViewProjParam, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
	cgGLSetStateMatrixParameter(m_ProjParam, CG_GL_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
	cgGLSetStateMatrixParameter(m_ModelViewInverseParam, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_INVERSE);
	
	cgGLSetStateMatrixParameter(m_ModelViewProjInverseParam, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_INVERSE);
}

bool FunctionSphereRenderer::unbindProgramAndParams()
{
	cgGLDisableTextureParameter(m_FunctionMapParam);
	cgGLDisableTextureParameter(m_NormalMapParam);
	cgGLDisableTextureParameter(m_DepthMapParam);
	cgGLDisableProfile(m_VertexProfile);
	cgGLDisableProfile(m_FragmentProfile); 	
	return true;
}

bool FunctionSphereRenderer::initCG()
{
	if ( cgGLIsProfileSupported(CG_PROFILE_VP20) ) 
		m_VertexProfile = CG_PROFILE_VP20;
	else 
		return false;

	if ( cgGLIsProfileSupported(CG_PROFILE_FP30) ) 
		m_FragmentProfile = CG_PROFILE_FP30;
	else 
		return false;

	return true;
}

bool FunctionSphereRenderer::loadProgram()
{
	if( !m_Data ) return false; // this shouldnt crash the rendering, ensure that

	if( m_FragmentProgram ) cgDestroyProgram(m_FragmentProgram);
	if( m_VertexProgram ) cgDestroyProgram(m_VertexProgram);

	CGcontext context = GlobalCGContext::getCGContext();

	// Create Vertex Program for Spheres
	//m_VertexProgram = cgCreateProgramFromFile(context, CG_SOURCE,
	//	"cgGLVertexFunctionShader.cg", m_VertexProfile, 0, 0);
	m_VertexProgram = cgCreateProgram(context, CG_SOURCE,cgGLVertexFunctionShader,
		m_VertexProfile, 0, 0 );

	// Load Vertex Program
	cgGLLoadProgram(m_VertexProgram);

	// get parameter handles
	m_PositionParam = cgGetNamedParameter(m_VertexProgram, "IN.center");
	m_ColorParam = cgGetNamedParameter(m_VertexProgram, "IN.color");
	m_ModelViewITParam = cgGetNamedParameter(m_VertexProgram, "ModelViewIT");
	m_ModelViewInverseParam = cgGetNamedParameter(m_VertexProgram, "ModelViewInverse");
	m_ModelViewProjParam = cgGetNamedParameter(m_VertexProgram, "ModelViewProj");
	m_ProjParam = cgGetNamedParameter(m_VertexProgram, "Proj");

	if (!m_ModelViewITParam || !m_ModelViewProjParam || !m_ProjParam || !m_ColorParam || !m_PositionParam ) 
		return false;

	// Create Fragment Program
	//m_FragmentProgram = cgCreateProgramFromFile(context, CG_SOURCE,
	//	"cgGLFragmentFunctionShader.cg", m_FragmentProfile, 0, 0);
	m_FragmentProgram = cgCreateProgram(context, CG_SOURCE,cgGLFragmentFunctionShader,
		m_FragmentProfile, 0, 0 );

	// Load Fragment Program
	cgGLLoadProgram(m_FragmentProgram);

	// get parameter handles
	m_MainColorParam = cgGetNamedParameter(m_FragmentProgram, "maincolor");
	m_NormalMapParam = cgGetNamedParameter(m_FragmentProgram, "normalmap");
	m_DepthMapParam = cgGetNamedParameter(m_FragmentProgram, "depthmap");
	m_FunctionMapParam = cgGetNamedParameter(m_FragmentProgram, "functionmap");
	m_ModelViewProjInverseParam = cgGetNamedParameter(m_FragmentProgram, "ModelViewProjInverse");
	m_MinExtentParam = cgGetNamedParameter(m_FragmentProgram, "minExtent");
	m_MaxExtentParam = cgGetNamedParameter(m_FragmentProgram, "maxExtent");

	// prepare the textures
	m_TextureNormalMap = new Texture();
	//m_TextureNormalMap->loadPGM("alphamask.pgm");
	m_TextureNormalMap->calculateSphereOpacityAndNormalMap(512);

	m_TextureDepthMap = new Texture();
	m_TextureDepthMap->calculateDepthMap(512,512);

	m_TextureFunctionMap = new Texture();
	if( !m_TextureFunctionMap->loadFunction(m_Data, m_Width, m_Height, m_Depth)) return false;

	cgGLSetTextureParameter(m_NormalMapParam, m_TextureNormalMap->getTextureID());
	cgGLSetTextureParameter(m_DepthMapParam, m_TextureDepthMap->getTextureID());
	cgGLSetTextureParameter(m_FunctionMapParam, m_TextureFunctionMap->getTextureID());
	return true;
}

bool FunctionSphereRenderer::addFunction( unsigned char* data, double minx, double miny, double minz, double maxx, double maxy, double maxz, int width, int height, int depth)
{
	delete [] m_Data; // how to delete from CG ?
	m_Data = data;
	m_minx = minx;
	m_miny = miny;
	m_minz = minz;
	m_maxx = maxx;
	m_maxy = maxy;
	m_maxz = maxz;
	m_Width = width;
	m_Height = height;
	m_Depth = depth;
	return true;
}

// loads cubemap without making CG calls
bool FunctionSphereRenderer::fallbackLoadProgram() {
        m_TextureFunctionMap = new Texture();
        return m_TextureFunctionMap->loadFunction(m_Data, m_Width, m_Height, m_Depth);
}
