DragonNest/Common/EternityEngine/EtSwordTrail.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

462 lines
No EOL
14 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtSwordTrail.h"
#include "EtBackBufferMng.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
EtIndexBuffer *CEtSwordTrail::s_pCommonIndexBuffer = NULL;
EtMaterialHandle CEtSwordTrail::s_hMaterial;
/*********************************** R N S **************************************************/
// cubic curve defined by 2 positions and 2 velocities
D3DXVECTOR3 CEtRNS::GetPositionOnCubic(const D3DXVECTOR3 &startPos, const D3DXVECTOR3 &startVel, const D3DXVECTOR3 &endPos, const D3DXVECTOR3 &endVel, float time)
{
D3DXMATRIX hermite( 2.f,-2.f, 1.f, 1.f,
-3.f, 3.f,-2.f,-1.f,
0.f, 0.f, 1.f, 0.f,
1.f, 0.f, 0.f, 0.f);
D3DXMATRIX m;
*(D3DXVECTOR3*)&m._11 = startPos;
*(D3DXVECTOR3*)&m._21 = endPos;
*(D3DXVECTOR3*)&m._31 = startVel;
*(D3DXVECTOR3*)&m._41 = endVel;
D3DXMatrixMultiply(&m, &hermite, &m);
D3DXVECTOR4 timeVector = D3DXVECTOR4(time*time*time, time*time, time, 1);
D3DXVec4Transform(&timeVector, &timeVector, &m);
return D3DXVECTOR3(timeVector.x, timeVector.y, timeVector.z);
}
// adds node and updates segment length
void CEtRNS::AddNode(const D3DXVECTOR3 &pos)
{
if (m_nodeCount == 0)
m_maxDistance = 0.f;
else
{
m_nodes[m_nodeCount-1].distance = D3DXVec3Length(&(m_nodes[m_nodeCount-1].position - pos));
m_maxDistance += m_nodes[m_nodeCount-1].distance;
}
m_nodes[m_nodeCount++].position = pos;
}
// called after all nodes added. This function calculates the node velocities
void CEtRNS::BuildSpline()
{
for (int i = 1; i<m_nodeCount-1; i++) {
// split the angle (figure 4)
D3DXVECTOR3 v1 = m_nodes[i+1].position - m_nodes[i].position;
D3DXVECTOR3 v2 = m_nodes[i-1].position - m_nodes[i].position;
D3DXVec3Normalize(&v1, &v1);
D3DXVec3Normalize(&v2, &v2);
D3DXVec3Normalize(&m_nodes[i].velocity, &(v1 - v2));
}
// calculate start and end velocities
m_nodes[0].velocity = GetStartVelocity(0);
m_nodes[m_nodeCount-1].velocity = GetEndVelocity(m_nodeCount-1);
}
// spline access function. time is 0 -> 1
D3DXVECTOR3 CEtRNS::GetPosition(float time)
{
float distance = time * m_maxDistance;
float currentDistance = 0.f;
int i = 0;
while (i < m_maxCount && currentDistance + m_nodes[i].distance < distance ) {
currentDistance += m_nodes[i].distance;
i++;
}
if( i > m_maxCount-2 ) {
return m_nodes.back().position;
}
float t = distance - currentDistance;
t /= m_nodes[i].distance; // scale t in range 0 - 1
D3DXVECTOR3 startVel = m_nodes[i].velocity * m_nodes[i].distance;
D3DXVECTOR3 endVel = m_nodes[i+1].velocity * m_nodes[i].distance;
return GetPositionOnCubic(m_nodes[i].position, startVel,
m_nodes[i+1].position, endVel, t);
}
// internal. Based on Equation 14
D3DXVECTOR3 CEtRNS::GetStartVelocity(int index)
{
D3DXVECTOR3 temp = 3.f * (m_nodes[ index + 1 ].position - m_nodes[ index ].position) / m_nodes[ index ].distance;
return (temp - m_nodes[ index + 1 ].velocity) * 0.5f;
}
// internal. Based on Equation 15
D3DXVECTOR3 CEtRNS::GetEndVelocity(int index)
{
D3DXVECTOR3 temp = 3.f * (m_nodes[ index ].position - m_nodes[ index - 1 ].position) / m_nodes[ index - 1 ].distance;
return (temp - m_nodes[ index - 1 ].velocity) * 0.5f;
}
void CEtRNS::Init( int maxCount_ )
{
m_nodeCount = 0;
m_maxCount = maxCount_;
m_nodes.resize( maxCount_ );
}
//////////////////////////////////////////////////////////////////////////
CEtSwordTrail::CEtSwordTrail(void)
{
m_SwordColor = EtColor( 1.0f, 1.0f, 1.0f, 1.0f );
m_bAdd = false;
m_bPrevAdd = false;
m_nAddIndex = -1;
m_nTechniqueIndex = 0;
m_fElapsedTime = 0.f;
m_fTotalTime = 0.f;
m_fFinishTime = 0.f;
m_nLengthTime = 0;
m_fLifeTime = 0.f;
}
CEtSwordTrail::~CEtSwordTrail(void)
{
for( std::vector< TrailSet >::iterator it = m_Trails.begin(); it != m_Trails.end(); ++it ) {
SAFE_DELETE( it->pMeshStream );
}
m_Trails.clear();
}
void CEtSwordTrail::Initialize( EtAniObjectHandle hAniObject, EtTextureHandle hTexture, EtTextureHandle hNormalTexture, float fLifeTime, float fMinSegment )
{
m_fLifeTime = fLifeTime;
m_hParent = hAniObject;
if( !m_hParent || !m_hParent->GetMesh() || m_hParent->GetMesh()->GetDummyNameList().empty() ) {
return;
}
std::map< std::string, int > DummyIndices;
int nIndex = 0;
for each ( std::string szName in m_hParent->GetMesh()->GetDummyNameList() )
{
if( strncmp(szName.c_str(), "#trail", 6) == 0 )
DummyIndices[ szName ] = nIndex;
++nIndex;
}
// assert( (DummyIndices.size() % 2) == 0 );
if( ( DummyIndices.size() % 2 ) != 0 )
{
return;
}
std::map< std::string, int >::iterator it = DummyIndices.begin();
for ( int i = 0; i < (int)DummyIndices.size()/2; i++) {
TrailSet trailSet;
trailSet.nDummyIndex[ 0 ] = it->second; ++it;
trailSet.nDummyIndex[ 1 ] = it->second; ++it;
trailSet.pMeshStream = new CEtMeshStream;
CreateVertexBuffer( trailSet.pMeshStream );
m_Trails.push_back( trailSet );
}
#ifdef PRE_FIX_MATERIAL_DUMP
if( !s_hMaterial ) return;
#endif
int nTexIndex;
nTexIndex = hTexture ? hTexture->GetMyIndex() : -1;
AddCustomParam( m_vecCustomParam, EPT_TEX, s_hMaterial, "g_SwordTrailTexture", &nTexIndex );
nTexIndex = hNormalTexture ? hNormalTexture->GetMyIndex() : -1;
AddCustomParam( m_vecCustomParam, EPT_TEX, s_hMaterial, "g_SwordTrailNormalTexture", &nTexIndex );
int nBackBufferIndex = GetEtBackBufferMng()->GetBackBufferIndex();
AddCustomParam( m_vecCustomParam, EPT_TEX, s_hMaterial, "g_BackBuffer", &nBackBufferIndex );
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, s_hMaterial, "g_SwordTrailColor", &m_SwordColor );
}
void CEtSwordTrail::ChangeTexture( EtTextureHandle hTexture, EtTextureHandle hNormalTexture )
{
#ifdef PRE_FIX_MATERIAL_DUMP
if( !s_hMaterial ) return;
#endif
int nTexIndex;
nTexIndex = ( hTexture ) ? hTexture->GetMyIndex() : -1;
AddCustomParam( m_vecCustomParam, EPT_TEX, s_hMaterial, "g_SwordTrailTexture", &nTexIndex );
nTexIndex = ( hNormalTexture ) ? hNormalTexture->GetMyIndex() : -1;
AddCustomParam( m_vecCustomParam, EPT_TEX, s_hMaterial, "g_SwordTrailNormalTexture", &nTexIndex );
}
void CEtSwordTrail::CreateVertexBuffer( CEtMeshStream *pMeshStream )
{
pMeshStream->CreateVertexStream( MST_POSITION, 0, MAX_SWORD_TRAIL_VERTEX );
pMeshStream->CreateVertexStream( MST_TEXCOORD, 0, MAX_SWORD_TRAIL_VERTEX );
pMeshStream->SetIndexBuffer( s_pCommonIndexBuffer, ( MAX_SWORD_TRAIL_VERTEX - 2 ) * 3 );
}
void CEtSwordTrail::CopyVertexBuffer()
{
for( std::vector< TrailSet >::iterator it = m_Trails.begin(); it != m_Trails.end(); ++it ) {
CMemoryStream Stream;
int nVertexCount;
nVertexCount = min( ( int )it->vecPosition.size(), MAX_SWORD_TRAIL_VERTEX );
if( nVertexCount <= 2 ) {
continue;
}
it->vecPositionResult.clear();
it->vecTimeResult.clear();
int nHalfVertexCount = nVertexCount / 2;
it->spline[0].Init( nHalfVertexCount );
it->spline[1].Init( nHalfVertexCount );
for( int i = 0; i < nHalfVertexCount; i++) {
it->spline[0].AddNode( it->vecPosition[ i*2 ] );
it->spline[1].AddNode( it->vecPosition[ i*2+1 ] );
}
it->spline[0].BuildSpline();
it->spline[1].BuildSpline();
int nTotalVertexCount = min( 40, nHalfVertexCount*4 );
for( int i = 0; i <= nTotalVertexCount; i++) {
float t = float(i) / (nTotalVertexCount) + 0.01f;
if( nVertexCount == 4 ) {
EtVector3 vPos1, vPos2;
EtVec3Lerp(&vPos1, &it->vecPosition[0], &it->vecPosition[2], t);
EtVec3Lerp(&vPos2, &it->vecPosition[1], &it->vecPosition[3], t);
it->vecPositionResult.push_back( vPos1 );
it->vecPositionResult.push_back( vPos2 );
}
else {
it->vecPositionResult.push_back( it->spline[0].GetPosition( t ) );
it->vecPositionResult.push_back( it->spline[1].GetPosition( t ) );
}
it->vecTimeResult.push_back( EtVector2(t, 1) );
it->vecTimeResult.push_back( EtVector2(t, 0) );
}
if( !it->vecPositionResult.empty() ) {
int nVertexCountInner = (int)it->vecPositionResult.size();
Stream.Initialize( &it->vecPositionResult[ 0 ], nVertexCountInner * sizeof( EtVector3 ) );
it->pMeshStream->LoadVertexStream( &Stream, MST_POSITION, 0, nVertexCountInner );
Stream.Initialize( &it->vecTimeResult[ 0 ], nVertexCountInner * sizeof( EtVector2 ) );
it->pMeshStream->LoadVertexStream( &Stream, MST_TEXCOORD, 0, nVertexCountInner );
}
}
}
void CEtSwordTrail::AddPoint( int nIndex, int nLengthTime )
{
if( m_bAdd ) return;
m_bAdd = true;
m_nAddIndex = nIndex;
m_nLengthTime = nLengthTime;
}
void CEtSwordTrail::Render( float fElapsedTime )
{
m_fElapsedTime += fElapsedTime; // Can Reset
m_fTotalTime += fElapsedTime; // Cannot Reset
ProcessAdd();
int nEraseEnd;
float fCurTime = m_fElapsedTime;
for( std::vector< TrailSet >::iterator it = m_Trails.begin(); it != m_Trails.end(); ++it ) {
nEraseEnd = -1;
for( int i = 0; i < ( int )it->vecTime.size(); i ++ ) {
if( fCurTime - it->vecTime[ i ] > m_fLifeTime )
{
nEraseEnd = i + 1;
}
else
{
break;
}
}
if( nEraseEnd != -1 ) {
it->vecPosition.erase( it->vecPosition.begin(), it->vecPosition.begin() + nEraseEnd * 2);
it->vecTime.erase( it->vecTime.begin(), it->vecTime.begin() + nEraseEnd );
}
if( it->vecPosition.size() <= 2 ) {
continue;
}
CopyVertexBuffer();
if( it->vecPositionResult.size() <= 2 ) {
continue;
}
SRenderStackElement RenderElement;
EtMatrix WorldMat;
EtMatrixIdentity( &WorldMat );
RenderElement.hMaterial = s_hMaterial;
RenderElement.nTechniqueIndex = m_nTechniqueIndex;
RenderElement.WorldMat = WorldMat;
RenderElement.nSaveMatIndex = -1;
RenderElement.pvecCustomParam = &m_vecCustomParam;
RenderElement.pRenderMeshStream = it->pMeshStream;
RenderElement.nDrawCount = ( int )it->vecPositionResult.size() - 2;
SStateBlock RenderState;
RenderState.AddRenderState( D3DRS_CULLMODE, CULL_NONE );
RenderState.AddRenderState( D3DRS_BLENDOP, m_BlendOP );
RenderState.AddRenderState( D3DRS_SRCBLEND, m_SourceBlend );
RenderState.AddRenderState( D3DRS_DESTBLEND, m_DestBlend );
RenderElement.nStateBlockIndex = CEtStateBlockManager::GetInstance().CreateStateBlock(&RenderState);
GetCurRenderStack()->AddUseBackBufferRenderElement( RenderElement );
}
}
void CEtSwordTrail::InitializeEffect()
{
s_hMaterial = LoadResource( "SwordTrail.fx", RT_SHADER );
if( s_pCommonIndexBuffer == NULL )
{
int i, nQuadCount, nFaceCount;
WORD *pIndexBuffer;
CMemoryStream Stream;
nFaceCount = ( MAX_SWORD_TRAIL_VERTEX - 2 );
nQuadCount = MAX_SWORD_TRAIL_VERTEX / 2 - 1;
s_pCommonIndexBuffer = GetEtDevice()->CreateIndexBuffer( nFaceCount * 3 * sizeof( WORD ) );
s_pCommonIndexBuffer->Lock( 0, nFaceCount * 3 * sizeof( WORD ), ( void ** )&pIndexBuffer, 0 );
for( i = 0; i < nQuadCount; i++ )
{
pIndexBuffer[ i * 6 ] = i * 2;
pIndexBuffer[ i * 6 + 1 ] = i * 2 + 2;
pIndexBuffer[ i * 6 + 2 ] = i * 2 + 1;
pIndexBuffer[ i * 6 + 3 ] = i * 2 + 1;
pIndexBuffer[ i * 6 + 4 ] = i * 2 + 2;
pIndexBuffer[ i * 6 + 5 ] = i * 2 + 3;
}
s_pCommonIndexBuffer->Unlock();
}
}
void CEtSwordTrail::FinializeEffect()
{
SAFE_RELEASE_SPTR( s_hMaterial );
SAFE_RELEASE( s_pCommonIndexBuffer );
}
void CEtSwordTrail::ProcessAdd()
{
if( m_bPrevAdd != m_bAdd ) {
if( m_bAdd ) {
m_fFinishTime = m_fTotalTime + m_nLengthTime * 0.001f;
}
m_bPrevAdd = m_bAdd;
}
if( m_bAdd ) {
if( m_fFinishTime < m_fTotalTime ) {
m_bAdd = false;
m_bPrevAdd = false;
return;
}
}
else {
return;
}
if( !m_hParent ) {
return;
}
if( !m_hParent->GetMesh() || m_hParent->GetMesh()->GetDummyMatrixList().empty() ) {
return;
}
int nIndex = 0;
for( std::vector< TrailSet >::iterator it = m_Trails.begin(); it != m_Trails.end(); ++it, nIndex++ ) {
if( it->nDummyIndex[0] >= (int)m_hParent->GetMesh()->GetDummyMatrixList().size() ||
it->nDummyIndex[1] >= (int)m_hParent->GetMesh()->GetDummyMatrixList().size() ||
it->nDummyIndex[0] < 0 || it->nDummyIndex[1] < 0 ) {
continue;
}
if( m_nAddIndex != -1 && nIndex != m_nAddIndex ) {
continue;
}
EtVector3 PointA(0,0,0), PointB(0,0,0);
EtMatrix *pMatParent = m_hParent->GetWorldMat();
if( m_hParent->GetAniHandle() ) {
// if( !m_hParent->GetAniHandle() ) {
// continue;
// }
const char *szBoneName1 = m_hParent->GetMesh()->GetDummyNameList()[ it->nDummyIndex[0] ].c_str();
const char *szBoneName2 = m_hParent->GetMesh()->GetDummyNameList()[ it->nDummyIndex[1] ].c_str();
EtVector3 vLocalPos1 = m_hParent->GetMesh()->GetDummyPosByName( szBoneName1 );
EtVector3 vLocalPos2 = m_hParent->GetMesh()->GetDummyPosByName( szBoneName2 );
char *pParentName1 = m_hParent->GetMesh()->GetDummyParentByName( szBoneName1 );
char *pParentName2 = m_hParent->GetMesh()->GetDummyParentByName( szBoneName2 );
int nBoneIndex1 = m_hParent->GetAniHandle()->GetBoneIndex( pParentName1 );
int nBoneIndex2 = m_hParent->GetAniHandle()->GetBoneIndex( pParentName2 );
if( ( nBoneIndex1 == -1 ) || ( nBoneIndex1 == -1 ) )
{
EtVec3TransformCoord(&PointA, ( EtVector3 * )&m_hParent->GetMesh()->GetDummyMatrixList()[ it->nDummyIndex[0] ]._41, pMatParent);
EtVec3TransformCoord(&PointB, ( EtVector3 * )&m_hParent->GetMesh()->GetDummyMatrixList()[ it->nDummyIndex[1] ]._41, pMatParent);
}
else
{
EtMatrix mat;
EtMatrixMultiply( &mat, m_hParent->GetBoneTransMat( nBoneIndex1 ), pMatParent );
EtVec3TransformCoord(&PointA, &vLocalPos1, &mat);
EtMatrixMultiply( &mat, m_hParent->GetBoneTransMat( nBoneIndex2 ), pMatParent );
EtVec3TransformCoord(&PointB, &vLocalPos2, &mat);
}
}
else {
EtVec3TransformCoord(&PointA, ( EtVector3 * )&m_hParent->GetMesh()->GetDummyMatrixList()[ it->nDummyIndex[0] ]._41, pMatParent);
EtVec3TransformCoord(&PointB, ( EtVector3 * )&m_hParent->GetMesh()->GetDummyMatrixList()[ it->nDummyIndex[1] ]._41, pMatParent);
}
if( !it->vecPosition.empty() )
{
float fLastTime = it->vecTime.back();
float fCurTime = m_fElapsedTime;
if( ( fCurTime - fLastTime ) < 0.01666f ) // 60<36><30><EFBFBD><EFBFBD> 1<>ʺ<EFBFBD><CABA><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
{
it->vecPosition.back() = PointA;
it->vecPosition.back() = PointB;
}
else {
it->vecPosition.push_back( PointA );
it->vecPosition.push_back( PointB );
it->vecTime.push_back( fCurTime );
}
}
else
{
m_fElapsedTime = 0.f;
it->vecPosition.push_back( PointA );
it->vecPosition.push_back( PointB );
it->vecTime.push_back( 0.0f );
}
}
}