diff options
Diffstat (limited to 'materialsystem/shaderapidx9/meshbase.h')
| -rw-r--r-- | materialsystem/shaderapidx9/meshbase.h | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/materialsystem/shaderapidx9/meshbase.h b/materialsystem/shaderapidx9/meshbase.h new file mode 100644 index 0000000..b566099 --- /dev/null +++ b/materialsystem/shaderapidx9/meshbase.h @@ -0,0 +1,309 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef MESHBASE_H +#define MESHBASE_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "materialsystem/imesh.h" +#include "materialsystem/imaterial.h" + + +//----------------------------------------------------------------------------- +// Base vertex buffer +//----------------------------------------------------------------------------- +abstract_class CVertexBufferBase : public IVertexBuffer +{ + // Methods of IVertexBuffer +public: + virtual void Spew( int nVertexCount, const VertexDesc_t &desc ); + virtual void ValidateData( int nVertexCount, const VertexDesc_t& desc ); + +public: + // constructor, destructor + CVertexBufferBase( const char *pBudgetGroupName ); + virtual ~CVertexBufferBase(); + + // Displays the vertex format + static void PrintVertexFormat( VertexFormat_t vertexFormat ); + + // Used to construct vertex data + static void ComputeVertexDescription( unsigned char *pBuffer, VertexFormat_t vertexFormat, VertexDesc_t &desc ); + + // Returns the vertex format size + static int VertexFormatSize( VertexFormat_t vertexFormat ); + +protected: + const char *m_pBudgetGroupName; +}; + + +//----------------------------------------------------------------------------- +// Base index buffer +//----------------------------------------------------------------------------- +abstract_class CIndexBufferBase : public IIndexBuffer +{ + // Methods of IIndexBuffer +public: + virtual void Spew( int nIndexCount, const IndexDesc_t &desc ); + virtual void ValidateData( int nIndexCount, const IndexDesc_t& desc ); + + // Other public methods +public: + // constructor, destructor + CIndexBufferBase( const char *pBudgetGroupName ); + virtual ~CIndexBufferBase() {} + +protected: + const char *m_pBudgetGroupName; +}; + + +//----------------------------------------------------------------------------- +// Base mesh +//----------------------------------------------------------------------------- +class CMeshBase : public IMesh +{ + // Methods of IMesh +public: + + // Other public methods that need to be overridden +public: + // Begins a pass + virtual void BeginPass( ) = 0; + + // Draws a single pass of the mesh + virtual void RenderPass() = 0; + + // Does it have a color mesh? + virtual bool HasColorMesh() const = 0; + + // Am I using morph data? + virtual bool IsUsingMorphData() const = 0; + + virtual bool HasFlexMesh() const = 0; + + virtual IMesh *GetMesh() { return this; } + +public: + // constructor, destructor + CMeshBase(); + virtual ~CMeshBase(); + +}; + +//----------------------------------------------------------------------------- +// Utility method for VertexDesc_t (don't want to expose it in public, in imesh.h) +//----------------------------------------------------------------------------- +inline void ComputeVertexDesc( unsigned char * pBuffer, VertexFormat_t vertexFormat, VertexDesc_t & desc ) +{ + int i; + int *pVertexSizesToSet[64]; + int nVertexSizesToSet = 0; + static ALIGN32 ModelVertexDX8_t temp[4]; + float *dummyData = (float*)&temp; // should be larger than any CMeshBuilder command can set. + + // Determine which vertex compression type this format specifies (affects element sizes/decls): + VertexCompressionType_t compression = CompressionType( vertexFormat ); + desc.m_CompressionType = compression; + + // We use fvf instead of flags here because we may pad out the fvf + // vertex structure to optimize performance + int offset = 0; + // NOTE: At the moment, we assume that if you specify wrinkle, you also specify position + Assert( ( ( vertexFormat & VERTEX_WRINKLE ) == 0 ) || ( ( vertexFormat & VERTEX_POSITION ) != 0 ) ); + if ( vertexFormat & VERTEX_POSITION ) + { + // UNDONE: compress position+wrinkle to SHORT4N, and roll the scale into the transform matrices + desc.m_pPosition = reinterpret_cast<float*>(pBuffer); + offset += GetVertexElementSize( VERTEX_ELEMENT_POSITION, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_Position; + + if ( vertexFormat & VERTEX_WRINKLE ) + { + desc.m_pWrinkle = reinterpret_cast<float*>( pBuffer + offset ); + offset += GetVertexElementSize( VERTEX_ELEMENT_WRINKLE, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_Wrinkle; + } + else + { + desc.m_pWrinkle = dummyData; + desc.m_VertexSize_Wrinkle = 0; + } + } + else + { + desc.m_pPosition = dummyData; + desc.m_VertexSize_Position = 0; + desc.m_pWrinkle = dummyData; + desc.m_VertexSize_Wrinkle = 0; + } + + // Bone weights/matrix indices + desc.m_NumBoneWeights = NumBoneWeights( vertexFormat ); + + Assert( ( desc.m_NumBoneWeights == 2 ) || ( desc.m_NumBoneWeights == 0 ) ); + + // We assume that if you have any indices/weights, you have exactly two of them + Assert( ( ( desc.m_NumBoneWeights == 2 ) && ( ( vertexFormat & VERTEX_BONE_INDEX ) != 0 ) ) || + ( ( desc.m_NumBoneWeights == 0 ) && ( ( vertexFormat & VERTEX_BONE_INDEX ) == 0 ) ) ); + + if ( ( vertexFormat & VERTEX_BONE_INDEX ) != 0 ) + { + if ( desc.m_NumBoneWeights > 0 ) + { + Assert( desc.m_NumBoneWeights == 2 ); + + // Always exactly two weights + desc.m_pBoneWeight = reinterpret_cast<float*>(pBuffer + offset); + offset += GetVertexElementSize( VERTEX_ELEMENT_BONEWEIGHTS2, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_BoneWeight; + } + else + { + desc.m_pBoneWeight = dummyData; + desc.m_VertexSize_BoneWeight = 0; + } + + desc.m_pBoneMatrixIndex = pBuffer + offset; + offset += GetVertexElementSize( VERTEX_ELEMENT_BONEINDEX, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_BoneMatrixIndex; + } + else + { + desc.m_pBoneWeight = dummyData; + desc.m_VertexSize_BoneWeight = 0; + + desc.m_pBoneMatrixIndex = (unsigned char*)dummyData; + desc.m_VertexSize_BoneMatrixIndex = 0; + } + + if ( vertexFormat & VERTEX_NORMAL ) + { + desc.m_pNormal = reinterpret_cast<float*>(pBuffer + offset); + // See PackNormal_[SHORT2|UBYTE4|HEND3N] in mathlib.h for the compression algorithm + offset += GetVertexElementSize( VERTEX_ELEMENT_NORMAL, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_Normal; + } + else + { + desc.m_pNormal = dummyData; + desc.m_VertexSize_Normal = 0; + } + + if ( vertexFormat & VERTEX_COLOR ) + { + desc.m_pColor = pBuffer + offset; + offset += GetVertexElementSize( VERTEX_ELEMENT_COLOR, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_Color; + } + else + { + desc.m_pColor = (unsigned char*)dummyData; + desc.m_VertexSize_Color = 0; + } + + if ( vertexFormat & VERTEX_SPECULAR ) + { + desc.m_pSpecular = pBuffer + offset; + offset += GetVertexElementSize( VERTEX_ELEMENT_SPECULAR, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_Specular; + } + else + { + desc.m_pSpecular = (unsigned char*)dummyData; + desc.m_VertexSize_Specular = 0; + } + + // Set up texture coordinates + for ( i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; ++i ) + { + // FIXME: compress texcoords to SHORT2N/SHORT4N, with a scale rolled into the texture transform + VertexElement_t texCoordElements[4] = { VERTEX_ELEMENT_TEXCOORD1D_0, VERTEX_ELEMENT_TEXCOORD2D_0, VERTEX_ELEMENT_TEXCOORD3D_0, VERTEX_ELEMENT_TEXCOORD4D_0 }; + int nSize = TexCoordSize( i, vertexFormat ); + if ( nSize != 0 ) + { + desc.m_pTexCoord[i] = reinterpret_cast<float*>(pBuffer + offset); + VertexElement_t texCoordElement = (VertexElement_t)( texCoordElements[ nSize - 1 ] + i ); + offset += GetVertexElementSize( texCoordElement, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_TexCoord[i]; + } + else + { + desc.m_pTexCoord[i] = dummyData; + desc.m_VertexSize_TexCoord[i] = 0; + } + } + + // Binormal + tangent... + // Note we have to put these at the end so the vertex is FVF + stuff at end + if ( vertexFormat & VERTEX_TANGENT_S ) + { + // UNDONE: use normal compression here (use mem_dumpvballocs to see if this uses much memory) + desc.m_pTangentS = reinterpret_cast<float*>(pBuffer + offset); + offset += GetVertexElementSize( VERTEX_ELEMENT_TANGENT_S, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_TangentS; + } + else + { + desc.m_pTangentS = dummyData; + desc.m_VertexSize_TangentS = 0; + } + + if ( vertexFormat & VERTEX_TANGENT_T ) + { + // UNDONE: use normal compression here (use mem_dumpvballocs to see if this uses much memory) + desc.m_pTangentT = reinterpret_cast<float*>(pBuffer + offset); + offset += GetVertexElementSize( VERTEX_ELEMENT_TANGENT_T, compression ); + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_TangentT; + } + else + { + desc.m_pTangentT = dummyData; + desc.m_VertexSize_TangentT = 0; + } + + // User data.. + int userDataSize = UserDataSize( vertexFormat ); + if ( userDataSize > 0 ) + { + desc.m_pUserData = reinterpret_cast<float*>(pBuffer + offset); + VertexElement_t userDataElement = (VertexElement_t)( VERTEX_ELEMENT_USERDATA1 + ( userDataSize - 1 ) ); + // See PackNormal_[SHORT2|UBYTE4|HEND3N] in mathlib.h for the compression algorithm + offset += GetVertexElementSize( userDataElement, compression ); + + pVertexSizesToSet[nVertexSizesToSet++] = &desc.m_VertexSize_UserData; + } + else + { + desc.m_pUserData = dummyData; + desc.m_VertexSize_UserData = 0; + } + + // We always use vertex sizes which are half-cache aligned (16 bytes) + // x360 compressed vertexes are not compatible with forced alignments + bool bCacheAlign = ( vertexFormat & VERTEX_FORMAT_USE_EXACT_FORMAT ) == 0; + if ( bCacheAlign && ( offset > 16 ) && IsPC() ) + { + offset = (offset + 0xF) & (~0xF); + } + desc.m_ActualVertexSize = offset; + + // Now set the m_VertexSize for all the members that were actually valid. + Assert( nVertexSizesToSet < sizeof(pVertexSizesToSet)/sizeof(pVertexSizesToSet[0]) ); + for ( int iElement=0; iElement < nVertexSizesToSet; iElement++ ) + { + *pVertexSizesToSet[iElement] = offset; + } +} + +#endif // MESHBASE_H |