📄 meshdx8.cpp
字号:
// Locks/unlocks the entire mesh
//-----------------------------------------------------------------------------
void CMeshDX8::LockMesh( int numVerts, int numIndices, MeshDesc_t& desc )
{
#ifdef MEASURE_STATS
MaterialSystemStats()->BeginTimedStat(MATERIAL_SYSTEM_STATS_MESH_BUILD_TIME);
#endif
LockVertexBuffer( numVerts, desc );
if (m_Type != MATERIAL_POINTS)
LockIndexBuffer( -1, numIndices, desc );
else
desc.m_pIndices = 0;
}
void CMeshDX8::UnlockMesh( int numVerts, int numIndices, MeshDesc_t& desc )
{
UnlockVertexBuffer(numVerts);
if (m_Type != MATERIAL_POINTS)
UnlockIndexBuffer(numIndices);
// The actual # we wrote
m_NumVertices = numVerts;
m_NumIndices = numIndices;
#ifdef MEASURE_STATS
MaterialSystemStats()->EndTimedStat(MATERIAL_SYSTEM_STATS_MESH_BUILD_TIME);
#endif
}
//-----------------------------------------------------------------------------
// Locks mesh for modifying
//-----------------------------------------------------------------------------
void CMeshDX8::ModifyBegin( int firstVertex, int numVerts, int firstIndex, int numIndices, MeshDesc_t& desc )
{
#ifdef MEASURE_STATS
MaterialSystemStats()->BeginTimedStat(MATERIAL_SYSTEM_STATS_MESH_BUILD_TIME);
#endif
// Just give the app crap buffers to fill up while we're suppressed...
if (ShaderAPI()->IsDeactivated())
{
// Set up a bogus descriptor
g_MeshMgr.ComputeVertexDescription( 0, 0, desc );
desc.m_pIndices = 0;
return;
}
Assert( m_pVertexBuffer );
// Lock it baby
unsigned char* pVertexMemory = m_pVertexBuffer->Modify( firstVertex, numVerts );
if ( pVertexMemory )
{
m_IsVBLocked = true;
g_MeshMgr.ComputeVertexDescription( pVertexMemory, m_VertexFormat, desc );
#ifdef RECORDING
m_LockVertexBufferSize = numVerts * desc.m_ActualVertexSize;
m_LockVertexBuffer = pVertexMemory;
#endif
}
desc.m_FirstVertex = firstVertex;
LockIndexBuffer( firstIndex, numIndices, desc );
}
void CMeshDX8::ModifyEnd( )
{
UnlockIndexBuffer(0);
UnlockVertexBuffer(0);
#ifdef MEASURE_STATS
MaterialSystemStats()->EndTimedStat(MATERIAL_SYSTEM_STATS_MESH_BUILD_TIME);
#endif
}
//-----------------------------------------------------------------------------
// returns the # of vertices (static meshes only)
//-----------------------------------------------------------------------------
int CMeshDX8::NumVertices() const
{
return m_pVertexBuffer ? m_pVertexBuffer->VertexCount() : 0;
}
//-----------------------------------------------------------------------------
// returns the # of indices
//-----------------------------------------------------------------------------
int CMeshDX8::NumIndices( ) const
{
return m_pIndexBuffer ? m_pIndexBuffer->IndexCount() : 0;
}
//-----------------------------------------------------------------------------
// Sets up the vertex and index buffers
//-----------------------------------------------------------------------------
void CMeshDX8::UseIndexBuffer( CIndexBuffer* pBuffer )
{
m_pIndexBuffer = pBuffer;
}
void CMeshDX8::UseVertexBuffer( CVertexBuffer* pBuffer )
{
m_pVertexBuffer = pBuffer;
}
//-----------------------------------------------------------------------------
// Computes the mode
//-----------------------------------------------------------------------------
D3DPRIMITIVETYPE CMeshDX8::ComputeMode( MaterialPrimitiveType_t type )
{
switch(type)
{
case MATERIAL_POINTS:
return D3DPT_POINTLIST;
case MATERIAL_LINES:
return D3DPT_LINELIST;
case MATERIAL_TRIANGLES:
return D3DPT_TRIANGLELIST;
case MATERIAL_TRIANGLE_STRIP:
return D3DPT_TRIANGLESTRIP;
// Here, we expect to have the type set later. only works for static meshes
case MATERIAL_HETEROGENOUS:
return (D3DPRIMITIVETYPE)-1;
default:
Assert(0);
return (D3DPRIMITIVETYPE)-1;
}
}
//-----------------------------------------------------------------------------
// Sets the primitive type
//-----------------------------------------------------------------------------
void CMeshDX8::SetPrimitiveType( MaterialPrimitiveType_t type )
{
m_Type = type;
m_Mode = ComputeMode( type );
}
MaterialPrimitiveType_t CMeshDX8::GetPrimitiveType( ) const
{
return m_Type;
}
//-----------------------------------------------------------------------------
// Computes the number of primitives we're gonna draw
//-----------------------------------------------------------------------------
int CMeshDX8::NumPrimitives( int numVerts, int numIndices ) const
{
switch(m_Mode)
{
case D3DPT_POINTLIST:
return numVerts;
case D3DPT_LINELIST:
return numIndices / 2;
case D3DPT_TRIANGLELIST:
return numIndices / 3;
case D3DPT_TRIANGLESTRIP:
return numIndices - 2;
default:
// invalid, baby!
Assert(0);
}
return 0;
}
//-----------------------------------------------------------------------------
// Checks if it's a valid format
//-----------------------------------------------------------------------------
static void OutputVertexFormat( VertexFormat_t format )
{
if( format & VERTEX_POSITION )
{
Warning( "VERTEX_POSITION|" );
}
if( format & VERTEX_NORMAL )
{
Warning( "VERTEX_NORMAL|" );
}
if( format & VERTEX_COLOR )
{
Warning( "VERTEX_COLOR|" );
}
if( format & VERTEX_SPECULAR )
{
Warning( "VERTEX_SPECULAR|" );
}
if( format & VERTEX_TANGENT_S )
{
Warning( "VERTEX_TANGENT_S|" );
}
if( format & VERTEX_TANGENT_T )
{
Warning( "VERTEX_TANGENT_T|" );
}
if( format & VERTEX_BONE_INDEX )
{
Warning( "VERTEX_BONE_INDEX|" );
}
if( format & VERTEX_FORMAT_VERTEX_SHADER )
{
Warning( "VERTEX_FORMAT_VERTEX_SHADER|" );
}
Warning( "Bone weights: %d\n",
( int )( ( format & VERTEX_BONE_WEIGHT_MASK ) >> VERTEX_BONE_WEIGHT_BIT ) );
Warning( "user data size: %d\n",
( int )( ( format & USER_DATA_SIZE_MASK ) >> USER_DATA_SIZE_BIT ) );
Warning( "num tex coords: %d\n",
( int )( ( format & NUM_TEX_COORD_MASK ) >> NUM_TEX_COORD_BIT ) );
// NOTE: This doesn't print texcoord sizes.
}
bool CMeshDX8::IsValidVertexFormat()
{
IMaterialInternal* pMaterial = ShaderAPI()->GetBoundMaterial();
Assert( pMaterial );
VertexFormat_t fmt = pMaterial->GetVertexFormat() & ~VERTEX_FORMAT_VERTEX_SHADER;
bool isValid = (fmt == (m_VertexFormat & ~VERTEX_FORMAT_VERTEX_SHADER));
#ifdef _DEBUG
if( !isValid )
{
Warning( "material format:" );
OutputVertexFormat( fmt );
Warning( "mesh format:" );
OutputVertexFormat( m_VertexFormat );
}
#endif
return isValid;
}
//-----------------------------------------------------------------------------
// Flushes queued data
//-----------------------------------------------------------------------------
static CIndexBuffer* g_pLastIndex = 0;
static CVertexBuffer* g_pLastVertex = 0;
static int g_LastVertexIdx = -1;
static CMeshDX8 *g_pLastColorMesh = 0;
//-----------------------------------------------------------------------------
// Makes sure that the render state is always set next time
//-----------------------------------------------------------------------------
static void ResetRenderState()
{
g_pLastIndex = 0;
g_pLastVertex = 0;
g_LastVertexIdx = -1;
}
bool CMeshDX8::SetRenderState( int firstVertexIdx )
{
MEASURE_TIMED_STAT( MATERIAL_SYSTEM_STATS_SET_RENDER_STATE );
// Can't set the state if we're deactivated
if (ShaderAPI()->IsDeactivated())
{
ResetRenderState();
return false;
}
// make sure the vertex format is a superset of the current material's
// vertex format...
if (!IsValidVertexFormat())
{
Warning("Material %s is being applied to a model, you need $model=1 in the .vmt file!\n",
ShaderAPI()->GetBoundMaterial()->GetName() );
return false;
}
if( m_pColorMesh != g_pLastColorMesh )
{
HRESULT hr;
if( m_pColorMesh )
{
RECORD_COMMAND( DX8_SET_STREAM_SOURCE, 3 );
RECORD_INT( m_pColorMesh->GetVertexBuffer()->UID() );
RECORD_INT( 1 );
RECORD_INT( m_pColorMesh->GetVertexBuffer()->VertexSize() );
hr = D3DDevice()->SetStreamSource( 1,
m_pColorMesh->GetVertexBuffer()->GetInterface(),
0,
m_pColorMesh->GetVertexBuffer()->VertexSize() );
}
else
{
RECORD_COMMAND( DX8_SET_STREAM_SOURCE, 3 );
RECORD_INT( -1 ); // vertex buffer id
RECORD_INT( 1 ); // stream
RECORD_INT( 0 ); // vertex size
hr = D3DDevice()->SetStreamSource( 1, 0, 0, 0 );
}
Assert( !FAILED(hr) );
g_pLastColorMesh = m_pColorMesh;
}
if (g_pLastVertex != m_pVertexBuffer)
{
Assert( m_pVertexBuffer );
RECORD_COMMAND( DX8_SET_STREAM_SOURCE, 3 );
RECORD_INT( m_pVertexBuffer->UID() );
RECORD_INT( 0 );
RECORD_INT( m_pVertexBuffer->VertexSize() );
HRESULT hr;
hr = D3DDevice()->SetStreamSource( 0,
m_pVertexBuffer->GetInterface(), 0, m_pVertexBuffer->VertexSize() );
Assert( !FAILED(hr) );
MaterialSystemStats()->IncrementCountedStat(MATERIAL_SYSTEM_STATS_DYNAMIC_STATE, 1 );
g_pLastVertex = m_pVertexBuffer;
}
if ((g_pLastIndex != m_pIndexBuffer) || (firstVertexIdx != g_LastVertexIdx))
{
Assert( m_pIndexBuffer );
RECORD_COMMAND( DX8_SET_INDICES, 2 );
RECORD_INT( m_pIndexBuffer->UID() );
RECORD_INT( firstVertexIdx );
HRESULT hr;
hr = D3DDevice()->SetIndices( m_pIndexBuffer->GetInterface() );
m_FirstIndex = firstVertexIdx;
Assert( !FAILED(hr) );
MaterialSystemStats()->IncrementCountedStat(MATERIAL_SYSTEM_STATS_DYNAMIC_STATE, 1 );
g_pLastIndex = m_pIndexBuffer;
g_LastVertexIdx = firstVertexIdx;
}
return true;
}
//-----------------------------------------------------------------------------
// Draws the static mesh
//-----------------------------------------------------------------------------
void CMeshDX8::Draw( int firstIndex, int numIndices )
{
if ( ShaderUtil()->IsInStubMode() )
return;
CPrimList primList;
if( firstIndex == -1 || numIndices == 0 )
{
primList.m_FirstIndex = 0;
primList.m_NumIndices = m_NumIndices;
}
else
{
primList.m_FirstIndex = firstIndex;
primList.m_NumIndices = numIndices;
}
Draw( &primList, 1 );
}
void CMeshDX8::Draw( CPrimList *pLists, int nLists )
{
if ( ShaderUtil()->IsInStubMode() )
return;
// Make sure there's something to draw..
int i;
for( i=0; i < nLists; i++ )
{
if( pLists[i].m_NumIndices > 0 )
break;
}
if( i == nLists )
return;
// can't do these in selection mode!
Assert( !ShaderAPI()->IsInSelectionMode() );
if (!SetRenderState(0))
return;
s_pPrims = pLists;
s_nPrims = nLists;
#ifdef _DEBUG
for ( i = 0; i < nLists; ++i)
{
Assert( pLists[i].m_NumIndices > 0 );
}
#endif
s_FirstVertex = 0;
s_NumVertices = m_pVertexBuffer->VertexCount();
DrawMesh();
}
//-----------------------------------------------------------------------------
// Actually does the dirty deed of rendering
//-----------------------------------------------------------------------------
void CMeshDX8::RenderPass()
{
VPROF( "CMeshDX8::RenderPass" );
MEASURE_TIMED_STAT( MATERIAL_SYSTEM_STATS_DRAW_INDEXED_PRIMITIVE );
HRESULT hr;
Assert( m_Type != MATERIAL_HETEROGENOUS );
for( int iPrim=0; iPrim < s_nPrims; iPrim++ )
{
CPrimList *pPrim = &s_pPrims[iPrim];
if (pPrim->m_NumIndices == 0)
continue;
if (m_Type == MATERIAL_POINTS)
{
RECORD_COMMAND( DX8_DRAW_PRIMITIVE, 3 );
RECORD_INT( m_Mode );
RECORD_INT( s_FirstVertex );
RECORD_INT( pPrim->m_NumIndices );
// (For point lists, we don't actually fill in indices, but we treat it as
// though there are indices for the list up until here).
hr = D3DDevice()->DrawPrimitive( m_Mode, s_FirstVertex, pPrim->m_NumIndices );
MaterialSystemStats()->IncrementCountedStat(MATERIAL_SYSTEM_STATS_NUM_PRIMITIVES, pPrim->m_NumIndices );
}
else
{
int numPrimitives = NumPrimitives( s_NumVertices, pPrim->m_NumIndices );
#ifdef CHECK_INDICES_NOT_RIGHT_NOW_NO_LINELIST_SUPPORT_WHICH_MAKES_THIS_PAINFUL_FOR_DEBUG_MODE
// g_pLastVertex - this is the current vertex buffer
// g_pLastColorMesh - this is the curent color mesh, if there is one.
// g_pLastIndex - this is the current index buffer.
// vertoffset : m_FirstIndex
Assert( m_Mode == D3DPT_TRIANGLELIST || m_Mode == D3DPT_TRIANGLESTRIP );
Assert( pPrim->m_FirstIndex >= 0 && pPrim->m_FirstIndex < g_pLastIndex->IndexCount() );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -