366 lines
11 KiB
C++
366 lines
11 KiB
C++
|
|
#include "StdAfx.h"
|
|||
|
|
#include "EtGrassBlock.h"
|
|||
|
|
#include "EtRenderStack.h"
|
|||
|
|
|
|||
|
|
#ifdef _DEBUG
|
|||
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
CEtGrassBlock::CEtGrassBlock(void)
|
|||
|
|
{
|
|||
|
|
m_InteractivePos = EtVector4(0,0,0,0);
|
|||
|
|
m_InteractiveVelocity = EtVector2(0,0);
|
|||
|
|
m_nRenderUniqueID = -1;
|
|||
|
|
m_nGrassCount = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CEtGrassBlock::~CEtGrassBlock(void)
|
|||
|
|
{
|
|||
|
|
Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::Clear()
|
|||
|
|
{
|
|||
|
|
SAFE_RELEASE_SPTR( m_hMaterial );
|
|||
|
|
SAFE_RELEASE_SPTR( m_hTexture );
|
|||
|
|
m_MeshStream.Clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::Initialize( CEtTerrainArea *pTerrainArea )
|
|||
|
|
{
|
|||
|
|
// Clear();
|
|||
|
|
|
|||
|
|
SAFE_RELEASE_SPTR( m_hMaterial );
|
|||
|
|
m_MeshStream.Clear();
|
|||
|
|
CreateMaterial();
|
|||
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|||
|
|
if( !m_hMaterial ) return;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
int i, j, k;
|
|||
|
|
|
|||
|
|
m_nGrassCount = 0;
|
|||
|
|
for( i = 0; i < m_GrassBlockInfo.nSizeY; i++ )
|
|||
|
|
{
|
|||
|
|
for( j = 0; j < m_GrassBlockInfo.nSizeX; j++ )
|
|||
|
|
{
|
|||
|
|
char cValue;
|
|||
|
|
|
|||
|
|
cValue = GetGrassValue( j, i );
|
|||
|
|
m_nGrassCount += cValue & 0x03;
|
|||
|
|
m_nGrassCount += ( cValue >> 2 ) & 0x03;
|
|||
|
|
m_nGrassCount += ( cValue >> 4 ) & 0x03;
|
|||
|
|
m_nGrassCount += ( cValue >> 6 ) & 0x03;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if( m_nGrassCount <= 0 )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int nVertexCount, nIndexCount, nCurGrass;
|
|||
|
|
EtVector3 *pPosition;
|
|||
|
|
EtVector2 *pTexCoord;
|
|||
|
|
float *pShake;
|
|||
|
|
DWORD *pColor;
|
|||
|
|
WORD *pIndex;
|
|||
|
|
|
|||
|
|
nVertexCount = m_nGrassCount * 3 * 4;
|
|||
|
|
nIndexCount = m_nGrassCount * 18;
|
|||
|
|
pPosition = new EtVector3[ nVertexCount ];
|
|||
|
|
pTexCoord = new EtVector2[ nVertexCount ];
|
|||
|
|
pColor = new DWORD[ nVertexCount ];
|
|||
|
|
pShake = new float[ nVertexCount ];
|
|||
|
|
memset( pColor, 0xff, sizeof( DWORD ) * nVertexCount );
|
|||
|
|
pIndex = new WORD[ nIndexCount ];
|
|||
|
|
nCurGrass = 0;
|
|||
|
|
m_BoundingBox.Reset();
|
|||
|
|
for( i = 0; i < m_GrassBlockInfo.nSizeY; i++ )
|
|||
|
|
{
|
|||
|
|
for( j = 0; j < m_GrassBlockInfo.nSizeX; j++ )
|
|||
|
|
{
|
|||
|
|
char cGrassValue;
|
|||
|
|
|
|||
|
|
cGrassValue = GetGrassValue( j, i );
|
|||
|
|
for( k = 0; k < ( cGrassValue & 0x03 ); k++ )
|
|||
|
|
{
|
|||
|
|
CreateGrass( pTerrainArea, j, i, nCurGrass, 0, pPosition + nCurGrass * 12, pTexCoord + nCurGrass * 12, pShake + nCurGrass * 12, pIndex + nCurGrass * 18 );
|
|||
|
|
nCurGrass++;
|
|||
|
|
}
|
|||
|
|
for( k = 0; k < ( ( cGrassValue >> 2 ) & 0x03 ); k++ )
|
|||
|
|
{
|
|||
|
|
CreateGrass( pTerrainArea, j, i, nCurGrass, 1, pPosition + nCurGrass * 12, pTexCoord + nCurGrass * 12, pShake + nCurGrass * 12, pIndex + nCurGrass * 18 );
|
|||
|
|
nCurGrass++;
|
|||
|
|
}
|
|||
|
|
for( k = 0; k < ( ( cGrassValue >> 4 ) & 0x03 ); k++ )
|
|||
|
|
{
|
|||
|
|
CreateGrass( pTerrainArea, j, i, nCurGrass, 2, pPosition + nCurGrass * 12, pTexCoord + nCurGrass * 12, pShake + nCurGrass * 12, pIndex + nCurGrass * 18 );
|
|||
|
|
nCurGrass++;
|
|||
|
|
}
|
|||
|
|
for( k = 0; k < ( ( cGrassValue >> 6 ) & 0x03 ); k++ )
|
|||
|
|
{
|
|||
|
|
CreateGrass( pTerrainArea, j, i, nCurGrass, 3, pPosition + nCurGrass * 12, pTexCoord + nCurGrass * 12, pShake + nCurGrass * 12, pIndex + nCurGrass * 18 );
|
|||
|
|
nCurGrass++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CMemoryStream Stream;
|
|||
|
|
Stream.Initialize( pPosition, sizeof( EtVector3 ) * nVertexCount );
|
|||
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_POSITION, 0, nVertexCount );
|
|||
|
|
Stream.Initialize( pTexCoord, sizeof( EtVector2 ) * nVertexCount );
|
|||
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_TEXCOORD, 0, nVertexCount );
|
|||
|
|
Stream.Initialize( pShake, sizeof( float ) * nVertexCount );
|
|||
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_DEPTH, 0, nVertexCount );
|
|||
|
|
Stream.Initialize( pColor, sizeof( DWORD ) * nVertexCount );
|
|||
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_COLOR, 0, nVertexCount );
|
|||
|
|
Stream.Initialize( pIndex, sizeof( WORD ) * nIndexCount );
|
|||
|
|
m_MeshStream.LoadIndexStream( &Stream, false, nIndexCount );
|
|||
|
|
|
|||
|
|
delete [] pIndex;
|
|||
|
|
delete [] pColor;
|
|||
|
|
delete [] pTexCoord;
|
|||
|
|
delete [] pPosition;
|
|||
|
|
delete [] pShake;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::CreateGrass( CEtTerrainArea *pTerrainArea, int nTileX, int nTileY, int nGrassIndex, char cKind, EtVector3 *pPosition,
|
|||
|
|
EtVector2 *pTexCoord, float *pShake, WORD *pIndex )
|
|||
|
|
{
|
|||
|
|
int nLoop;
|
|||
|
|
float fGrassWidth, fGrassHeight, fRotateAngle, fShake;
|
|||
|
|
EtVector3 BasePos[ 4 ], GrassPos, UpVec, XVec, ZVec;
|
|||
|
|
EtMatrix RotateMat, LandMat;
|
|||
|
|
|
|||
|
|
GrassPos.x = m_GrassBlockInfo.GrassOffset.x + ( nTileX + rand() / ( float )RAND_MAX ) * m_GrassBlockInfo.fTileSize;
|
|||
|
|
GrassPos.z = m_GrassBlockInfo.GrassOffset.z + ( nTileY + rand() / ( float )RAND_MAX ) * m_GrassBlockInfo.fTileSize;
|
|||
|
|
GrassPos.y = pTerrainArea->GetLandHeight( GrassPos.x, GrassPos.z, &UpVec );
|
|||
|
|
XVec = EtVector3( 1.0f, 0.0f, 0.0f );
|
|||
|
|
EtVec3Cross( &ZVec, &XVec, &UpVec );
|
|||
|
|
EtVec3Normalize( &ZVec, &ZVec );
|
|||
|
|
EtVec3Cross( &XVec, &UpVec, &ZVec );
|
|||
|
|
EtVec3Normalize( &XVec, &XVec );
|
|||
|
|
EtMatrixTranslation( &LandMat, GrassPos.x, GrassPos.y, GrassPos.z );
|
|||
|
|
memcpy( &LandMat._11, &XVec, sizeof( EtVector3 ) );
|
|||
|
|
memcpy( &LandMat._21, &UpVec, sizeof( EtVector3 ) );
|
|||
|
|
memcpy( &LandMat._31, &ZVec, sizeof( EtVector3 ) );
|
|||
|
|
|
|||
|
|
fGrassWidth = m_GrassBlockInfo.fGrassWidth[ cKind ] * 0.5f;
|
|||
|
|
fGrassHeight = ( rand() / ( float )RAND_MAX ) * ( m_GrassBlockInfo.fMaxGrassHeight[ cKind ] - m_GrassBlockInfo.fMinGrassHeight[ cKind ] ) +
|
|||
|
|
m_GrassBlockInfo.fMinGrassHeight[ cKind ];
|
|||
|
|
BasePos[ 0 ] = EtVector3( -fGrassWidth, 0.0f, 0.0f );
|
|||
|
|
BasePos[ 1 ] = EtVector3( fGrassWidth, 0.0f, 0.0f );
|
|||
|
|
BasePos[ 2 ] = EtVector3( fGrassWidth, fGrassHeight, 0.0f );
|
|||
|
|
BasePos[ 3 ] = EtVector3( -fGrassWidth, fGrassHeight, 0.0f );
|
|||
|
|
fRotateAngle = rand() / ( float )RAND_MAX * 360.0f;
|
|||
|
|
for( nLoop = 0; nLoop < 12; nLoop++ )
|
|||
|
|
{
|
|||
|
|
EtVector3 *pCurPos;
|
|||
|
|
|
|||
|
|
if( nLoop % 4 == 0 )
|
|||
|
|
{
|
|||
|
|
EtMatrixRotationY( &RotateMat, EtToRadian( fRotateAngle ) );
|
|||
|
|
EtMatrixMultiply( &RotateMat, &RotateMat, &LandMat );
|
|||
|
|
fRotateAngle += 120.0f;
|
|||
|
|
}
|
|||
|
|
pCurPos = pPosition + nLoop;
|
|||
|
|
EtVec3TransformCoord( pCurPos, BasePos + nLoop % 4, &RotateMat );
|
|||
|
|
|
|||
|
|
if( pCurPos->x > m_BoundingBox.Max.x ) m_BoundingBox.Max.x = pCurPos->x;
|
|||
|
|
else if( pCurPos->x < m_BoundingBox.Min.x ) m_BoundingBox.Min.x = pCurPos->x;
|
|||
|
|
if( pCurPos->y > m_BoundingBox.Max.y ) m_BoundingBox.Max.y = pCurPos->y;
|
|||
|
|
else if( pCurPos->y < m_BoundingBox.Min.y ) m_BoundingBox.Min.y = pCurPos->y;
|
|||
|
|
if( pCurPos->z > m_BoundingBox.Max.z ) m_BoundingBox.Max.z = pCurPos->z;
|
|||
|
|
else if( pCurPos->z < m_BoundingBox.Min.z ) m_BoundingBox.Min.z = pCurPos->z;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fShake = ( rand() / ( float )RAND_MAX ) * ( m_GrassBlockInfo.fMaxShake - m_GrassBlockInfo.fMinShake ) + m_GrassBlockInfo.fMinShake;
|
|||
|
|
for( nLoop = 0; nLoop < 3; nLoop++ )
|
|||
|
|
{
|
|||
|
|
pTexCoord[ nLoop * 4 ] = EtVector2( cKind * 0.25f, 1.0f );
|
|||
|
|
pTexCoord[ nLoop * 4 + 1 ] = EtVector2( cKind * 0.25f + 0.25f, 1.0f );
|
|||
|
|
pTexCoord[ nLoop * 4 + 2 ] = EtVector2( cKind * 0.25f + 0.25f, 0.0f );
|
|||
|
|
pTexCoord[ nLoop * 4 + 3 ] = EtVector2( cKind * 0.25f, 0.0f );
|
|||
|
|
|
|||
|
|
pShake[ nLoop * 4 ] = 0.0f;
|
|||
|
|
pShake[ nLoop * 4 + 1 ] = 0.0f;
|
|||
|
|
pShake[ nLoop * 4 + 2 ] = fShake;
|
|||
|
|
pShake[ nLoop * 4 + 3 ] = fShake;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pIndex[ 0 ] = nGrassIndex * 12;
|
|||
|
|
pIndex[ 1 ] = nGrassIndex * 12 + 1;
|
|||
|
|
pIndex[ 2 ] = nGrassIndex * 12 + 3;
|
|||
|
|
pIndex[ 3 ] = nGrassIndex * 12 + 1;
|
|||
|
|
pIndex[ 4 ] = nGrassIndex * 12 + 2;
|
|||
|
|
pIndex[ 5 ] = nGrassIndex * 12 + 3;
|
|||
|
|
|
|||
|
|
pIndex[ 6 ] = nGrassIndex * 12 + 4;
|
|||
|
|
pIndex[ 7 ] = nGrassIndex * 12 + 5;
|
|||
|
|
pIndex[ 8 ] = nGrassIndex * 12 + 7;
|
|||
|
|
pIndex[ 9 ] = nGrassIndex * 12 + 5;
|
|||
|
|
pIndex[ 10 ] = nGrassIndex * 12 + 6;
|
|||
|
|
pIndex[ 11 ] = nGrassIndex * 12 + 7;
|
|||
|
|
|
|||
|
|
pIndex[ 12 ] = nGrassIndex * 12 + 8;
|
|||
|
|
pIndex[ 13 ] = nGrassIndex * 12 + 9;
|
|||
|
|
pIndex[ 14 ] = nGrassIndex * 12 + 11;
|
|||
|
|
pIndex[ 15 ] = nGrassIndex * 12 + 9;
|
|||
|
|
pIndex[ 16 ] = nGrassIndex * 12 + 10;
|
|||
|
|
pIndex[ 17 ] = nGrassIndex * 12 + 11;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::CreateMaterial()
|
|||
|
|
{
|
|||
|
|
m_hMaterial = LoadResource( "Grass.fx", RT_SHADER );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::SetTexture( const char *pFileName )
|
|||
|
|
{
|
|||
|
|
#ifdef PRE_FIX_MATERIAL_DUMP
|
|||
|
|
if( !m_hMaterial ) return;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
SAFE_RELEASE_SPTR( m_hTexture );
|
|||
|
|
|
|||
|
|
int nTexIndex = -1;
|
|||
|
|
m_hTexture = LoadResource( pFileName, RT_TEXTURE );
|
|||
|
|
if( m_hTexture )
|
|||
|
|
{
|
|||
|
|
nTexIndex = m_hTexture->GetMyIndex();
|
|||
|
|
}
|
|||
|
|
AddCustomParam( m_vecCustomParam, EPT_TEX, m_hMaterial, "g_DiffuseTex", &nTexIndex );
|
|||
|
|
|
|||
|
|
// <20>̰<EFBFBD><CCB0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> CustomParam Setting !!
|
|||
|
|
AddCustomParam( m_vecCustomParam, EPT_VECTOR_PTR, m_hMaterial, "g_InteractivePos", &m_InteractivePos );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const char *CEtGrassBlock::GetTextureName()
|
|||
|
|
{
|
|||
|
|
if( !m_hTexture ) return NULL;
|
|||
|
|
return m_hTexture->GetFileName();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::Render()
|
|||
|
|
{
|
|||
|
|
if( m_nGrassCount <= 0 )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if( !m_hTexture )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SRenderStackElement RenderElement;
|
|||
|
|
EtMatrix WorldMat;
|
|||
|
|
|
|||
|
|
EtMatrixIdentity( &WorldMat );
|
|||
|
|
RenderElement.hMaterial = m_hMaterial;
|
|||
|
|
RenderElement.nTechniqueIndex = 0;
|
|||
|
|
RenderElement.WorldMat = WorldMat;
|
|||
|
|
RenderElement.PrevWorldMat = WorldMat;
|
|||
|
|
RenderElement.nSaveMatIndex = -1;
|
|||
|
|
RenderElement.pvecCustomParam = &m_vecCustomParam;
|
|||
|
|
RenderElement.pRenderMeshStream = &m_MeshStream;
|
|||
|
|
|
|||
|
|
SStateBlock RenderState;
|
|||
|
|
|
|||
|
|
RenderState.AddRenderState( D3DRS_CULLMODE, CULL_NONE );
|
|||
|
|
RenderElement.nStateBlockIndex = CEtStateBlockManager::GetInstance().CreateStateBlock(&RenderState);
|
|||
|
|
RenderElement.nDiffuseTexIndex = m_hTexture ? m_hTexture->GetMyIndex() : -1;
|
|||
|
|
RenderElement.nBakeDepthIndex = DT_GRASS;
|
|||
|
|
|
|||
|
|
m_nRenderUniqueID = GetCurRenderStack()->AddNormalRenderElement( RenderElement, m_nRenderUniqueID );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::GetExtent( EtVector3 &Origin, EtVector3 &Extent )
|
|||
|
|
{
|
|||
|
|
Origin = ( m_BoundingBox.Max + m_BoundingBox.Min ) / 2;
|
|||
|
|
Extent = ( m_BoundingBox.Max - m_BoundingBox.Min ) / 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::SetLightMapInfluence( char *pTexBuffer, int nTexStride, int nTexWidth, int nTexHeight, float fOffsetU, float fOffsetV )
|
|||
|
|
{
|
|||
|
|
if( m_nGrassCount <= 0 )
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int i, j, nVertexCount;
|
|||
|
|
EtVector3 *pPosition;
|
|||
|
|
DWORD *pColor;
|
|||
|
|
EtColor Ambient;
|
|||
|
|
|
|||
|
|
Ambient = *CEtLight::GetGlobalAmbient();
|
|||
|
|
Ambient.r *= 0.381f;
|
|||
|
|
Ambient.g *= 0.381f;
|
|||
|
|
Ambient.b *= 0.381f;
|
|||
|
|
nVertexCount = m_MeshStream.GetVertexCount();
|
|||
|
|
pPosition = new EtVector3[ nVertexCount ];
|
|||
|
|
pColor = new DWORD[ nVertexCount ];
|
|||
|
|
m_MeshStream.GetVertexStream( MST_POSITION, pPosition, 0 );
|
|||
|
|
for( i = 0; i < m_nGrassCount; i++ )
|
|||
|
|
{
|
|||
|
|
EtVector3 *pCurPosition, CenterPos;
|
|||
|
|
float fU, fV;
|
|||
|
|
int nTexOffset;
|
|||
|
|
DWORD dwGrassColor;
|
|||
|
|
|
|||
|
|
pCurPosition = pPosition + i * 12;
|
|||
|
|
CenterPos = ( pCurPosition[ 0 ] + pCurPosition[ 1 ] ) * 0.5f - m_GrassBlockInfo.GrassOffset;
|
|||
|
|
fU = CenterPos.x / ( m_GrassBlockInfo.nSizeX * m_GrassBlockInfo.fTileSize ) * 0.5f + fOffsetU;
|
|||
|
|
fV = CenterPos.z / ( m_GrassBlockInfo.nSizeY * m_GrassBlockInfo.fTileSize ) * 0.5f + fOffsetV;
|
|||
|
|
nTexOffset = ( ( ( int )( fV * ( nTexHeight - 1 ) ) ) * nTexStride ) + ( ( int )( fU * ( nTexWidth - 1 ) ) ) * 4;
|
|||
|
|
if( pTexBuffer[ nTexOffset + 1 ] == 0 )
|
|||
|
|
{
|
|||
|
|
dwGrassColor = Ambient;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
EtColor Color;
|
|||
|
|
|
|||
|
|
Color = *( ( DWORD * )( pTexBuffer + nTexOffset ) );
|
|||
|
|
Color += Ambient;
|
|||
|
|
dwGrassColor = Color;
|
|||
|
|
}
|
|||
|
|
for( j = 0; j < 12; j++ )
|
|||
|
|
{
|
|||
|
|
pColor[ i * 12 + j ] = dwGrassColor;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CMemoryStream Stream( pColor, nVertexCount * sizeof( DWORD ) );
|
|||
|
|
m_MeshStream.LoadVertexStream( &Stream, MST_COLOR, 0, nVertexCount );
|
|||
|
|
|
|||
|
|
delete [] pPosition;
|
|||
|
|
delete [] pColor;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CEtGrassBlock::SetInteractivePos( EtVector3 *vPos, float fDelta )
|
|||
|
|
{
|
|||
|
|
EtVector2 vCurrVelocity = EtVector2(vPos->x - m_InteractivePos.x, vPos->z - m_InteractivePos.y);
|
|||
|
|
if( fDelta != 0.0f ) {
|
|||
|
|
vCurrVelocity /= fDelta;
|
|||
|
|
}
|
|||
|
|
m_InteractiveVelocity += (vCurrVelocity - m_InteractiveVelocity) * min( 1.0f, ( fDelta * 5.0f ));
|
|||
|
|
|
|||
|
|
static float fVelocityScale = 0.01f;
|
|||
|
|
static float fMaxVelocity = 5.f;
|
|||
|
|
|
|||
|
|
m_InteractivePos.z = (float)(m_InteractiveVelocity.x * fVelocityScale + 0.001f );
|
|||
|
|
m_InteractivePos.w = (float)(m_InteractiveVelocity.y * fVelocityScale + 0.001f );
|
|||
|
|
|
|||
|
|
float fVelLength = sqrtf( m_InteractivePos.z*m_InteractivePos.z+m_InteractivePos.w*m_InteractivePos.w);
|
|||
|
|
if( fVelLength > fMaxVelocity ) {
|
|||
|
|
m_InteractivePos.z /= fVelLength;
|
|||
|
|
m_InteractivePos.w /= fVelLength;
|
|||
|
|
m_InteractivePos.z *= fMaxVelocity;
|
|||
|
|
m_InteractivePos.w *= fMaxVelocity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_InteractivePos.x = vPos->x;
|
|||
|
|
m_InteractivePos.y = vPos->z;
|
|||
|
|
|
|||
|
|
}
|