/****************************************************************************************************

		PrimitiveSampler.h
		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	pascalc
		Date:	9/1/2005

****************************************************************************************************/

#ifndef __PrimitiveSampler__
#define __PrimitiveSampler__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCRandom.h"
#include "Transforms.h"
#include "Vector3.h"
#include "MCCountedPtr.h"
#include "MCArray.h"
#include "ISelfSampler.h"

struct I3DShPrimitive;
struct FacetMesh;

struct FacetRecord : public TMCObject
{
	FacetRecord(int32 facetIndex,real probablity) : fIndex(facetIndex),fProbability(probablity) {}

	int32	fIndex;
	real	fProbability;
};

struct TSamplePoint : public TMCObject
{
	// facet where is the sample point
	uint32 fFacetIndex;
	// coordinates in the facet
	real fU, fV, fW;

	boolean		GetPointInfos(const FacetMesh* mesh, I3DShPrimitive* primitive, ShadingIn& infos, boolean needAdditionalInfos) const;
	boolean		GetPointUV(const FacetMesh* mesh, I3DShPrimitive* primitive, TVector2& uv) const;
};

class TTriangleSampler : public TMCObject
{
public:
	TTriangleSampler();
	~TTriangleSampler();

	int32	GetTriangleCount() const { return fSortedFacets.GetElemCount(); }
	void	SetTriangleCount(int32 count);
	void	AddTriangle(int32 index, real area);

	// ****************************************************************************
	//								GetSamplePoint
	// 
	/// returns a sample point: the facet index and the coordinates in the facet
	/// 
	/// \param outSample  
	/// 
	int32	GetSamplePoint(TSamplePoint& outSample);

	void	SetNewSeeds(uint32 fromSeed);
	uint32	GetSeed() const;
	real	GetTotalArea() { return fTotalArea; }

private:
	TMCArray<FacetRecord>			fSortedFacets;
	real							fTotalArea;

protected:
	TMCAtomicCounterHolder			fSampleNum;
};

class TPrimitiveSampler : public TTriangleSampler
{
public:
	static const uint32				kAllIDs;

	TPrimitiveSampler(I3DShPrimitive* primitive,const TTransform3D& transform,uint32 inUVSpaceID = kAllIDs, boolean useRenderingMesh = true, boolean useSelfSampling = false);

	// Returns true if the primitive can be sampled
	boolean InitSampling();

	// ****************************************************************************
	//								GetPoint
	// 
	/// returns a point in global coordinates on the surface of the primitive 
	/// 
	/// \param position       the resulting point
	/// \param normal         the resulting normal
	/// 
	void GetPoint(TVector3& position,TVector3& normal);

	// ****************************************************************************
	//								GetSamplePoint
	// 
	/// returns a sample point: the facet index and the coordinates in the facet
	/// 
	/// \param outSample  
	/// 
	int32 GetSamplePoint(TSamplePoint& outSample);

	// ****************************************************************************
	//								GetSampleInfos
	// 
	/// Get the current position, normal and shading infos of a sample point
	/// 
	/// \param place        the sample point
	/// \param shadingInfos return the shading infos
	/// 
	void GetSampleInfos(const TSamplePoint& place, ShadingIn& shadingInfos);

protected:
	FacetMesh* GetFacetMeshSource();

	TMCCountedPtr<I3DShPrimitive>	fPrimitive;
	TMCCountedPtr<FacetMesh>		fFacetMesh;
	TMCCountedPtr<ISelfSampler>		fSelfSampler;

	const TTransform3D				fTransform;
	const TTransform3D				fInvTransform;

	uint32							fUVSpaceID;
	boolean							fUseRenderingMesh;
	boolean							fNoTransform;
};

#endif
