974 lines
24 KiB
C++
974 lines
24 KiB
C++
#include "stdafx.h"
|
|
#include "KPrimitive.h"
|
|
#include "KResource.h"
|
|
#include "KPrimitiveMesh.h"
|
|
#include "KRenderDevice.h"
|
|
#include "KViewport.h"
|
|
#include "KResourceDXDynamic.h"
|
|
#include "KResourceManager.h"
|
|
#include <toolkit/SafeTickCount.h>
|
|
|
|
#define MAX_BONES 57
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KMeshPrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
KMeshPrimitive::KMeshPrimitive()
|
|
{
|
|
m_type = KPRIMITIVE_MESH;
|
|
m_nPrimitivesCount = 0;
|
|
|
|
m_pMtl = NULL;
|
|
m_pWeight = NULL;
|
|
|
|
m_SkinDiffuse.r = 0;
|
|
m_SkinDiffuse.g = 0;
|
|
m_SkinDiffuse.b = 0;
|
|
m_SkinDiffuse.a = 0;
|
|
|
|
Clear();
|
|
}
|
|
KMeshPrimitive::~KMeshPrimitive()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KMeshPrimitive::Clear()
|
|
{
|
|
m_nRenderState = 0;
|
|
m_fVisibility = 1.0f;
|
|
m_nBoneCount = 0;
|
|
m_pOffSetMat = NULL;
|
|
m_pBoneMat = NULL;
|
|
m_pUVTransform = NULL;
|
|
m_pBoundOcclusion = NULL;
|
|
}
|
|
|
|
|
|
#include <dump/XException.h>
|
|
void KMeshPrimitive::Render( KViewportObject *pViewport,K3DRenderDevice* pDev, bool bUseAccum )
|
|
{
|
|
//MTE
|
|
// Please tell me the default input parameters that can be used in a vertex shader
|
|
if( m_bIsMTE )
|
|
{
|
|
static float f1 = 0.0f;
|
|
static DWORD dwBeforeTime = GetSafeTickCount();
|
|
DWORD dwCurrTime = GetSafeTickCount();
|
|
DWORD dwDelta = dwCurrTime - dwBeforeTime;
|
|
f1 += (float)dwDelta / 10000.0f;
|
|
dwBeforeTime = dwCurrTime;
|
|
|
|
if( f1 > 1.0f )
|
|
f1 -= 1.0f;
|
|
|
|
K3DVector4 uvani(f1, f1, 0, 1.0f );
|
|
pDev->SetVertexShaderConstant(CONSTANT_UVANIMATION, (float *)&uvani, 4);
|
|
}
|
|
else if ( m_pUVTransform )
|
|
{
|
|
K3DVector4 uvani(m_pUVTransform->_31, m_pUVTransform->_32, 0, m_pUVTransform->_11);
|
|
pDev->SetVertexShaderConstant(CONSTANT_UVANIMATION, (float *)&uvani, 4);
|
|
}
|
|
|
|
assert(m_spIB != NULL && m_spVB != NULL);
|
|
|
|
_SetMatrixArrayForVS(pViewport, pDev, bUseAccum);
|
|
|
|
pDev->SetVertexShaderConstant(CONSTANT_VISIBILITY, &m_fVisibility, 1);
|
|
|
|
K3DVector4 diffuse(m_SkinDiffuse.r, m_SkinDiffuse.g, m_SkinDiffuse.b, m_SkinDiffuse.a != 0 ? 1.0f : 0.0f );
|
|
pDev->SetVertexShaderConstant(CONSTANT_SKIN_DIFFUSE, (float *)&diffuse, 4);
|
|
|
|
if(IsUseLightMap())
|
|
{
|
|
if( IsUseFixMap() )
|
|
{
|
|
pDev->SetTexture( 0, m_TexPack.spTexture_Fix);
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Fix);
|
|
}
|
|
else
|
|
{
|
|
pDev->SetTexture( 0, m_TexPack.spTexture_Light);
|
|
pDev->SetTexture( 1, m_TexPack.spTexture );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( IsUseFixMap() )
|
|
pDev->SetTexture( 0, m_TexPack.spTexture_Fix);
|
|
else
|
|
{
|
|
#ifdef _SPECULAR_EDITING_
|
|
switch( g_testTextureUseType )
|
|
{
|
|
case TYPE_0D1S2SC:
|
|
case TYPE_0D1S2X:
|
|
case TYPE_0D1X2X:
|
|
pDev->SetTexture( 0, m_TexPack.spTexture );
|
|
break;
|
|
case TYPE_0S1X2SC:
|
|
case TYPE_0S1S2SC:
|
|
case TYPE_0S1X2X:
|
|
pDev->SetTexture( 0, m_TexPack.spTexture_Specular );
|
|
break;
|
|
}
|
|
#else
|
|
pDev->SetTexture( 0, m_TexPack.spTexture );
|
|
#endif
|
|
|
|
if( m_nBlendMode == K3DMaterial::MBM_ALPHABLEND_NOALPHAUVANI || m_nBlendMode == K3DMaterial::MBM_ALPHABLEND_NOCOLORUVANI ||
|
|
m_nBlendMode == K3DMaterial::MBM_ADDITIVE_NOALPHAUVANI || m_nBlendMode == K3DMaterial::MBM_ADDITIVE_NOCOLORUVANI )
|
|
pDev->SetTexture( 1, m_TexPack.spTexture );
|
|
}
|
|
|
|
if(IsSpecular() || IsBump())
|
|
{
|
|
_SetSpecularBumpTexture(pViewport, pDev);
|
|
_SetHalfWay(pViewport,pDev);
|
|
}
|
|
|
|
//MTE
|
|
if( m_bIsMTE )
|
|
{
|
|
IsSpecular() ? pDev->SetTexture( 3, m_TexPack.spTexture_MTE ) : pDev->SetTexture( 1, m_TexPack.spTexture_MTE );
|
|
}
|
|
}
|
|
|
|
pDev->DrawIndexedTriangleVB_VS( m_spVB, m_spIB, m_nPrimitivesCount, 1 );
|
|
|
|
if ( m_pUVTransform )
|
|
{
|
|
K3DVector4 uvani(0.f,0.f,0.f,1.f);
|
|
pDev->SetVertexShaderConstant(CONSTANT_UVANIMATION, (float *)&uvani, 4);
|
|
}
|
|
}
|
|
|
|
void KMeshPrimitive::_SetMatrixArrayForVS(KViewportObject* pViewport, K3DRenderDevice* pDev, bool bUseAccum)
|
|
{
|
|
if(m_pWeight != NULL)
|
|
{
|
|
static K3DMatrix matArray[MAX_BONES];
|
|
|
|
K3DMatrix world_mat;
|
|
|
|
//사용된 Bone만 설정
|
|
assert( m_pWeight->m_nUseBoneCount <= MAX_BONES && "사용하는 뼈 갯수가 57개보다 많다." );
|
|
|
|
if( !m_pBoneMat || !m_pOffSetMat ) {
|
|
// No bone : Reset transform matrix
|
|
K3DMatrixIdentity(world_mat);
|
|
pDev->SetTransform(K3DRenderDevice::TS_WORLD, &world_mat, 1);
|
|
return;
|
|
}
|
|
|
|
if( m_bIsEffectMat )
|
|
{
|
|
K3DMatrixMultiply( world_mat, *m_pEffectMat, *m_pTransform );
|
|
K3DMatrixMultiply( world_mat, world_mat, m_RootMat );
|
|
}
|
|
else
|
|
{
|
|
K3DMatrixMultiply( world_mat, *m_pTransform, m_RootMat );
|
|
}
|
|
|
|
for( int i=0; i < m_pWeight->m_nUseBoneCount; ++i)
|
|
{
|
|
//사용되는 실제 본의 인덱스...
|
|
int nUseBoneIndex = m_pWeight->m_pUseBoneList[i];
|
|
K3DMatrixMultiply( matArray[i], m_pOffSetMat[nUseBoneIndex], m_pBoneMat[nUseBoneIndex] );
|
|
K3DMatrixMultiply( matArray[i], matArray[i], world_mat );
|
|
}
|
|
|
|
pDev->SetTransform(K3DRenderDevice::TS_WORLD, matArray, m_pWeight->m_nUseBoneCount );
|
|
}
|
|
else
|
|
{
|
|
K3DMatrix world_mat;
|
|
K3DMatrixMultiply( world_mat, *m_pTransform, m_RootMat );
|
|
pDev->SetTransform(K3DRenderDevice::TS_WORLD, &world_mat, 1);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void KMeshPrimitive::_SetSpecularBumpTexture(KViewportObject* pViewport, K3DRenderDevice* pDev)
|
|
{
|
|
if( IsBump() && pViewport->GetRenderBumpMapMode() )
|
|
{
|
|
if( IsUseFixMap() )
|
|
{
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Fix);
|
|
pDev->SetTexture( 2, NULL );
|
|
}
|
|
else
|
|
{
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Bump );
|
|
pDev->SetTexture( 2, NULL );
|
|
}
|
|
}
|
|
else if( ( IsSpecular() || ( IsBump() && !pViewport->GetRenderBumpMapMode() ) ) && pViewport->GetUseSpecular() )
|
|
{
|
|
if( IsUseFixMap() )
|
|
{
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Fix );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_Fix );
|
|
}
|
|
else
|
|
{
|
|
#ifdef _SPECULAR_EDITING_
|
|
switch( g_testTextureUseType )
|
|
{
|
|
case TYPE_0D1S2SC:
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Specular );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_SpecularColor );
|
|
break;
|
|
case TYPE_0D1S2X:
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Specular );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_Fix );
|
|
break;
|
|
case TYPE_0D1X2X:
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Fix );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_Fix );
|
|
break;
|
|
case TYPE_0S1X2SC:
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Fix );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_SpecularColor );
|
|
break;
|
|
case TYPE_0S1S2SC:
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Specular );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_SpecularColor );
|
|
break;
|
|
case TYPE_0S1X2X:
|
|
break;
|
|
}
|
|
#else
|
|
pDev->SetTexture( 1, m_TexPack.spTexture_Specular );
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_SpecularColor );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if( m_TexPack.spTexture_Illumin && IsBump() )
|
|
{
|
|
if( IsUseFixMap() )
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_Fix );
|
|
else
|
|
pDev->SetTexture( 2, m_TexPack.spTexture_Illumin );
|
|
}
|
|
}
|
|
|
|
|
|
void KMeshPrimitive::_SetHalfWay(KViewportObject* pViewport, K3DRenderDevice* pDev)
|
|
{
|
|
static K3DVector halfway;
|
|
static K3DMatrix world;
|
|
K3DMatrixMultiply(world, *m_pTransform, m_RootMat);
|
|
|
|
halfway = pViewport->GetCameraPos() - world.GetPosVector();
|
|
|
|
float mag = K3DVectorLength( halfway );
|
|
halfway.z += mag/3;
|
|
halfway.y += halfway.x/3;
|
|
halfway.x -= halfway.y/3;
|
|
K3DVectorNormalize( halfway, halfway);
|
|
|
|
m_fHalfWay[0] = halfway.x;
|
|
m_fHalfWay[1] = halfway.y;
|
|
m_fHalfWay[2] = halfway.z;
|
|
m_fHalfWay[3] = 1.f;
|
|
|
|
pDev->SetVertexShaderConstant(CONSTANT_HALFWAY, m_fHalfWay, 4);
|
|
|
|
}
|
|
|
|
K3DTexture *KMeshPrimitive::getTexture(const char *texname)
|
|
// load texture from manager
|
|
{
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
if( KTextureManager::GetManager()->IsExistTexture( texname, &loadpack ) ) {
|
|
return KTextureManager::GetManager()
|
|
->GetTexture( texname, &loadpack, true, KTextureManager::GetManager()->GetMipMapBiasLevel() );
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void KMeshPrimitive::RenderBoundOcclusion( KViewportObject* pViewport, K3DRenderDevice* pDev )
|
|
{
|
|
const static WORD ctBBox[24] = { 0, 1, 0, 2, 0, 4, 7, 6, 7, 5, 7, 3, // Bounding Box 용 Index
|
|
1, 3, 1, 5, 2, 3, 2, 6, 4, 5, 4, 6 };
|
|
|
|
pDev->SetTexture( 0, NULL );
|
|
pDev->DrawIndexedPrimitiveUPLine( D3DFVF_XYZ, m_pBoundOcclusion->GetVertices(), (void*)ctBBox, 8, 12, 12 );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KPlanUtilPrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
KPlanUtilPrimitive::KPlanUtilPrimitive()
|
|
{
|
|
m_nVtxFormat = K3DFVF_XYZ | K3DFVF_DIFFUSE;
|
|
m_nVtxStride = K3DVertexBuffer::CalcVertexStride( m_nVtxFormat );
|
|
K3DMatrixIdentity( m_matTransform );
|
|
m_Mtl.SetAmbient( K3DColor(1.f,1.f,1.f) );
|
|
m_Mtl.SetDiffuse( K3DColor(1.f,1.f,1.f) );
|
|
|
|
m_nCurCount = 0;
|
|
}
|
|
|
|
KPlanUtilPrimitive::~KPlanUtilPrimitive()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KPlanUtilPrimitive::Clear()
|
|
{
|
|
int iSize = (int) m_verts.size();
|
|
m_verts.erase( m_verts.begin(), m_verts.end() );
|
|
}
|
|
|
|
void KPlanUtilPrimitive::AddVertex( const K3DVector &vertex1, const K3DVector &vertex2, const K3DVector &vertex3, const KColor &diffuse )
|
|
{
|
|
PLANVERTEX v1, v2, v3;
|
|
v1.pos = vertex1;
|
|
v1.diffuse = diffuse;
|
|
|
|
v2.pos = vertex2;
|
|
v2.diffuse = diffuse;
|
|
|
|
v3.pos = vertex3;
|
|
v3.diffuse = diffuse;
|
|
|
|
m_verts.push_back( v1 );
|
|
m_verts.push_back( v2 );
|
|
m_verts.push_back( v3 );
|
|
m_nCurCount++;
|
|
}
|
|
|
|
void KPlanUtilPrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum/* = true*/ )
|
|
{
|
|
if( 0 < m_verts.size() )
|
|
{
|
|
dev->SetTransform( K3DRenderDevice::TS_WORLD, &m_matTransform );
|
|
dev->SetMaterial( &m_Mtl );
|
|
dev->SetTexture( 0, NULL );
|
|
dev->DrawTriangles( m_nVtxFormat, &m_verts.front(), static_cast<int>(m_verts.size()), m_nVtxStride );
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KWireUtilPrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
KWireUtilPrimitive::KWireUtilPrimitive()
|
|
{
|
|
m_type = KPRIMITIVE_WIREUTIL;
|
|
m_nVtxFormat = K3DFVF_XYZ | K3DFVF_DIFFUSE;
|
|
m_nVtxStride = K3DVertexBuffer::CalcVertexStride( m_nVtxFormat );
|
|
K3DMatrixIdentity( m_matTransform );
|
|
m_Mtl.SetAmbient( K3DColor(1.f,1.f,1.f) );
|
|
m_Mtl.SetDiffuse( K3DColor(1.f,1.f,1.f) );
|
|
|
|
m_nCurCount = 0;
|
|
|
|
m_nDrawType = DRAW_LINE;
|
|
}
|
|
|
|
KWireUtilPrimitive::~KWireUtilPrimitive()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KWireUtilPrimitive::Clear()
|
|
{
|
|
m_nCurCount = 0;
|
|
int iSize = (int) m_verts.size();
|
|
m_verts.erase( m_verts.begin(), m_verts.end() );
|
|
}
|
|
|
|
void KWireUtilPrimitive::AddLine( const K3DVector &pos1, const K3DVector &pos2, const KColor &diffuse )
|
|
{
|
|
WIREVERTEX v1, v2;
|
|
v1.pos = pos1;
|
|
v1.diffuse = diffuse;
|
|
v2.pos = pos2;
|
|
v2.diffuse = diffuse;
|
|
m_verts.push_back( v1 );
|
|
m_verts.push_back( v2 );
|
|
m_nCurCount++;
|
|
}
|
|
|
|
void KWireUtilPrimitive::AddSphere( const K3DVector ¢er, float radius, const KColor& diffuse, int lineCount )
|
|
{
|
|
if( lineCount < 4 ) lineCount = 4;
|
|
float step = 2 * K3D_PI / lineCount;
|
|
|
|
K3DVector
|
|
begin_y( cosf( 0.0f ) * radius + center.x, center.y, sinf( 0.0f ) * radius + center.z ),
|
|
begin_z( cosf( 0.0f ) * radius + center.x, sinf( 0.0f ) * radius + center.y, center.z ),
|
|
begin_x( center.x, cosf( 0.0f ) * radius + center.y, sinf( 0.0f ) * radius + center.z );
|
|
K3DVector end;
|
|
|
|
for( int i = 1; i < lineCount + 1; ++i )
|
|
{
|
|
float current_radian = i * step;
|
|
float current_cos = cosf( current_radian ) * radius;
|
|
float current_sin = sinf( current_radian ) * radius;
|
|
|
|
end.x = current_cos + center.x;
|
|
end.y = center.y;
|
|
end.z = current_sin + center.z;
|
|
AddLine( begin_y, end, diffuse );
|
|
begin_y = end;
|
|
|
|
end.x = current_cos + center.x;
|
|
end.y = current_sin + center.y;
|
|
end.z = center.z;
|
|
AddLine( begin_z, end, diffuse );
|
|
begin_z = end;
|
|
|
|
end.x = center.x;
|
|
end.y = current_cos + center.y;
|
|
end.z = current_sin + center.z;
|
|
AddLine( begin_x, end, diffuse );
|
|
begin_x = end;
|
|
}
|
|
}
|
|
|
|
void KWireUtilPrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if( 0 < m_verts.size() )
|
|
{
|
|
dev->SetTransform( K3DRenderDevice::TS_WORLD, &m_matTransform );
|
|
dev->SetMaterial( &m_Mtl );
|
|
dev->SetTexture( 0, NULL );
|
|
dev->DrawLines( m_nVtxFormat, &m_verts.front(), static_cast<int>(m_verts.size()), m_nVtxStride );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//=======================================================================
|
|
// Morphing용
|
|
//=======================================================================
|
|
|
|
MorphedPrimitive::MorphedPrimitive() : KMeshPrimitive()
|
|
{
|
|
indexBuffer=NULL;
|
|
vertexBuffer=NULL;
|
|
polygonCount=0;
|
|
Additive = 0;
|
|
m_bIsValidMinMax = false;
|
|
m_vMin = K3DVertex( 100.f, 100.f, 100.f);
|
|
m_vMax = K3DVertex(-100.f,-100.f,-100.f);
|
|
m_bEnableFlag = true;
|
|
}
|
|
|
|
MorphedPrimitive::~MorphedPrimitive()
|
|
{
|
|
close();
|
|
}
|
|
|
|
void MorphedPrimitive::init(KMeshPrimitive *source)
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
// Make buffers
|
|
initMesh(source);
|
|
|
|
// Original init routine starts here
|
|
if (indexBuffer==NULL || vertexBuffer==NULL) return;
|
|
|
|
// WORKAROUND : to prevent 'smartptr burst' on deleting m_spIB / m_spVB
|
|
indexBuffer->AddRef();
|
|
vertexBuffer->AddRef();
|
|
|
|
// Notify mesh informations to parent
|
|
SetIndexBuffer(indexBuffer); // set m_spIB
|
|
SetVertexBuffer(vertexBuffer); // set m_spVB
|
|
SetPrimitivesCount(polygonCount);
|
|
|
|
// Init basic members
|
|
K3DMaterial *tempMaterial=new K3DMaterial;
|
|
tempMaterial->Power=1.0f;
|
|
SetMaterial(tempMaterial);
|
|
|
|
// m_pTransform=new K3DMatrix;
|
|
// K3DMatrixIdentity(m_pTransform);
|
|
|
|
K3DMatrix *tempMatrix=new K3DMatrix;
|
|
K3DMatrixIdentity(*tempMatrix);
|
|
SetUVTransform(tempMatrix);
|
|
|
|
m_vCenterPosition.x=0.f;
|
|
m_vCenterPosition.y=0.f;
|
|
m_vCenterPosition.z=0.f;
|
|
|
|
// Set texture
|
|
SetTexture(&texpack);
|
|
|
|
// Set bone blending info
|
|
SetBlendedInfo(source->getBoneCount(), source->getOffsetMatrix(), source->getBoneMatrix());
|
|
SetWeight(source->GetWeight());
|
|
SetVSMode( true ); // <- 의미 있는건지?
|
|
|
|
// Set basic rendering parameters
|
|
|
|
if( Additive == 0 )
|
|
{
|
|
if (getBoneCount()==0) {
|
|
// No bone
|
|
SetBlendMode(K3DMaterial::MBM_ALPHATEX_EDGEENHANCE); // 렌더링 모드 : edge-enhance / no-blend
|
|
} else {
|
|
// use mesh blending
|
|
SetBlendMode(K3DMaterial::MBM_ALPHATEX_EDGEENHANCE_BLEND); // 렌더링 모드 : edge-enhance / mesh-blend
|
|
}
|
|
}
|
|
else if( Additive == 1 )
|
|
{
|
|
if (getBoneCount()==0) {
|
|
// No bone
|
|
SetBlendMode(K3DMaterial::MBM_ALPHATEX_EDGEENHANCE_ADD); // 렌더링 모드 : edge-enhance / no-blend
|
|
} else {
|
|
// use mesh blending
|
|
SetBlendMode(K3DMaterial::MBM_ALPHATEX_EDGEENHANCE_BLEND_ADD); // 렌더링 모드 : edge-enhance / mesh-blend
|
|
}
|
|
}
|
|
|
|
SetTransparent(true); // Add to Transparent primitive queue
|
|
SetVisibility(1.0f); // Master alpha value
|
|
}
|
|
|
|
void MorphedPrimitive::close()
|
|
{
|
|
// clear buffers
|
|
SetIndexBuffer(NULL);
|
|
SetVertexBuffer(NULL);
|
|
SetPrimitivesCount(0);
|
|
|
|
if (indexBuffer!=NULL) { // SAFE_RELEASE(indexBuffer);
|
|
indexBuffer->Release(); // Release() will delete SELF
|
|
indexBuffer=NULL;
|
|
}
|
|
|
|
if (vertexBuffer!=NULL) {
|
|
vertexBuffer->Release();
|
|
vertexBuffer=NULL;
|
|
}
|
|
|
|
polygonCount=0;
|
|
|
|
K3DMatrix *tempMatrix=GetUVTransform();
|
|
SetUVTransform(NULL);
|
|
SAFE_DELETE(tempMatrix);
|
|
|
|
// SAFE_DELETE(m_pTransform);
|
|
|
|
K3DMaterial *tempMaterial=GetMaterial();
|
|
SetMaterial(NULL);
|
|
SAFE_DELETE(tempMaterial);
|
|
|
|
// Delete textures
|
|
texpack.spTexture=NULL;
|
|
}
|
|
|
|
void MorphedPrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
KMeshPrimitive::Render(viewport, dev, bUseAccum);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------
|
|
//
|
|
//
|
|
|
|
|
|
|
|
|
|
struct SkinMeshVertex { // 라펠즈의 버텍스 포맷
|
|
K3DVertex pos;
|
|
K3DVertex normal;
|
|
DWORD color;
|
|
float u, v;
|
|
float t0, t1, t2, t3; // tangents
|
|
DWORD blendIndices;
|
|
float blendWeight0, blendWeight1;
|
|
};
|
|
|
|
|
|
void MorphedPrimitive::copyMesh(KMeshPrimitive *source)
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
close();
|
|
if (source==NULL) return;
|
|
|
|
|
|
int idxCount, vtxCount, polyCount;
|
|
K3DVertexBuffer *srcVertex=source->GetVertexBuffer();
|
|
K3DIndexBuffer *srcIndex=source->GetIndexBuffer();
|
|
|
|
if (srcIndex==NULL || srcVertex==NULL)
|
|
return;
|
|
|
|
// Check vertex format
|
|
//DWORD vtxFormat=srcVertex->GetVertexFormat();
|
|
//if (vtxFormat !=...) return;
|
|
|
|
idxCount=srcIndex->GetIndexCount();
|
|
vtxCount=srcVertex->GetVertexCount();
|
|
polyCount=source->GetPrimitivesCount();
|
|
|
|
assert(idxCount == polyCount*3); // Triangle set
|
|
|
|
try {
|
|
void *p, *pSrc;
|
|
int size=0, srcSize=0;
|
|
int i;
|
|
|
|
// Copy indexes
|
|
indexBuffer=new KIndexBufferDX_dynamic();
|
|
if (indexBuffer!=NULL) {
|
|
if (!indexBuffer->create(idxCount * sizeof(WORD), D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT)) {
|
|
// index buffer creation failed
|
|
throw 0;
|
|
}
|
|
}
|
|
indexBuffer->setIndexCount(idxCount);
|
|
indexBuffer->Lock(&p, size);
|
|
srcIndex->Lock(&pSrc, srcSize); //, D3DLOCK_READONLY);
|
|
if (p!=NULL && pSrc!=NULL) {
|
|
/* // Sanity check
|
|
WORD *pd=(WORD *)p;
|
|
WORD *ps=(WORD *)pSrc;
|
|
for (i=0; i<idxCount; i++) {
|
|
assert(*ps < (WORD)vtxCount);
|
|
*(pd++)=*(ps++);
|
|
}
|
|
*/ memcpy(p, pSrc, sizeof(WORD)*idxCount);
|
|
}
|
|
if (p!=NULL) indexBuffer->Unlock();
|
|
if (pSrc!=NULL) srcIndex->Unlock();
|
|
|
|
// Copy vertexes
|
|
vertexBuffer=new KVertexBufferDX_dynamic();
|
|
if (vertexBuffer!=NULL) {
|
|
// (UINT length, DWORD usage, DWORD FVF, D3DPOOL pool)
|
|
if (!vertexBuffer->create(sizeof(DynamicVertex) * vtxCount, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, DynamicVertex::FVF, D3DPOOL_DEFAULT)) {
|
|
throw 0;
|
|
}
|
|
}
|
|
vertexBuffer->setVertexCount(vtxCount);
|
|
vertexBuffer->Lock(&p, size, D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
srcVertex->Lock(&pSrc, srcSize); // , D3DLOCK_READONLY);
|
|
if (p!=NULL && pSrc!=NULL) {
|
|
|
|
KVertexBufferDX_dynamic *pd=dynamic_cast<KVertexBufferDX_dynamic *>(srcVertex);
|
|
if (pd==NULL) { // Normal skinmesh vertex
|
|
// Build dynamic vertex parameters
|
|
SkinMeshVertex *skinMeshVertex=(SkinMeshVertex *) pSrc;
|
|
DynamicVertex *dynamicVertex=(DynamicVertex *) p;
|
|
|
|
for (i=0; i<vtxCount; i++) {
|
|
dynamicVertex->pos = skinMeshVertex->pos;
|
|
|
|
dynamicVertex->normal = skinMeshVertex->normal;
|
|
|
|
dynamicVertex->color0 = skinMeshVertex->color;
|
|
dynamicVertex->color1 = 0x00;
|
|
|
|
dynamicVertex->u0 = skinMeshVertex->u;
|
|
dynamicVertex->v0 = skinMeshVertex->v;
|
|
|
|
dynamicVertex->blendIndices = skinMeshVertex->blendIndices;
|
|
dynamicVertex->blendWeight0 = skinMeshVertex->blendWeight0;
|
|
dynamicVertex->blendWeight1 = skinMeshVertex->blendWeight1;
|
|
dynamicVertex->blendWeight2 = 0.0f;
|
|
|
|
dynamicVertex++;
|
|
skinMeshVertex++;
|
|
}
|
|
} else { // Dynamicvertex
|
|
// copy dynamic vertex parameters
|
|
DynamicVertex *dynamicVertexSrc=(DynamicVertex *) pSrc;
|
|
DynamicVertex *dynamicVertex=(DynamicVertex *) p;
|
|
|
|
for (i=0; i<vtxCount; i++) {
|
|
*(dynamicVertex++) = *(dynamicVertexSrc++);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (p!=NULL) vertexBuffer->Unlock();
|
|
if (pSrc!=NULL) srcVertex->Unlock();
|
|
|
|
// Set primitive count
|
|
polygonCount=polyCount;
|
|
|
|
} catch (int) {
|
|
close();
|
|
}
|
|
}
|
|
|
|
|
|
void MorphedPrimitive::calculateVertexNormals()
|
|
// 각 vertex의 normal을 다시 계산
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
if (indexBuffer==NULL || vertexBuffer==NULL) return;
|
|
|
|
DynamicVertex *vertex=NULL;
|
|
WORD *index=NULL;
|
|
int indexCount, vertexCount;
|
|
DynamicVertex *node[3];
|
|
int n=0;
|
|
int i,j;
|
|
|
|
K3DVertex s, t;
|
|
K3DVertex norm;
|
|
|
|
while( true )
|
|
{
|
|
vertexBuffer->Lock((void **)&vertex, n, D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
if (vertex==NULL) break;
|
|
|
|
indexBuffer->Lock((void **)&index, n);
|
|
if (index==NULL) break;
|
|
|
|
// Clear vertex normals
|
|
vertexCount=vertexBuffer->GetVertexCount();
|
|
indexCount=indexBuffer->GetIndexCount();
|
|
for (i=0; i<vertexCount; i++) {
|
|
vertex[i].normal.x=vertex[i].normal.y=vertex[i].normal.z=0.f;
|
|
}
|
|
|
|
// Sum face normals
|
|
for (i=0; i<polygonCount; i++) {
|
|
// Get polygon nodes
|
|
node[0]=vertex+index[i*3];
|
|
node[1]=vertex+index[i*3+1];
|
|
node[2]=vertex+index[i*3+2];
|
|
|
|
// Calc normal
|
|
s = node[1]->pos - node[0]->pos;
|
|
t = node[2]->pos - node[1]->pos;
|
|
norm=CrossProduct(t, s);
|
|
|
|
// Sum normals of each nodes
|
|
node[0]->normal+=norm;
|
|
node[1]->normal+=norm;
|
|
node[2]->normal+=norm;
|
|
}
|
|
|
|
// Join overlapped vertexes
|
|
// Note : 이게 없으면, 시각적으로 붙어있으나 topology적으로 edge를 공유하지 않는 폴리곤은 edge가 분리된다 i.e. '찢어진다' T_T
|
|
// O(n^2)므로 별로 안 효율적. 나중에 바꾸든 말든
|
|
K3DVector v;
|
|
for (i=0; i<vertexCount; i++) {
|
|
for (j=i+1; j<vertexCount; j++) {
|
|
if (vertex[i].pos == vertex[j].pos) { // Change to sigma-delta comparison? if (ABS(vertex[i].pos-vertex[j].pos) < DELTA) {...
|
|
v = vertex[i].normal+vertex[j].normal;
|
|
vertex[i].normal=v;
|
|
vertex[j].normal=v;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Normalize normals
|
|
for (i=0; i<vertexCount; i++) {
|
|
Normalize(vertex[i].normal);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (vertex!=NULL) vertexBuffer->Unlock();
|
|
if (index!=NULL) indexBuffer->Unlock();
|
|
}
|
|
|
|
|
|
void MorphedPrimitive::offsetVertexPosition(float offset)
|
|
// Move vertex position along vertex normal
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
DynamicVertex *vertex=NULL;
|
|
int i, n=0;
|
|
|
|
try {
|
|
vertexBuffer->Lock((void **)&vertex, n, D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
if (vertex==NULL) throw 0;
|
|
|
|
DynamicVertex *p=vertex;
|
|
n=vertexBuffer->GetVertexCount();
|
|
for (i=0; i<n; i++, p++) {
|
|
p->pos.x += p->normal.x * offset;
|
|
p->pos.y += p->normal.y * offset;
|
|
p->pos.z += p->normal.z * offset;
|
|
}
|
|
} catch (int) {
|
|
// empty
|
|
}
|
|
if (vertex!=NULL) vertexBuffer->Unlock();
|
|
}
|
|
|
|
//#define _NEW_MORPH_
|
|
|
|
void MorphedPrimitive::setVertexColors(DWORD color0, DWORD color1) // 모든 vertex에 대해 색깔 변환
|
|
// Set vertex colors
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
DynamicVertex *vertex=NULL;
|
|
int i, n=0;
|
|
|
|
try {
|
|
vertexBuffer->Lock((void **)&vertex, n, D3DLOCK_NOSYSLOCK /*| D3DLOCK_DISCARD*/);
|
|
if (vertex==NULL) throw 0;
|
|
|
|
#ifdef _NEW_MORPH_
|
|
if( m_bIsValidMinMax == false )
|
|
{
|
|
DynamicVertex *p=vertex;
|
|
n=vertexBuffer->GetVertexCount();
|
|
float fMax = -100.f;
|
|
float fMin = 100.f;
|
|
float fLength = 0.f;
|
|
for (i=0; i<n; i++, p++)
|
|
{
|
|
fLength = K3DVectorLength( p->pos );
|
|
|
|
if( fLength < fMin )
|
|
{
|
|
fMin = fLength;
|
|
m_vMin = p->pos;
|
|
}
|
|
|
|
if( fLength > fMax )
|
|
{
|
|
fMax = fLength;
|
|
m_vMax = p->pos;
|
|
}
|
|
}
|
|
|
|
m_bIsValidMinMax = true;
|
|
}
|
|
|
|
float fMaxLength = K3DVectorLength( m_vMax - m_vMin );
|
|
float fRatio = 1.f;
|
|
|
|
DynamicVertex *p=vertex;
|
|
n=vertexBuffer->GetVertexCount();
|
|
K3DColor out;
|
|
KColor color;
|
|
for (i=0; i<n; i++, p++)
|
|
{
|
|
fRatio = (float)K3DVectorLength( p->pos - m_vMin )/fMaxLength;
|
|
// _oprint( "Color Ratio : %f\n", fRatio );
|
|
|
|
K3DColorLerp( out, K3DColor(color0), K3DColor(color1), fRatio );
|
|
|
|
p->color0=((KColor)out).color;
|
|
p->color1=((KColor)out).color;
|
|
}
|
|
#else
|
|
DynamicVertex *p=vertex;
|
|
n=vertexBuffer->GetVertexCount();
|
|
for (i=0; i<n; i++, p++) {
|
|
p->color0=color0;
|
|
p->color1=color1;
|
|
}
|
|
#endif
|
|
|
|
} catch (int) {
|
|
// empty
|
|
}
|
|
if (vertex!=NULL) vertexBuffer->Unlock();
|
|
}
|
|
|
|
|
|
/*
|
|
// TEMPLATE
|
|
void MorphedPrimitive::for_each_vertex()
|
|
{
|
|
DynamicVertex *vertex=NULL;
|
|
int i, n=0;
|
|
|
|
try {
|
|
vertexBuffer->Lock((void **)&vertex, n);
|
|
if (vertex==NULL) throw 0;
|
|
|
|
DynamicVertex *p=vertex;
|
|
n=vertexBuffer->GetVertexCount();
|
|
for (i=0; i<n; i++, p++) {
|
|
// vertex 건드리는 코드 여기에 넣을 것
|
|
// p->......
|
|
}
|
|
} catch (int) {
|
|
// empty
|
|
}
|
|
if (vertex!=NULL) vertexBuffer->Unlock();
|
|
}
|
|
*/
|
|
|
|
|
|
void MorphedPrimitive::initMesh(KMeshPrimitive *source) // called by init(), to initialize mesh
|
|
{
|
|
if( !m_bEnableFlag ) return;
|
|
|
|
copyMesh(source);
|
|
|
|
//
|
|
// Initialization example
|
|
//
|
|
//if (indexBuffer==NULL || vertexBuffer==NULL) return; // validity check
|
|
//calculateVertexNormals(); // Disable하고 polygon의 내부 normal사용해도 됨 (다행히도 제대로 들어 있는 듯...?)
|
|
//texpack.spTexture=MorphedPrimitive::getTexture("zone005_stone003.dds"); // 텍스처 설정
|
|
//offsetVertexPosition(0.3f); // 약간 확장
|
|
//setVertexColors(0x40ffffff, 0x20c08080); // 버텍스 컬러 주기
|
|
//
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================
|
|
// FxResizedPrimitive
|
|
//=============================================================
|
|
|
|
FxResizedPrimitive::FxResizedPrimitive()
|
|
{
|
|
offset=0;
|
|
color0=color1=0x00000000;
|
|
texName=NULL;
|
|
}
|
|
|
|
void FxResizedPrimitive::init(KMeshPrimitive *source, float _offset, DWORD _color0, DWORD _color1, const char *_textureName, int nAdditive)
|
|
{
|
|
offset=_offset;
|
|
color0=_color0;
|
|
color1=_color1;
|
|
texName=_textureName;
|
|
Additive = nAdditive;
|
|
|
|
MorphedPrimitive::init(source);
|
|
}
|
|
|
|
void FxResizedPrimitive::initMesh(KMeshPrimitive *source) // called by init(), to initialize mesh
|
|
{
|
|
copyMesh(source);
|
|
|
|
if (indexBuffer==NULL || vertexBuffer==NULL) return;
|
|
|
|
offsetVertexPosition(offset);
|
|
setVertexColors(color0, color1);
|
|
if (texName!=NULL) {
|
|
texpack.spTexture=KMeshPrimitive::getTexture(texName);
|
|
}
|
|
} |