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

		I3DShShader.h

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

		I3DShShader definition

		Author:	Emil
		Date:	7/16/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		01/06/99	EricB		Removed IShapeShader; added IsVisible, IsSelected, SetVisible, SetSelected
		12/14/98	EricB		Added IShapeShader

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

#ifndef __I3DShShader__
#define __I3DShShader__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "ComTypes.h"
#include "APITypes.h"
#include "ShaderTypes.h"

class TTransform2D;

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

MCDEFINE_GUID_SAFELIB(IID_I3DShShader,       0x88a44710, 0x1d12, 0x11d2, 0x8f, 0x38, 0x0, 0x60, 0x97, 0x98,0xe7, 0x7d);
MCDEFINE_GUID_SAFELIB(IID_I3DShMasterShader, 0x2bd230ea, 0x8431, 0x11d2, 0x8b, 0x39, 0x0, 0x60, 0x97, 0xb, 0xc5, 0x21);
MCDEFINE_GUID_SAFELIB(IID_IShadingDomain   , 0x88a44711, 0x8431, 0x11d2, 0x8b, 0x39, 0x0, 0x60, 0x97, 0xb, 0xc5, 0x21);


// Classes always available
MCDEFINE_GUID_SAFELIB(CLSID_StandardMasterShader, 0x2bd230eb, 0x8431, 0x11d2, 0x8b, 0x39, 0x0, 0x60, 0x97, 0xb, 0xc5, 0x21);

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

struct IShTextureMap;
struct I3DExShader;
struct I3DShScene;
struct I3DShMaster;
struct IShParameterComponent;
struct LightingDetail;
struct LightingContext;
struct IPreviewMaker;
struct I3DShMasterShader;
struct IShTextureMapBucketCache;

class TAbsorptionFunction;

/// \addtogroup ShellInterface
/// \{

/// I3DShShader is the shell interface of a shader function.
///
/// <P>There are two interfaces to access a component: The shell interface (I3DShShader) and
/// the external interface (I3DExShader) . You can get one from the other using QueryInterface.</P>
///
/// <P>Whenever it is possible you should use the Shell interface (I3DShShader) to access the component
/// because the Shell will make sure that the parameter map of the external component is valid.
/// This is especially important if the component is animated. For more information on components
/// see the Overview of the SDK.</P>
///
/// \see I3DExShader
///
struct I3DShShader : public IMCUnknown
{
	// ****************************************************************************
	//								Clone
	// 
	/// Makes a copy of a shader and its sub shaders.
	/// 
	/// \param clone  A pointer to the copy of the shader.
	/// \param mode   The clone Mode (see ECloneMode).
	/// 
	virtual void		MCCOMAPI Clone					(I3DShShader** clone,ECloneMode mode) const	= 0; 

	// ****************************************************************************
	//								IsConstant
	// 
	/// Returns true if the shader has a constant result (to optimize things like
	/// Value and Color shaders).
	/// 
	virtual boolean		MCCOMAPI IsConstant				() = 0;
	
	// ****************************************************************************
	//								AssignsChannels
	// 
	/// Should returns true if DoShade is implemented.
	/// 
	virtual boolean		MCCOMAPI AssignsChannels		() = 0;
	
	// ****************************************************************************
	//								GetShadingFlags
	// 
	/// Returns the ShadingFlags associated with this shader.
	/// 
	/// \param theFlags  The ShadingFlags associated with this shader.
	/// 
	virtual void		MCCOMAPI GetShadingFlags		(ShadingFlags& theFlags) = 0;


	/// ****************************************************************************
	///						HasExplicitLightingModel		
	/// 
	/// Returns true if there is an explicit lighting model in the subtree. This is
	/// mostly used for layer lists to determine if DoShade or ShadeAndLight2 should
	/// be called on the layer.
	///
	/// \param lightingContext  The information about the point that should be lit.
	/// 
	virtual boolean MCCOMAPI HasExplicitLightingModel(const LightingContext& lightingContext)=0;

	// ****************************************************************************
	//								ShadeAndLight2
	// 
	/// Calculates the shading and lighting in one point
	/// 
	/// \param result				The color seen by the observer
	/// \param lightingContext		info about the point being shaded and the lighting of the scene
	/// \param absorptionFunction	The absorption function that corresponds to the current medium.
	/// 
	virtual void		MCCOMAPI ShadeAndLight2(LightingDetail&				result,
												const LightingContext&		lightingContext,
												TAbsorptionFunction*		absorptionFunction)=0;

	// ****************************************************************************
	//								DoShade
	// 
	/// Returns the shading for a given point.
	/// 
	/// \param result     The shading of the point.
	/// \param shadingIn  The information about the point to shade.
	/// 
	virtual void		MCCOMAPI DoShade				(ShadingOut& result,ShadingIn& shadingIn) = 0;

	// ****************************************************************************
	//								GetValue
	// 
	/// Returns the value of the shading function at a given point.
	/// 
	/// \param result     The value of the shading function
	/// \param fullArea   True if the shading as been averaged for antiliasing.
	/// \param shadingIn  The info about the point to shade.
	/// 
	virtual real		MCCOMAPI GetValue				(real& result,boolean& fullArea,ShadingIn& shadingIn) = 0;
	
	// ****************************************************************************
	//								GetColor
	// 
	/// Returns the value of the shading function at a given point.
	/// 
	/// \param result     The value of the shading function
	/// \param fullArea   True if the shading as been averaged for antiliasing.
	/// \param shadingIn  The info about the point to shade.
	/// 
	virtual real		MCCOMAPI GetColor				(TMCColorRGBA& result,boolean& fullArea,ShadingIn& shadingIn) = 0;
	
	// ****************************************************************************
	//								GetVector
	// 
	/// Returns a pertubation of the normal in local coordinates
	/// 
	/// \param result     A vector in local coordinates.
	/// \param shadingIn  The info about the point to shade.
	/// 
	virtual real		MCCOMAPI GetVector				(TVector3& result,ShadingIn& shadingIn) = 0;



	// ****************************************************************************
	//								GetReflection
	// 
	/// Returns the parameters used to calculate the reflection. This function is
	/// only called if the shader is placed in the reflection channel of a multichannel.
	/// 
	/// \param reflectionParams  The parameters used for reflections calculations
	/// \param shadingIn         The info about the point to shade
	/// 
	virtual void		MCCOMAPI GetReflection(TReflectionParameters& reflectionParams,const ShadingIn& shadingIn) = 0;

	// ****************************************************************************
	//								GetTransparency
	// 
	/// Returns the parameters used to calculate the transparency. This function is
	/// only called if the shader is placed in the transparency channel of a multichannel.
	/// 
	/// \param transparencyParams  The parameters used for transparency calculations
	/// \param shadingIn           The info about the point to shade
	/// 
	virtual void		MCCOMAPI GetTransparency(TTransparencyParameters& transparencyParams,const ShadingIn& shadingIn) = 0;

	// ****************************************************************************
	//								GetShaderApproximation
	// 
	/// Returns information used to approximate the shading for the real time display
	/// 
	/// \param result						The approximation of the shading.
	/// \param shadingIn					The info about the point to shade.
	/// 
	virtual void		MCCOMAPI GetShaderApproximation(ShadingOut& result,ShadingIn& shadingIn) = 0;

	// ****************************************************************************
	//								GetShaderApproxColor
	// 
	/// Returns information used to approximate the shading for the real time display
	/// 
	/// \param result						The approximation of the shading.
	/// \param shadingIn					The info about the point to shade.
	/// 
	virtual void		MCCOMAPI GetShaderApproxColor(TMCColorRGBA& result,ShadingIn& shadingIn) = 0;

	// ****************************************************************************
	//								GetBump
	// 
	/// \deprecated Do not implement at this point.
	/// 
	/// \param result     
	/// \param shadingIn  
	/// 
	virtual void		MCCOMAPI GetBump				(TVector3& result,ShadingIn& shadingIn) = 0;

	// Editing misc. info
	// ****************************************************************************
	//								GetImplementedOutput
	// 
	/// Returns a bit field that determines which methods are implemented by this
	/// shading function.
	/// 
	virtual EShaderOutput	MCCOMAPI GetImplementedOutput	() const = 0;

	// ****************************************************************************
	//								GetOriginalParametricTextureMap
	// 
	/// Returns a texture map if there is one for a given channel (Color, Alpha, Transparency...)
	/// 
	/// \param uvSpaceID     The UVSpaceID that is considered.
	/// \param channelIndex  The index of the channel
	/// \param outMap        The map the is output if there is one.
	/// 
	virtual MCCOMErr	MCCOMAPI GetOriginalParametricTextureMap(const uint32& uvSpaceID, const uint32& channelIndex, IShTextureMap** outMap) = 0; 

	// ****************************************************************************
	//								GetTransformComponent
	// 
	/// Returns a pointer to the transform component that defines the 3D transform
	/// of the shader.
	/// 
	/// \return A pointer to this shader's Transform component, or NULL if the shader
	///			does not have a Transform component.
	///
	virtual IShParameterComponent*	MCCOMAPI	GetTransformComponent() =0;

	// ****************************************************************************
	//								GetSubShaderPreview
	// 
	/// Creates a shader that can be used to preview one of the subshader.
	/// 
	/// \param shader				Shader created to be used for the preview.
	/// \param subShader			Shader to put in the sub shader with the keyword subShaderKeyword.
	/// \param subShaderKeyword     Keywork of the sub shader (in the PMap).
	/// \return true		if the shader created have to be processed by the parent shader
	///			false		if not.
	///
	virtual boolean		MCCOMAPI GetSubShaderPreview(IShParameterComponent** shader, IShParameterComponent* subShader, FourCharT subShaderKeyword) = 0;

	// ****************************************************************************
	//								GetShaderPreview
	// 
	/// Creates a shader that can be used to preview this shader.
	/// 
	/// \param shader				Shader created to be used for the preview (this shader must
	///								be a clone).
	///
	virtual void		MCCOMAPI GetShaderPreview(IShParameterComponent** shader) = 0;


	// ****************************************************************************
	//								GetSubShaderType
	// 
	/// Get the type of a sub shader.
	/// 
	/// \param keyword				Id of the sub shader.
	/// \return the type of the sub shader.
	///
	virtual EShaderFunctionType MCCOMAPI GetSubShaderType(IDType keyword) = 0;

	// ****************************************************************************
	//								SetupPreviewScene
	// 
	/// Setup the preview maker to render a preview of this shader.
	/// 
	/// \param previewMaker			The preview maker to setup.
	/// \param masterShader			The master shader to be previewed.
	///
	virtual MCCOMErr	MCCOMAPI SetupPreviewScene(IPreviewMaker* previewMaker, I3DShMasterShader* masterShader) = 0;

	// ****************************************************************************
	//								IsChannelConstantInUVSpace
	// 
	/// Return true if this channel is constant on that UV Space. If not, an exporter should try to bake a texture map.
	/// 
	/// \param uvSpaceID     The UVSpaceID that is considered.
	/// \param channelIndex  The index of the channel
	/// 
	virtual boolean		MCCOMAPI IsChannelConstantInUVSpace(const uint32& uvSpaceID, const uint32& channelIndex) = 0;


	// ****************************************************************************
	//								CanBeTransparent
	// 
	/// Return true if the shader can have some transparency.
	/// 
	/// \param shadingDomainIndex     The shading domain that is considered.
	/// 
	virtual boolean		MCCOMAPI CanBeTransparent(int32 shadingDomainIndex) = 0;

	// ****************************************************************************
	//								GetMasterShader
	// 
	/// Returns the master shader associated with this shader.
	/// 
	virtual I3DShMasterShader*		MCCOMAPI GetMasterShader()=0;

	// ****************************************************************************
	//								GetShadersForChannel
	// 
	/// Returns the shader part of a given uvspace / channel.
	///
	/// \param uvSpaceID The uvSpaceID for which we want the texture
	/// \param channelIndex The index of the channel that we want (color,alpha,...)
	/// \param outShaders Returns the list of the shaders found.
	///
	virtual MCCOMErr	MCCOMAPI GetShadersForChannel(const uint32& uvSpaceID, const uint32& channelIndex, TMCPtrArray<I3DShShader>& outShaders) = 0;  
    // ****************************************************************************
    //                             GetRecommendedTextureSize
    //
    /// Calculate the intrinsic appropriate texture size.
    /// \param[in]  channelIndex The channel for which texture is searched
    // \return true if there is such a size, or false of the texture is procedural 
    virtual boolean  MCCOMAPI GetRecommendedTextureSize(uint32 channelIndex, uint32& width, uint32& height) const = 0;
    // ****************************************************************************
    //                             GetRelevantTextureBucketCache
    //
    /// \param[in]  channelIndex The channel for which texture is searched
    /// Get the texture map file associated to the specified shading domain.
    virtual void MCCOMAPI GetRelevantTextureBucketCache(uint32 channelIndex, boolean allowMultiplierModification, IShTextureMapBucketCache **outTextureMapFile) const = 0;

    // ****************************************************************************
	//								GetConstantColor
    //
	//  Get the constant color of the shader
    //
    // \return MC_S_OK if there is such a constant color, or MC_E_NOTIMPL otherwise
    virtual MCCOMErr	MCCOMAPI GetConstantColor(TMCColorRGBA& resColor) const = 0;
    // ****************************************************************************
	//								GetTextureMultiplyColor
    //
	//  Get the texture multiply color
    virtual TMCColorRGB MCCOMAPI GetTextureMultiplyColor() const = 0;
    // ****************************************************************************
	//								GetBumpAmplitude
    //
	//  Get the bump amplitude
    virtual real MCCOMAPI GetBumpAmplitude() const = 0;
    // ****************************************************************************
	//								GetConstantValue
    //
	//  Get the constant value of the shader
    //
    // \return MC_S_OK if there is such a constant value, or MC_E_NOTIMPL otherwise
    virtual MCCOMErr	MCCOMAPI GetConstantValue(real& resValue) const = 0;
};


// ****************************************************************************
//								I3DShMasterShader
// 
/// <P>I3DShMasterShader represents a Master Shader. A Master Shader can be applied
/// to multiple objects in a scene.</P>
///
/// <P>It supports multiple interfaces such as IMaster and ISelectableObject</P>
///
struct I3DShMasterShader : public IMCUnknown
{	
	// ****************************************************************************
	//								GetInstancesCount
	// 
	/// Returns the number of instances of this master in the scene.
	/// 
	virtual uint32	 MCCOMAPI	GetInstancesCount		() = 0;
	
	// ****************************************************************************
	//								GetInstanceArray
	// 
	/// Returns an array of all the instances that points to that class.
	/// 
	/// \param instances  An array of instances.
	/// 
	virtual void 	 MCCOMAPI	GetInstanceArray		(TMCCountedPtrArray<I3DShTreeElement>& instances) = 0;

	// ****************************************************************************
	//								SetName
	// 
	/// <P>Sets the name of a master. Note that you should not call this method
	/// once the master is inserted in a scene because it does not garantee the
	/// unicity of the name.</P>
	///
	/// <P>If you want to change the name of a Master Shader once it is inserted in
	/// a scene, you should call I3DShScene::RenameMasterShader().</P>
	/// 
	/// \param name  The new name of the master.
	/// 
	virtual MCCOMErr	  MCCOMAPI SetName(const TMCString& name)								= 0;
	
	// ****************************************************************************
	//								GetName
	// 
	/// Returns the name of the Master Shader.
	/// 
	/// \param name  The name of the Master Shader.
	/// 
	virtual MCCOMErr	  MCCOMAPI GetName(TMCString& name)										= 0;

	// ****************************************************************************
	//								SetShader
	// 
	/// Sets the shader tree that defines this Master Shader.
	/// 
	/// \param shader     A pointer to the root of the shader tree.
	/// \param cloneMode  The clone Mode (see ECloneMode).
	/// 
	virtual MCCOMErr	  MCCOMAPI SetShader(I3DShShader* shader, ECloneMode cloneMode)			= 0;
	
	// ****************************************************************************
	//								GetShader
	// 
	/// Returns a pointer to the shader tree that defines this Master Shader.
	/// 
	/// \param shader  A pointer to the root of the shader tree.
	/// 
	virtual MCCOMErr	  MCCOMAPI GetShader(I3DShShader** shader)								= 0;

	// ****************************************************************************
	//								SetDisplacementShader
	// 
	/// Sets the displacement shader tree that defines this Master Shader.
	/// 
	/// \param shader     A pointer to the root of the displacement shader tree.
	/// \param cloneMode  The clone Mode (see ECloneMode).
	/// 
	virtual MCCOMErr	  MCCOMAPI SetDisplacementShader(I3DShShader* shader, ECloneMode cloneMode)	= 0;
	
	// ****************************************************************************
	//								GetShader
	// 
	/// Returns a pointer to the displacement shader tree that defines this Master Shader.
	/// 
	/// \param shader  A pointer to the root of the shader tree.
	/// 
	virtual MCCOMErr	  MCCOMAPI GetDisplacementShader(I3DShShader** shader)					= 0;

	// ****************************************************************************
	//								Clone
	// 
	/// Makes a copy of the Master Shader.
	/// 
	/// \param clone      The copy that is returned.
	/// \param cloneMode  The clone Mode (see ECloneMode).
	/// \param cloneDisplacementMapping	Clone the displacement mapping
	/// 
	virtual MCCOMErr	  MCCOMAPI Clone(I3DShMasterShader** clone, ECloneMode cloneMode, boolean cloneDisplacementMapping = true) const = 0;
	
	// ****************************************************************************
	//								GetScene
	// 
	/// Returns a pointer to the scene that contains this Master Shader.
	/// 
	/// \param scene  A pointer to the scene that contains this Master Shader. (NULL if it is
	///					not inserted in a scene.
	/// 
	virtual MCCOMErr	  MCCOMAPI GetScene(I3DShScene** scene) const							= 0;
	
	// ****************************************************************************
	//								IsDefaultMaster
	// 
	/// Returns true if the Master Shader is the default Master Shaders.
	/// 
	virtual boolean		  MCCOMAPI IsDefaultMaster() const										= 0;

	// ****************************************************************************
	//								GetThisMaster
	// 
	/// Returns the I3DShMaster interface.
	/// 
	virtual I3DShMaster*  MCCOMAPI GetThisMaster	()											= 0;

	// ****************************************************************************
	//								IsReferencedByThisSubTree
	// 
	/// Return true if the given sub tree keeps a reference to that master shader
	///
	/// \param subTree		The sub tree that might reference that master object
	/// \param scene		The scene that contains that sub tree.
	/// 
	virtual boolean MCCOMAPI IsReferencedByThisSubTree(I3DShTreeElement* subTree,I3DShScene* scene) = 0;

	// ****************************************************************************
	//								MasterShaderModified
	// 
	/// Notify that the master shader is modified
	/// 
	virtual MCCOMErr	MCCOMAPI MasterShaderModified(boolean onlyShading=false) = 0;
};


// ****************************************************************************
//								I3DShLightingModel
// 
/// This interface is passed to I3DExShader::ShadeAndLight2() and provides a default
/// implementation for the lighting model calls.
/// 
struct I3DShLightingModel
{
	// ****************************************************************************
	//								ShadeAndLight2
	// 
	/// <P>Default implementation for the shading and lighting in one point.
	/// 
	/// \param result					The lighting that is returned.
	/// \param lightingContext			Info about the point being shaded and the lighting of the scene.
	/// \param absorptionFunction		The absorption function that corresponds to the current medium.
	/// 
	virtual void MCCOMAPI ShadeAndLight2(LightingDetail& result,const LightingContext& lightingContext,TAbsorptionFunction* absorptionFunction)=0;

	// ****************************************************************************
	//								CalculateDirectLighting
	// 
	/// Default implementation of the direct lighting.
	/// 
	/// \param result           The result direct lighting.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// 
	virtual void MCCOMAPI CalculateDirectLighting(LightingDetail& result,const LightingContext&	lightingContext) = 0;
	
	// ****************************************************************************
	//								CalculateReflection
	// 
	/// Default implementation of the reflections.
	/// 
	/// \param reflectionColor  The resulting reflection color.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// \param shading          The shading at this point.
	/// 
	virtual void MCCOMAPI CalculateReflection(TMCColorRGB& reflectionColor,const LightingContext&	lightingContext,const ShadingOut& shading) = 0;
	
	// ****************************************************************************
	//								CalculateCaustics
	// 
	/// Default implementation of the caustics.
	/// 
	/// \param causticColor     The resulting caustic color.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// \param shading          The shading at this point.
	/// 
	virtual void MCCOMAPI CalculateCaustics(TMCColorRGB& causticColor,const LightingContext&	lightingContext,const ShadingOut& shading) = 0;
	
	// ****************************************************************************
	//								CalculateIndirectLighting
	// 
	/// Default implementation of the Global Illumination.
	/// 
	/// \param indirectDiffuseColor		The resulting indirect lighting color.
	/// \param ambientOcclusionFactor	The ambient occlusion factor.
	/// \param lightingContext			Info about the point being shaded and the lighting of the scene.
	/// \param shading					The shading at this point.
	/// 
	virtual void MCCOMAPI CalculateIndirectLighting(TMCColorRGB& indirectDiffuseColor, real& ambientOcclusionFactor, const LightingContext& lightingContext, const ShadingOut& shading) = 0;
	
	// ****************************************************************************
	//								CalculateTransparency
	// 
	/// Default implementation of the Transparency.
	/// 
	/// \param resColor         The resulting transparency color to add to the final color.
	/// \param outAlpha         The resulting alpha.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// \param shading          The shading at this point.
	/// 
	virtual void MCCOMAPI CalculateTransparency(TMCColorRGB& resColor,real32& outAlpha,const LightingContext&	lightingContext,const ShadingOut& shading) = 0;
	
	// ****************************************************************************
	//								CalculateAlpha
	// 
	/// Default implementation of the Alpha channel.
	/// 
	/// \param resColor         The resulting color.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// \param shading          The shading at this point.
	/// 
	virtual void MCCOMAPI CalculateAlpha(LightingDetail& result,const LightingContext&	lightingContext,const ShadingOut& shading,TAbsorptionFunction* absorptionFunction) = 0;
	
	// ****************************************************************************
	//								CalculateSubsurfaceScattering
	// 
	/// Default implementation of the Subsurface Scattering.
	/// 
	/// \param subsurfaceColor  The resulting subsurface scattering color to add to the final color.
	/// \param currentColor		The current final color.
	/// \param lightingContext  Info about the point being shaded and the lighting of the scene.
	/// \param shading          The shading at this point.
	///
	virtual void MCCOMAPI CalculateSubsurfaceScattering(TMCColorRGB& subsurfaceColor,const TMCColorRGB& currentColor,const LightingContext&	lightingContext,const ShadingOut& shading) = 0;
};

/// \}

/*****************************************************************************\
*                                                                             *
*  IShadingDomain                                                             *
*                                                                             *
*    ShadingDomain interface                                                  *
*                                                                             *
*   shader with projection mapping support this interface                     *
*                                                                             *
\*****************************************************************************/

struct IShadingDomain : public IMCUnknown
{
	virtual void	GetNewShadingIn(ShadingIn& newShadingIn, ShadingIn& shadingIn)	=0;
	virtual boolean KeepUVSpaceID( const ShadingIn&  shadIn  ) const				=0;

	virtual IDType  GetMappingMode() const											=0;
	virtual boolean UseMappingTransform() const										=0;
	virtual int16	FindBoxMappingFace(TVector3* pt) const							=0;
	virtual void	GetUVSpaceInfo(UVSpaceInfo& uvSpaceInfo) const					=0;
	virtual uint32	GetUVSpaceId() const											=0;

	virtual void	XYZ2UV(ShadingIn& shadingIn, const ShadingFlags &needs) const	=0;
	virtual int32	UV2Ray( const TVector2 &uv, int16 uvSpaceID, TVector3& srcPt, TVector3& destPt) const =0;

	// -Description:
	//			get the transformation applied to the UV.
	// -Parameters:
	//			result: the 2d transform matrix
	// -returns:
	//			error code
	virtual MCCOMErr	MCCOMAPI Get2DTransform(TTransform2D& result)=0;
};


#endif
