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

		I3DExPrimitive.h

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

		I3DExGeometricPrimitive definition                                        
		IVolumePrimitive definition     
		IRaytracablePrimitive definition     

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/19/99	Yann		Removed GetPolygonInfo
		09/01/99	Mathieu		ID for infinite plane
		08/26/99	cph			Added family ids
		08/10/99	Arnaud		FacetMesh is now counted.
		7/14/99		cph			added GetPolygonInfo() to geo prim interface
		2/24/99		Alec		added AppendToRenderables call
		
*****************************************************************************************/

#ifndef __I3DEXPRIMITIVE__
#define __I3DEXPRIMITIVE__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "IExtension.h"
#include "I3DShRenderable.h"
#include "APITypes.h"
#include "RenderTypes.h"
#include "InterfaceIDs.h"
#include "LodParamEnum.h"

//****** Globally Unique Ids **************************************************

MCDEFINE_GUID_H(IID_I3DExGeometricPrimitive);
MCDEFINE_GUID_H(IID_I3DExSphere);
MCDEFINE_GUID_H(IID_I3DExCube);
MCDEFINE_GUID_H(IID_I3DExInfinitePlane);
MCDEFINE_GUID_H(IID_IRaytracablePrimitive);
MCDEFINE_GUID_H(IID_IVolumePrimitive);
MCDEFINE_GUID_H(IID_I3DExNewVolumePrimitive);

//****** Family Id *************************************************

const FourCharT kGeometricPrimitiveFamilyID = kRID_GeometricPrimitiveFamilyID;


/*****************************************************************************\
*  I3DExGeometricPrimitive                                                    *
*                                                                             *
*    I3DExGeometricPrimitive is used to define external geometric objects.    *
*    It can implement very few calls to start working, or may implement more  *
*    to provide better integration with other renderers (like being able      *
*    to do the ray-tracing calculations directly).                            *
*                                                                             *
\*****************************************************************************/

struct FacetMesh;
struct UVSpaceInfo;
struct I3DShShader;
struct I3DImportData;
struct TFaceSet;

namespace MeshDataStructure
{
	class TMeshList;
}

#ifndef qDemoVersion //regular interface

/// \addtogroup ExternalInterface
///
/// \{

/// <P>Geometric primitives define a geometric object.  They return a list of facets
/// or bicubic patches and can give information on an object’s UV Space.  The shell
/// will check for patches first by calling EnumPatches() and then call GetFacetMesh()
/// if EnumPatches() fails.  At least one or both of these two methods must be implemented.</P>
///
/// <P>In addition to describing geometry, a geometric primitive can define a custom ray-tracing
/// routine rather than relying only on facets or patches.  This is done by inheriting from the
/// IRaytracablePrimitive Interface  in addition to I3DExGeometricPrimitive (or TBasicPrimitive).</P>
///
/// <P>A primitive can also support skinning (skinning is the deformation of the primitive geometry
/// using a skeleton composed of bones). This is done by inheriting from the I3dExSkinable Interface
/// in addition to I3DExGeometricPrimitive (or TBasicPrimitive).</P>
///
/// <P>Rather than defining geometry, a primitive can also describe a volume.  This is achieved by 
/// inheriting from the IVolumePrimitive Interface as well as I3DExGeometricPrimitive
/// (or TBasicPrimitive).</P>
///
/// <P>The structure of a primitive is a bit more complex than the average component:</P>
///
/// <P>There are 2 COM objects to consider:</P>
///  - The <B>Primitive</B> that supports I3DShExternalPrimitive, I3DShPrimitive and I3DShObject.
///  - The <B>Primitive Component</B> that supports IShComponent, I3DShPrimitiveComponent and I3DExGeometricPrimitive
///
/// <P>For advanced users: You should note that there are actually 3 C++ object (The primitive,
/// the primitive component and the primitive light). However the primitive component and the external
/// primitive are aggregated by COM which means that you can be considered as one single COM object).
///
/// <P>To get a pointer to a I3DShExternalPrimitive from a I3DExGeometricPrimitive, you can use the following code:</P>
///
/// \code
///
/// TMCCountedPtr<I3DShPrimitiveComponent> primitiveComponent;
/// exPrimitive->QueryInterface(IID_I3DShPrimitiveComponent,(void**)&primitiveComponent);
/// ThrowIfNil(primitiveComponent);
///
/// TMCCountedPtr<I3DShPrimitive> primitive;
/// primitiveComponent->GetPrimitive(&primitive);
/// ThrowIfNil(primitive);
///
/// TMCCountedPtr<I3DShExternalPrimitive> externalPrimitive;
/// primitive->QueryInterface(IID_I3DShExternalPrimitive.(void**)&externalPrimitive);
///
/// \endcode
///
/// <P>To access I3DExGeometricPrimitive from I3DShPrimitive, you can use the following code: </P>
///
/// \code
///
/// TMCCountedPtr<I3DShExternalPrimitive> externalPrimitive;
/// shPrimitive->QueryInterface(IID_I3DShExternalPrimitive.(void**)&externalPrimitive);
/// ThrowIfNil(externalPrimitive);
/// 
/// TMCCountedPtr<IShComponent> primitiveComponent;
/// externalPrimitive->GetPrimitiveComponent(&primitiveComponent);
/// ThrowIfNil(primitiveComponent);
///
/// TMCCountedPtr<I3DExGeometricPrimitive> externalPrimitive;
/// primitiveComponent->QueryInterface(IID_I3DExGeometricPrimitive,(void**)&externalPrimitive);
///
/// \endcode
///
/// <P>This code might seem a bit complicated at first but it is actually simple. You have two COM objects
/// that point on each other. I3DShExternalPrimitive::GetPrimitiveComponent() and I3DShPrimitiveComponent::GetPrimitive()
/// allow you to get a pointer from one object to the other. The rest is only calling QueryInterface to get
/// the right interface on each object.</P>
///
/// \see I3DShPrimitiveComponent
/// \see I3DShExternalPrimitive
/// \see I3DShPrimitive
/// 
struct I3DExGeometricPrimitive: public IMCUnknown
{
	// ****************************************************************************
	//								GetBoundingBox
	// 
	/// Computes the bounding box of the primitive to the 3D Shell. If this call is not implemented
	/// the bounding box will be calculated automatically from the patches or facets list. However
	/// it is recommended to implement it to speed up the bounding box calculation.
	///
	/// \param bbox A reference to a structure where the bounding box should be stored.
	///
	virtual void	   MCCOMAPI GetBoundingBox		(TBBox3D& bbox) = 0;
	
	// ****************************************************************************
	//								GetRenderingBoundingBox
	// 
	/// Computes the bounding box for rendering.
	/// 
	/// \param bbox A reference to a structure where the bounding box should be stored.
	/// 
	virtual void	   MCCOMAPI GetRenderingBoundingBox		(TBBox3D& bbox) = 0;

	// ****************************************************************************
	//								GetApproximateBoundingBox
	// 
	/// Computes the approximate bounding box (should not used any other object geometry).
	/// 
	/// \param bbox A reference to a structure where the bounding box should be stored.
	/// 
	virtual MCCOMErr   MCCOMAPI GetApproximateBoundingBox	(TBBox3D& bbox) = 0;
	
	// ****************************************************************************
	//								EnumPatches
	// 
	/// Returns the primitive as a list of bicubic patches. It is recommended to use
	/// GetFacetMesh() instead.
	///
	/// \param callback Callback procedure that should be called for each Patch generated by the Primitive.
	/// \param privData Points to private data from the Shell. Pass this pointer to callback.
	/// \param closed Returns True when the surface is closed. This helps set the backface mask correctly.
	///
	virtual MCCOMErr   MCCOMAPI EnumPatches			(EnumPatchesCallback callback, void* privData, boolean& closed) = 0;
	
	// ****************************************************************************
	//								GetNbrLOD
	// 
	/// Returns the number of levels of detail (lod) of the primitive.  This value is
	/// used to determine the lodIndex in GetLOD().
	///
	/// \param nbrLod The number returned for the levels of detail for the primitive.
	///
	/// \note :	Read the technical explanations in BasicPrimitive.cpp to learn everything about LOD (Level Of Details) management,
	///			and multi-resolution support.
	///
	///
	virtual MCCOMErr   MCCOMAPI GetNbrLOD			(int16& nbrLod) = 0;

	// ****************************************************************************
	//								GetLOD
	// 
	/// Return the floating point value of the level of detail that corresponds to
	/// the 0-based 'lodIndex'. (lodIndex=0 means highest resolution)
	///
	/// \param lodIndex The index of the level of detail
	/// \param lod The returned lod precision.
	///
	virtual MCCOMErr   MCCOMAPI GetLOD				(int16 lodIndex, real& lod) = 0;

	// ****************************************************************************
	//								GetFacetMesh
	// 
	/// Returns the Facet Mesh for this lod index.
	///
	/// \param lodIndex The index of the level of detail that is asked (see GetNbrLOD())
	/// \param outMesh A pointer to a pointer that should be set to point on the FacetMesh.
	///
	virtual MCCOMErr   MCCOMAPI GetFacetMesh		(uint32 lodIndex, FacetMesh** outMesh) = 0;


	// ****************************************************************************
	//								HasRenderingFacetMesh
	// 
	/// Returns true if this primitive has a mesh used only for final rendering. If
	/// it returns false, you can assume that the mesh for lod 0 and the rendering
	/// mesh are the same.
	/// 
	virtual boolean	   MCCOMAPI HasRenderingFacetMesh() = 0;

	// ****************************************************************************
	//								GetRenderingFacetMesh
	// 
	/// Returns the mesh that should be used for final rendering.
	///
	/// You should only implement this method if you use a mesh for previewing that
	/// is different from the the mesh for final rendering.
	/// 
	/// \param outMesh  A pointer to a pointer to the FacetMesh that is returned.
	///
	/// \return MC_S_OK if implemented, MC_E_NOTIMPL otherwise
	///
	virtual MCCOMErr   MCCOMAPI GetRenderingFacetMesh(FacetMesh** outMesh) = 0;

	// ****************************************************************************
	//								GetRenderingMesh
	// 
	/// Returns a pointer to the rendering mesh associated with the primitive. Note
	/// that the mesh should not be cached by the primitive so it can be modified
	/// by the caller.
	///
	/// The mesh can be composed either of triangles or quads. More complexe polygons
	/// should be triangulated before the mesh is returned.
	///
	/// It is the caller responsability to call release on the mesh once it is not used
	/// anymore.
	///
	/// \param meshList  The mesh list that is returned. NULL if this call is not
	///					 supported (in which case the caller can use the facet mesh)
	/// 
	virtual void MCCOMAPI GetRenderingMesh(MeshDataStructure::TMeshList** meshList) = 0;

	// ****************************************************************************
	//								GetFaceSetList
	// 
	/// Gets the list of face sets associated with the primitive.
	///
	/// \param faceSetList  The face set list that is returned.
	///
	virtual void MCCOMAPI GetFaceSetList(TMCCountedPtrArray<TFaceSet>& faceSetList) = 0;

	// ****************************************************************************
	//								GetFacetMesh
	// 
	/// Never implement that one, reserved for future use (primitives with an infinite number of resolutions)
	///
	//virtual MCCOMErr   MCCOMAPI GetFacetMesh		(real lod, FacetMesh** outMesh) = 0;
	
	// ****************************************************************************
	//								CanBeSplit
	// 
	/// Returns true if the primitive can split itself into sub parts of the same type.
	///
	virtual boolean    MCCOMAPI CanBeSplit			() = 0;

	// ****************************************************************************
	//								SplitPrimitive
	// 
	/// Builds a list of sub-parts of itself. 'subPartPositions' gives the relative position of 
	/// each sub part in the object local coordinates. Both arrays need to be of same size.
	/// <P>Note: the original primitive needs to remain intact.</P>
	///
	/// \param subParts An array of sub primitives.
	/// \param subPartPositions For each sub primitives, its transform.
	///
	virtual MCCOMErr   MCCOMAPI SplitPrimitive		(TMCCountedPtrArray<I3DExGeometricPrimitive>& subParts, TMCArray<TTransform3D>& subPartPositions) = 0;
	
	// ****************************************************************************
	//								SplitPrimitive
	// 
	/// Returns the number of UV space on the primitives.
	///
	virtual uint32     MCCOMAPI GetUVSpaceCount		() = 0;

	// ****************************************************************************
	//								GetUVSpace
	// 
	/// Returns the information regarding a particular uvSpace (= shading domain).
	///
	/// \param uvSpaceID The ID of the uvspace (0 based index)
	/// \param uvSpaceInfo A pointer to a structure where the information will be stored.
	///
	virtual MCCOMErr   MCCOMAPI GetUVSpace			(uint32 uvSpaceID, UVSpaceInfo* uvSpaceInfo) = 0;	// Note: UV Spaces are now normalized to 0..1

	// ****************************************************************************
	//								CanRenameUVSpace
	// 
	/// Returns true if the primitive can rename uv spaces (ie. implements RenameUVSpace()).
	///
	virtual boolean	   MCCOMAPI CanRenameUVSpace	() = 0;
	
	// ****************************************************************************
	//								RenameUVSpace
	// 
	/// Rename a particular uvSpace (= shading domain).
	///
	/// \param uvSpaceID The ID of the uvspace (0 based index)
	/// \param name		 The new name of the uvspace.
	///
	virtual MCCOMErr   MCCOMAPI RenameUVSpace		(uint32 uvSpaceID, const TMCString& name) = 0;

	// ****************************************************************************
	//								SplitPrimitive
	// 
	/// Returns the position in 3D of a point given a set of UV coordinates. This is
	/// useful if you want to calculate a UV texture from a 3D shaders for instance.
	///
	/// \return  MC_S_OK if it is implemented, E_NOTIMPL if it isn't (in which case
	/// a default implementation will be used by the shell).
	///
	/// \param uv The uv coordinates used as input
	/// \param uvSpaceID The uv space ID to which this uv coordinates corresponds
	/// \param resultPosition The 3D Position that is returned.
	/// \param inUVSpace Returns true if the point was found in the upSpaceID specified.
	///
	virtual MCCOMErr   MCCOMAPI UV2XYZ				(TVector2* uv, uint32 uvSpaceID, TVector3* resultPosition, boolean* inUVSpace) = 0; // Optional - Return E_NOTIMPL if not implemented
	
	// ****************************************************************************
	//								GetUVSpaceRDS5
	// 
	/// Returns the information regarding a particular uvSpace (= shading domain).
	/// To be implemented only if your primitive existed in RDS 5 or earlier, so that UV spaces can be mapped properly to the new 0..1 boundaries
	///
	/// \param uvSpaceID The ID of the uvspace (0 based index)
	/// \param uvSpaceInfoRDS5 A pointer to a structure where the information will be stored.
	///
	virtual MCCOMErr   MCCOMAPI GetUVSpaceRDS5		(uint32 uvSpaceID, UVSpaceInfoRDS5* uvSpaceInfoRDS5) = 0; 

	// ****************************************************************************
	//								AppendToRenderables
	// 
	/// Appends the renderable to the renderable array. This is used to append extra renderables
	/// on top of the geometry itself. If the function returns MC_S_FALSE instead of MC_S_OK, the
	/// default renderable will not be visible.
	///
	/// \param worldFromModelTfm The global transform of the primitive.
	/// \param renderableAndTfm The array of renderable and transforms.
	///
	virtual MCCOMErr   MCCOMAPI AppendToRenderables	(const TTransform3D& worldFromModelTfm, TRenderableAndTfmArray& renderableAndTfm ) = 0;

	// ****************************************************************************
	//								AutoSwitchToModeler
	// 
	/// Returns true if the primitive should be open in its modeler immediately after its insertion
	///
	virtual boolean		MCCOMAPI AutoSwitchToModeler() const = 0;

	// ****************************************************************************
	//								IsBBoxPickable
	// 
	/// Returns true if the primitive can be picked in the 3D View when clicking on its bounding box. Usually, you want
	/// to reply no, since the picking is done thru a ray-tracing hit test. However, some primitives such as volumic primitives
	/// or particles systems may want to answer yes. Default implementation in TBasicPrimitive returns false.
	///
	virtual boolean		MCCOMAPI IsBBoxPickable() const = 0;


	// ****************************************************************************
	//								IsExcludedFromTripleBuffer
	// 
	/// Return true if its instances should be excluded from the triple buffer (eg used for skinning)
	///
	virtual boolean		MCCOMAPI IsExcludedFromTripleBuffer() = 0;

	// ****************************************************************************
	//								GetDefaultShader
	// 
	/// Returns the default shader for this primitive. This is called each time a
	/// primitive is inserted in a scene without a shader
	///
	/// \param shader  should return a pointer to the shader that should be used for this primitive (NULL to use the default master shader)
	/// \param name    if not nil can fill with the name of the default shader
	/// 
	virtual void MCCOMAPI GetDefaultShader(I3DShShader** shader, TMCString* name = nil) = 0;

	// ****************************************************************************
	//								GetDefaultShaderInfo
	//
	/// Returns the info necessary to load the default shader for this primitive.
	/// This is called each time a primitive is inserted in a scene without a shader.
	///
	/// \param outShaderResID		Resource ID of the SHAD resource storing the shader
	/// \param outNameStringResID   Resource ID of the STR# resource to use for the shader's name
	/// \param outNameStringIndex   Index of the string for the shader name
	virtual void MCCOMAPI GetDefaultShaderInfo(	int32& 		outShaderResID,
												int32& 		outNameStringResID,
												int32& 		outNameStringIndex) = 0;

	// ****************************************************************************
	//								ChangedData
	// 
	/// Do not use. Temporary call.
	///
	virtual void MCCOMAPI ChangedData() = 0; //arnaud: hack to fix the text modeler bug #2416

	// ****************************************************************************
	//								GetWizardPath
	/// 
	/// Returns the path to the primitive wizard file (wizard.txt) from the application folder.
	///
	/// \param path path to the primitive wizard file from the application folder
	/// 
	virtual MCCOMErr	 MCCOMAPI GetWizardPath(TMCString& path) = 0;

	// ****************************************************************************
	//								CanConvertToOtherModeler
	// 
	/// Returns true if need an apparent button to convert to other modeler.
	/// 
	/// 
	virtual boolean		 MCCOMAPI CanConvertToOtherModeler() = 0;

	// ****************************************************************************
	//								ChangeLocalTimeInHit
	// 
	/// Let the object change the local time after a hit
	/// 
	/// \param params  the parameters of the hit, only params.fHit->fTime should be changed
	/// 
	virtual void		MCCOMAPI ChangeLocalTimeInHit(RayHitParameters& params) = 0;

	// ****************************************************************************
	//								NeedAnimatedShader
	// 
	/// Return true if the object uses local time and therefore will need animated shader
	/// 
	/// 
	virtual boolean		MCCOMAPI NeedAnimatedShader() = 0;

	// ****************************************************************************
	//								IsGenerator
	// 
	/// Return true if the object can generate sub instances
	/// if true the component should also implements I3DExInstancePrimitive
	/// 
	virtual boolean		MCCOMAPI IsGenerator() const = 0;

	// ****************************************************************************
	//								GetPreviewObject
	// 
	/// Return the Master object to preview if different from main one.
	/// Return NULL if it is the same,
	/// \param masterShader			the master shader being previewed
	/// \param object				the object to use to preview the shader
	/// \param previewTree			a tree to set the transform of the preview object (only the transform will be used)
	/// \param additionnalChild		the master object can also add an instance that will be used for the preview as well, puting it
	///								as child of the previewed object
	/// 
	virtual void		MCCOMAPI GetPreviewObject(I3DShMasterShader* masterShader, I3DShObject** object, I3DShTreeElement** previewTree, I3DShTreeElement** additionnalChildInstance) = 0;

	// ****************************************************************************
	//								GetPrimitiveInstanceType
	// 
	/// Return the instance type for this primitive. \see I3DShInstance::EInstanceType
	/// 
	virtual int32		MCCOMAPI GetPrimitiveInstanceType() const = 0;

	// ****************************************************************************
	//								IsScalable
	// 
	/// If true, the primitive is scaled at insertion in a scene, so that one unit
	/// for the primitive corresponds to one unit in the scene.
	/// 
	virtual boolean	MCCOMAPI IsScalable() const = 0;

	// ****************************************************************************
	//								GetScalingFactor
	// 
	/// Returns the scaling that should be applied to the primitive, i.e. the
	/// number of inches in the primitive's unit.
	/// 
	virtual real32	MCCOMAPI GetScalingFactor() const = 0;

	// ****************************************************************************
	//								SetScalingFactor
	// 
	///  Sets the scaling factor of the primitive.
	///
	/// \param inValue	the number of inches to which the primitive's unit is 
	///					equivalent
	/// 
	virtual void	MCCOMAPI SetScalingFactor(real32 inValue) = 0;

	/// Returns true if the Primitive can import the given data on the given instance
	virtual boolean	MCCOMAPI CanImportData	(I3DImportData*	inImportData, I3DShInstance* inInstance) = 0;

	/// Imports the given data on the given instance, returns false if the import was aborted
	virtual boolean	MCCOMAPI ImportData		(I3DImportData* inImportData, I3DShInstance* inInstance) = 0;

	// ****************************************************************************
	//								SetScalingFactor
	// 
	/// Returns true if the primite can apply the displacement mapping by itself
	///
	/// 
	virtual boolean MCCOMAPI ImplementDisplacementMapping() = 0;

	// ****************************************************************************
	//								DisplacementShaderChanged
	// 
	/// Called to invalidate the primitive when the displacement shader has changed
	///
	/// 
	virtual void MCCOMAPI DisplacementShaderChanged()=0;
   	// ****************************************************************************
	//								GetLodParamType
	// 
	/// \return The type of information used to calculate the appropriate LOD
	/// 
	virtual ELODParamType	MCCOMAPI GetLODParamType() const = 0;
   	// ****************************************************************************
	//								GetLodIndex
	//
    //  Calculate the appropriate LOD index for the specified distance
    //  the GetLodParamType() must kLod_DistanceFromCamera be otherwise there would be an exception
	/// 
	virtual int16	MCCOMAPI GetLODIndex(real32 distance) const = 0;
   	// ****************************************************************************
	//								GetAdditionalBoundingBoxVertices
	//
    //  Get an array of additional points needed to calculate the bounding box
	/// 
	virtual void GetAdditionalBoundingBoxVertices(TMCArray<TVector3>& additionalVertices) const = 0;

	//called just before the instance is removed from the master's list
	virtual void	MCCOMAPI AboutToRemoveInstance(I3DShInstance* instance)=0;

	///return true if the master should be deleted with the instance (used for figures)
	virtual boolean	MCCOMAPI ShouldDeleteWithInstance(I3DShInstance* inInstance)=0;
};

/// \}

#else 	//(qDemoVersion) begin scrambled interface

struct I3DExGeometricPrimitive: public IMCUnknown
{
	virtual void		MCCOMAPI ChangedData() = 0;
	virtual void		MCCOMAPI GetPreviewObject(I3DShMasterShader* masterShader, I3DShObject** object, I3DShTreeElement** previewTree, I3DShTreeElement** additionnalChildInstance) = 0;
	virtual MCCOMErr   MCCOMAPI EnumPatches			(EnumPatchesCallback callback, void* privData, boolean& closed) = 0;
	virtual void	   MCCOMAPI GetBoundingBox		(TBBox3D& bbox) = 0;		
	virtual MCCOMErr   MCCOMAPI GetFacetMesh		(uint32 lodIndex, FacetMesh** outMesh) = 0;
	virtual MCCOMErr   MCCOMAPI RenameUVSpace		(uint32 uvSpaceID, const TMCString& name) = 0;
	//virtual MCCOMErr   MCCOMAPI GetFacetMesh		(real lod, FacetMesh** outMesh) = 0;
	virtual boolean	   MCCOMAPI HasRenderingFacetMesh() = 0;
	virtual boolean	   MCCOMAPI IsExcludedFromTripleBuffer() = 0;
	virtual MCCOMErr   MCCOMAPI GetNbrLOD			(int16& nbrLod) = 0;
	virtual void		MCCOMAPI ChangeLocalTimeInHit(RayHitParameters& params) = 0;
	virtual MCCOMErr   MCCOMAPI GetLOD				(int16 lodIndex, real& lod) = 0;
	virtual boolean	   MCCOMAPI CanRenameUVSpace	() = 0;
	virtual MCCOMErr   MCCOMAPI UV2XYZ				(TVector2* uv, uint32 uvSpaceID, TVector3* resultPosition, boolean* inUVSpace) = 0; // Optional - Return E_NOTIMPL if not implemented
	virtual MCCOMErr   MCCOMAPI GetUVSpaceRDS5		(uint32 uvSpaceID, UVSpaceInfoRDS5* uvSpaceInfoRDS5) = 0; // To be implemented only if your primitive existed in RDS 5 or earlier, so that UV spaces can be mapped properly to the new 0..1 boundaries
	virtual MCCOMErr   MCCOMAPI AppendToRenderables	(const TTransform3D& worldFromModelTfm, TRenderableAndTfmArray& renderableAndTfm ) = 0;
	virtual boolean	   MCCOMAPI AutoSwitchToModeler() const = 0;
	virtual boolean    MCCOMAPI CanBeSplit			() = 0;
	virtual boolean		MCCOMAPI IsGenerator() const = 0;
	virtual void MCCOMAPI GetRenderingMesh(MeshDataStructure::TMeshList** meshList) = 0;
	virtual MCCOMErr   MCCOMAPI SplitPrimitive		(TMCCountedPtrArray<I3DExGeometricPrimitive>& subParts, TMCArray<TTransform3D>& subPartPositions) = 0;
	virtual MCCOMErr   MCCOMAPI GetRenderingFacetMesh(FacetMesh** outMesh) = 0;
	virtual MCCOMErr	 MCCOMAPI GetWizardPath(TMCString& path) = 0;
	virtual uint32     MCCOMAPI GetUVSpaceCount		() = 0;
	virtual boolean		 MCCOMAPI CanConvertToOtherModeler() = 0;
	virtual boolean		MCCOMAPI NeedAnimatedShader() = 0;
	virtual boolean	   MCCOMAPI IsBBoxPickable		() const = 0;
	virtual MCCOMErr   MCCOMAPI GetUVSpace			(uint32 uvSpaceID, UVSpaceInfo* uvSpaceInfo) = 0;	// Note: UV Spaces are now normalized to 0..1			
	virtual void MCCOMAPI GetDefaultShader(I3DShShader** shader, TMCString* name = nil) = 0;
};


#endif	//(qDemoVersion) end scrambled


/// \addtogroup ExternalInterface
///
/// \{

/// In addition to describing geometry a geometric primitive can define a custom
/// ray-tracing routine rather than relying only on facets or patches.
/// This is done by inheriting from IRaytracablePrimitive in addition to I3DExGeometricPrimitive (or TBasicPrimitive).
///
struct IRaytracablePrimitive: public IMCUnknown
{
	// ****************************************************************************
	//							RayHit	
	// 
	/// Perform specific ray-tracing calculations instead of relying on the facets
	/// or patches. For example, a sphere can provide its intersection routine so the
	/// ray-tracing renders perfect spheres.
	///
	/// \param params		The parameters (ray, hit ...)
	///
	/// \return True if there is a valid intersection, false otherwise
	///
	virtual boolean  MCCOMAPI RayHit(RayHitParameters& params)=0; 
	
	/// Sets a boolean to true if the object is infinite.
	///
	/// \param isInfinite True on exit if the bounding box is infinite.
	///
	virtual MCCOMErr MCCOMAPI IsInfiniteBB(boolean& isInfinite) = 0;
};

/// Rather than defining geometry, a primitive can also describe a volume.  This is
/// achieved by inheriting from IVolumePrimitive as well as I3DExGeometricPrimitive
/// (or TBasicPrimitive).
///
/// There are two methods for implementing a volume primitive.  IVolumePrimitive::GetVolumedensity
/// provides a filter color and a glow color for each point of the volume primitive.
/// IVolumePrimitive::GetVolumeAttenuation calculates the color from a ray.
///
struct IVolumePrimitive: public IMCUnknown
{
	/// Called during rendering to calculate a color from a ray going thru the volume primitive.
	/// The shell calls this method to get a filtered color and a glow color for many points on the ray.
	/// It begins with a base color from an object or background color behind the volumetric primitive
	/// to calculate the color within the volume:
	///
	/// <P>Volume Color = (base color * filtered color) + glow</P>
	///
	/// \param point	The point within the volume in local coordinates.
	/// \param filter	The resulting filtered color.
	/// \param glow		The resulting glow value.
	///
	virtual MCCOMErr MCCOMAPI GetVolumeDensity		(const TVector3& point,TMCColorRGBA& filter,TMCColorRGBA& glow) = 0;

	/// Called by the shell to get a color from a ray going thru a volume primitive.
	///
	/// \param from				The intersection of the ray with the back of the volume primitive. This is where the calculation begins.
	/// \param to				The intersection of the ray with the front of the volume primitive. This is where the calculation ends.
	/// \param attenuation		The color behind the object is given.  The resulting color is returned.
	/// \param isShadowCasting	True if the ray is used to calculate shadows (object -> light source)
	///
	virtual MCCOMErr MCCOMAPI GetVolumeAttenuation	(const TVector3& from,const TVector3& to,TMCColorRGBA& attenuation, TColorRGBLinearEffect* linearEffect, boolean isShadowCasting, boolean oldShadowFiltering) = 0;	
};

/// \}



/// \addtogroup ExternalInterface
///
/// \{

/// This interface contains extra methods for volume primitives allowing more advanced interaction with the
/// scene. If this interface is implemented, neither GetVolumeDensity nor GetVolumeAttenuation are called.
///
struct I3DExNewVolumePrimitive : public IMCUnknown
{
	// ****************************************************************************
	//								BeginRender
	// 
	/// Called at the beginning of a rendering.
	/// 
	virtual void MCCOMAPI BeginRender()=0;

	// ****************************************************************************
	//								EndRender
	// 
	/// Called at the end of a rendering.
	/// 
	virtual void MCCOMAPI EndRender()=0;

	// ****************************************************************************
	//								TraceRay
	// 
	/// Filter a ray by a volume primitive.
	///  
	/// \param ray          The ray in global coordinates
	/// \param localRay      The ray in local coordinates
	/// \param tmin          The beginning of the segment
	/// \param tmax          The end of the segment
	/// \param inOutColor    On input, the color of the point behind the ray. On ouput
	///                      the color of the light once filtered through the volume
	/// \param raytracer     A pointer to the raytracer used for the lighting
	/// \param instance      The instance of the volume primitive
	/// \param instanceNb    A id in the raytraced grid for the hit instance (can be different with same instance in replicators)
	/// \param isShadowRay   True if the ray is a shadow ray.
	/// \param isIndirectRay True if the ray has already hit a reflective or semi transparent surface
	/// 
	virtual void MCCOMAPI TraceRay (const Ray3D&			ray,
								    const Ray3D&			localRay,
								    const real64&			tmin,
								    const real64&			tmax,
								    TMCColorRGBA&			inOutColor,
									TColorRGBLinearEffect*	linearEffect,
								    I3DExRaytracer*			raytracer,
								    I3DShInstance*			instance,
								    uint32					instanceNb,
								    boolean					isShadowRay,
								    boolean					isIndirectRay,
									boolean					oldShadowFiltering) = 0;

	// ****************************************************************************
	//								UsesShaders
	// 
	/// Returns true if this volume primitive uses the shaders that are applyed to it.
	/// 
	virtual boolean  MCCOMAPI UsesShaders() const = 0;
};

/// \}

#endif
