//////////////////////////////////////////////////////////////////////
//
//	Crytek SuperFramework Source code
//	
//	File:PolyBump.h
//
//	History: 	
//    * July 16,2001: Created by Marco Corbetta
//    * 2/15/2002:    modified by Martin Mittring, integrated in a 3D Studio Plugin
//		- 2/21/2002 modified to work in 3DStudio max as a thread
//
//////////////////////////////////////////////////////////////////////

#ifndef POLYBUMP_H
#define POLYBUMP_H

#if _MSC_VER > 1000
# pragma once
#endif

//#include "Cry_Plane.h"																// Plane
#include "PbTri.h"																		// CPbTri
#include "EveryObjectOnlyOnce.h"											// CEveryObjectOnlyOnce

#ifdef USE_RASTERCUBE
	#include "TGA.h"																		// PIX_LoadTGA32
	#include "RasterCube.h"															// CRasterCube
#endif

class CSimpleIndexedMesh;
class CPolyBumpWorkerThread;
class CPBCloneMap;



#define TRIALVERSION_MAXHIGHPOLYCOUNT		35000

#define TRIALVERSION_MAXTEXTURESIZE			256

//////////////////////////////////////////////////////////////////////
class CPbMesh
{
public:
	//! constructor
									CPbMesh													();
		
	//! destructor
									~CPbMesh												();

	//! copy the data, doesn´t build a accelerator data structure
	//! /param mesh pointer to the input mesh
  void						GetNormalsAndClearBaseVectors	( CSimpleIndexedMesh *mesh, int iniMaterialID );

	//! for clonespace
	//! copy the data, doesn´t build a accelerator data structure (classes BuildNormalsAndClearBaseVectors)
	//! /param mesh pointer to the input mesh
	//! /param inpCloneMap pointer to the clonemap, must not be 0
	//! /param iniMaterialID -1 for every one, otherwise it's the triangle material id we want to calculated
	void						BuildNormalsAndBaseVectors			( CSimpleIndexedMesh *mesh, CPBCloneMap *inpCloneMap, int iniMaterialID );

	//! for object and tangentspace
	//! copy the data, doesn´t build a accelerator data structure (classes BuildNormalsAndClearBaseVectors)
	//! /param mesh pointer to the input mesh
	//! /param iniMaterialID -1 for every one, otherwise it's the triangle material id we want to calculated
	void						BuildNormalsAndBaseVectors			( CSimpleIndexedMesh *mesh, int iniMaterialID );

	//! this methor builds the internal data structured for speedup the raycasting
	//! /param inbDebug debug output is generated
	//! /return status information that could be shown later (is terminated with '\n')
	std::string			BuildRayAccelerator							( const bool inbDebug );

	//! paint all triangles into the texture, every triangle with its pointer
  void						DrawTrisPointers								( const bool inbDebug );

	//!
	//! /param invStart start vector of ray
	//! /param invEnd end vector of ray
  CPbTri *				ChooseNearestIntersection				( CIntInfoList &inIntersections, const Vec3 &invStart, const Vec3 &invEnd,
																									  const Vec3 &refnormal, Vec3 &respoint );

	//!
	//! /param invStart start vector of ray
	//! /param invEnd end vector of ray
  CPbTri *			ChooseNearestAcceptableIntersection( CIntInfoList &inIntersections, const Vec3 &invStart, const Vec3 &invEnd,
																									 const Vec3 &refnormal, Vec3 &respoint );

	//!
	//! /param invStart start vector of ray
	//! /param invEnd end vector of ray
  CPbTri *				ChooseLatestIntersection				( CIntInfoList &inIntersections, const Vec3 &invStart, const Vec3 &invEnd, 
																										const Vec3 &refnormal, Vec3 &respoint );

	//! calculate the size of the bounding sphere
	//! /return outMin minimum x,y,z of the bounding box
	//! /return outMin maximum x,y,z of the bounding box
	//! /return diameter size
	float						CalcBoundingVolume							( Vec3 &outMin, Vec3 &outMax );

	
	//! raytracing, gather unsorted hits
	//! call ClearListBefore and GetHitList afterwards
	//! /param inStart start vector in worldspace
	//! /param inDirection end vector of the ray
	//! /param outIntersections reference to the intersection list (make sure the list is empty)
	void						GatherRayHits										( const Vec3 invStart, const Vec3 invEnd, CIntInfoList &outIntersections, const CPbTri *inpIgnoreObject );

	//! raytracing, test if there is a hit or not
	//! /param inStart start vector in worldspace
	//! /param inDirection end vector of the ray
	//! /return true: ray has a intersection, false: otherwise
	bool						CalcIntersection								( const Vec3 invStart, const Vec3 invEnd, const CPbTri *inpIgnoreObject );
	
	// ****************************************************************************************

  int						m_nNumTris;								//!< number of triangles in the mesh
  CPbTri *			m_pMesh;									//!< pointer to the triangle data

#ifdef USE_RASTERCUBE
		CRasterCube<CPbTri *>			m_Raster;
#endif // USE_RASTERCUBE


  static int		m_nBumpImageSizeX;
  static int		m_nBumpImageSizeY;
  static int *	m_pnTriPointer;  
  static unsigned char *m_pcNormalMap;

private:
	int						m_iMaterialID;						//!< -1 for every one, otherwise it's the triangle material id we want to calculated

	//!
	std::string TestRasterCube( void );
};


bool CreateBumpMap( CPolyBumpWorkerThread *inpData );

//! \param invPos
//! \param invNormal
//! \param inpHighMesh
//! \param infRayLength
//! \param iniQuality 0=worst..10=very good
//! \param outvAverageNormal may not ne normalized (depending an accessibility)
float CalcAccessability( const Vec3 invPos, const Vec3 invNormal, CPbMesh *inpHighMesh, float infRayLength,
	int iniQuality, Vec3 &outvAverageNormal, const CPbTri *inpIgnoreObject );

#endif


