DragonNest/Common/EternityEngine/D3DDevice9/EtMeshStream.cpp
2024-12-20 16:56:44 +08:00

803 lines
46 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtMeshStream.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
CEtMeshStream::CEtMeshStream(void)
{
m_pIB = NULL;
m_bStrip = false;
m_bGenerateTangentSpace = false;
m_bDeleteVB = true;
m_bDeleteIB = true;
m_Usage = USAGE_DEFAULT;
m_Pool = POOL_MANAGED;
m_pPointSpriteTexture = NULL;
m_nIndexCount = 0;
m_nVertexCount = 0;
m_pPointSpriteTexture = NULL;
}
CEtMeshStream::~CEtMeshStream(void)
{
Clear();
}
void CEtMeshStream::Clear()
{
int i;
// 외부에서 생성해서 셋팅한 버퍼들은 여기서 삭제하지 않는다.
if( m_bDeleteIB )
{
SAFE_RELEASE( m_pIB );
}
if( m_bDeleteVB )
{
for( i = 0; i < ( int )m_vecElements.size(); i++ )
{
SAFE_RELEASE( m_vecElements[ i ].m_pVB );
}
SAFE_DELETE_VEC( m_vecElements );
}
}
EtVertexBuffer *CEtMeshStream::FindVertexStream( MeshStreamType Type, int nStreamIndex, int &nStride )
{
int i, nSize;
nSize = ( int )m_vecElements.size();
for( i = 0; i < nSize; i++ )
{
if( ( m_vecElements[ i ].Type == Type ) && ( m_vecElements[ i ].nStreamIndex == nStreamIndex ) )
{
nStride = m_vecElements[ i ].nStride;
return m_vecElements[ i ].m_pVB;
}
}
return NULL;
}
void CEtMeshStream::GenerateTangentSpace()
{
if( m_bGenerateTangentSpace )
{
return;
}
int i, nStride;
EtVertexBuffer *pTangentVB, *pBinormalVB, *pPositionVB, *pNormalVB, *pTextureVB;
SStreamElement Element;
EtVector3 *pPosition, *pNormal, *pTangent, *pBinormal;
EtVector2 *pTexture;
WORD *pFace;
pTangentVB = FindVertexStream( MST_TANGENT, 0, nStride );
if( !pTangentVB )
{
nStride = sizeof( EtVector3 );
pTangentVB = GetEtDevice()->CreateVertexBuffer( m_nVertexCount * nStride, MST_TANGENT, m_Usage, m_Pool );
Element.m_pVB = pTangentVB;
Element.nStreamIndex = 0;
Element.nStride = nStride;
Element.Type = MST_TANGENT;
m_vecElements.push_back( Element );
}
pBinormalVB = FindVertexStream( MST_BINORMAL, 0, nStride );
if( !pBinormalVB )
{
nStride = sizeof( EtVector3 );
pBinormalVB = GetEtDevice()->CreateVertexBuffer( m_nVertexCount * nStride, MST_BINORMAL, m_Usage, m_Pool );
Element.m_pVB = pBinormalVB;
Element.nStreamIndex = 0;
Element.nStride = nStride;
Element.Type = MST_BINORMAL;
m_vecElements.push_back( Element );
}
pPositionVB = FindVertexStream( MST_POSITION, 0, nStride );
if( !pPositionVB )
{
ASSERT( 0 && "Position Vertex Stream Not Found" );
return;
}
pNormalVB = FindVertexStream( MST_NORMAL, 0, nStride );
if( !pNormalVB )
{
ASSERT( 0 && "Normal Vertex Stream Not Found" );
return;
}
pTextureVB = FindVertexStream( MST_TEXCOORD, 0, nStride );
if( !pTextureVB )
{
ASSERT( 0 && "Texture Coordinate Vertex Stream Not Found" );
return;
}
pTangentVB->Lock( 0, m_nVertexCount * nStride, ( void ** )&pTangent, 0 );
pBinormalVB->Lock( 0, m_nVertexCount * nStride, ( void ** )&pBinormal, 0 );
pPositionVB->Lock( 0, m_nVertexCount * nStride, ( void ** )&pPosition, 0 );
pNormalVB->Lock( 0, m_nVertexCount * nStride, ( void ** )&pNormal, 0 );
pTextureVB->Lock( 0, m_nVertexCount * nStride, ( void ** )&pTexture, 0 );
m_pIB->Lock( 0, sizeof( WORD ) * m_nIndexCount, ( void ** )&pFace, 0 );
for( i = 0; i < m_nIndexCount; )
{
int nVert1, nVert2, nVert3;
EtVector3 PVec, QVec;
float s1, s2, t1, t2, fValue;
EtVector3 CalcTangent, CalcBinormal;
if( m_bStrip )
{
if( i > m_nIndexCount - 3 )
{
break;
}
if( pFace[ i + 2 ] == 0xffff )
{
i += 3;
}
}
nVert1 = pFace[ i ];
nVert2 = pFace[ i + 1 ];
nVert3 = pFace[ i + 2 ];
PVec = pPosition[ nVert2 ] - pPosition[ nVert1 ];
QVec = pPosition[ nVert3 ] - pPosition[ nVert1 ];
s1 = pTexture[ nVert2 ].x - pPosition[ nVert1 ].x;
t1 = pTexture[ nVert2 ].y - pPosition[ nVert1 ].y;
s2 = pTexture[ nVert3 ].x - pPosition[ nVert1 ].x;
t2 = pTexture[ nVert3 ].y - pPosition[ nVert1 ].y;
fValue = s1 * t2 - s2 * t1;
if( fabsf( fValue ) <= 0.0001f )
{
fValue = 1.0f;
}
else
{
fValue = 1.0f / fValue;
}
CalcTangent = fValue * ( t2 * PVec - t1 * QVec );
CalcBinormal = fValue * ( s1 * QVec - s2 * PVec );
pTangent[ nVert1 ] += CalcTangent;
pBinormal[ nVert1 ] += CalcBinormal;
pTangent[ nVert2 ] += CalcTangent;
pBinormal[ nVert2 ] += CalcBinormal;
pTangent[ nVert3 ] += CalcTangent;
pBinormal[ nVert3 ] += CalcBinormal;
if( m_bStrip )
{
i++;
}
else
{
i += 3;
}
}
for( i = 0; i < m_nVertexCount; i++ )
{
EtVector3 CalcTangent, CalcBinormal;
float fLenTangent, fLenBinormal;
EtVec3Normalize( pTangent + i, pTangent + i );
EtVec3Normalize( pBinormal + i, pBinormal + i );
CalcTangent = pTangent[ i ] - ( EtVec3Dot( pNormal + i , pTangent + i ) * pNormal[ i ] );
CalcBinormal = pBinormal[ i ] - ( EtVec3Dot( pNormal + i , pBinormal + i ) * pNormal[ i ] )
- ( EtVec3Dot( &CalcTangent, pBinormal + i ) * CalcTangent );
EtVec3Normalize( pTangent + i, &CalcTangent );
EtVec3Normalize( pBinormal + i, &CalcBinormal );
fLenTangent = EtVec3Length( pTangent + i );
fLenBinormal = EtVec3Length( pBinormal + i );;
if( ( fLenTangent <= 0.001f ) || ( fLenBinormal <= 0.001f ) )
{
if( fLenTangent > 0.5f)
{
EtVec3Cross( pBinormal + i, pNormal + i, pTangent + i );
}
else if( fLenBinormal > 0.5 )
{
EtVec3Cross( pTangent + i , pBinormal + i, pNormal + i );
}
else
{
EtVector3 XAxis( 1.0f , 0.0f , 0.0f);
EtVector3 YAxis( 0.0f , 1.0f , 0.0f);
EtVector3 StartAxis;
if( EtVec3Dot( &XAxis, pNormal + i ) < EtVec3Dot( &YAxis, pNormal + i ) )
{
StartAxis = XAxis;
}
else
{
StartAxis = YAxis;
}
EtVec3Cross( pTangent + i, pNormal + i, &StartAxis );
EtVec3Cross( pBinormal + i, pNormal + i, pTangent + i );
}
}
else
{
if( EtVec3Dot( pBinormal + i, pTangent + i ) > 0.999f )
{
D3DXVec3Cross( pBinormal + i, pNormal + i, pTangent + i );
}
}
}
pTangentVB->Unlock();
pBinormalVB->Unlock();
pPositionVB->Unlock();
pNormalVB->Unlock();
pTextureVB->Unlock();
m_pIB->Unlock();
m_bGenerateTangentSpace = true;
}
void CEtMeshStream::CreateVertexStream( MeshStreamType Type, int nStreamIndex, int nVertexCount )
{
DWORD dwFVF;
SStreamElement Element;
int nStride;
switch( Type )
{
case MST_POSITION:
nStride = sizeof( EtVector3 );
dwFVF = D3DFVF_XYZ;
break;
case MST_NORMAL:
nStride = sizeof( EtVector3 );
dwFVF = D3DFVF_NORMAL;
break;
case MST_TEXCOORD:
nStride = sizeof( float ) * 2;
dwFVF = D3DFVF_TEX0 + nStreamIndex;
dwFVF <<= D3DFVF_TEXCOUNT_SHIFT;
break;
case MST_COLOR:
nStride = sizeof( DWORD );
dwFVF = D3DFVF_DIFFUSE;
break;
case MST_BONEINDEX:
nStride = sizeof( short ) * 4;
dwFVF = 0; // FVF 뭘로 해야 하지?
break;
case MST_BONEWEIGHT:
nStride = sizeof( float ) * 4;
dwFVF = 0; // FVF 뭘로 해야 하지?
break;
case MST_DEPTH:
nStride = sizeof( float );
dwFVF = 0;
break;
case MST_PSIZE:
nStride = sizeof( float );
dwFVF = D3DFVF_PSIZE;
break;
default:
ASSERT( 0 && "Invalid Stream Type!!!" );
return;
}
m_nVertexCount = nVertexCount;
Element.Type = Type;
Element.m_pVB = GetEtDevice()->CreateVertexBuffer( nVertexCount * nStride, dwFVF, m_Usage, m_Pool );
Element.nStride = nStride;
Element.nStreamIndex = nStreamIndex;
m_vecElements.push_back( Element );
}
void CEtMeshStream::LoadVertexStream( CStream *pStream, MeshStreamType Type, int nStreamIndex, int nVertexCount )
{
int nStride;
SStreamElement Element;
Element.m_pVB = FindVertexStream( Type, nStreamIndex, nStride );
if( !Element.m_pVB )
{
CreateVertexStream( Type, nStreamIndex, nVertexCount );
Element.m_pVB = FindVertexStream( Type, nStreamIndex, nStride );
}
if( pStream && Element.m_pVB )
{
void *pBuffer = NULL;
Element.m_pVB->Lock( 0, nStride * nVertexCount, &pBuffer, 0 );
if( pBuffer )
pStream->Read( pBuffer, nStride * nVertexCount );
Element.m_pVB->Unlock();
}
else if( pStream && Element.m_pVB == NULL )
{
pStream->Seek( nStride * nVertexCount, SEEK_CUR );
}
}
void CEtMeshStream::LoadIndexStream( CStream *pStream, bool bStrip, int nIndexCount )
{
void *pBuffer = NULL;
m_bStrip = bStrip;
if( !m_pIB )
{
m_pIB = GetEtDevice()->CreateIndexBuffer( sizeof( WORD ) * nIndexCount, m_Usage, m_Pool );
}
if( pStream && m_pIB )
{
m_pIB->Lock( 0, sizeof( WORD ) * nIndexCount, &pBuffer, 0 );
if( pBuffer )
pStream->Read( pBuffer, sizeof( WORD ) * nIndexCount );
m_pIB->Unlock();
}
else if( pStream && m_pIB == NULL )
{
pStream->Seek( sizeof( WORD ) * nIndexCount, SEEK_CUR );
}
m_nIndexCount = nIndexCount;
}
int CEtMeshStream::GetVertexStream( MeshStreamType Type, void *pDest, int nStreamIndex )
{
int nStride;
EtVertexBuffer *pVB;
void *pLockBuffer = NULL;
pVB = FindVertexStream( Type, nStreamIndex, nStride );
if( !pVB )
{
ASSERT( 0 && "Not Find Mesh Stream" );
return 0;
}
pVB->Lock( 0, nStride * m_nVertexCount, &pLockBuffer, 0 );
if( pLockBuffer )
memcpy( pDest, pLockBuffer, nStride * m_nVertexCount );
pVB->Unlock();
return nStride;
}
void CEtMeshStream::SetVertexStream( MeshStreamType Type, void *pSource, int nStreamIndex )
{
int nStride;
EtVertexBuffer *pVB;
void *pLockBuffer = NULL;
pVB = FindVertexStream( Type, nStreamIndex, nStride );
if( !pVB )
{
ASSERT( 0 && "Invalid Mesh Stream Type" );
return;
}
pVB->Lock( 0, nStride * m_nVertexCount, &pLockBuffer, 0 );
if( pLockBuffer )
memcpy( pLockBuffer, pSource, nStride * m_nVertexCount );
pVB->Unlock();
}
void CEtMeshStream::GetIndexStream( WORD *pDest )
{
void *pLockBuffer = NULL;
if( m_pIB ) {
m_pIB->Lock( 0, sizeof( WORD ) * m_nIndexCount, &pLockBuffer, D3DLOCK_READONLY );
if( pLockBuffer != NULL )
memcpy( pDest, pLockBuffer, sizeof( WORD ) * m_nIndexCount );
m_pIB->Unlock();
}
}
void CEtMeshStream::SetIndexStream( WORD *pSource )
{
void *pLockBuffer = NULL;
if( m_pIB ) {
m_pIB->Lock( 0, sizeof( WORD ) * m_nIndexCount, &pLockBuffer, 0 );
if( pLockBuffer ) {
memcpy( pLockBuffer, pSource, sizeof( WORD ) * m_nIndexCount );
}
m_pIB->Unlock();
}
}
void *CEtMeshStream::Lock( MeshStreamType Type, int nStreamIndex, DWORD dwFlag, int &nStride )
{
EtVertexBuffer *pVB;
void *pLockBuffer = NULL;
pVB = FindVertexStream( Type, nStreamIndex, nStride );
if( !pVB )
{
ASSERT( 0 && "Invalid Mesh Stream Type" );
return NULL;
}
pVB->Lock( 0, nStride * m_nVertexCount, &pLockBuffer, dwFlag );
return pLockBuffer;
}
void CEtMeshStream::Unlock( MeshStreamType Type, int nStreamIndex )
{
EtVertexBuffer *pVB;
int nStride;
pVB = FindVertexStream( Type, nStreamIndex, nStride );
if( !pVB )
{
ASSERT( 0 && "Invalid Mesh Stream Type" );
return;
}
pVB->Unlock();
}
void CEtMeshStream::SetIndexBuffer( EtIndexBuffer *pBuffer, int nIndexCount )
{
if( m_bDeleteIB ) {
SAFE_RELEASE( m_pIB );
}
m_pIB = pBuffer;
m_bDeleteIB = false;
m_nIndexCount = nIndexCount;
}
void CEtMeshStream::Draw( int nVertexDeclIndex, int nDrawStart, int nDrawCount )
{
int i, nElementCount;
EtVertexDecl *pDecl;
D3DVERTEXELEMENT9 Decl[ 32 ];
if( nDrawStart < 0 )
{
nDrawStart = 0;
}
if( nVertexDeclIndex != -1 )
{
GetEtDevice()->SetVertexDeclaration( nVertexDeclIndex );
}
pDecl = GetEtDevice()->GetVertexDeclaration( nVertexDeclIndex );
if( !pDecl ) {
return;
}
GetEtDevice()->GetVertexElement( nVertexDeclIndex, Decl, ( UINT * )&nElementCount );
for( i = 0; i < nElementCount; i++ )
{
EtVertexBuffer *pBuffer;
int nStride;
if( Decl[ i ].Stream == 0xff )
{
continue;
}
pBuffer = FindVertexStream( ( MeshStreamType )Decl[ i ].Usage, ( int )Decl[ i ].UsageIndex, nStride );
if( pBuffer == NULL ) return;
GetEtDevice()->SetStreamSource( Decl[ i ].Stream, pBuffer, nStride );
}
if( m_pIB )
{
GetEtDevice()->SetIndexBuffer( m_pIB );
}
if( m_pPointSpriteTexture )
{
GetEtDevice()->SetTexture( 0, m_pPointSpriteTexture );
GetEtDevice()->SetPixelShader( NULL );
GetEtDevice()->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
GetEtDevice()->DrawPrimitive( PT_POINTLIST, 0, m_nVertexCount);
GetEtDevice()->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
GetEtDevice()->SetTexture( 0, NULL);
}
else if( m_bStrip ) // 스트립일때는 DrawCount를 측정 못해서.. 적용안한다. 전체만 드로우 된다..
{
if( nDrawCount == 0 )
{
nDrawCount = m_nIndexCount - 2;
}
else
{
nDrawCount = nDrawCount + 2;
}
GetEtDevice()->DrawIndexedPrimitive( PT_TRIANGLESTRIP, 0, m_nVertexCount, 0, nDrawCount );
}
else
{
if( nDrawCount == 0 )
{
nDrawCount = m_nIndexCount / 3;
}
GetEtDevice()->DrawIndexedPrimitive( PT_TRIANGLELIST, 0, m_nVertexCount, nDrawStart * 3, nDrawCount );
}
}
void CEtMeshStream::DrawInstancing( int nVertexDeclIndex, EtVertexBuffer *pVB, int nStartIndex, int nInstanceCount )
{
int i, nElementCount;
EtVertexDecl *pDecl;
D3DVERTEXELEMENT9 Decl[ 32 ];
if( nVertexDeclIndex != -1 )
{
GetEtDevice()->SetVertexDeclaration( nVertexDeclIndex );
}
pDecl = GetEtDevice()->GetVertexDeclaration( nVertexDeclIndex );
if( !pDecl ) {
return;
}
GetEtDevice()->GetVertexElement( nVertexDeclIndex, Decl, ( UINT * )&nElementCount );
int nMatrixStream = 0;
for( i = 0; i < nElementCount; i++ )
{
if( Decl[i].UsageIndex != 0 ) {
nMatrixStream = Decl[i].Stream;
break;
}
EtVertexBuffer *pBuffer;
int nStride;
pBuffer = FindVertexStream( ( MeshStreamType )Decl[ i ].Usage, ( int )Decl[ i ].UsageIndex, nStride );
ASSERT( pBuffer != NULL );
GetEtDevice()->SetStreamSource( Decl[ i ].Stream, pBuffer, nStride );
GetEtDevice()->SetStreamSourceFreq( Decl[ i ].Stream, D3DSTREAMSOURCE_INDEXEDDATA | nInstanceCount );
}
if( m_pIB )
{
GetEtDevice()->SetIndexBuffer( m_pIB );
}
GetEtDevice()->SetStreamSource( nMatrixStream, pVB, sizeof(EtMatrix), sizeof(EtMatrix) * nStartIndex );
GetEtDevice()->SetStreamSourceFreq( nMatrixStream, D3DSTREAMSOURCE_INSTANCEDATA | 1ul );
if( m_bStrip ) // 스트립일때는 DrawCount를 측정 못해서.. 적용안한다. 전체만 드로우 된다..
{
GetEtDevice()->DrawIndexedPrimitive( PT_TRIANGLESTRIP, 0, m_nVertexCount, 0, m_nIndexCount - 2 );
}
else
{
int nDrawCount = m_nIndexCount / 3;
GetEtDevice()->DrawIndexedPrimitive( PT_TRIANGLELIST, 0, m_nVertexCount, 0, nDrawCount );
}
for( i = 0; i <= nMatrixStream; i++) {
GetEtDevice()->SetStreamSourceFreq( i, 1 );
}
}
void CEtMeshStream::Attach( CEtMeshStream *pMeshStream, std::vector<int> &BoneRemapTable, EtVector4 ScaleBias, int nMergeOrder )
{
int nSize;
nSize = (int)m_vecElements.size();
int nNewVertexCount = (m_nVertexCount + pMeshStream->m_nVertexCount);
for( int i = 0; i < nSize; i++) {
int nStride = m_vecElements[ i ].nStride;
BYTE *pVertexBuffer = new BYTE[ nStride * pMeshStream->m_nVertexCount ];
BYTE *pCurrVertexBuffer = new BYTE[ nStride * m_nVertexCount ];
memset(pCurrVertexBuffer, 0, nStride*m_nVertexCount);
pMeshStream->GetVertexStream( m_vecElements[ i ].Type, pVertexBuffer, m_vecElements[ i ].nStreamIndex );
void *pPtr = NULL;
m_vecElements[ i ].m_pVB->Lock( 0, nStride * m_nVertexCount, &pPtr, 0 );
if( pPtr ) {
memcpy( pCurrVertexBuffer, pPtr, nStride * m_nVertexCount );
}
m_vecElements[ i ].m_pVB->Unlock();
EtVertexBuffer *pVB = GetEtDevice()->CreateVertexBuffer( nNewVertexCount * nStride, 0, m_Usage, m_Pool );
void *pDestBuffer = NULL;
pVB->Lock(0, nNewVertexCount * nStride, &pDestBuffer, 0);
if( pDestBuffer ) {
memcpy( pDestBuffer, pCurrVertexBuffer, nStride*m_nVertexCount);
if( m_vecElements[ i ].Type == MST_TEXCOORD ) {
for( int j = 0; j < pMeshStream->m_nVertexCount; j++) {
((EtVector2*)pDestBuffer)[m_nVertexCount+j].x = float(nMergeOrder) + ((EtVector2*)pVertexBuffer)[j].x * ScaleBias.x + ScaleBias.z;
((EtVector2*)pDestBuffer)[m_nVertexCount+j].y = ((EtVector2*)pVertexBuffer)[j].y * ScaleBias.y + ScaleBias.w;
}
}
else {
memcpy( ((BYTE*)pDestBuffer) + nStride * m_nVertexCount, pVertexBuffer, nStride*pMeshStream->m_nVertexCount);
}
}
pVB->Unlock();
delete [] pVertexBuffer;
delete [] pCurrVertexBuffer;
SAFE_RELEASE( m_vecElements[ i ].m_pVB );
m_vecElements[ i ].m_pVB = pVB;
}
if( pMeshStream->m_bStrip ) {
int nNewIndexCount = m_nIndexCount + (pMeshStream->m_nIndexCount-2)*3;
WORD *pIndices = new WORD[ nNewIndexCount ];
GetIndexStream( pIndices );
WORD *pAttachIndices = new WORD[ pMeshStream->m_nIndexCount ];
pMeshStream->GetIndexStream( pAttachIndices );
for( int i = 0; i < pMeshStream->m_nIndexCount-2; i++) {
if( (i&1)==0) {
pIndices[m_nIndexCount+i*3+0] = pAttachIndices[i] + m_nVertexCount;
pIndices[m_nIndexCount+i*3+1] = pAttachIndices[i+1] + m_nVertexCount;
pIndices[m_nIndexCount+i*3+2] = pAttachIndices[i+2] + m_nVertexCount;
}
else {
pIndices[m_nIndexCount+i*3+0] = pAttachIndices[i+1] + m_nVertexCount;
pIndices[m_nIndexCount+i*3+1] = pAttachIndices[i] + m_nVertexCount;
pIndices[m_nIndexCount+i*3+2] = pAttachIndices[i+2] + m_nVertexCount;
}
}
m_nIndexCount = nNewIndexCount;
SAFE_RELEASE( m_pIB );
m_pIB = GetEtDevice()->CreateIndexBuffer( sizeof( WORD ) * m_nIndexCount, m_Usage, m_Pool );
SetIndexStream( pIndices );
delete [] pIndices;
delete [] pAttachIndices;
}
else {
int nNewIndexCount = m_nIndexCount + pMeshStream->m_nIndexCount;
WORD *pIndices = new WORD[ nNewIndexCount ];
GetIndexStream( pIndices );
pMeshStream->GetIndexStream( pIndices + m_nIndexCount );
for( int i = m_nIndexCount; i < nNewIndexCount; i++) {
pIndices[i] += m_nVertexCount;
}
m_nIndexCount = nNewIndexCount;
SAFE_RELEASE( m_pIB );
m_pIB = GetEtDevice()->CreateIndexBuffer( sizeof( WORD ) * m_nIndexCount, m_Usage, m_Pool );
SetIndexStream( pIndices );
delete [] pIndices;
}
int nOldVertexCount = m_nVertexCount;
m_nVertexCount = nNewVertexCount;
if( !BoneRemapTable.empty() ) {
WORD *pBoneIndices = new WORD[m_nVertexCount*4];
if( GetVertexStream( MST_BONEINDEX, pBoneIndices, 0 ) != 0 ) {
int nMaxIndex = -1;
for( int i = nOldVertexCount; i < m_nVertexCount; i++) {
if( pBoneIndices[i*4+0] != 65535 ) nMaxIndex = EtMax( nMaxIndex, pBoneIndices[i*4+0] );
if( pBoneIndices[i*4+1] != 65535 ) nMaxIndex = EtMax( nMaxIndex, pBoneIndices[i*4+1] );
if( pBoneIndices[i*4+2] != 65535 ) nMaxIndex = EtMax( nMaxIndex, pBoneIndices[i*4+2] );
if( pBoneIndices[i*4+3] != 65535 ) nMaxIndex = EtMax( nMaxIndex, pBoneIndices[i*4+3] );
}
if( (int)BoneRemapTable.size() > nMaxIndex ) {
for( int i = nOldVertexCount; i < m_nVertexCount; i++) {
if( pBoneIndices[i*4+0] != 65535 ) pBoneIndices[i*4+0] = BoneRemapTable[ pBoneIndices[i*4+0] ];
if( pBoneIndices[i*4+1] != 65535 ) pBoneIndices[i*4+1] = BoneRemapTable[ pBoneIndices[i*4+1] ];
if( pBoneIndices[i*4+2] != 65535 ) pBoneIndices[i*4+2] = BoneRemapTable[ pBoneIndices[i*4+2] ];
if( pBoneIndices[i*4+3] != 65535 ) pBoneIndices[i*4+3] = BoneRemapTable[ pBoneIndices[i*4+3] ];
}
}
SetVertexStream( MST_BONEINDEX, pBoneIndices, 0 );
}
delete [] pBoneIndices;
}
}
void CEtMeshStream::RemapBoneIndices( std::vector<int> &BoneRemapTable )
{
if( BoneRemapTable.empty() ) return;
WORD *pBoneIndices = new WORD[m_nVertexCount*4];
int nStride = GetVertexStream( MST_BONEINDEX, pBoneIndices, 0 );
if( nStride ) {
for( int i = 0; i < m_nVertexCount; i++) {
if( pBoneIndices[i*4+0] != 65535 ) pBoneIndices[i*4+0] = BoneRemapTable[ pBoneIndices[i*4+0] ];
if( pBoneIndices[i*4+1] != 65535 ) pBoneIndices[i*4+1] = BoneRemapTable[ pBoneIndices[i*4+1] ];
if( pBoneIndices[i*4+2] != 65535 ) pBoneIndices[i*4+2] = BoneRemapTable[ pBoneIndices[i*4+2] ];
if( pBoneIndices[i*4+3] != 65535 ) pBoneIndices[i*4+3] = BoneRemapTable[ pBoneIndices[i*4+3] ];
}
SetVertexStream( MST_BONEINDEX, pBoneIndices, 0 );
}
delete [] pBoneIndices;
}
void CEtMeshStream::Assign( CEtMeshStream *pMeshStream, EtVector4 ScaleBias )
{
m_bStrip = pMeshStream->m_bStrip;
m_bGenerateTangentSpace = pMeshStream->m_bGenerateTangentSpace;
m_nIndexCount = pMeshStream->m_nIndexCount;
m_nVertexCount = pMeshStream->m_nVertexCount;
m_bDeleteVB = pMeshStream->m_bDeleteVB;
m_bDeleteIB = pMeshStream->m_bDeleteIB;
m_Usage = pMeshStream->m_Usage;
m_Pool = pMeshStream->m_Pool;
WORD *pIndices = new WORD[ m_nIndexCount ];
pMeshStream->GetIndexStream( pIndices );
ASSERT( m_pIB == NULL );
SAFE_RELEASE( m_pIB );
if( m_bStrip ) {
int nOldIndexCount = m_nIndexCount;
m_nIndexCount = (m_nIndexCount -2)*3;
m_pIB = GetEtDevice()->CreateIndexBuffer( sizeof( WORD ) * m_nIndexCount, m_Usage, m_Pool );
WORD *pNewIndices = new WORD[ m_nIndexCount ];
for( int i = 0; i < nOldIndexCount-2; i++) {
if( (i&1)==0) {
pNewIndices[i*3+0] = pIndices[i];
pNewIndices[i*3+1] = pIndices[i+1];
pNewIndices[i*3+2] = pIndices[i+2];
}
else {
pNewIndices[i*3+0] = pIndices[i+1];
pNewIndices[i*3+1] = pIndices[i];
pNewIndices[i*3+2] = pIndices[i+2];
}
}
SetIndexStream( pNewIndices );
delete [] pNewIndices;
m_bStrip = false;
}
else {
m_pIB = GetEtDevice()->CreateIndexBuffer( sizeof( WORD ) * m_nIndexCount, m_Usage, m_Pool );
SetIndexStream( pIndices );
}
delete [] pIndices;
int i, nSize;
nSize = (int)pMeshStream->m_vecElements.size();
for( i = 0; i < nSize; i++) {
if( !pMeshStream->m_vecElements[ i ].m_pVB ) continue;
int nStride = pMeshStream->m_vecElements[ i ].nStride;
BYTE *pVertexBuffer = new BYTE[ nStride * m_nVertexCount ];
memset( pVertexBuffer, 0, nStride * m_nVertexCount );
SStreamElement StreamElement;
StreamElement.nStreamIndex = pMeshStream->m_vecElements[ i ].nStreamIndex;
StreamElement.nStride = pMeshStream->m_vecElements[ i ].nStride;
StreamElement.Type = pMeshStream->m_vecElements[ i ].Type;
void *pPtr = NULL;
pMeshStream->m_vecElements[ i ].m_pVB->Lock( 0, nStride * m_nVertexCount, &pPtr, 0 );
if( pPtr )
memcpy( pVertexBuffer, pPtr, nStride * m_nVertexCount );
pMeshStream->m_vecElements[ i ].m_pVB->Unlock();
StreamElement.m_pVB = GetEtDevice()->CreateVertexBuffer( m_nVertexCount * nStride, 0, m_Usage, m_Pool );
pPtr = NULL;
StreamElement.m_pVB->Lock( 0, nStride * m_nVertexCount, &pPtr, 0);
if( pPtr ) {
if( StreamElement.Type == MST_TEXCOORD ) {
for( int j = 0; j < m_nVertexCount; j++) {
((EtVector2*)pPtr)[j].x = ((EtVector2*)pVertexBuffer)[j].x * ScaleBias.x + ScaleBias.z;
((EtVector2*)pPtr)[j].y = ((EtVector2*)pVertexBuffer)[j].y * ScaleBias.y + ScaleBias.w;
}
}
else {
memcpy( pPtr, pVertexBuffer, nStride * m_nVertexCount );
}
}
StreamElement.m_pVB->Unlock();
m_vecElements.push_back( StreamElement );
delete [] pVertexBuffer;
}
}