text: // Copyright information can be found in the file named COPYING
  // located in the root directory of this distribution.
  
  #ifndef _GFXVERTEXFORMAT_H_
  #define _GFXVERTEXFORMAT_H_
  
  #ifndef _TVECTOR_H_
  #include "core/util/tVector.h"
  #endif
  #ifndef _GFXENUMS_H_
  #include "gfx/gfxEnums.h"
  #endif
  
  
  /// The known Torque vertex element semantics.  You can use
  /// other semantic strings, but they will be interpreted as
  /// a TEXCOORD.
  /// @see GFXVertexElement
  /// @see GFXVertexFormat
  namespace GFXSemantic
  {
     extern const String POSITION;
     extern const String NORMAL;
     extern const String BINORMAL;
     extern const String TANGENT;
     extern const String TANGENTW;
     extern const String COLOR;
     extern const String TEXCOORD;
  }
  
  
  /// This is a simple wrapper for the platform specific
  /// vertex declaration data which is held by the vertex
  /// format.  
  ///
  /// If your using it... you probably shouldn't be.
  ///
  /// @see GFXVertexFormat
  class GFXVertexDecl
  {
  public:
     virtual ~GFXVertexDecl() {}
  };
  
  
  /// The element structure helps define the data layout 
  /// for GFXVertexFormat.
  ///
  /// @see GFXVertexFormat
  ///
  class GFXVertexElement
  {
     friend class GFXVertexFormat;
  
  protected:
  
     /// The stream index when rendering from multiple
     /// vertex streams.  In most cases this is 0.
     U32 mStreamIndex;
  
     /// A valid Torque shader symantic.
     /// @see GFXSemantic   
     String mSemantic;
  
     /// The semantic index is used where there are
     /// multiple semantics of the same type.  For 
     /// instance with texcoords.
     U32 mSemanticIndex;
  
     /// The element type.
     GFXDeclType mType;
  
  public:
  
     /// Default constructor.
     GFXVertexElement()
        :  mStreamIndex( 0 ),
           mSemanticIndex( 0 ),         
           mType( GFXDeclType_Float4 )
     {
     }
  
     /// Copy constructor.
     GFXVertexElement( const GFXVertexElement &elem )
        :  mStreamIndex( elem.mStreamIndex ),
           mSemantic( elem.mSemantic ),
           mSemanticIndex( elem.mSemanticIndex ),         
           mType( elem.mType )
     {
     }
  
     /// Returns the stream index.
     U32 getStreamIndex() const { return mStreamIndex; }
  
     /// Returns the semantic name which is usually a
     /// valid Torque semantic.
     /// @see GFXSemantic
     const String& getSemantic() const { return mSemantic; }
  
     /// Returns the semantic index which is used where there
     /// are multiple semantics of the same type.  For instance
     /// with texcoords.
     U32 getSemanticIndex() const { return mSemanticIndex; }
  
     /// Returns the type for the semantic.
     GFXDeclType getType() const { return mType; }
  
     /// Returns true of the semantic matches.
     bool isSemantic( const String& str ) const { return ( mSemantic == str ); }
  
     /// Returns the size in bytes of the semantic type.
     U32 getSizeInBytes() const;
  };
  
  
  /// The vertex format structure usually created via the declare and 
  /// implement macros.
  ///
  /// You can use this class directly to create a vertex format, but
  /// note that it is expected to live as long as the VB that uses it 
  /// exists.
  ///
  /// @see GFXDeclareVertexFormat
  /// @see GFXImplementVertexFormat
  /// @see GFXVertexElement
  ///
  class GFXVertexFormat
  {
  public:
  
     /// Default constructor for an empty format.
     GFXVertexFormat();
  
     /// The copy constructor.
     GFXVertexFormat( const GFXVertexFormat &format ) { copy( format ); }
  
     /// Copy the other vertex format.
     void copy( const GFXVertexFormat &format );
  
     /// Used to append a vertex format to the end of this one.
     void append( const GFXVertexFormat &format, U32 streamIndex = -1 );
  
     /// Returns a unique description string for this vertex format.
     const String& getDescription() const;
  
     /// Clears all the vertex elements.
     void clear();
  
     /// Adds a vertex element to the format.
     ///
     /// @param semantic A valid Torque semantic string.
     /// @param type The element type.
     /// @param index The semantic index which is typically only used for texcoords.
     ///
     void addElement( const String& semantic, GFXDeclType type, U32 index = 0, U32 stream = 0 );
     
     /// Returns true if there is a NORMAL semantic in this vertex format.
     bool hasNormal() const;
  
     /// Returns true if there is a TANGENT semantic in this vertex format.
     bool hasTangent() const;
  
     /// Returns true if there is a COLOR semantic in this vertex format.
     bool hasColor() const;
  
     /// Returns the texture coordinate count by 
     /// counting the number of TEXCOORD semantics.
     U32 getTexCoordCount() const;
  
     /// Returns true if these two formats are equal.
     inline bool isEqual( const GFXVertexFormat &format ) const;
  
     /// Returns the total elements in this format.
     U32 getElementCount() const { return mElements.size(); }
  
     /// Returns the vertex element by index.
     const GFXVertexElement& getElement( U32 index ) const { return mElements[index]; }
  
     /// Returns the size in bytes of the format as described.
     U32 getSizeInBytes() const;
  
     /// Returns the hardware specific vertex declaration for this format.
     GFXVertexDecl* getDecl() const;
  
  protected:
  
     /// We disable the copy operator.
     GFXVertexFormat& operator =( const GFXVertexFormat& ) { return *this; }
  
     /// Recreates the description and state when 
     /// the format has been modified.
     void _updateDirty();
  
     /// Requests the vertex declaration from the GFX device.
     void _updateDecl();
  
     /// Set when the element list is changed.
     bool mDirty;
  
     /// Is set if there is a NORMAL semantic in this vertex format.   
     bool mHasNormal;
  
     /// Is true if there is a TANGENT semantic in this vertex format.
     bool mHasTangent;
  
     /// Is true if there is a COLOR semantic in this vertex format.
     bool mHasColor;
  
     /// The texture coordinate count by counting the 
     /// number of "TEXCOORD" semantics.
     U32 mTexCoordCount;
  
     /// The size in bytes of the vertex format as described.
     U32 mSizeInBytes;
  
     /// An interned string which uniquely identifies the format.
     String mDescription;
     
     /// The elements of the vertex format.
     Vector<GFXVertexElement> mElements;
  
     /// The hardware specific vertex declaration.
     GFXVertexDecl *mDecl;
  };
  
  
  inline bool GFXVertexFormat::isEqual( const GFXVertexFormat &format ) const 
  {
     // Comparing the strings works because we know both 
     // these are interned strings.  This saves one comparison
     // over the string equality operator.
     return getDescription().c_str() == format.getDescription().c_str(); 
  }
  
  
  /// This template class is usused to initialize the format in 
  /// the GFXImplement/DeclareVertexFormat macros.  You shouldn't
  /// need to use it directly in your code.
  ///
  /// @see GFXVertexFormat
  /// @see GFXImplementVertexFormat
  ///
  template<class T>
  class _GFXVertexFormatConstructor : public GFXVertexFormat
  {
  protected:
  
     void _construct();
  
  public:
  
     _GFXVertexFormatConstructor() { _construct(); }
  };
  
  
  /// Helper template function which returns the correct 
  /// GFXVertexFormat object for a vertex structure.
  /// @see GFXVertexFormat
  template<class T> inline const GFXVertexFormat* getGFXVertexFormat();
  
  #ifdef TORQUE_OS_XENON
  
     /// On the Xbox360 we want we want to be sure that verts
     /// are on aligned boundariess.
     #define GFX_VERTEX_STRUCT __declspec(align(16)) struct
  
  #else
     #define GFX_VERTEX_STRUCT struct
  #endif
  
  
  /// The vertex format declaration which is usally placed in your header 
  /// file.  It should be used in conjunction with the implementation macro.
  /// 
  /// @param name The name for the vertex structure.
  ///
  /// @code
  ///   
  ///   // A simple vertex format declaration.
  ///   GFXDeclareVertexFormat( GFXVertexPCT )
  ///   {
  ///      Point3F pos;
  ///      GFXVertexColor color;
  ///      Point2F texCoord;
  ///   }
  ///
  /// @endcode
  ///
  /// @see GFXImplementVertexFormat
  ///
  #define GFXDeclareVertexFormat( name ) \
     GFX_VERTEX_STRUCT name; \
     extern const GFXVertexFormat _gfxVertexFormat##name; \
     template<> inline const GFXVertexFormat* getGFXVertexFormat<name>() { static _GFXVertexFormatConstructor<name> vertexFormat; return &vertexFormat; } \
     GFX_VERTEX_STRUCT name \
  
  
  /// The vertex format implementation which is usally placed in your source 
  /// file.  It should be used in conjunction with the declaration macro.
  /// 
  /// @param name The name of the vertex structure.
  ///
  /// @code
  ///   
  ///   // A simple vertex format implementation.
  ///   GFXImplementVertexFormat( GFXVertexPCT )
  ///   {
  ///      addElement( "POSITION", GFXDeclType_Float3 );
  ///      addElement( "COLOR", GFXDeclType_Color );
  ///      addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
  ///   }
  ///
  /// @endcode
  ///
  /// @see GFXDeclareVertexFormat
  ///
  #define GFXImplementVertexFormat( name ) \
     template<>   void _GFXVertexFormatConstructor<name>::_construct() \
  
  #endif // _GFXVERTEXFORMAT_H_
  