📄 imesh.h
字号:
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Interface used to construct vertex and index buffers (high performance!)
//=============================================================================
#ifndef IMESH_H
#define IMESH_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include "imaterialsystem.h"
#include <float.h>
#include <string.h>
#include "tier0/dbg.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class IMaterial;
class CMeshBuilder;
class IMaterialVar;
//-----------------------------------------------------------------------------
// The Vertex Buffer interface
//-----------------------------------------------------------------------------
enum
{
VERTEX_MAX_TEXTURE_COORDINATES = 4,
BONE_MATRIX_INDEX_INVALID = 255
};
//-----------------------------------------------------------------------------
// The Mesh memory descriptor
//-----------------------------------------------------------------------------
struct MeshDesc_t
{
// These can be set to zero if there are pointers to dummy buffers, when the
// actual buffer format doesn't contain the data but it needs to be safe to
// use all the CMeshBuilder functions.
int m_VertexSize_Position;
int m_VertexSize_BoneWeight;
int m_VertexSize_BoneMatrixIndex;
int m_VertexSize_Normal;
int m_VertexSize_Color;
int m_VertexSize_Specular;
int m_VertexSize_TexCoord[VERTEX_MAX_TEXTURE_COORDINATES];
int m_VertexSize_TangentS;
int m_VertexSize_TangentT;
int m_VertexSize_TangentSxT;
int m_VertexSize_UserData;
int m_ActualVertexSize; // Size of the vertices.. Some of the m_VertexSize_ elements above
// are set to this value and some are set to zero depending on which
// fields exist in a buffer's vertex format.
// The first vertex index
int m_FirstVertex;
// Number of bone weights per vertex...
int m_NumBoneWeights;
// Pointers to our current vertex data
float* m_pPosition;
float* m_pBoneWeight;
#ifndef NEW_SKINNING
unsigned char* m_pBoneMatrixIndex;
#else
float* m_pBoneMatrixIndex;
#endif
float* m_pNormal;
unsigned char* m_pColor;
unsigned char* m_pSpecular;
float* m_pTexCoord[VERTEX_MAX_TEXTURE_COORDINATES];
// Tangent space *associated with one particular set of texcoords*
float* m_pTangentS;
float* m_pTangentT;
float* m_pTangentSxT;
// user data
float* m_pUserData;
// Pointers to the index data
unsigned short* m_pIndices;
};
//-----------------------------------------------------------------------------
// Used in lists of indexed primitives.
//-----------------------------------------------------------------------------
class CPrimList
{
public:
CPrimList();
CPrimList( int firstIndex, int numIndices );
public:
int m_FirstIndex;
int m_NumIndices;
};
inline CPrimList::CPrimList()
{
}
inline CPrimList::CPrimList( int firstIndex, int numIndices )
{
m_FirstIndex = firstIndex;
m_NumIndices = numIndices;
}
//-----------------------------------------------------------------------------
// Interface to the mesh
//-----------------------------------------------------------------------------
class IMesh
{
public:
// Locks/ unlocks the mesh, providing space for numVerts and numIndices.
// numIndices of -1 means don't lock the index buffer...
virtual void LockMesh( int numVerts, int numIndices, MeshDesc_t& desc ) = 0;
// Unlocks the mesh, indicating how many verts and indices we actually used
virtual void UnlockMesh( int numVerts, int numIndices, MeshDesc_t& desc ) = 0;
// Locks mesh for modifying
virtual void ModifyBegin( int firstVertex, int numVerts, int firstIndex, int numIndices, MeshDesc_t& desc ) = 0;
virtual void ModifyEnd() = 0;
// Helper methods to create various standard index buffer types
virtual void GenerateSequentialIndexBuffer( unsigned short* pIndexMemory,
int numIndices, int firstVertex ) = 0;
virtual void GenerateQuadIndexBuffer( unsigned short* pIndexMemory,
int numIndices, int firstVertex ) = 0;
virtual void GeneratePolygonIndexBuffer( unsigned short* pIndexMemory,
int numIndices, int firstVertex ) = 0;
virtual void GenerateLineStripIndexBuffer( unsigned short* pIndexMemory,
int numIndices, int firstVertex ) = 0;
virtual void GenerateLineLoopIndexBuffer( unsigned short* pIndexMemory,
int numIndices, int firstVertex ) = 0;
// returns the # of vertices (static meshes only)
virtual int NumVertices() const = 0;
// Sets/gets the primitive type
virtual void SetPrimitiveType( MaterialPrimitiveType_t type ) = 0;
// Draws the mesh
virtual void Draw( int firstIndex = -1, int numIndices = 0 ) = 0;
virtual void SetColorMesh( IMesh *pColorMesh ) = 0;
// Draw a list of (lists of) primitives. Batching your lists together that use
// the same lightmap, material, vertex and index buffers with multipass shaders
// can drastically reduce state-switching overhead.
// NOTE: this only works with STATIC meshes.
virtual void Draw( CPrimList *pLists, int nLists ) = 0;
// Copy verts and/or indices to a mesh builder. This only works for temp meshes!
virtual void CopyToMeshBuilder(
int iStartVert, // Which vertices to copy.
int nVerts,
int iStartIndex, // Which indices to copy.
int nIndices,
int indexOffset, // This is added to each index.
CMeshBuilder &builder ) = 0;
// Spews the mesh data
virtual void Spew( int numVerts, int numIndices, MeshDesc_t const& desc ) = 0;
// Call this in debug mode to make sure our data is good.
virtual void ValidateData( int numVerts, int numIndices, MeshDesc_t const& desc ) = 0;
// Causes the software vertex shader to be applied to the mesh
virtual void CallSoftwareVertexShader( CMeshBuilder *pMeshBuilder ) = 0;
};
//-----------------------------------------------------------------------------
// Helper class used to define meshes
//-----------------------------------------------------------------------------
class CMeshBuilder : private MeshDesc_t
{
public:
CMeshBuilder();
// 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 numVertices, int numIndices );
// Use this when you're done writing
// Set bDraw to true to call m_pMesh->Draw automatically.
void End( bool spewData = false, bool bDraw = false );
// Locks the vertex buffer to modify existing data
// Passing numVertices == -1 says to lock all the vertices for modification.
// Pass 0 for numIndices to not lock the index buffer.
void BeginModify( IMesh* pMesh, int firstVertex = 0, int numVertices = -1, int firstIndex = 0, int numIndices = 0 );
void EndModify( bool spewData = false );
// A helper method since this seems to be done a whole bunch.
void DrawQuad( IMesh* pMesh, float const* v1, float const* v2,
float const* v3, float const* v4, unsigned char const* pColor, bool wireframe = false );
// returns the number of indices and vertices
int NumVertices() const;
int NumIndices() const;
// Resets the mesh builder so it points to the start of everything again
void Reset();
// Returns the base vertex memory pointer
void* BaseVertexData();
// Selects the nth Vertex and Index
void SelectVertex( int idx );
void SelectIndex( int idx );
// 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();
int GetCurrentIndex();
// Data retrieval...
float const* Position( ) const;
float const* Normal( ) const;
unsigned int Color() const;
float const* TexCoord( int stage ) const;
float const* TangentS( ) const;
float const* TangentT( ) const;
float const* TangentSxT( ) const;
float const* BoneWeight() 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 );
void Position3fv( float const *v );
// normal setting
void Normal3f( float nx, float ny, float nz );
void Normal3fv( float const *n );
// color setting
void Color3f( float r, float g, float b );
void Color3fv( float const *rgb );
void Color4f( float r, float g, float b, float a );
void Color4fv( float const *rgba );
// Faster versions of color
void Color3ub( unsigned char r, unsigned char g, unsigned char b );
void Color3ubv( unsigned char const* rgb );
void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a );
void Color4ubv( unsigned char const* rgba );
// specular color setting
void Specular3f( float r, float g, float b );
void Specular3fv( const float *rgb );
// Faster version of specular
void Specular3ub( unsigned char r, unsigned char g, unsigned char b );
void Specular3ubv( unsigned char const *c );
// texture coordinate setting
void TexCoord2f( int stage, float s, float t );
void TexCoord2fv( int stage, float const *st );
void TexCoord3f( int stage, float s, float t, float u );
void TexCoord3fv( int stage, float const *stu );
// tangent space
void TangentS3f( float sx, float sy, float sz );
void TangentS3fv( float const* s );
void TangentT3f( float tx, float ty, float tz );
void TangentT3fv( float const* t );
void TangentSxT3f( float sxtx, float sxty, float sxtz );
void TangentSxT3fv( float const* sxt );
// bone weights
void BoneWeight( int idx, float weight );
// bone matrix index
void BoneMatrix( int idx, int matrixIndex );
// Generic per-vertex data
void UserData( float const* pData );
// Used to define the indices (only used if you aren't using primitives)
void Index( unsigned short index );
// Fast Index! No need to call advance index, and no random access allowed
void FastIndex( unsigned short index );
private:
// Computes number of verts and indices
void ComputeNumVertsAndIndices( MaterialPrimitiveType_t type,
int numPrimitives );
int IndicesFromVertices( MaterialPrimitiveType_t type, int numVerts );
// Internal helper methods
float const* OffsetFloatPointer( float const* pBufferPointer, int numVerts, int vertexSize ) const;
float* OffsetFloatPointer( float* pBufferPointer, int numVerts, int vertexSize );
void IncrementFloatPointer( float* &pBufferPointer, int vertexSize );
// The mesh we're modifying
IMesh* m_pMesh;
// Used to make sure Begin/End calls and BeginModify/EndModify calls match.
bool m_bModify;
// Max number of indices and vertices
int m_MaxVertices;
int m_MaxIndices;
// Number of indices and vertices
int m_NumVertices;
int m_NumIndices;
// The current vertex and index
mutable int m_CurrentVertex;
mutable int m_CurrentIndex;
// Generate indices?
MaterialPrimitiveType_t m_Type;
bool m_GenerateIndices;
// Optimization: Pointer to the current pos, norm, texcoord, and color
mutable float *m_pCurrPosition;
mutable float *m_pCurrNormal;
mutable float *m_pCurrTexCoord[VERTEX_MAX_TEXTURE_COORDINATES];
mutable unsigned char *m_pCurrColor;
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
inline CMeshBuilder::CMeshBuilder() : m_pMesh(0), m_NumIndices(0),
m_NumVertices(0), m_CurrentVertex(0), m_CurrentIndex(0), m_MaxVertices(0),
m_MaxIndices(0), m_GenerateIndices(false)
{
#ifdef _DEBUG
m_pCurrPosition = NULL;
m_pCurrNormal = NULL;
m_pCurrColor = NULL;
m_pCurrTexCoord[0] = NULL;
m_pCurrTexCoord[1] = NULL;
m_pCurrTexCoord[2] = NULL;
m_pCurrTexCoord[3] = NULL;
m_bModify = false;
#endif
}
//-----------------------------------------------------------------------------
// Computes the number of verts and indices based on primitive type and count
//-----------------------------------------------------------------------------
inline void CMeshBuilder::ComputeNumVertsAndIndices( MaterialPrimitiveType_t type,
int numPrimitives )
{
switch(type)
{
case MATERIAL_POINTS:
m_MaxVertices = m_MaxIndices = numPrimitives;
break;
case MATERIAL_LINES:
m_MaxVertices = m_MaxIndices = numPrimitives * 2;
break;
case MATERIAL_LINE_STRIP:
m_MaxVertices = numPrimitives + 1;
m_MaxIndices = numPrimitives * 2;
break;
case MATERIAL_LINE_LOOP:
m_MaxVertices = numPrimitives;
m_MaxIndices = numPrimitives * 2;
break;
case MATERIAL_TRIANGLES:
m_MaxVertices = m_MaxIndices = numPrimitives * 3;
break;
case MATERIAL_TRIANGLE_STRIP:
m_MaxVertices = m_MaxIndices = numPrimitives + 2;
break;
case MATERIAL_QUADS:
m_MaxVertices = numPrimitives * 4;
m_MaxIndices = numPrimitives * 6;
break;
case MATERIAL_POLYGON:
m_MaxVertices = numPrimitives;
m_MaxIndices = (numPrimitives - 2) * 3;
break;
default:
Assert(0);
}
}
inline int CMeshBuilder::IndicesFromVertices( MaterialPrimitiveType_t type, int numVerts )
{
if (type == MATERIAL_QUADS)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -