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

644 lines
13 KiB
C++

#include "stdafx.h"
#include "KPrimitivePathEffect.h"
#include "KRenderDeviceDX.h"
// KLinePrimitive
KLinePrimitive::KLinePrimitive()
{
m_numVerts = 0;
m_pVerts = NULL;
//m_bDrawPr = false;
// m_bDrawPr = true;
}
KLinePrimitive::~KLinePrimitive()
{
Clear();
}
void KLinePrimitive::Clear()
{
SAFE_DELETE_ARRAY(m_pVerts);
m_numVerts = 0;
}
void KLinePrimitive::Update(PfxPrVertex* pVerts, int numVerts)
{
Clear();
if(!pVerts || numVerts < 2) return;
m_pVerts = new PfxPrVertex[numVerts];
if(!m_pVerts)
{
m_numVerts = 0;
return;
}
memcpy(m_pVerts, pVerts, sizeof(PfxPrVertex) * numVerts);
m_numVerts = numVerts;
}
void KLinePrimitive::Render( KViewportObject *viewport, K3DRenderDevice *dev, bool bUseAccum )
{
if(!m_pVerts || !m_numVerts) return;
//dev->SetTransformIdentity(K3DRenderDevice::TS_WORLD);
//dev->SetVertexShaderDefault();
//if(m_bDrawPr)
//{
// dev->DrawLineStrip(D3DFVF_XYZ | D3DFVF_DIFFUSE, m_pVerts, m_numVerts, sizeof(SVertex));
//}
dev->DrawLineStrip(D3DFVF_XYZ | D3DFVF_DIFFUSE, m_pVerts, m_numVerts, sizeof(PfxPrVertex));
}
// Path를 그릴 것인가..
//void KLinePrimitive::SetPrDrawMode(bool bDrawPr)
//{
// m_bDrawPr = bDrawPr;
//}
// KQuadPrimitive
KQuadPrimitive::KQuadPrimitive()
{
m_numVerts = 0;
m_pVerts = NULL;
//m_fRadius = 1.0f; // 나중에 에디터에서 설정할 수 있게 하자
m_fSize = 1.0f;
}
KQuadPrimitive::~KQuadPrimitive()
{
Clear();
}
void KQuadPrimitive::SetSize(float fSize)
{
//m_fRadius = fRadius;
m_fSize = fSize;
}
void KQuadPrimitive::Clear()
{
SAFE_DELETE_ARRAY(m_pVerts);
m_numVerts = 0;
}
void KQuadPrimitive::Update(PfxPrVertex* pVerts, int numVerts)
{
Clear();
if(!pVerts || !numVerts) return;
m_pVerts = new PfxPrVertex[numVerts];
if(!m_pVerts)
{
m_numVerts = 0;
return;
}
memcpy(m_pVerts, pVerts, sizeof(PfxPrVertex) * numVerts);
m_numVerts = numVerts;
}
// 졸라 느림.. 에디터에서만 쓰자
void KQuadPrimitive::Render( KViewportObject *viewport, K3DRenderDevice *dev, bool bUseAccum )
{
if(!m_pVerts || !m_numVerts) return;
float x1, x2, y1, y2, z;
DWORD c;
PfxPrVertex v[4];
for(int i = 0; i < m_numVerts; i++)
{
x1 = m_pVerts[i].pos.x - m_fSize;
x2 = m_pVerts[i].pos.x + m_fSize;
y1 = m_pVerts[i].pos.y - m_fSize;
y2 = m_pVerts[i].pos.y + m_fSize;
z = m_pVerts[i].pos.z;
c = m_pVerts[i].color;
v[0].pos.x = x1;
v[0].pos.y = y1;
v[0].pos.z = z;
v[0].color = c;
v[1].pos.x = x1;
v[1].pos.y = y2;
v[1].pos.z = z;
v[1].color = c;
v[2].pos.x = x2;
v[2].pos.y = y2;
v[2].pos.z = z;
v[2].color = c;
v[3].pos.x = x2;
v[3].pos.y = y1;
v[3].pos.z = z;
v[3].color = c;
dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE, v, 4, sizeof(PfxPrVertex));
}
}
// KPolyLinePrimitive
KPolyLinePrimitive::KPolyLinePrimitive()
{
m_pPrVerts = NULL;
//m_numVerts = 0;
for(int i = 0; i < 4; i++)
{
m_FirstPrVerts[i].pos.x = 0.0f;
m_FirstPrVerts[i].pos.y = 0.0f;
m_FirstPrVerts[i].pos.z = 0.0f;
m_FirstPrVerts[i].color = 0;
m_LastPrVerts[i].pos.x = 0.0f;
m_LastPrVerts[i].pos.y = 0.0f;
m_LastPrVerts[i].pos.z = 0.0f;
m_LastPrVerts[i].color = 0;
}
m_fWidth = 0.0f;
m_bOverrideFirstPrVerts = FALSE;
m_bOverrideLastPrVerts = FALSE;
m_dwColor = 0;
m_nFirstDrawQuad = 0;
m_nLastDrawQuad = 0;
m_fTotalPathLength = 0.0f;
}
KPolyLinePrimitive::~KPolyLinePrimitive()
{
Clear();
}
void KPolyLinePrimitive::Clear()
{
m_vPathVerts.erase(m_vPathVerts.begin(), m_vPathVerts.end());
m_vPathNormals.erase(m_vPathNormals.begin(), m_vPathNormals.end());
SAFE_DELETE_ARRAY(m_pPrVerts);
m_bOverrideFirstPrVerts = FALSE;
m_bOverrideLastPrVerts = FALSE;
m_nFirstDrawQuad = 0;
m_nLastDrawQuad = 0;
m_fTotalPathLength = 0.0f;
}
void KPolyLinePrimitive::AddPathVert(K3DVector vPos)
{
PfxPathVertex pathVert;
pathVert.vPos = vPos;
int numVerts = m_vPathVerts.size();
if(numVerts >= 1)
{
K3DVector v = vPos - m_vPathVerts[numVerts - 1].vPos;
m_fTotalPathLength += v.Magnitude();
}
pathVert.fLength = m_fTotalPathLength;
m_vPathVerts.push_back(pathVert);
}
void KPolyLinePrimitive::AddPathNormal(K3DVector vNormal)
{
m_vPathNormals.push_back(vNormal);
}
// _KSeqPathEffect가 Update() 할 때 한번만 호출
void KPolyLinePrimitive::Update()
{
//Clear();
int numPathVerts = m_vPathVerts.size();
if(numPathVerts < 2 || numPathVerts != m_vPathNormals.size())
{
//assert(0);
Clear();
return;
}
int numPrVerts = (numPathVerts - 1) * 4;
m_pPrVerts = new PfxPlPrVertex[numPrVerts];
if(!m_pPrVerts)
{
Clear();
return;
}
K3DVector vTan, vBiNorm, vNorm, v1, v2, v3, v4;
for(int i = 0; i < numPathVerts - 1; i++)
{
if(i == 0)
{
vBiNorm = m_vPathVerts[1].vPos - m_vPathVerts[0].vPos;
}
else
{
vBiNorm = m_vPathVerts[i + 1].vPos - m_vPathVerts[i - 1].vPos;
}
Normalize(vBiNorm);
vNorm = m_vPathNormals[i];
Normalize(vNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v1 = m_vPathVerts[i].vPos - vTan;
v4 = m_vPathVerts[i].vPos + vTan;
if(i == numPathVerts - 2)
{
vBiNorm = m_vPathVerts[numPathVerts - 1].vPos - m_vPathVerts[numPathVerts - 2].vPos;
}
else
{
vBiNorm = m_vPathVerts[i + 2].vPos - m_vPathVerts[i].vPos;
}
Normalize(vBiNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v2 = m_vPathVerts[i + 1].vPos - vTan;
v3 = m_vPathVerts[i + 1].vPos + vTan;
m_pPrVerts[i * 4 + 0].pos = *((D3DXVECTOR3*) &v1);
m_pPrVerts[i * 4 + 1].pos = *((D3DXVECTOR3*) &v2);
m_pPrVerts[i * 4 + 2].pos = *((D3DXVECTOR3*) &v3);
m_pPrVerts[i * 4 + 3].pos = *((D3DXVECTOR3*) &v4);
m_pPrVerts[i * 4 + 0].color = m_dwColor;
m_pPrVerts[i * 4 + 1].color = m_dwColor;
m_pPrVerts[i * 4 + 2].color = m_dwColor;
m_pPrVerts[i * 4 + 3].color = m_dwColor;
}
m_nFirstDrawQuad = 0;
m_nLastDrawQuad = numPathVerts - 2;
}
void KPolyLinePrimitive::UpdateUV(float fStart, float fEnd)
{
float fU1, fU2, fV1, fV2;
fV1 = 0.0f;
fV2 = 1.0f;
for(int i = m_nFirstDrawQuad; i <= m_nLastDrawQuad; i++)
{
fU1 = ((m_vPathVerts[i].fLength / m_fTotalPathLength) - fStart) / (fEnd - fStart);
fU2 = ((m_vPathVerts[i + 1].fLength / m_fTotalPathLength) - fStart) / (fEnd - fStart);
m_pPrVerts[i * 4 + 0].u = fU1;
m_pPrVerts[i * 4 + 0].v = fV1;
m_pPrVerts[i * 4 + 1].u = fU2;
m_pPrVerts[i * 4 + 1].v = fV1;
m_pPrVerts[i * 4 + 2].u = fU2;
m_pPrVerts[i * 4 + 2].v = fV2;
m_pPrVerts[i * 4 + 3].u = fU1;
m_pPrVerts[i * 4 + 3].v = fV2;
}
}
// _KSeqPathEffect가 Render() 할 때마다 매번 호출
void KPolyLinePrimitive::Update(float fStart, float fEnd)
{
int numPathVerts = m_vPathVerts.size();
if(numPathVerts < 2 || numPathVerts != m_vPathNormals.size()) return;
if(!m_pPrVerts) return;
if(fStart < 0.0f) fStart = 0.0f;
if(fStart > 1.0f) fStart = 1.0f;
if(fEnd < 0.0f) fEnd = 0.0f;
if(fEnd > 1.0f) fEnd = 1.0f;
if(fStart == fEnd) return;
if(fStart > fEnd)
{
float fTemp = fStart;
fStart = fEnd;
fEnd = fTemp;
}
K3DVector vTemp;
K3DVertex vStart, vEnd;
int nStart = GetPathVert(fStart, vStart);
vTemp = vStart - m_vPathVerts[nStart].vPos;
if(vTemp.Magnitude() < 0.1f)
{
m_bOverrideFirstPrVerts = FALSE;
m_nFirstDrawQuad = nStart;
}
else
{
m_bOverrideFirstPrVerts = TRUE;
m_nFirstDrawQuad = nStart + 1;
}
int nEnd = GetPathVert(fEnd, vEnd);
vTemp = vEnd - m_vPathVerts[nEnd].vPos;
if(vTemp.Magnitude() < 0.1f)
{
m_bOverrideLastPrVerts = FALSE;
m_nLastDrawQuad = nEnd - 1;
}
else
{
m_bOverrideLastPrVerts = TRUE;
m_nLastDrawQuad = nEnd - 1;
}
K3DVector vTan, vBiNorm, vNorm, v1, v2, v3, v4;
if(nStart == nEnd) // 예외처리
{
vBiNorm = m_vPathVerts[nStart + 1].vPos - m_vPathVerts[nStart].vPos;
Normalize(vBiNorm);
vNorm = m_vPathNormals[nStart];
Normalize(vNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v1 = vStart - vTan;
v4 = vStart + vTan;
//vBiNorm = m_vPathVerts[nEnd + 1].vPos - m_vPathVerts[nEnd].vPos;
//Normalize(vBiNorm);
//vTan = CrossProduct(vBiNorm, vNorm);
//vTan *= m_fWidth;
v2 = vEnd - vTan;
v3 = vEnd + vTan;
m_FirstPrVerts[0].pos = *((D3DXVECTOR3*) &v1);
m_FirstPrVerts[1].pos = *((D3DXVECTOR3*) &v2);
m_FirstPrVerts[2].pos = *((D3DXVECTOR3*) &v3);
m_FirstPrVerts[3].pos = *((D3DXVECTOR3*) &v4);
m_FirstPrVerts[0].color = m_dwColor;
m_FirstPrVerts[1].color = m_dwColor;
m_FirstPrVerts[2].color = m_dwColor;
m_FirstPrVerts[3].color = m_dwColor;
float fU1, fU2, fV1, fV2;
fV1 = 0.0f;
fV2 = 1.0f;
//fU1 = fStart;
//fU2 = fEnd;
fU1 = 0.0f;
fU2 = 1.0f;
m_FirstPrVerts[0].u = fU1;
m_FirstPrVerts[0].v = fV1;
m_FirstPrVerts[1].u = fU2;
m_FirstPrVerts[1].v = fV1;
m_FirstPrVerts[2].u = fU2;
m_FirstPrVerts[2].v = fV2;
m_FirstPrVerts[3].u = fU1;
m_FirstPrVerts[3].v = fV2;
m_bOverrideFirstPrVerts = TRUE;
m_bOverrideLastPrVerts = FALSE;
return;
}
if(m_bOverrideFirstPrVerts)
{
vBiNorm = m_vPathVerts[nStart + 1].vPos - m_vPathVerts[nStart].vPos;
Normalize(vBiNorm);
vNorm = m_vPathNormals[nStart];
Normalize(vNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v1 = vStart - vTan;
v4 = vStart + vTan;
if(nStart == numPathVerts - 2)
{
vBiNorm = m_vPathVerts[numPathVerts - 1].vPos - m_vPathVerts[numPathVerts - 2].vPos;
}
else
{
vBiNorm = m_vPathVerts[nStart + 2].vPos - m_vPathVerts[nStart].vPos;
}
Normalize(vBiNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v2 = m_vPathVerts[nStart + 1].vPos - vTan;
v3 = m_vPathVerts[nStart + 1].vPos + vTan;
m_FirstPrVerts[0].pos = *((D3DXVECTOR3*) &v1);
m_FirstPrVerts[1].pos = *((D3DXVECTOR3*) &v2);
m_FirstPrVerts[2].pos = *((D3DXVECTOR3*) &v3);
m_FirstPrVerts[3].pos = *((D3DXVECTOR3*) &v4);
m_FirstPrVerts[0].color = m_dwColor;
m_FirstPrVerts[1].color = m_dwColor;
m_FirstPrVerts[2].color = m_dwColor;
m_FirstPrVerts[3].color = m_dwColor;
float fU1, fU2, fV1, fV2;
fV1 = 0.0f;
fV2 = 1.0f;
//fU1 = fStart;
fU1 = 0.0f;
fU2 = ((m_vPathVerts[nStart + 1].fLength / m_fTotalPathLength) - fStart) / (fEnd - fStart);
m_FirstPrVerts[0].u = fU1;
m_FirstPrVerts[0].v = fV1;
m_FirstPrVerts[1].u = fU2;
m_FirstPrVerts[1].v = fV1;
m_FirstPrVerts[2].u = fU2;
m_FirstPrVerts[2].v = fV2;
m_FirstPrVerts[3].u = fU1;
m_FirstPrVerts[3].v = fV2;
}
if(m_bOverrideLastPrVerts)
{
if(nEnd == 0) // 위에서 예외처리를 하므로 이 코드에 도달하지 않는다.
{
//vBiNorm = m_vPathVerts[1].vPos - m_vPathVerts[0].vPos;
assert(0);
}
else // nEnd = numPathVerts - 1 은 fEnd가 1.0f일 때에만 성립하므로 nEnd + 1이 참조에러를 내지 않는다. (fEnd == 1.0f 일때 m_bOverrideLastPrVerts == FALSE 이므로)
{
vBiNorm = m_vPathVerts[nEnd + 1].vPos - m_vPathVerts[nEnd - 1].vPos;
}
Normalize(vBiNorm);
vNorm = m_vPathNormals[nEnd];
Normalize(vNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v1 = m_vPathVerts[nEnd].vPos - vTan;
v4 = m_vPathVerts[nEnd].vPos + vTan;
vBiNorm = m_vPathVerts[nEnd + 1].vPos - m_vPathVerts[nEnd].vPos;
Normalize(vBiNorm);
vTan = CrossProduct(vBiNorm, vNorm);
vTan *= m_fWidth;
v2 = vEnd - vTan;
v3 = vEnd + vTan;
m_LastPrVerts[0].pos = *((D3DXVECTOR3*) &v1);
m_LastPrVerts[1].pos = *((D3DXVECTOR3*) &v2);
m_LastPrVerts[2].pos = *((D3DXVECTOR3*) &v3);
m_LastPrVerts[3].pos = *((D3DXVECTOR3*) &v4);
m_LastPrVerts[0].color = m_dwColor;
m_LastPrVerts[1].color = m_dwColor;
m_LastPrVerts[2].color = m_dwColor;
m_LastPrVerts[3].color = m_dwColor;
float fU1, fU2, fV1, fV2;
fV1 = 0.0f;
fV2 = 1.0f;
fU1 = ((m_vPathVerts[nEnd].fLength / m_fTotalPathLength) - fStart) / (fEnd - fStart);
//fU2 = fEnd;
fU2 = 1.0f;
m_LastPrVerts[0].u = fU1;
m_LastPrVerts[0].v = fV1;
m_LastPrVerts[1].u = fU2;
m_LastPrVerts[1].v = fV1;
m_LastPrVerts[2].u = fU2;
m_LastPrVerts[2].v = fV2;
m_LastPrVerts[3].u = fU1;
m_LastPrVerts[3].v = fV2;
}
UpdateUV(fStart, fEnd);
}
int KPolyLinePrimitive::GetPathVert(float fPos, K3DVertex& vRes)
{
if(fPos < 0.0f || fPos > 1.0f) return -1; // 에러
int n;
int numPathVerts = m_vPathVerts.size();
if(fPos == 1.0f) // 예외 처리
{
vRes = m_vPathVerts[numPathVerts - 1].vPos;
return (numPathVerts - 1);
}
fPos *= m_fTotalPathLength; // 절대 좌표값으로 바꾼다.
for(n = 0; n < numPathVerts; n++)
{
if(m_vPathVerts[n].fLength > fPos) break;
}
--n;
float fraction = fPos - m_vPathVerts[n].fLength;
K3DVector vec = m_vPathVerts[n + 1].vPos - m_vPathVerts[n].vPos;
fraction /= vec.Magnitude();
vRes = m_vPathVerts[n].vPos + vec * fraction;
return n;
}
void KPolyLinePrimitive::Render(KViewportObject* viewport, class K3DRenderDevice* dev, bool bUseAccum)
{
int numPathVerts = m_vPathVerts.size();
if(numPathVerts < 2 || numPathVerts != m_vPathNormals.size()) return;
if(!m_pPrVerts) return;
dev->SetTexture(0, m_spTexture);
if(m_bOverrideFirstPrVerts)
{
dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, m_FirstPrVerts, 4, sizeof(PfxPlPrVertex));
}
for(int i = m_nFirstDrawQuad; i <= m_nLastDrawQuad; i++)
{
PfxPlPrVertex* v = &m_pPrVerts[i * 4];
dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, v, 4, sizeof(PfxPlPrVertex));
}
if(m_bOverrideLastPrVerts)
{
dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, m_LastPrVerts, 4, sizeof(PfxPlPrVertex));
}
}
void KPolyLinePrimitive::SetWidth(float fWidth)
{
m_fWidth = fWidth;
}
void KPolyLinePrimitive::SetColor(DWORD dwColor)
{
m_dwColor = dwColor;
}
void KPolyLinePrimitive::SetTexture(K3DTexture* pTexture)
{
m_spTexture = pTexture;
}