📄 polygridfx.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : PolyGridFX.cpp
//
// PURPOSE : PolyGrid special FX - Implementation
//
// CREATED : 10/13/97
//
// ----------------------------------------------------------------------- //
#include "PolyGridFX.h"
#include "Plasma.h"
#include "cpp_client_de.h"
#include "ClientServerShared.h"
#include "BloodClientShell.h"
static DFLOAT s_PolyGridYaw = 0.0f;
static DFLOAT s_PolyGridPitch = 0.0f;
static DFLOAT s_PolyGridRoll = 0.0f;
static char g_SinTable[256];
static DBOOL g_bSinTableInitted=DFALSE;
// ----------------------------------------------------------------------- //
//
// ROUTINE: CPolyGridFX::Init
//
// PURPOSE: Create the poly grid
//
// ----------------------------------------------------------------------- //
DBOOL CPolyGridFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
if (!psfxCreateStruct) return DFALSE;
CSpecialFX::Init(psfxCreateStruct);
PGCREATESTRUCT* pg = (PGCREATESTRUCT*)psfxCreateStruct;
VEC_COPY(m_vDims, pg->vDims);
VEC_COPY(m_vColor1, pg->vColor1);
VEC_COPY(m_vColor2, pg->vColor2);
m_fXScaleMin = pg->fXScaleMin;
m_fXScaleMax = pg->fXScaleMax;
m_fYScaleMin = pg->fYScaleMin;
m_fYScaleMax = pg->fYScaleMax;
m_fXScaleDuration = pg->fXScaleDuration;
m_fYScaleDuration = pg->fYScaleDuration;
m_fXPan = pg->fXPan;
m_fYPan = pg->fYPan;
m_hstrSurfaceSprite = pg->hstrSurfaceSprite;
m_dwNumPolies = pg->dwNumPolies;
m_fAlpha = pg->fAlpha;
m_nPlasmaType = pg->nPlasmaType;
m_nRingRate[0] = pg->nRingRate[0];
m_nRingRate[1] = pg->nRingRate[1];
m_nRingRate[2] = pg->nRingRate[2];
m_nRingRate[3] = pg->nRingRate[3];
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CPolyGridFX::CreateObject
//
// PURPOSE: Create object associated the poly grid
//
// ----------------------------------------------------------------------- //
DBOOL CPolyGridFX::CreateObject(CClientDE *pClientDE)
{
ColorRamp colorRamps[2];
colorRamps[0].m_Color.Init(m_vColor1.x, m_vColor1.y, m_vColor1.z);
colorRamps[0].m_Index = 0;
colorRamps[1].m_Color.Init(m_vColor2.x, m_vColor2.y, m_vColor2.z);
colorRamps[1].m_Index = 256;
if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE;
DVector vPos;
pClientDE->GetObjectPos(m_hServerObject, &vPos);
DRotation rRot;
pClientDE->GetObjectRotation(m_hServerObject, &rRot);
// Setup the PolyGrid...
ObjectCreateStruct createStruct;
INIT_OBJECTCREATESTRUCT(createStruct);
createStruct.m_ObjectType = OT_POLYGRID;
createStruct.m_Flags = FLAG_VISIBLE;
VEC_COPY(createStruct.m_Pos, vPos);
ROT_COPY(createStruct.m_Rotation, rRot);
DDWORD dwSize = 2;
if (m_dwNumPolies > 4)
{
dwSize = (DDWORD)sqrt((DFLOAT)(m_dwNumPolies/2)) + 1;
if (m_nPlasmaType == PLASMA_FOUR_RING)
{
// Make sure dwSize is a factor of 2 if using four ring plasma...
if (2 <= dwSize && dwSize < 4) dwSize = 2;
else if (4 <= dwSize && dwSize <= 6) dwSize = 4;
else if (6 < dwSize && dwSize <= 12) dwSize = 8;
else dwSize = 16;
}
}
// Adjust the size of the polygrid based on the current polygrids and
// special fx detail setting...
DBYTE nVal = g_pBloodClientShell->GetGlobalDetail();
if (nVal == DETAIL_LOW || nVal == DETAIL_MEDIUM)
{
dwSize = 4 + 1; // Smallest possible
}
m_hObject = m_pClientDE->CreateObject(&createStruct);
m_pClientDE->SetupPolyGrid(m_hObject, dwSize, dwSize, DFALSE);
// Set alpha value...
DFLOAT r, g, b, a;
m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
m_pClientDE->SetObjectColor(m_hObject, r, g, b, m_fAlpha);
DVector vMin, vMax, vScale;
VEC_SUB(vMin, vPos, m_vDims);
VEC_ADD(vMax, vPos, m_vDims);
m_pClientDE->FitPolyGrid(m_hObject, &vMin, &vMax, &vPos, &vScale);
if (m_hstrSurfaceSprite)
{
char* pSpriteName = m_pClientDE->GetStringData(m_hstrSurfaceSprite);
if (pSpriteName && pSpriteName[0])
{
m_pClientDE->SetPolyGridTexture(m_hObject, pSpriteName);
m_pClientDE->SetPolyGridTextureInfo(m_hObject, m_fXPan, m_fYPan, m_fXScaleMin, m_fYScaleMin);
}
}
m_pClientDE->SetObjectPos(m_hObject, &vPos);
m_pClientDE->SetObjectScale(m_hObject, &vScale);
SetPolyGridPalette(colorRamps, sizeof(colorRamps)/sizeof(colorRamps[0]));
PrecalculatePlasma();
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CPolyGridFX::Update
//
// PURPOSE: Update the grid
//
// ----------------------------------------------------------------------- //
DBOOL CPolyGridFX::Update()
{
if(!m_hObject || !m_pClientDE || !m_hServerObject || !g_pBloodClientShell) return DFALSE;
if (m_bWantRemove)
return DFALSE;
// Set the flags of the polygrid based on the the server object...
DDWORD dwUserFlags;
m_pClientDE->GetObjectUserFlags(m_hServerObject, &dwUserFlags);
DDWORD dwFlags = m_pClientDE->GetObjectFlags(m_hObject);
if (dwUserFlags & USRFLG_VISIBLE)
{
m_pClientDE->SetObjectFlags(m_hObject, dwFlags | FLAG_VISIBLE);
}
else // We're hidden, no need to update...
{
m_pClientDE->SetObjectFlags(m_hObject, dwFlags & ~FLAG_VISIBLE);
return DTRUE;
}
// Don't update if not drawn :)
if (!(m_pClientDE->GetObjectFlags(m_hObject) & FLAG_WASDRAWN) && !m_bAlwaysUpdate)
{
return DTRUE;
}
// Update the position of the polygrid to reflect the position of the
// server object...
DVector vPos;
m_pClientDE->GetObjectPos(m_hServerObject, &vPos);
m_pClientDE->SetObjectPos(m_hObject, &vPos);
// Don't update if low detail.
DBYTE byDetailLevel;
if ((byDetailLevel = g_pBloodClientShell->GetGlobalDetail()) == DETAIL_LOW)
{
// g_pBloodClientShell->CSPrint("not updating polygrid");
return DTRUE;
}
// Update the plasma based on the type of plasma...
switch (m_nPlasmaType)
{
case PLASMA_FOUR_RING :
UpdateFourRingPlasma();
break;
case PLASMA_NORMAL:
default :
UpdatePlasma();
break;
}
if (m_hstrSurfaceSprite)
{
UpdateSurface();
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CPolyGridFX::UpdateSurface
//
// PURPOSE: Update the polygrid's surface fx
//
// ----------------------------------------------------------------------- //
void CPolyGridFX::UpdateSurface()
{
if (!m_pClientDE || !m_hstrSurfaceSprite) return;
DFLOAT fXPan, fYPan, fXScale, fYScale;
m_pClientDE->GetPolyGridTextureInfo(m_hObject, &fXPan, &fYPan, &fXScale, &fYScale);
DFLOAT fDeltaTime = m_pClientDE->GetFrameTime();
// Scale in X direction...
if (m_fXScaleDuration > 0.0f)
{
if (m_bScalingXUp)
{
fXScale += fDeltaTime * (m_fXScaleMax - m_fXScaleMin) / m_fXScaleDuration;
if (fXScale > m_fXScaleMax)
{
fXScale = m_fXScaleMax;
m_bScalingXUp = DFALSE;
}
}
else
{
fXScale -= fDeltaTime * (m_fXScaleMax - m_fXScaleMin) / m_fXScaleDuration;
if (fXScale < m_fXScaleMin)
{
fXScale = m_fXScaleMin;
m_bScalingXUp = DTRUE;
}
}
}
// Scale in Y direction...
if (m_fYScaleDuration > 0.0f)
{
if (m_bScalingYUp)
{
fYScale += fDeltaTime * (m_fYScaleMax - m_fYScaleMin) / m_fYScaleDuration;
if (fYScale > m_fYScaleMax)
{
fYScale = m_fYScaleMax;
m_bScalingYUp = DFALSE;
}
}
else
{
fYScale -= fDeltaTime * (m_fYScaleMax - m_fYScaleMin) / m_fYScaleDuration;
if (fYScale < m_fYScaleMin)
{
fYScale = m_fYScaleMin;
m_bScalingYUp = DTRUE;
}
}
}
m_pClientDE->SetPolyGridTextureInfo(m_hObject, m_fXPan, m_fYPan, fXScale, fYScale);
}
// ----------------------------------------------------------------------- //
// Precalculates the lookup tables for plasma FX.
// ----------------------------------------------------------------------- //
void CPolyGridFX::PrecalculatePlasma()
{
DDWORD width, height;
int halfWidth, halfHeight, x, y;
char *pData;
PGColor *pColorTable;
float scale, val, maxDistSqr, testDist, t;
int i;
// Create the (scaled) sin table.
if(!g_bSinTableInitted)
{
scale = (MATH_CIRCLE / 255.0f) * 3.0f;
for(i=0; i < 256; i++)
{
val = (float)i * scale;
g_SinTable[i] = (char)(sin(val) * 128.0f);
}
g_bSinTableInitted = DTRUE;
}
// Fill in the distance grid.
m_pClientDE->GetPolyGridInfo(m_hObject, &pData, &width, &height, &pColorTable);
m_DistanceGrid = (DBYTE*)malloc(width*height);
halfWidth = width >> 1;
halfHeight = height >> 1;
maxDistSqr = (float)(halfWidth*halfWidth + halfHeight*halfHeight);
for(y=0; y < (int)height; y++)
{
for(x=0; x < (int)width; x++)
{
testDist = (float)((x-halfWidth)*(x-halfWidth) + (y-halfHeight)*(y-halfHeight));
t = testDist / maxDistSqr;
m_DistanceGrid[y*height+x] = (DBYTE)(t * 255.0f);
}
}
}
// ----------------------------------------------------------------------- //
// Inits the palette for the grid. Pass in a ramp list for it to interpolate thru.
// ----------------------------------------------------------------------- //
void CPolyGridFX::SetPolyGridPalette(ColorRamp *pRamps, int nRamps)
{
float t;
DDWORD width, height;
char *pData;
PGColor *pColorTable, color1, color2;
int ramp, i, index1, index2;
// Randomize the poly grid values.
m_pClientDE->GetPolyGridInfo(m_hObject, &pData, &width, &height, &pColorTable);
// Make the color table go from white to black.
for(ramp=0; ramp < nRamps-1; ramp++)
{
index1 = pRamps[ramp].m_Index;
index2 = pRamps[ramp+1].m_Index;
VEC_COPY(color1, pRamps[ramp].m_Color);
VEC_COPY(color2, pRamps[ramp+1].m_Color);
for(i=index1; i < index2; i++)
{
t = (float)(i - index1) / (index2 - index1);
VEC_LERP(pColorTable[i], color1, color2, t);
pColorTable[i].a = 255.0f;
}
}
}
// ----------------------------------------------------------------------- //
// Updates the plasma effect.
// ----------------------------------------------------------------------- //
void CPolyGridFX::UpdatePlasma()
{
DDWORD width, height, x, y;
char *pData, *pCur;
PGColor *pColorTable;
DBYTE count, *pDistanceGrid;
m_fCount += 50.0f * m_pClientDE->GetFrameTime();
count = (DBYTE)m_fCount;
// Randomize the poly grid values.
m_pClientDE->GetPolyGridInfo(m_hObject, &pData, &width, &height, &pColorTable);
for(y=0; y < height; y++)
{
pCur = pData + (y*width);
pDistanceGrid = &m_DistanceGrid[y*width];
x = width;
while(x--)
{
*pCur = g_SinTable[(DBYTE)((*pDistanceGrid) + count)];
++pDistanceGrid;
++pCur;
}
}
}
float g_Counts[4] = {0.0f, 1.0f, 4.0f, 3.0f};
long g_Offsets[4][2] =
{
6, 10,
13, 3,
17, 1,
31, 22
};
// ----------------------------------------------------------------------- //
// Updates the plasma effect.
// ----------------------------------------------------------------------- //
void CPolyGridFX::UpdateFourRingPlasma()
{
DDWORD dwWidth, dwHeight;
long width, height, x, y, xMask, yMask, yOffsets[4];
char *pData, *pCur;
PGColor *pColorTable;
DBYTE val[4], counts[4], *pDistanceGrid;
long i;
for(i=0; i < 4; i++)
{
g_Counts[i] += ((float)m_nRingRate[i]) * m_pClientDE->GetFrameTime();
counts[i] = (DBYTE)g_Counts[i];
}
m_pClientDE->GetPolyGridInfo(m_hObject, &pData, &dwWidth, &dwHeight, &pColorTable);
width = (long)dwWidth;
height = (long)dwHeight;
xMask = width - 1;
yMask = height - 1;
for(y=0; y < height; y++)
{
pCur = pData + (y*width);
//pDistanceGrid = &m_DistanceGrid[y*width];
pDistanceGrid = m_DistanceGrid;
yOffsets[0] = ((y+g_Offsets[0][1]) & yMask)*width;
yOffsets[1] = ((y+g_Offsets[1][1]) & yMask)*width;
yOffsets[2] = ((y+g_Offsets[2][1]) & yMask)*width;
yOffsets[3] = ((y+g_Offsets[3][1]) & yMask)*width;
x = width;
while(x--)
{
val[0] = pDistanceGrid[yOffsets[0] + ((x+g_Offsets[0][0]) & xMask)];
val[1] = pDistanceGrid[yOffsets[1] + ((x+g_Offsets[1][0]) & xMask)];
val[2] = pDistanceGrid[yOffsets[2] + ((x+g_Offsets[2][0]) & xMask)];
val[3] = pDistanceGrid[yOffsets[3] + ((x+g_Offsets[3][0]) & xMask)];
*pCur = (
g_SinTable[(DBYTE)(val[0] + counts[0])] +
g_SinTable[(DBYTE)(val[1] + counts[1])] +
g_SinTable[(DBYTE)(val[2] + counts[2])] +
g_SinTable[(DBYTE)(val[3] + counts[3])]
) >> 2;
//++pDistanceGrid;
++pCur;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -