class CIndexBuilder : IndexDesc_t
{
public:
CIndexBuilder();
CIndexBuilder(IIndexBuffer *pIndexBuffer, MaterialIndexFormat_t fmt = MATERIAL_INDEX_FORMAT_UNKNOWN);
~CIndexBuilder(){}
// Begins, ends modification of the index buffer (returns true if the lock succeeded)
// A lock may not succeed if append is set to true and there isn't enough room
// NOTE: Append is only used with dynamic index buffers; it's ignored for static buffers
bool Lock(int nMaxIndexCount, int nIndexOffset, bool bAppend = false);
void Unlock();
// Spews the current data
// NOTE: Can only be called during a lock/unlock block
void SpewData() const;
// Returns the number of indices we can fit into the buffer without needing to discard
int GetRoomRemaining() const;
// Binds this index buffer
void Bind(IMatRenderContext *pContext) const;
// Returns the byte offset
int Offset() const;
// Begins, ends modification of the index buffer
// NOTE: IndexOffset is the number to add to all indices written into the buffer;
// useful when using dynamic vertex buffers.
void Begin(IIndexBuffer *pIndexBuffer, int nMaxIndexCount, int nIndexOffset = 0);
void End(bool bSpewData = false);
// Locks the index buffer to modify existing data
// Passing nVertexCount == -1 says to lock all the vertices for modification.
// Pass 0 for nIndexCount to not lock the index buffer.
void BeginModify(IIndexBuffer *pIndexBuffer, int nFirstIndex = 0, int nIndexCount = 0, int nIndexOffset = 0);
void EndModify(bool bSpewData = false);
// returns the number of indices
int IndexCount() const;
// Returns the total number of indices across all Locks()
int TotalIndexCount() const;
// Resets the mesh builder so it points to the start of everything again
void Reset() const;
// Selects the nth Index
void SelectIndex(int nBufferIndex) const;
// Advances the current index by one
void AdvanceIndex();
void AdvanceIndices(int nIndexCount);
int GetCurrentIndex() const;
int GetFirstIndex() const;
unsigned short const* Index() const;
// Used to define the indices (only used if you aren't using primitives)
void Index(unsigned short nIndex) const;
// Fast Index! No need to call advance index, and no random access allowed
void FastIndex(unsigned short nIndex);
// NOTE: This version is the one you really want to achieve write-combining;
// Write combining only works if you write in 4 bytes chunks.
void FastIndex2(unsigned short nIndex1, unsigned short nIndex2);
// Generates indices for a particular primitive type
void GenerateIndices(MaterialPrimitiveType_t primitiveType, int nIndexCount);
// FIXME: Remove! Backward compat so we can use this from a CMeshBuilder.
void AttachBegin(IMesh* pMesh, int nMaxIndexCount, const MeshDesc_t &desc);
void AttachEnd();
void AttachBeginModify(IMesh* pMesh, int nFirstIndex, int nIndexCount, const MeshDesc_t &desc);
void AttachEndModify();
private:
// The mesh we're modifying
IIndexBuffer *m_pIndexBuffer;
// Max number of indices
int m_nMaxIndexCount;
// Number of indices
int m_nIndexCount;
// Offset to add to each index as it's written into the buffer
int m_nIndexOffset;
// The current index
mutable int m_nCurrentIndex;
// Total number of indices appended
int m_nTotalIndexCount;
// First index buffer offset + first index
unsigned int m_nBufferOffset;
unsigned int m_nBufferFirstIndex;
// Used to make sure Begin/End calls and BeginModify/EndModify calls match.
bool m_bModify;
};
class CVertexBuilder : VertexDesc_t
{
public:
CVertexBuilder();
CVertexBuilder(IVertexBuffer *pVertexBuffer, VertexFormat_t fmt = 0);
~CVertexBuilder();
// Begins, ends modification of the index buffer (returns true if the lock succeeded)
// A lock may not succeed if append is set to true and there isn't enough room
// NOTE: Append is only used with dynamic index buffers; it's ignored for static buffers
bool Lock(int nMaxIndexCount, bool bAppend = false);
void Unlock();
// Spews the current data
// NOTE: Can only be called during a lock/unlock block
void SpewData() const;
// Returns the number of indices we can fit into the buffer without needing to discard
int GetRoomRemaining() const;
// Binds this vertex buffer
void Bind(IMatRenderContext *pContext, int nStreamID, VertexFormat_t usage = 0) const;
// Returns the byte offset
int Offset() const;
// This must be called before Begin, if a vertex buffer with a compressed format is to be used
void SetCompressionType(VertexCompressionType_t compressionType);
static void ValidateCompressionType();
void Begin(IVertexBuffer *pVertexBuffer, int nVertexCount, int *nFirstVertex);
void Begin(IVertexBuffer *pVertexBuffer, int nVertexCount);
// Use this when you're done writing
// Set bDraw to true to call m_pMesh->Draw automatically.
void End(bool bSpewData = false);
// Locks the vertex buffer to modify existing data
// Passing nVertexCount == -1 says to lock all the vertices for modification.
void BeginModify(IVertexBuffer *pVertexBuffer, int nFirstVertex = 0, int nVertexCount = -1);
void EndModify(bool bSpewData = false);
// returns the number of vertices
int VertexCount() const;
// Returns the total number of vertices across all Locks()
int TotalVertexCount() const;
// Resets the mesh builder so it points to the start of everything again
void Reset();
// Returns the size of the vertex
int VertexSize() { return m_ActualVertexSize; }
// returns the data size of a given texture coordinate
int TextureCoordinateSize(int nTexCoordNumber) { return m_VertexSize_TexCoord[nTexCoordNumber]; }
// Returns the base vertex memory pointer
void* BaseVertexData() const;
// Selects the nth Vertex and Index
void SelectVertex(int idx);
// Advances the current vertex and index by one
void AdvanceVertex();
void AdvanceVertices(int nVerts);
int GetCurrentVertex() const;
int GetFirstVertex() const;
// Data retrieval...
const float *Position() const;
const float *Normal() const;
unsigned int Color() const;
unsigned char *Specular() const;
const float *TexCoord(int stage) const;
const float *TangentS() const;
const float *TangentT() const;
const float *BoneWeight() const;
float Wrinkle() const;
int NumBoneWeights() const;
#ifndef NEW_SKINNING
unsigned char *BoneMatrix() const;
#else
float *BoneMatrix() const;
#endif
// position setting
void Position3f(float x, float y, float z) const;
void Position3fv(const float *v) const;
// normal setting
void Normal3f(float nx, float ny, float nz) const;
void Normal3fv(const float *n) const;
void NormalDelta3fv(const float *n) const;
void NormalDelta3f(float nx, float ny, float nz) const;
// normal setting (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedNormal3f(float nx, float ny, float nz) const;
template <VertexCompressionType_t T> void CompressedNormal3fv(const float *n) const;
// color setting
void Color3f(float r, float g, float b) const;
void Color3fv(const float *rgb) const;
void Color4f(float r, float g, float b, float a) const;
void Color4fv(const float *rgba) const;
// Faster versions of color
void Color3ub(unsigned char r, unsigned char g, unsigned char b) const;
void Color3ubv(unsigned char const* rgb) const;
void Color4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;
void Color4ubv(unsigned char const* rgba) const;
// specular color setting
void Specular3f(float r, float g, float b) const;
void Specular3fv(const float *rgb) const;
void Specular4f(float r, float g, float b, float a) const;
void Specular4fv(const float *rgba) const;
// Faster version of specular
void Specular3ub(unsigned char r, unsigned char g, unsigned char b) const;
void Specular3ubv(unsigned char const *c) const;
void Specular4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;
void Specular4ubv(unsigned char const *c) const;
// texture coordinate setting
void TexCoord1f(int stage, float s) const;
void TexCoord2f(int stage, float s, float t) const;
void TexCoord2fv(int stage, const float *st) const;
void TexCoord3f(int stage, float s, float t, float u) const;
void TexCoord3fv(int stage, const float *stu) const;
void TexCoord4f(int stage, float s, float t, float u, float w) const;
void TexCoord4fv(int stage, const float *stuv) const;
void TexCoordSubRect2f(int stage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT) const;
void TexCoordSubRect2fv(int stage, const float *st, const float *offset, const float *scale) const;
// tangent space
void TangentS3f(float sx, float sy, float sz) const;
void TangentS3fv(const float* s) const;
void TangentT3f(float tx, float ty, float tz) const;
void TangentT3fv(const float* t) const;
// Wrinkle
void Wrinkle1f(float flWrinkle) const;
// bone weights
void BoneWeight(int idx, float weight) const;
// bone weights (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedBoneWeight3fv(const float * pWeights) const;
// bone matrix index
void BoneMatrix(int idx, int matrixIndex) const;
// Generic per-vertex data
void UserData(const float* pData) const;
// Generic per-vertex data (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedUserData(const float* pData) const;
// Fast Vertex! No need to call advance vertex, and no random access allowed.
// WARNING - these are low level functions that are intended only for use
// in the software vertex skinner.
void FastVertex(/*ModelVertexDX7_t*/ const int &vertex);
void FastVertexSSE(/*ModelVertexDX7_t*/ const int &vertex);
// store 4 dx7 vertices fast. for special sse dx7 pipeline
void Fast4VerticesSSE(
/*ModelVertexDX7_t*/ const int *vtx_a,
/*ModelVertexDX7_t*/ const int *vtx_b,
/*ModelVertexDX7_t*/ const int *vtx_c,
/*ModelVertexDX7_t*/ const int *vtx_d);
void FastVertex(/*ModelVertexDX8_t*/ const float &vertex);
void FastVertexSSE(/*ModelVertexDX8_t*/ const float &vertex);
// Add number of verts and current vert since FastVertex routines do not update.
void FastAdvanceNVertices(int n);
#if defined( _X360 )
void VertexDX8ToX360(const ModelVertexDX8_t &vertex);
#endif
// FIXME: Remove! Backward compat so we can use this from a CMeshBuilder.
void AttachBegin(IMesh* pMesh, int nMaxVertexCount, const MeshDesc_t &desc);
void AttachEnd();
void AttachBeginModify(IMesh* pMesh, int nFirstVertex, int nVertexCount, const MeshDesc_t &desc);
void AttachEndModify();
private:
// The vertex buffer we're modifying
IVertexBuffer *m_pVertexBuffer;
// Used to make sure Begin/End calls and BeginModify/EndModify calls match.
bool m_bModify;
// Max number of indices and vertices
int m_nMaxVertexCount;
// Number of indices and vertices
int m_nVertexCount;
// The current vertex and index
mutable int m_nCurrentVertex;
// Optimization: Pointer to the current pos, norm, texcoord, and color
mutable float *m_pCurrPosition;
mutable float *m_pCurrNormal;
mutable float *m_pCurrTexCoord[8];
mutable unsigned char *m_pCurrColor;
// Total number of vertices appended
int m_nTotalVertexCount;
// First vertex buffer offset + index
unsigned int m_nBufferOffset;
unsigned int m_nBufferFirstVertex;
#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )
// Debug checks to make sure we write userdata4/tangents AFTER normals
bool m_bWrittenNormal : 1;
bool m_bWrittenUserData : 1;
#endif
friend class CMeshBuilder;
};
class CMeshBuilder : public MeshDesc_t
{
public:
CMeshBuilder();
~CMeshBuilder() { /*if(m_pMesh) throw std::exception("CMeshBuilder: Begin() without an End()");*/ } // if this fires you did a Begin() without an End()
// This must be called before Begin, if a vertex buffer with a compressed format is to be used
void SetCompressionType(VertexCompressionType_t compressionType);
// Locks the vertex buffer
// (*cannot* use the Index() call below)
void Begin(IMesh *pMesh, MaterialPrimitiveType_t type, int numPrimitives);
// Locks the vertex buffer, can specify arbitrary index lists
// (must use the Index() call below)
void Begin(IMesh *pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex);
void Begin(IMesh *pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount);
// forward compat
static void Begin(IVertexBuffer *pVertexBuffer, MaterialPrimitiveType_t type, int numPrimitives);
static void Begin(IVertexBuffer *pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex);
static void Begin(IVertexBuffer *pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount);
// Use this when you're done writing
// Set bDraw to true to call m_pMesh->Draw automatically.
void End(bool bSpewData = false, bool bDraw = false);
// Locks the vertex buffer to modify existing data
// Passing nVertexCount == -1 says to lock all the vertices for modification.
// Pass 0 for nIndexCount to not lock the index buffer.
void BeginModify(IMesh *pMesh, int nFirstVertex = 0, int nVertexCount = -1, int nFirstIndex = 0, int nIndexCount = 0);
void EndModify(bool bSpewData = false);
// A helper method since this seems to be done a whole bunch.
void DrawQuad(IMesh* pMesh, const float *v1, const float *v2,
const float *v3, const float *v4, unsigned char const *pColor, bool wireframe = false);
// returns the number of indices and vertices
int VertexCount() const;
int IndexCount() const;
// Resets the mesh builder so it points to the start of everything again
void Reset();
// Returns the size of the vertex
int VertexSize() { return m_ActualVertexSize; }
// returns the data size of a given texture coordinate
int TextureCoordinateSize(int nTexCoordNumber) { return m_VertexSize_TexCoord[nTexCoordNumber]; }
// Returns the base vertex memory pointer
void* BaseVertexData() const;
// Selects the nth Vertex and Index
void SelectVertex(int idx);
void SelectIndex(int idx) const;
// Given an index, point to the associated vertex
void SelectVertexFromIndex(int idx);
// Advances the current vertex and index by one
void AdvanceVertex();
void AdvanceVertices(int nVerts);
void AdvanceIndex();
void AdvanceIndices(int nIndices);
int GetCurrentVertex() const;
int GetCurrentIndex() const;
// Data retrieval...
const float *Position() const;
const float *Normal() const;
unsigned int Color() const;
unsigned char *Specular() const;
const float *TexCoord(int stage) const;
const float *TangentS() const;
const float *TangentT() const;
const float *BoneWeight() const;
float Wrinkle() const;
int NumBoneWeights() const;
#ifndef NEW_SKINNING
unsigned char *BoneMatrix() const;
#else
float *BoneMatrix() const;
#endif
unsigned short const *Index() const;
// position setting
void Position3f(float x, float y, float z) const;
void Position3fv(const float *v) const;
// normal setting
void Normal3f(float nx, float ny, float nz) const;
void Normal3fv(const float *n) const;
void NormalDelta3fv(const float *n) const;
void NormalDelta3f(float nx, float ny, float nz) const;
// normal setting (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedNormal3f(float nx, float ny, float nz) const;
template <VertexCompressionType_t T> void CompressedNormal3fv(const float *n) const;
// color setting
void Color3f(float r, float g, float b) const;
void Color3fv(const float *rgb) const;
void Color4f(float r, float g, float b, float a) const;
void Color4fv(const float *rgba) const;
// Faster versions of color
void Color3ub(unsigned char r, unsigned char g, unsigned char b) const;
void Color3ubv(unsigned char const* rgb) const;
void Color4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;
void Color4ubv(unsigned char const* rgba) const;
// specular color setting
void Specular3f(float r, float g, float b) const;
void Specular3fv(const float *rgb) const;
void Specular4f(float r, float g, float b, float a) const;
void Specular4fv(const float *rgba) const;
// Faster version of specular
void Specular3ub(unsigned char r, unsigned char g, unsigned char b) const;
void Specular3ubv(unsigned char const *c) const;
void Specular4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const;
void Specular4ubv(unsigned char const *c) const;
// texture coordinate setting
void TexCoord1f(int stage, float s) const;
void TexCoord2f(int stage, float s, float t) const;
void TexCoord2fv(int stage, const float *st) const;
void TexCoord3f(int stage, float s, float t, float u) const;
void TexCoord3fv(int stage, const float *stu) const;
void TexCoord4f(int stage, float s, float t, float u, float w) const;
void TexCoord4fv(int stage, const float *stuv) const;
void TexCoordSubRect2f(int stage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT) const;
void TexCoordSubRect2fv(int stage, const float *st, const float *offset, const float *scale) const;
// tangent space
void TangentS3f(float sx, float sy, float sz) const;
void TangentS3fv(const float *s) const;
void TangentT3f(float tx, float ty, float tz) const;
void TangentT3fv(const float *t) const;
// Wrinkle
void Wrinkle1f(float flWrinkle) const;
// bone weights
void BoneWeight(int idx, float weight) const;
// bone weights (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedBoneWeight3fv(const float * pWeights) const;
// bone matrix index
void BoneMatrix(int idx, int matrixIndex) const;
// Generic per-vertex data
void UserData(const float *pData) const;
// Generic per-vertex data (templatized for code which needs to support compressed vertices)
template <VertexCompressionType_t T> void CompressedUserData(const float* pData) const;
// Used to define the indices (only used if you aren't using primitives)
void Index(unsigned short index) const;
// NOTE: Use this one to get write combining! Much faster than the other version of FastIndex
// Fast Index! No need to call advance index, and no random access allowed
void FastIndex2(unsigned short nIndex1, unsigned short nIndex2);
// Fast Index! No need to call advance index, and no random access allowed
void FastIndex(unsigned short index);
// Fast Vertex! No need to call advance vertex, and no random access allowed.
// WARNING - these are low level functions that are intended only for use
// in the software vertex skinner.
void FastVertex(/*ModelVertexDX7_t*/ const int &vertex);
void FastVertexSSE(/*ModelVertexDX7_t*/ const int &vertex);
// store 4 dx7 vertices fast. for special sse dx7 pipeline
void Fast4VerticesSSE(
/*ModelVertexDX7_t*/ const int *vtx_a,
/*ModelVertexDX7_t*/ const int *vtx_b,
/*ModelVertexDX7_t*/ const int *vtx_c,
/*ModelVertexDX7_t*/ const int *vtx_d);
void FastVertex(/*ModelVertexDX8_t*/ const float &vertex);
void FastVertexSSE(/*ModelVertexDX8_t*/ const float &vertex);
// Add number of verts and current vert since FastVertexxx routines do not update.
void FastAdvanceNVertices(int n);
#if defined( _X360 )
void VertexDX8ToX360(const ModelVertexDX8_t &vertex);
#endif
private:
// Computes number of verts and indices
static void ComputeNumVertsAndIndices(int *pMaxVertices, int *pMaxIndices,
MaterialPrimitiveType_t type, int nPrimitiveCount);
static int IndicesFromVertices(MaterialPrimitiveType_t type, int nVertexCount);
// The mesh we're modifying
IMesh *m_pMesh;
MaterialPrimitiveType_t m_Type;
// Generate indices?
bool m_bGenerateIndices;
CIndexBuilder m_IndexBuilder;
CVertexBuilder m_VertexBuilder;
};