
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {

/// \brief This is the base class for a renderer implementation, which transforms a mesh into the opengl pipeline.
///
/// Every mesh has one or more renderers associated, which are responsible to render the mesh, or in other 
/// words, send the mesh data (vertex positions, texture coordinates, normals etc...) to opengl. These renderers
/// are child objects of the mesh (since both the mesh and the renderer objects are inherited from TreeNode)
/// They are used in different circumstances, for example mudbox uses one renderer for plain rendering, and 
/// another one for wireframe rendering. These renderer object can hold cached buffers in memory, to be able 
/// to render the mesh as fast as possible. The reason why mudbox keeps multiple renderers and not uses a single
/// one to render the mesh in different modes is that this way the renderers can hold precalculated data in buffers.
/// A naiv implementation of this interface would
/// go through all the faces in the mesh, and pump the mesh data with immediate opengl calls to the hardware,
/// but of course this solution would be slow for most of the objects.
class MBDLL_DECL MeshRenderer : public TreeNode
{
	DECLARE_CLASS;

	/// This function is called when the plugin first used. This is responsible for one time initialization.
	virtual void Initialize( void );
	/// Called to set the mesh for the renderer node. Usually called only once right after the creation of a node. Each mesh has its own renderer nodes so dont expect this function to be called often.
	virtual void SetMesh( Mesh *pMesh );
	/// \brief Render the mesh to the current framebuffer with the current pipeline settings. 
	/// 
	/// This is the main function of the class, this will do the job.
	/// The pipeline is already set up for accepting the mesh data, so this function should leave all opengl states 
	/// untouched.
	virtual void Render( 
		const Selector *pSelector = 0, /// This is a pointer to a selector object (for example a camera frustum selector), or can be NULL. When this pointer is specified, the renderer object should filter the data and only render those parts which are selected by the selector node. The renderer can ignore this parameter, but for the best performance it is recommended to use it. See class Selector for more details.
		bool bSkipMaterials = false, /// When this parameter is true, the renderer should ignore the material data stored for the mesh. This parameter will be removed from future releases.
		const Camera *pCamera = 0, /// This pointer specifies which camera will be used during the rendering.
		const AxisAlignedBoundingBox &bUVFilter = AxisAlignedBoundingBox() /// Only those faces should be rendered whose texture coordinates are inside this bounding box, the others should be ignored.
		);

	/// This function is responsible to render some data into the framebuffer, which later should tell the exact vertex index of one of the corners of the current face. The rendered value have to be greater or equal to iStart. The function have to return the lowest value not used by the funtion (That value will be used as iStart for further RenderData() calls). See also VertexIndexFromData().
	virtual unsigned int RenderData( const Selector *pSelector, unsigned int iStart, const Camera *pCamera );
	/// This function have to calculate the vertex or face index from the value rendered by RenderData(). If a value is unknown it must be set to 0xffffffff.
	virtual void DecodeData( unsigned int iData, unsigned int &iFaceIndex, unsigned int &iVertexIndex );

	/// Called when any vertex of the associated mesh is changed its position.
	virtual void OnVertexPositionChange( unsigned int iVertexIndex, unsigned int iFaceIndex );
	/// Called when any vertex of the associated mesh is changed its state.
	virtual void OnVertexStateChange( unsigned int iVertexIndex, unsigned int iFaceIndex );
	/// Called when the mesh changed in any way, like changed the number of vertices or faces.
	virtual void OnMeshChange( void );

	/// Set the level of detail for the renderer. 
	virtual void SetLODLevel( float fLevel );
	/// Returns the level of detail for the renderer.
	virtual float LODLevel( void ) const;

	/// Returns the currently rendered UV tile
	virtual const AxisAlignedBoundingBox &ActiveUVArea( void ) const;

	/// Set wireframe status. If set to true, the surface will be rendered as wireframe.
	virtual void SetWireFrameMode( bool bMode );
	/// Returns true if wireframe is on.
	virtual bool WireFrameMode( void ) const;
	/// Set the color mode. If set to true, colors for each vertex will be passed to the pipeline based on the status of the vertex.
	virtual void SetColorMode( bool bMode );
	/// Returns true if the renderer currently contains color information.
	virtual bool ColorMode( void ) const;
	/// Set the subdivision level for the wireframe display. Zero means the base level.
	virtual void SetWireLevel( unsigned int iLevel );
	/// Returns the current wire level.
	virtual unsigned int WireLevel( void ) const;
	/// Set the texture coordinate mode. If true, the texture coordinates will be passed to the opengl pipeline.
	virtual void SetTextureCoordinateMode( bool bMode );
	/// Returns true if the renderer contains texture coordinates.
	virtual bool TextureCoordinateMode( void ) const;
	/// Set the tangent mode. If true, tangents and binormals will be also passed to the pipeline.
	virtual void SetTangentMode( bool bMode );
	/// Returns true if the renderer contains tangents.
	virtual bool TangentMode( void ) const;

	virtual bool ReadyForClientRender() { return true;}

	/// Set the faceted mode. If true, shading will use face normal, otherwise it will use vertex normal.
	virtual void SetFacetedMode( bool bMode );
	/// Returns if faceted mode is on.
	virtual bool FacetedMode( void ) const;
};

/// \brief This interface can be used to provide additional vertex data for the rendering.
///
/// When an object with this type is added as a child to a Mesh object in the scene graph,
/// the renderer uses that object to obtain additional vertex data for the rendering (like
/// vertex color, bone indices and weights). This interface is important when you want to
/// use your own custom shader for rendering, which needs more data than the usual 
/// vertex data (position, normal, etc.).
class MBDLL_DECL VertexDataProvider : public TreeNode
{
	DECLARE_CLASS;

public:
	/// This structure carries information about a component.
	struct ComponentDescription
	{
		/// Type of the component.
		enum Type
		{
			eFloat,
			eByte,
			eColor,
			eShort
		} m_eType;
		/// Dimension of the component, must not be greater than 4.
		int m_iDimension;
		/// This tells the renderer what to do with this data. It can be used for general purposes, or directly
		/// passed to the shader in a texture coordinate channel. \see VertexDataUsage
		Material::VertexDataUsage m_eUsage;
	};

	/// Returns the number of different vertex components this object has data for.
	virtual int ComponentCount( void ) const;

	/// Returns the description of a given component.
	virtual ComponentDescription Component( 
		int iIndex ///< [in] Index of the component.
		) const;

	/// Returns the data for a given vertex and component.
	virtual const void *VertexData( 
		unsigned int iVertexIndex, ///< [in] Index of the vertex.
		int iComponentIndex ///< [in] Index of the component.
		) const;

	/// This structure describes a dirty vertex.
	struct DirtyVertex
	{
		unsigned int m_iVertexIndex;	/// Index of the vertex.
		unsigned int m_iFaceIndex;		/// Index of a face which uses the vertex. If this information is not valid, the update won't be
													/// correct when LOD based rendering is used.
	};

	/// \brief This function must return an array of vertex indices whose data has been changed since the last call to this function.
	///
	/// There are two ways to update the buffers in the renderer object:
	///
	/// \li When most or all of the vertices need to update, the VertexDataProvider object can instruct the renderer to do a global
	/// update on all the vertices by calling ContentChanged() on itself. This way the renderer will know about the change, and refresh
	/// every vertex buffer which contains data from this object.
	///
	/// \li If only subset of the vertices are changed, the VertexDataProvider can collect the indices of the changed vertices to an array,
	/// and pass that array to the renderer when this function is called. The renderer will update the specified vertices, and clear the array.
	/// The VertexDataProvider can continue storing dirty vertex indices into the array after the call. 
	virtual QVector<DirtyVertex> &DirtyVertexList( void );
};

}; // end of namespace mudbox
