#pragma once

#include <vector>														// STL vector<>


#include "Cry_Math.h"												// Vec3


// stats: CPbBaseTri,CPbHighTri 4*3*3 + 4*3*3 + 4*4 = 88 bytes
// stats: CPbLowTri CPbBaseTri + 4*3*3 + 3*2*4 + 4 + 4 = 88+68 = 156 bytes

class CPbBaseTri
{
public: 

	Vec3					m_Verts[3];						//!< vertex positions
  Vec3					m_VertsNormal[3];			//!< vertex normals
	Plane					m_Plane;							//!< plane of the triangle 

	// ------------------------------------------------------------------------

	//! calculates m_Plane
	void RefreshInternals();

	//! extend the given bounding box
	void ExtendMinMax( Vec3 &inoutMin, Vec3 &inoutMax ) const;

	//!
	void ExtendSphere( Vec3 invMid, float &outfRadius2 );

	//! /return FLT_MAX nothing was intersected
	float CalcIntersectionFromDir( const Vec3 &invStart, const Vec3 &invDir );
};



//////////////////////////////////////////////////////////////////////
class CPbHighTri :public CPbBaseTri
{
public:

	//! /param inbDoClipping do clipping within the triangle area
  void CalcBarycentricCoordsFromPoint( const Vec3 &point, Vec3 &normal, bool inbDoClipping );


	// -------------------------------------------------------------------------------------------

};

//////////////////////////////////////////////////////////////////////
class CPbLowTri :public CPbBaseTri
{
public:
	//! normalize normal after calling this function
	//! /param s x coordinate in the texture
	//! /param t y coordinate in the texture
	//! /param inbDoClipping do clipping within the triangle area
  void CalcBarycentricCoordsFromUV( float s, float t, Vec3 &point, Vec3 &normal, bool inbDoClipping );

	//! calculates m_Plane and m_fUVArea
	void RefreshInternals();

	void CalcBarycentrics( float inS, float inT, float outCoor[3], bool inbDoClipping );

	// -------------------------------------------------------------------------------------------

	DWORD					m_iTriMaterialID;			//!< material id 0..

	Vec3					m_vTangent[3];				//!< used for tangent space bumpmapping
	Vec3					m_vBinormal[3];				//!< used for tangent space bumpmapping
	Vec3					m_vTNormal[3];				//!< used for tangent space bumpmapping

	float					m_fS[3];							//!< texture x=s coordinates
  float					m_fT[3];							//!< texture y=t coordinates

  float					m_fUVArea;						//!< area in texture-space
};



template <class TTri>
class CIntersInfo
{
public:
  Vec3					m_Point;							//!<
  float					m_fDist;							//!< from starting point

	uint32				m_dwObjectIndex;			//!< only valid if m_pTri!=0
	TTri *				m_pTri;								//!< must not be 0
};


//! calculates the area of a 2D triangle
//! /param pfX pointer to three x values
//! /param pfY pointer to three y values
inline float CalcUVArea( float *pfX, float *pfY )
{
  float prod1=pfX[1]*pfY[2]-pfY[1]*pfX[2];
  float prod2=pfX[0]*pfY[1]-pfY[0]*pfX[1];
  float prod3=pfY[0]*pfX[2]-pfX[0]*pfY[2];

  return (prod1+prod2+prod3)/2.0f; 
}


typedef std::vector<CIntersInfo<CPbHighTri> >						CIntInfoHighList;
typedef CIntInfoHighList::iterator											CIntInfoHighIt;

typedef std::vector<CIntersInfo<CPbLowTri> >						CIntInfoLowList;
typedef CIntInfoLowList::iterator												CIntInfoLowIt;

