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

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

		Author:	Benjamin
		Date:	12/17/2002

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

#ifndef __I3dExInstancePrimitive__
#define __I3dExInstancePrimitive__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "APITypes.h"
#include "RenderTypes.h"
#include "InterfaceIDs.h"
#include "MCArray.h"
#include "MCSMPCountedObject.h"


MCDEFINE_GUID(IID_I3DExInstancePrimitive, 0xe8b9a65f, 0xeba0, 0x4b83, 0xb8, 0xee, 0xc4, 0x89, 0xd2, 0xde, 0xc5, 0xd4);

// representation of an instance
/// Undocumented
///
struct TObjectInstance
{
	uint32 fInstanceKind;		// type of instance - when several objects are instanciated
	TTransform3D fTransform;    // rotation + uniform scaling transform - no XYZ scaling !!
	real32 fScaling;			// uniform scaling (for computing inverse transform)

	TTransform3D GetInverse()
	{
/*		TTransform3D transform;
		if (fScaling == 0)
		{
			transform.fRotationAndScale = TMatrix33::kZero;
			transform.fTranslation = TVector3::kZero;
			return transform;
		}
		TMatrix33 m = (1 / fScaling) * fTransform.fRotationAndScale;
		TMatrix33 tm = m.GetTranspose();
		transform.fTranslation =  - fTransform.fTranslation;
		transform.fRotationAndScale = (1 / fScaling) * tm;*/
		return fTransform.GetInverse();
	};
	
} ;

/// A counted list of instances
///
struct TInstanceList : public TMCSMPCountedObject, public TMCArray<TObjectInstance>
{
	inline void*	operator new			(MCSIZE_T byteCount)		{ return TMCSMPCountedObject::operator new(byteCount); }
	inline void*	operator new[]			(MCSIZE_T byteCount)		{ return TMCSMPCountedObject::operator new[](byteCount); }
	inline void		operator delete			(void* block)				{ TMCSMPCountedObject::operator delete(block); }
	inline void		operator delete[]		(void* block)				{ TMCSMPCountedObject::operator delete[](block); }
};


struct FacetMesh;


/// \addtogroup ExternalInterface
/// \{

/// A primitive (see I3DExGeometricPrimitive) can derive from this interface when it
/// is composed of multiple identical parts. For example a tree in which leaves are
/// stored as instances or Generators that duplicate existing (linked) instances.
/// This allow storing the geometry of each object type only once.
/// Note that you will either need to provide your own Ray tracing implementation for
/// this primitive (see IRaytracablePrimitive) or use the Instance link .
///
struct I3DExInstancePrimitive : public IMCUnknown
{
	// ****************************************************************************
	//							GetObjectNumber	
	// 
	/// Returns the number of "template" objects being instanciated in the primitive
	///
	virtual uint32 MCCOMAPI GetObjectNumber() = 0;

	// ****************************************************************************
	//							GetInstanceMesh	
	// 
	/// Returns the mesh for a given object.
	///
	/// \param instanceKind A 0-based index that identifies the object (the number of objects is defined
	///						by GetObjectNumber())
	///
	/// \param mesh			A pointer to the facet mesh that is returned.
	///
	virtual void MCCOMAPI GetInstanceMesh(uint32 instanceKind, FacetMesh** mesh) = 0;

	// ****************************************************************************
	//							GetInstanceList	
	// 
	/// Returns the list of instances for a given object
	///
	/// \param instanceKind A 0-based index that identifies the object (the number of objects is defined
	///						by GetObjectNumber())
	///
	/// \param instanceList A pointer (counted) to the instance list that is returned.
	///
	virtual void MCCOMAPI GetInstanceList(uint32 instanceKind,TInstanceList** instanceList) = 0;

	// ****************************************************************************
	//								GetInstanceLink
	// 
	/// Returns the link to the instance for a given object.
	/// 
	/// \param instanceKind A 0-based index that identifies the object (the number of objects is defined
	///						by GetObjectNumber())  
	/// \param link			A pointer to the instance that is returned.         
	/// 
	virtual void MCCOMAPI GetInstanceLink(uint32 instanceKind, I3DShInstance** link) = 0;

	// ****************************************************************************
	//								GetInstanceKindFromInstance
	// 
	/// Return the number of an object given the instance
	/// 
	/// \param link			A pointer to the instance that identify the object
	/// \return				A 0-based index that identifies the object
	virtual uint32 MCCOMAPI GetInstanceKindFromInstance(I3DShInstance* link) = 0;

	// ****************************************************************************
	//								AllwaysRender
	// 
	/// True if the instances should be displayed even when not in final renderer
	/// 
	/// 
	virtual boolean MCCOMAPI AllwaysRender() = 0;
};

/// \}


#endif
