Files
Leviathan/Client/Game/engine/Renderer/KPrimitiveMesh.cpp
T
2026-06-01 12:46:52 +02:00

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 &center, 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);
}
}