mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-29 21:25:54 +01:00
2679 lines
78 KiB
C++
2679 lines
78 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
|
|
|
#include "stdh.h"
|
|
|
|
#include <Engine/Graphics/Texture.h>
|
|
#include <Engine/Graphics/TextureEffects.h>
|
|
|
|
#include <Engine/Math/Functions.h>
|
|
#include <Engine/Base/Timer.h>
|
|
#include <Engine/Base/Statistics_internal.h>
|
|
#include <Engine/Templates/DynamicArray.cpp>
|
|
#include <Engine/Templates/Stock_CtextureData.h>
|
|
#include <Engine/Templates/StaticArray.cpp>
|
|
|
|
// asm shortcuts
|
|
#define O offset
|
|
#define Q qword ptr
|
|
#define D dword ptr
|
|
#define W word ptr
|
|
#define B byte ptr
|
|
|
|
#define ASMOPT 1
|
|
|
|
|
|
static const __int64 mm1LO = 0x0000000000000001;
|
|
static const __int64 mm1HI = 0x0000000100000000;
|
|
static const __int64 mm1HILO = 0x0000000100000001;
|
|
static const __int64 mm0001 = 0x0000000000000001;
|
|
static const __int64 mm0010 = 0x0000000000010000;
|
|
static const __int64 mm00M0 = 0x00000000FFFF0000;
|
|
static __int64 mmBaseWidthShift=0, mmBaseWidth=0, mmBaseWidthMask=0, mmBaseHeightMask=0, mmBaseMasks=0, mmShift=0;
|
|
|
|
|
|
// speed table
|
|
static SBYTE asbMod3Sub1Table[256];
|
|
static BOOL bTableSet = FALSE;
|
|
|
|
static CTextureData *_ptdEffect, *_ptdBase;
|
|
static PIX _pixTexWidth, _pixTexHeight;
|
|
static PIX _pixBufferWidth, _pixBufferHeight;
|
|
static ULONG _ulBufferMask;
|
|
static INDEX _iWantedMipLevel;
|
|
static UBYTE *_pubDrawBuffer;
|
|
static SWORD *_pswDrawBuffer;
|
|
|
|
|
|
// randomizer
|
|
static ULONG ulRNDSeed;
|
|
|
|
inline void Randomize( ULONG ulSeed)
|
|
{
|
|
if( ulSeed==0) ulSeed = 0x87654321;
|
|
ulRNDSeed = ulSeed*262147;
|
|
};
|
|
|
|
inline ULONG Rnd(void)
|
|
{
|
|
ulRNDSeed = ulRNDSeed*262147;
|
|
return ulRNDSeed;
|
|
};
|
|
|
|
#define RNDW (Rnd()>>16)
|
|
|
|
|
|
|
|
// Initialize the texture effect source.
|
|
void CTextureEffectSource::Initialize( class CTextureEffectGlobal *ptegGlobalEffect,
|
|
ULONG ulEffectSourceType, PIX pixU0, PIX pixV0,
|
|
PIX pixU1, PIX pixV1)
|
|
{ // remember global effect for cross linking
|
|
tes_ptegGlobalEffect = ptegGlobalEffect;
|
|
tes_ulEffectSourceType = ulEffectSourceType;
|
|
|
|
// obtain effect source table for current effect class
|
|
struct TextureEffectSourceType *patestSourceEffectTypes =
|
|
_ategtTextureEffectGlobalPresets[ ptegGlobalEffect->teg_ulEffectType].tet_atestEffectSourceTypes;
|
|
|
|
// init for animating
|
|
patestSourceEffectTypes[ulEffectSourceType].test_Initialize(this, pixU0, pixV0, pixU1, pixV1);
|
|
}
|
|
|
|
// Animate the texture effect source.
|
|
void CTextureEffectSource::Animate(void)
|
|
{
|
|
// obtain effect source table for current effect class
|
|
struct TextureEffectSourceType *patestSourceEffectTypes =
|
|
_ategtTextureEffectGlobalPresets[ tes_ptegGlobalEffect->teg_ulEffectType]
|
|
.tet_atestEffectSourceTypes;
|
|
|
|
// animating it
|
|
patestSourceEffectTypes[tes_ulEffectSourceType].test_Animate(this);
|
|
}
|
|
|
|
|
|
// ----------------------------------------
|
|
// SLONG WATER
|
|
// ----------------------------------------
|
|
inline void PutPixelSLONG_WATER( PIX pixU, PIX pixV, INDEX iHeight)
|
|
{
|
|
_pswDrawBuffer[(pixV*_pixBufferWidth+pixU)&_ulBufferMask] += iHeight;
|
|
}
|
|
|
|
inline void PutPixel9SLONG_WATER( PIX pixU, PIX pixV, INDEX iHeightMid)
|
|
{
|
|
INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326;
|
|
INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951;
|
|
|
|
PutPixelSLONG_WATER( pixU-1, pixV-1, iHeightDiag);
|
|
PutPixelSLONG_WATER( pixU, pixV-1, iHeightSide);
|
|
PutPixelSLONG_WATER( pixU+1, pixV-1, iHeightDiag);
|
|
|
|
PutPixelSLONG_WATER( pixU-1, pixV, iHeightSide);
|
|
PutPixelSLONG_WATER( pixU, pixV, iHeightMid);
|
|
PutPixelSLONG_WATER( pixU+1, pixV, iHeightSide);
|
|
|
|
PutPixelSLONG_WATER( pixU-1, pixV+1, iHeightDiag);
|
|
PutPixelSLONG_WATER( pixU, pixV+1, iHeightSide);
|
|
PutPixelSLONG_WATER( pixU+1, pixV+1, iHeightDiag);
|
|
}
|
|
|
|
|
|
// ----------------------------------------
|
|
// UBYTE FIRE
|
|
// ----------------------------------------
|
|
inline void PutPixelUBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeight)
|
|
{
|
|
PIX pixLoc = (pixV*_pixBufferWidth+pixU) & _ulBufferMask;
|
|
_pubDrawBuffer[pixLoc] = Clamp( _pubDrawBuffer[pixLoc] +iHeight, 0L, 255L);
|
|
}
|
|
|
|
inline void PutPixel9UBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeightMid)
|
|
{
|
|
INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326;
|
|
INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951;
|
|
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV-1, iHeightDiag);
|
|
PutPixelUBYTE_FIRE( pixU, pixV-1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV-1, iHeightDiag);
|
|
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU, pixV, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV, iHeightSide);
|
|
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV+1, iHeightDiag);
|
|
PutPixelUBYTE_FIRE( pixU, pixV+1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV+1, iHeightDiag);
|
|
}
|
|
|
|
inline void PutPixel25UBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeightMid)
|
|
{
|
|
INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326;
|
|
INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951;
|
|
|
|
PutPixelUBYTE_FIRE( pixU-2, pixV-2, iHeightDiag);
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV-2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU, pixV-2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV-2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+2, pixV-2, iHeightDiag);
|
|
|
|
PutPixelUBYTE_FIRE( pixU-2, pixV-1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV-1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU, pixV-1, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV-1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+2, pixV-1, iHeightSide);
|
|
|
|
PutPixelUBYTE_FIRE( pixU-2, pixV, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU, pixV, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU+2, pixV, iHeightSide);
|
|
|
|
PutPixelUBYTE_FIRE( pixU-2, pixV+1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV+1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU, pixV+1, iHeightMid);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV+1, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+2, pixV+1, iHeightSide);
|
|
|
|
PutPixelUBYTE_FIRE( pixU+2, pixV+2, iHeightDiag);
|
|
PutPixelUBYTE_FIRE( pixU-1, pixV+2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU, pixV+2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU+1, pixV+2, iHeightSide);
|
|
PutPixelUBYTE_FIRE( pixU-2, pixV+2, iHeightDiag);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// WATER EFFECTS
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
#define DISTORSION 3 //3
|
|
|
|
|
|
///////////////// random surfer
|
|
struct Surfer {
|
|
FLOAT fU;
|
|
FLOAT fV;
|
|
FLOAT fAngle;
|
|
};
|
|
|
|
void InitializeRandomSurfer(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
Surfer &sf =
|
|
((Surfer&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
sf.fU = pixU0;
|
|
sf.fV = pixV0;
|
|
sf.fAngle = RNDW&7;
|
|
}
|
|
|
|
void AnimateRandomSurfer(CTextureEffectSource *ptes)
|
|
{
|
|
Surfer &sf =
|
|
((Surfer&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
|
|
PutPixel9SLONG_WATER(sf.fU, sf.fV, 125);
|
|
sf.fU += 2*sin(sf.fAngle);
|
|
sf.fV += 2*cos(sf.fAngle);
|
|
PutPixel9SLONG_WATER(sf.fU, sf.fV, 250);
|
|
|
|
if((RNDW&15)==0) {
|
|
sf.fAngle += 3.14f/7.0f;
|
|
}
|
|
if((RNDW&15)==0) {
|
|
sf.fAngle -= 3.14f/5.0f;
|
|
}
|
|
}
|
|
|
|
///////////////// raindrops
|
|
struct Raindrop {
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
SWORD iHeight;
|
|
SWORD iIndex;
|
|
};
|
|
|
|
|
|
void InitializeRaindrops(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1, int iHeight)
|
|
{
|
|
for (int iIndex=0; iIndex<5; iIndex++) {
|
|
Raindrop &rd =
|
|
((Raindrop&) ptes->tes_tespEffectSourceProperties.tesp_achDummy[iIndex*sizeof(Raindrop)]);
|
|
rd.pixU = RNDW&(_pixBufferWidth -1);
|
|
rd.pixV = RNDW&(_pixBufferHeight-1);
|
|
rd.iHeight = RNDW&iHeight;
|
|
rd.iIndex = iIndex*8;
|
|
}
|
|
}
|
|
void InitializeRaindropsStandard(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) {
|
|
InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 255);
|
|
}
|
|
void InitializeRaindropsBig(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) {
|
|
InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 1023);
|
|
}
|
|
void InitializeRaindropsSmall(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) {
|
|
InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 31);
|
|
}
|
|
|
|
|
|
void AnimateRaindrops(CTextureEffectSource *ptes, int iHeight)
|
|
{
|
|
for (int iIndex=0; iIndex<5; iIndex++) {
|
|
Raindrop &rd =
|
|
((Raindrop&) ptes->tes_tespEffectSourceProperties.tesp_achDummy[iIndex*sizeof(Raindrop)]);
|
|
if (rd.iIndex < 48) {
|
|
rd.iIndex++;
|
|
|
|
if (rd.iIndex < 8) {
|
|
PutPixel9SLONG_WATER(rd.pixU, rd.pixV, sin(rd.iIndex/4.0f*(-3.14f))*rd.iHeight);
|
|
}
|
|
} else {
|
|
rd.pixU = RNDW&(_pixBufferWidth -1);
|
|
rd.pixV = RNDW&(_pixBufferHeight-1);
|
|
rd.iHeight = RNDW&iHeight;
|
|
rd.iIndex = 0;
|
|
}
|
|
}
|
|
}
|
|
void AnimateRaindropsStandard(CTextureEffectSource *ptes) {
|
|
AnimateRaindrops(ptes, 255);
|
|
}
|
|
void AnimateRaindropsBig(CTextureEffectSource *ptes) {
|
|
AnimateRaindrops(ptes, 1023);
|
|
}
|
|
void AnimateRaindropsSmall(CTextureEffectSource *ptes) {
|
|
AnimateRaindrops(ptes, 31);
|
|
}
|
|
|
|
|
|
|
|
///////////////// oscilator
|
|
struct Oscilator {
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
FLOAT fAngle;
|
|
};
|
|
|
|
void InitializeOscilator(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
Oscilator &os =
|
|
((Oscilator&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
os.pixU = pixU0;
|
|
os.pixV = pixV0;
|
|
os.fAngle = -3.14f;
|
|
}
|
|
|
|
void AnimateOscilator(CTextureEffectSource *ptes)
|
|
{
|
|
Oscilator &os =
|
|
((Oscilator&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PutPixel9SLONG_WATER(os.pixU, os.pixV, sin(os.fAngle)*150);
|
|
os.fAngle += (3.14f/6);
|
|
}
|
|
|
|
|
|
///////////////// Vertical Line
|
|
struct VertLine{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
UWORD uwSize;
|
|
FLOAT fAngle;
|
|
};
|
|
|
|
void InitializeVertLine(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
VertLine &vl =
|
|
((VertLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
vl.pixU = pixU0;
|
|
vl.pixV = pixV0;
|
|
vl.fAngle = -3.14f;
|
|
if (pixV0==pixV1) {
|
|
vl.uwSize = 16;
|
|
} else {
|
|
vl.uwSize = abs(pixV1-pixV0);
|
|
}
|
|
}
|
|
|
|
void AnimateVertLine(CTextureEffectSource *ptes)
|
|
{
|
|
VertLine &vl =
|
|
((VertLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PIX pixV = vl.pixV;
|
|
for (int iCnt=0; iCnt<vl.uwSize; iCnt++) {
|
|
PutPixelSLONG_WATER(vl.pixU, pixV, sin(vl.fAngle)*25);
|
|
pixV = (pixV+1)&(_pixBufferHeight-1);
|
|
}
|
|
vl.fAngle += (3.14f/6);
|
|
}
|
|
|
|
|
|
///////////////// Horizontal Line
|
|
struct HortLine{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
UWORD uwSize;
|
|
FLOAT fAngle;
|
|
};
|
|
|
|
void InitializeHortLine(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
HortLine &hl =
|
|
((HortLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
hl.pixU = pixU0;
|
|
hl.pixV = pixV0;
|
|
hl.fAngle = -3.14f;
|
|
if (pixU0==pixU1) {
|
|
hl.uwSize = 16;
|
|
} else {
|
|
hl.uwSize = abs(pixU1-pixU0);
|
|
}
|
|
}
|
|
|
|
void AnimateHortLine(CTextureEffectSource *ptes)
|
|
{
|
|
HortLine &hl =
|
|
((HortLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PIX pixU = hl.pixU;
|
|
for (int iCnt=0; iCnt<hl.uwSize; iCnt++) {
|
|
PutPixelSLONG_WATER(pixU, hl.pixV, sin(hl.fAngle)*25);
|
|
pixU = (pixU+1)&(_pixBufferWidth-1);
|
|
}
|
|
hl.fAngle += (3.14f/6);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// FIRE EFFECTS
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////// Fire Point
|
|
struct FirePoint{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
};
|
|
|
|
void InitializeFirePoint(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ft.pixU = pixU0;
|
|
ft.pixV = pixV0;
|
|
}
|
|
|
|
void AnimateFirePoint(CTextureEffectSource *ptes)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PutPixel9UBYTE_FIRE(ft.pixU, ft.pixV, 255);
|
|
}
|
|
|
|
void InitializeRandomFirePoint(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ft.pixU = pixU0;
|
|
ft.pixV = pixV0;
|
|
}
|
|
|
|
void AnimateRandomFirePoint(CTextureEffectSource *ptes)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PutPixel9UBYTE_FIRE(ft.pixU, ft.pixV, RNDW&255);
|
|
}
|
|
|
|
void InitializeFireShakePoint(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ft.pixU = pixU0;
|
|
ft.pixV = pixV0;
|
|
}
|
|
|
|
void AnimateFireShakePoint(CTextureEffectSource *ptes)
|
|
{
|
|
FirePoint &ft =
|
|
((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
UBYTE pixU, pixV;
|
|
pixU = RNDW%3 - 1;
|
|
pixV = RNDW%3 - 1;
|
|
PutPixel9UBYTE_FIRE(ft.pixU+pixU, ft.pixV+pixV, 255);
|
|
}
|
|
|
|
|
|
///////////////// Fire Place
|
|
#define FIREPLACE_SIZE 60
|
|
|
|
struct FirePlace{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
UBYTE ubWidth;
|
|
UBYTE aubFire[FIREPLACE_SIZE];
|
|
};
|
|
|
|
void InitializeFirePlace(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FirePlace &fp =
|
|
((FirePlace&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
fp.pixU = pixU0;
|
|
fp.pixV = pixV0;
|
|
fp.ubWidth = abs(pixU1-pixU0);
|
|
if (fp.ubWidth>FIREPLACE_SIZE) fp.ubWidth=FIREPLACE_SIZE;
|
|
if (fp.ubWidth<10) fp.ubWidth = 10;
|
|
// clear fire array
|
|
for (int iCnt=0; iCnt<fp.ubWidth; iCnt++) {
|
|
fp.aubFire[iCnt] = 0;
|
|
}
|
|
}
|
|
|
|
void AnimateFirePlace(CTextureEffectSource *ptes)
|
|
{
|
|
INDEX iIndex;
|
|
FirePlace &fp =
|
|
((FirePlace&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ULONG ulRND = RNDW&255;
|
|
// match
|
|
if (ulRND>200) {
|
|
ULONG ulMatchIndex = ulRND%(fp.ubWidth-5);
|
|
for (iIndex=0; iIndex<5; iIndex++) {
|
|
fp.aubFire[ulMatchIndex+iIndex] = 255;
|
|
}
|
|
// water
|
|
} else if (ulRND<50) {
|
|
for (iIndex=0; iIndex<10; iIndex++) {
|
|
fp.aubFire[RNDW%fp.ubWidth] = 0;
|
|
}
|
|
}
|
|
// fix fire place
|
|
for (iIndex=0; iIndex<fp.ubWidth; iIndex++) {
|
|
UBYTE ubFlame = fp.aubFire[iIndex];
|
|
// flame is fading ?
|
|
if (ubFlame < 50) {
|
|
// starting to burn
|
|
if (ubFlame > 10) {
|
|
ubFlame += RNDW%30; //30
|
|
// give more fire
|
|
} else {
|
|
ubFlame += RNDW%30+30; //30,30
|
|
}
|
|
}
|
|
fp.aubFire[iIndex] = ubFlame;
|
|
}
|
|
// water on edges
|
|
for (iIndex=0; iIndex<4; iIndex++) {
|
|
INDEX iWater = RNDW%4;
|
|
fp.aubFire[iWater] = 0;
|
|
fp.aubFire[fp.ubWidth-1-iWater] = 0;
|
|
}
|
|
// smooth fire place
|
|
for (iIndex=1; iIndex<(fp.ubWidth-1); iIndex++) {
|
|
fp.aubFire[iIndex] = (fp.aubFire[iIndex-1]+fp.aubFire[iIndex]+fp.aubFire[iIndex+1])/3;
|
|
}
|
|
// draw fire place in buffer
|
|
for (iIndex=0; iIndex<fp.ubWidth; iIndex++) {
|
|
PutPixel9UBYTE_FIRE(fp.pixU+iIndex, fp.pixV, fp.aubFire[iIndex]);
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Roler
|
|
struct FireRoler{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
//FLOAT fRadius;
|
|
FLOAT fRadiusU;
|
|
FLOAT fRadiusV;
|
|
FLOAT fAngle;
|
|
FLOAT fAngleAdd;
|
|
};
|
|
|
|
void InitializeFireRoler(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireRoler &fr =
|
|
((FireRoler&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
fr.pixU = pixU0;
|
|
fr.pixV = pixV0;
|
|
if (pixU0==pixU1 && pixV0==pixV1) {
|
|
//fr.fRadius = 3;
|
|
fr.fRadiusU = 3;
|
|
fr.fRadiusV = 3;
|
|
fr.fAngleAdd = (3.14f/6);
|
|
} else {
|
|
//fr.fRadius = sqrt((pixU1-pixU0)*(pixU1-pixU0) + (pixV1-pixV0)*(pixV1-pixV0));
|
|
fr.fRadiusU = pixU1-pixU0;
|
|
fr.fRadiusV = pixV1-pixV0;
|
|
//fr.fAngleAdd = (3.14f/((fr.fRadius)*2));
|
|
fr.fAngleAdd = (3.14f/(Abs(fr.fRadiusU)+Abs(fr.fRadiusV)));
|
|
}
|
|
fr.fAngle = 0;
|
|
}
|
|
|
|
void AnimateFireRoler(CTextureEffectSource *ptes)
|
|
{
|
|
FireRoler &fr =
|
|
((FireRoler&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU,
|
|
sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 255);
|
|
fr.fAngle += fr.fAngleAdd;
|
|
PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU,
|
|
sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 200);
|
|
fr.fAngle += fr.fAngleAdd;
|
|
PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU,
|
|
sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 150);
|
|
fr.fAngle += fr.fAngleAdd;
|
|
}
|
|
|
|
|
|
///////////////// Fire Fall
|
|
#define FIREFALL_POINTS 100
|
|
|
|
struct FireFall{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
ULONG ulWidth;
|
|
ULONG ulPointToReinitialize;
|
|
};
|
|
|
|
struct FireFallPixel{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
UBYTE ubSpeed;
|
|
};
|
|
|
|
void InitializeFireFall(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireFall &ff =
|
|
((FireFall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ff.pixU = pixU0;
|
|
ff.pixV = pixV0;
|
|
if (pixU0==pixU1) {
|
|
ff.ulWidth = 15;
|
|
} else {
|
|
ff.ulWidth = abs(pixU1-pixU0);
|
|
}
|
|
// initialize fall points
|
|
ptes->tes_atepPixels.New(FIREFALL_POINTS);
|
|
ff.ulPointToReinitialize = 0;
|
|
for (INDEX iIndex=0; iIndex<FIREFALL_POINTS; iIndex++) {
|
|
FireFallPixel &ffp = ((FireFallPixel&) ptes->tes_atepPixels[iIndex]);
|
|
ffp.pixU = ff.pixU+(RNDW%ff.ulWidth);
|
|
ffp.pixV = ff.pixV+(RNDW%_pixBufferHeight);
|
|
ffp.ubSpeed = (RNDW&1)+2;
|
|
}
|
|
}
|
|
|
|
void AnimateFireFall(CTextureEffectSource *ptes)
|
|
{
|
|
FireFall &ff =
|
|
((FireFall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
// animate fall points
|
|
for (INDEX iIndex=0; iIndex<FIREFALL_POINTS; iIndex++) {
|
|
FireFallPixel &ffp = ((FireFallPixel&) ptes->tes_atepPixels[iIndex]);
|
|
// fall from fall
|
|
int iHeight = (RNDW&3)*64 + 40;
|
|
if (ffp.ubSpeed == 2) {
|
|
PutPixelUBYTE_FIRE(ffp.pixU+(RNDW%3)-1, ffp.pixV, iHeight);
|
|
PutPixelUBYTE_FIRE(ffp.pixU+(RNDW%3)-1, ffp.pixV+1, iHeight-40);
|
|
} else {
|
|
PutPixelUBYTE_FIRE(ffp.pixU, ffp.pixV, iHeight);
|
|
PutPixelUBYTE_FIRE(ffp.pixU, ffp.pixV+1, iHeight-40);
|
|
}
|
|
ffp.pixV+=ffp.ubSpeed;
|
|
// when falled down reinitialize
|
|
if (ffp.pixV >= _pixBufferHeight) {
|
|
if (ff.ulPointToReinitialize == iIndex) {
|
|
ff.ulPointToReinitialize++;
|
|
if (ff.ulPointToReinitialize >= FIREFALL_POINTS) ff.ulPointToReinitialize = 0;
|
|
ffp.pixU = ff.pixU+(RNDW%ff.ulWidth);
|
|
ffp.pixV -= _pixBufferHeight;
|
|
ffp.ubSpeed = (RNDW&1)+2;
|
|
} else {
|
|
ffp.pixV -= _pixBufferHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Fountain
|
|
#define FIREFOUNTAIN_POINTS 100
|
|
|
|
struct FireFountain{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
ULONG ulWidth;
|
|
ULONG ulBaseHeight;
|
|
ULONG ulRandomHeight;
|
|
|
|
};
|
|
|
|
struct FireFountainPixel{
|
|
SWORD pixU;
|
|
SWORD pixV;
|
|
UBYTE pixLastU;
|
|
UBYTE pixLastV;
|
|
SWORD sbSpeedU;
|
|
SWORD sbSpeedV;
|
|
};
|
|
|
|
void InitializeFireFountain(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireFountain &ff =
|
|
((FireFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
ff.pixU = pixU0;
|
|
ff.pixV = pixV0;
|
|
// fountain width
|
|
if (pixU0==pixU1) {
|
|
ff.ulWidth = 31;
|
|
} else {
|
|
ff.ulWidth = abs(pixU1-pixU0)*2;
|
|
}
|
|
// fountain height
|
|
if (pixV0==pixV1) {
|
|
ff.ulBaseHeight = 120;
|
|
ff.ulRandomHeight = 40;
|
|
} else {
|
|
ff.ulBaseHeight = abs(pixV1-pixV0)*3;
|
|
ff.ulRandomHeight = abs(pixV1-pixV0);
|
|
}
|
|
// initialize fountain points
|
|
ptes->tes_atepPixels.New(FIREFOUNTAIN_POINTS*2);
|
|
for (INDEX iIndex=0; iIndex<FIREFOUNTAIN_POINTS*2; iIndex+=2) {
|
|
FireFountainPixel &ffp = ((FireFountainPixel&) ptes->tes_atepPixels[iIndex]);
|
|
ffp.pixU = (ff.pixU)<<6;
|
|
ffp.pixV = (RNDW%(_pixBufferHeight-(_pixBufferHeight>>3))+(_pixBufferHeight>>3))<<6;
|
|
ffp.pixLastU = (ffp.pixU)>>6;
|
|
ffp.pixLastV = (ffp.pixV)>>6;
|
|
ffp.sbSpeedU = 0;
|
|
ffp.sbSpeedV = 0;
|
|
}
|
|
}
|
|
|
|
void AnimateFireFountain(CTextureEffectSource *ptes)
|
|
{
|
|
FireFountain &ff =
|
|
((FireFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
// animate fountain points
|
|
for (INDEX iIndex=0; iIndex<FIREFOUNTAIN_POINTS*2; iIndex+=2) {
|
|
FireFountainPixel &ffp = ((FireFountainPixel&) ptes->tes_atepPixels[iIndex]);
|
|
// fall from fountain
|
|
PutPixelUBYTE_FIRE((ffp.pixU)>>6, (ffp.pixV)>>6, 200);
|
|
PutPixelUBYTE_FIRE(ffp.pixLastU, ffp.pixLastV, 150);
|
|
// move pixel
|
|
ffp.pixLastU = (ffp.pixU)>>6;
|
|
ffp.pixLastV = (ffp.pixV)>>6;
|
|
ffp.pixU+=ffp.sbSpeedU;
|
|
ffp.pixV-=ffp.sbSpeedV;
|
|
ffp.sbSpeedV-=8;
|
|
// when falled down reinitialize
|
|
if ((ffp.pixV>>6) >= (_pixBufferHeight-5)) {
|
|
ffp.pixU = (ff.pixU)<<6;
|
|
ffp.pixV = (ff.pixV)<<6;
|
|
ffp.pixLastU = (ffp.pixU)>>6;
|
|
ffp.pixLastV = (ffp.pixV)>>6;
|
|
ffp.sbSpeedU = (RNDW%ff.ulWidth)-(ff.ulWidth/2-1);
|
|
ffp.sbSpeedV = (RNDW%ff.ulRandomHeight)+ff.ulBaseHeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Fountain
|
|
#define FIRESIDEFOUNTAIN_POINTS 100
|
|
|
|
struct FireSideFountain{
|
|
UBYTE pixU;
|
|
UBYTE pixV;
|
|
ULONG ulBaseWidth;
|
|
ULONG ulRandomWidth;
|
|
ULONG ulSide;
|
|
};
|
|
|
|
struct FireSideFountainPixel{
|
|
SWORD pixU;
|
|
SWORD pixV;
|
|
UBYTE pixLastU;
|
|
UBYTE pixLastV;
|
|
SWORD sbSpeedU;
|
|
SWORD sbSpeedV;
|
|
};
|
|
|
|
void InitializeFireSideFountain(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireSideFountain &fsf =
|
|
((FireSideFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
fsf.pixU = pixU0;
|
|
fsf.pixV = pixV0;
|
|
// fountain width
|
|
if (pixU0==pixU1) {
|
|
fsf.ulBaseWidth = 80;
|
|
fsf.ulRandomWidth = 40;
|
|
fsf.ulSide = (pixU0>(_pixBufferWidth/2));
|
|
} else {
|
|
fsf.ulBaseWidth = abs(pixU1-pixU0)*2;
|
|
fsf.ulRandomWidth = abs(pixU1-pixU0);
|
|
fsf.ulSide = (pixU1<pixU0);
|
|
}
|
|
// initialize fountain points
|
|
ptes->tes_atepPixels.New(FIRESIDEFOUNTAIN_POINTS*2);
|
|
for (INDEX iIndex=0; iIndex<FIRESIDEFOUNTAIN_POINTS*2; iIndex+=2) {
|
|
FireSideFountainPixel &fsfp = ((FireSideFountainPixel&) ptes->tes_atepPixels[iIndex]);
|
|
fsfp.pixU = (fsf.pixU)<<6;
|
|
fsfp.pixV = (RNDW%(_pixBufferHeight-(_pixBufferHeight>>3))+(_pixBufferHeight>>3))<<6;
|
|
fsfp.pixLastU = (fsfp.pixU)>>6;
|
|
fsfp.pixLastV = (fsfp.pixV)>>6;
|
|
fsfp.sbSpeedU = 0;
|
|
fsfp.sbSpeedV = 0;
|
|
}
|
|
}
|
|
|
|
void AnimateFireSideFountain(CTextureEffectSource *ptes)
|
|
{
|
|
FireSideFountain &fsf =
|
|
((FireSideFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
// animate fountain points
|
|
for (INDEX iIndex=0; iIndex<FIRESIDEFOUNTAIN_POINTS*2; iIndex+=2) {
|
|
FireSideFountainPixel &fsfp = ((FireSideFountainPixel&) ptes->tes_atepPixels[iIndex]);
|
|
// fall from fountain
|
|
PutPixelUBYTE_FIRE((fsfp.pixU)>>6, (fsfp.pixV)>>6, 200);
|
|
PutPixelUBYTE_FIRE(fsfp.pixLastU, fsfp.pixLastV, 150);
|
|
// move pixel
|
|
fsfp.pixLastU = (fsfp.pixU)>>6;
|
|
fsfp.pixLastV = (fsfp.pixV)>>6;
|
|
fsfp.pixU+=fsfp.sbSpeedU;
|
|
fsfp.pixV-=fsfp.sbSpeedV;
|
|
fsfp.sbSpeedV-=8;
|
|
// when falled down reinitialize
|
|
if ((fsfp.pixV>>6) >= (_pixBufferHeight-5)) {
|
|
fsfp.pixU = (fsf.pixU)<<6;
|
|
fsfp.pixV = (fsf.pixV)<<6;
|
|
fsfp.pixLastU = (fsfp.pixU)>>6;
|
|
fsfp.pixLastV = (fsfp.pixV)>>6;
|
|
fsfp.sbSpeedU = (RNDW%fsf.ulRandomWidth)+fsf.ulBaseWidth;
|
|
if (fsf.ulSide) {
|
|
fsfp.sbSpeedU = -fsfp.sbSpeedU;
|
|
}
|
|
fsfp.sbSpeedV = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Lightning
|
|
struct FireLightning{
|
|
FLOAT fpixUFrom;
|
|
FLOAT fpixVFrom;
|
|
FLOAT fpixUTo;
|
|
FLOAT fpixVTo;
|
|
FLOAT fvU;
|
|
FLOAT fvV;
|
|
FLOAT fvNormalU;
|
|
FLOAT fvNormalV;
|
|
FLOAT fDistance;
|
|
SLONG slCnt;
|
|
};
|
|
|
|
void InitializeFireLightning(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireLightning &fl =
|
|
((FireLightning&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
fl.fpixUFrom = (FLOAT) pixU0;
|
|
fl.fpixVFrom = (FLOAT) pixV0;
|
|
if (pixU0==pixU1 && pixV0==pixV1) {
|
|
fl.fpixUTo = Abs((FLOAT)_pixBufferWidth -fl.fpixUFrom);
|
|
fl.fpixVTo = Abs((FLOAT)_pixBufferHeight-fl.fpixVFrom);
|
|
} else {
|
|
fl.fpixUTo = (FLOAT) pixU1;
|
|
fl.fpixVTo = (FLOAT) pixV1;
|
|
}
|
|
fl.fDistance = sqrt((fl.fpixUTo-fl.fpixUFrom)*(fl.fpixUTo-fl.fpixUFrom)+
|
|
(fl.fpixVTo-fl.fpixVFrom)*(fl.fpixVTo-fl.fpixVFrom));
|
|
// vector
|
|
fl.fvU = (fl.fpixUTo-fl.fpixUFrom)/fl.fDistance;
|
|
fl.fvV = (fl.fpixVTo-fl.fpixVFrom)/fl.fDistance;
|
|
// normal vector
|
|
fl.fvNormalU = -fl.fvV;
|
|
fl.fvNormalV = fl.fvU;
|
|
// frame counter
|
|
fl.slCnt = 2;
|
|
}
|
|
|
|
void AnimateFireLightning(CTextureEffectSource *ptes)
|
|
{
|
|
FLOAT fU, fV, fLastU, fLastV;
|
|
FLOAT fDU, fDV, fCnt;
|
|
SLONG slRND;
|
|
ULONG ulDist;
|
|
|
|
FireLightning &fl =
|
|
((FireLightning&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
// last point -> starting point
|
|
fLastU = fl.fpixUFrom;
|
|
fLastV = fl.fpixVFrom;
|
|
|
|
fl.slCnt--;
|
|
if (fl.slCnt == 0) {
|
|
ulDist = 0;
|
|
while ((FLOAT)ulDist<fl.fDistance) {
|
|
// go away from source point to destination point
|
|
ulDist += (RNDW%5)+5;
|
|
if ((FLOAT)ulDist>=fl.fDistance) {
|
|
// move point to line end
|
|
fU = fl.fpixUTo;
|
|
fV = fl.fpixVTo;
|
|
} else {
|
|
// move point on line
|
|
fU = fl.fpixUFrom + fl.fvU*(FLOAT)ulDist;
|
|
fV = fl.fpixVFrom + fl.fvV*(FLOAT)ulDist;
|
|
// move point offset on normal line
|
|
slRND = (SLONG) (RNDW%11)-5;
|
|
fU += fl.fvNormalU*(FLOAT)slRND;
|
|
fV += fl.fvNormalV*(FLOAT)slRND;
|
|
}
|
|
// draw line
|
|
fDU = fU-fLastU;
|
|
fDV = fV-fLastV;
|
|
if (Abs(fDU)>Abs(fDV)) fCnt = Abs(fDU);
|
|
else fCnt = Abs(fDV);
|
|
fDU = fDU/fCnt;
|
|
fDV = fDV/fCnt;
|
|
while (fCnt>0.0f) {
|
|
PutPixelUBYTE_FIRE((PIX) fLastU, (PIX) fLastV, 255);
|
|
fLastU += fDU;
|
|
fLastV += fDV;
|
|
fCnt -= 1;
|
|
}
|
|
// store last point
|
|
fLastU = fU;
|
|
fLastV = fV;
|
|
}
|
|
fl.slCnt = 2;
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Lightning Ball
|
|
#define FIREBALL_LIGHTNINGS 2
|
|
|
|
struct FireLightningBall{
|
|
FLOAT fpixU;
|
|
FLOAT fpixV;
|
|
FLOAT fRadiusU;
|
|
FLOAT fRadiusV;
|
|
};
|
|
|
|
void InitializeFireLightningBall(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireLightningBall &flb =
|
|
((FireLightningBall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
flb.fpixU = (FLOAT) pixU0;
|
|
flb.fpixV = (FLOAT) pixV0;
|
|
if (pixU0==pixU1 && pixV0==pixV1) {
|
|
flb.fRadiusU = 20;
|
|
flb.fRadiusV = 20;
|
|
} else {
|
|
flb.fRadiusU = pixU1-pixU0;
|
|
flb.fRadiusV = pixV1-pixV0;
|
|
}
|
|
}
|
|
|
|
void AnimateFireLightningBall(CTextureEffectSource *ptes)
|
|
{
|
|
FLOAT fU, fV, fLastU, fLastV, fvU, fvV, fvNormalU, fvNormalV;
|
|
FLOAT fDU, fDV, fCnt, fDistance;
|
|
FLOAT fDestU, fDestV, fAngle;
|
|
SLONG slRND;
|
|
ULONG ulDist;
|
|
|
|
FireLightningBall &flb =
|
|
((FireLightningBall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
for (int iBalls=0; iBalls<FIREBALL_LIGHTNINGS; iBalls++) {
|
|
// last point -> starting point
|
|
fLastU = flb.fpixU;
|
|
fLastV = flb.fpixV;
|
|
// destination point
|
|
fAngle = (FLOAT) RNDW/10000;
|
|
fDestU = flb.fpixU + flb.fRadiusU*cos(fAngle);
|
|
fDestV = flb.fpixV + flb.fRadiusV*sin(fAngle);
|
|
fDistance = sqrt((fDestU-fLastU)*(fDestU-fLastU)+
|
|
(fDestV-fLastV)*(fDestV-fLastV));
|
|
// vector
|
|
fvU = (fDestU-fLastU)/fDistance;
|
|
fvV = (fDestV-fLastV)/fDistance;
|
|
// normal vector
|
|
fvNormalU = -fvV;
|
|
fvNormalV = fvU;
|
|
ulDist = 0;
|
|
while ((FLOAT)ulDist<fDistance) {
|
|
// go away from source point to destination point
|
|
ulDist += (RNDW%5)+5;
|
|
if ((FLOAT)ulDist>=fDistance) {
|
|
// move point on line
|
|
fU = fDestU;
|
|
fV = fDestV;
|
|
} else {
|
|
// move point on line
|
|
fU = flb.fpixU + fvU*(FLOAT)ulDist;
|
|
fV = flb.fpixV + fvV*(FLOAT)ulDist;
|
|
// move point offset on normal line
|
|
slRND = (SLONG) (RNDW%11)-5;
|
|
fU += fvNormalU*(FLOAT)slRND;
|
|
fV += fvNormalV*(FLOAT)slRND;
|
|
}
|
|
// draw line
|
|
fDU = fU-fLastU;
|
|
fDV = fV-fLastV;
|
|
// counter
|
|
if (Abs(fDU)>Abs(fDV)) fCnt = Abs(fDU);
|
|
else fCnt = Abs(fDV);
|
|
fDU = fDU/fCnt;
|
|
fDV = fDV/fCnt;
|
|
while (fCnt>0.0f) {
|
|
PutPixelUBYTE_FIRE((PIX) fLastU, (PIX) fLastV, 255);
|
|
fLastU += fDU;
|
|
fLastV += fDV;
|
|
fCnt -= 1;
|
|
}
|
|
// store last point
|
|
fLastU = fU;
|
|
fLastV = fV;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// Fire Smoke
|
|
#define SMOKE_POINTS 50
|
|
|
|
struct FireSmoke{
|
|
FLOAT fpixU;
|
|
FLOAT fpixV;
|
|
};
|
|
|
|
struct FireSmokePoint{
|
|
FLOAT fpixU;
|
|
FLOAT fpixV;
|
|
FLOAT fSpeedV;
|
|
};
|
|
|
|
void InitializeFireSmoke(CTextureEffectSource *ptes,
|
|
PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1)
|
|
{
|
|
FireSmoke &fs =
|
|
((FireSmoke&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
fs.fpixU = (FLOAT) pixU0;
|
|
fs.fpixV = (FLOAT) pixV0;
|
|
if (pixU0==pixU1 && pixV0==pixV1) {
|
|
} else {
|
|
}
|
|
// initialize smoke points
|
|
ptes->tes_atepPixels.New(SMOKE_POINTS*2);
|
|
for (INDEX iIndex=0; iIndex<SMOKE_POINTS*2; iIndex+=2) {
|
|
FireSmokePoint &fsp = ((FireSmokePoint&) ptes->tes_atepPixels[iIndex]);
|
|
fsp.fpixU = FLOAT (pixU0 + (iIndex-(SMOKE_POINTS))/8);
|
|
fsp.fpixV = FLOAT (pixV0);
|
|
fsp.fSpeedV = 0.0f;
|
|
}
|
|
}
|
|
|
|
void AnimateFireSmoke(CTextureEffectSource *ptes)
|
|
{
|
|
int iHeat;
|
|
FLOAT fRatio = 32.0f / (FLOAT)_pixBufferHeight;
|
|
UBYTE pixU, pixV;
|
|
|
|
FireSmoke &fs =
|
|
((FireSmoke&) ptes->tes_tespEffectSourceProperties.tesp_achDummy);
|
|
// animate smoke points
|
|
for (INDEX iIndex=0; iIndex<SMOKE_POINTS*2; iIndex+=2) {
|
|
FireSmokePoint &fsp = ((FireSmokePoint&) ptes->tes_atepPixels[iIndex]);
|
|
pixU = RNDW%3 - 1;
|
|
pixV = RNDW%3 - 1;
|
|
if (fsp.fSpeedV<0.1f) {
|
|
PutPixelUBYTE_FIRE((PIX) fsp.fpixU, (PIX) fsp.fpixV, RNDW%128);
|
|
} else {
|
|
iHeat = int(fsp.fpixV*fRatio+1);
|
|
PutPixel25UBYTE_FIRE((PIX) fsp.fpixU+pixU, (PIX) fsp.fpixV+pixV, RNDW%iHeat);
|
|
}
|
|
// start moving up
|
|
if (fsp.fSpeedV<0.1f && (RNDW&255)==0) {
|
|
fsp.fSpeedV = 1.0f;
|
|
}
|
|
// move up
|
|
fsp.fpixV -= fsp.fSpeedV;
|
|
// at the end of texture go on bottom
|
|
if (fsp.fpixV<=(FLOAT)_pixBufferHeight) {
|
|
fsp.fpixV = fs.fpixV;
|
|
fsp.fSpeedV = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////// Water
|
|
|
|
|
|
void InitializeWater(void)
|
|
{
|
|
Randomize( (ULONG)(_pTimer->GetHighPrecisionTimer().GetMilliseconds()));
|
|
}
|
|
|
|
|
|
/*******************************
|
|
Water Animation
|
|
********************************/
|
|
static void AnimateWater( SLONG slDensity)
|
|
{
|
|
_sfStats.StartTimer(CStatForm::STI_EFFECTRENDER);
|
|
|
|
/////////////////////////////////// move water
|
|
|
|
SWORD *pNew = (SWORD*)_ptdEffect->td_pubBuffer1;
|
|
SWORD *pOld = (SWORD*)_ptdEffect->td_pubBuffer2;
|
|
|
|
PIX pixV, pixU;
|
|
PIX pixOffset, iNew;
|
|
SLONG slLineAbove, slLineBelow, slLineLeft, slLineRight;
|
|
|
|
// inner rectangle (without 1 pixel top and bottom line)
|
|
pixOffset = _pixBufferWidth + 1;
|
|
for( pixV=_pixBufferHeight-2; pixV>0; pixV--) {
|
|
for( pixU=_pixBufferWidth; pixU>0; pixU--) {
|
|
iNew = (( (SLONG)pOld[pixOffset - _pixBufferWidth]
|
|
+ (SLONG)pOld[pixOffset + _pixBufferWidth]
|
|
+ (SLONG)pOld[pixOffset - 1]
|
|
+ (SLONG)pOld[pixOffset + 1]
|
|
) >> 1)
|
|
- (SLONG)pNew[pixOffset];
|
|
pNew[pixOffset] = iNew - (iNew >> slDensity);
|
|
pixOffset++;
|
|
}
|
|
}
|
|
|
|
// upper horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
slLineBelow = _pixBufferWidth + 1;
|
|
slLineLeft = 0;
|
|
slLineRight = 2;
|
|
pixOffset = 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
iNew = (( (SLONG)pOld[slLineAbove]
|
|
+ (SLONG)pOld[slLineBelow]
|
|
+ (SLONG)pOld[slLineLeft]
|
|
+ (SLONG)pOld[slLineRight]
|
|
) >> 1)
|
|
- (SLONG)pNew[pixOffset];
|
|
pNew[pixOffset] = iNew - (iNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// lower horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1;
|
|
slLineBelow = 1;
|
|
slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth;
|
|
slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2;
|
|
pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
iNew = (( (SLONG)pOld[slLineAbove]
|
|
+ (SLONG)pOld[slLineBelow]
|
|
+ (SLONG)pOld[slLineLeft]
|
|
+ (SLONG)pOld[slLineRight]
|
|
) >> 1)
|
|
- (SLONG)pNew[pixOffset];
|
|
pNew[pixOffset] = iNew - (iNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// corner ( 0, 0)
|
|
iNew = (( (SLONG)pOld[_pixBufferWidth]
|
|
+ (SLONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth]
|
|
+ (SLONG)pOld[1]
|
|
+ (SLONG)pOld[_pixBufferWidth-1]
|
|
) >> 1)
|
|
- (SLONG)pNew[0];
|
|
pNew[0] = iNew - (iNew >> slDensity);
|
|
// corner ( 0, _pixBufferWidth)
|
|
iNew = (( (SLONG)pOld[(2*_pixBufferWidth) - 1]
|
|
+ (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
+ (SLONG)pOld[0]
|
|
+ (SLONG)pOld[_pixBufferWidth-2]
|
|
) >> 1)
|
|
- (SLONG)pNew[_pixBufferWidth-1];
|
|
pNew[_pixBufferWidth-1] = iNew - (iNew >> slDensity);
|
|
// corner ( _pixBufferHeight, 0)
|
|
iNew = (( (SLONG)pOld[0]
|
|
+ (SLONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth]
|
|
+ (SLONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1]
|
|
+ (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
) >> 1)
|
|
- (SLONG)pNew[(_pixBufferHeight-1)*_pixBufferWidth];
|
|
pNew[(_pixBufferHeight-1)*_pixBufferWidth] = iNew - (iNew >> slDensity);
|
|
// corner ( _pixBufferHeight, _pixBufferWidth)
|
|
iNew = (( (SLONG)pOld[_pixBufferWidth-1]
|
|
+ (SLONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1]
|
|
+ (SLONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth]
|
|
+ (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2]
|
|
) >> 1)
|
|
- (SLONG)pNew[(_pixBufferHeight*_pixBufferWidth) - 1];
|
|
pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = iNew - (iNew >> slDensity);
|
|
|
|
// swap buffers
|
|
Swap( _ptdEffect->td_pubBuffer1, _ptdEffect->td_pubBuffer2);
|
|
|
|
_sfStats.StopTimer(CStatForm::STI_EFFECTRENDER);
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////// displace texture
|
|
|
|
|
|
#define PIXEL(u,v) pulTextureBase[ ((u)&(SLONG&)mmBaseWidthMask) + ((v)&(SLONG&)mmBaseHeightMask) *pixBaseWidth]
|
|
|
|
|
|
#pragma warning(disable: 4731)
|
|
static void RenderWater(void)
|
|
{
|
|
_sfStats.StartTimer(CStatForm::STI_EFFECTRENDER);
|
|
|
|
// get textures' parameters
|
|
ULONG *pulTexture = _ptdEffect->td_pulFrames;
|
|
PIX pixBaseWidth = _ptdBase->GetPixWidth();
|
|
PIX pixBaseHeight = _ptdBase->GetPixHeight();
|
|
ULONG *pulTextureBase = _ptdBase->td_pulFrames
|
|
+ GetMipmapOffset( _iWantedMipLevel, pixBaseWidth, pixBaseHeight);
|
|
pixBaseWidth >>= _iWantedMipLevel;
|
|
pixBaseHeight >>= _iWantedMipLevel;
|
|
mmBaseWidthMask = pixBaseWidth -1;
|
|
mmBaseHeightMask = pixBaseHeight-1;
|
|
|
|
ASSERT( _ptdEffect->td_pulFrames!=NULL && _ptdBase->td_pulFrames!=NULL);
|
|
SWORD *pswHeightMap = (SWORD*)_ptdEffect->td_pubBuffer1; // height map pointer
|
|
|
|
// copy top 2 lines from height map to bottom (so no mask offset will be needed)
|
|
memcpy( (void*)(pswHeightMap+(_pixBufferHeight*_pixBufferWidth)), (void*)pswHeightMap,
|
|
_pixBufferWidth*sizeof(SWORD)*2);
|
|
|
|
// execute corresponding displace routine
|
|
if( _pixBufferWidth >= _pixTexWidth)
|
|
{ // SUB-SAMPLING
|
|
SLONG slHeightMapStep, slHeightRowStep;
|
|
|
|
#if ASMOPT == 1
|
|
|
|
__asm {
|
|
push ebx
|
|
bsf ecx,D [_pixTexWidth]
|
|
dec ecx
|
|
mov eax,D [_pixBufferWidth]
|
|
sar eax,cl
|
|
mov D [slHeightMapStep],eax
|
|
|
|
bsf edx,eax
|
|
add edx,DISTORSION+2-1
|
|
mov D [mmShift],edx
|
|
|
|
sub eax,2
|
|
imul eax,D [_pixBufferWidth]
|
|
mov D [slHeightRowStep],eax
|
|
|
|
mov eax,D [pixBaseWidth]
|
|
mov edx,D [pixBaseHeight]
|
|
shl edx,16
|
|
or eax,edx
|
|
sub eax,0x00010001
|
|
mov D [mmBaseMasks],eax
|
|
|
|
mov eax,D [pixBaseWidth]
|
|
shl eax,16
|
|
or eax,1
|
|
mov D [mmBaseWidth],eax
|
|
|
|
mov ebx,D [pswHeightMap]
|
|
mov esi,D [pulTextureBase]
|
|
mov edi,D [pulTexture]
|
|
pxor mm6,mm6 // MM5 = 0 | 0 || pixV | pixU
|
|
mov eax,D [_pixBufferWidth]
|
|
mov edx,D [_pixTexHeight]
|
|
rowLoop:
|
|
push edx
|
|
mov ecx,D [_pixTexWidth]
|
|
pixLoop:
|
|
movd mm1,D [ebx]
|
|
movd mm3,D [ebx+ eax*2]
|
|
movq mm2,mm1
|
|
psubw mm3,mm1
|
|
pslld mm1,16
|
|
psubw mm2,mm1
|
|
pand mm2,Q [mm00M0]
|
|
por mm2,mm3
|
|
psraw mm2,Q [mmShift]
|
|
|
|
paddw mm2,mm6
|
|
pand mm2,Q [mmBaseMasks]
|
|
pmaddwd mm2,Q [mmBaseWidth]
|
|
movd edx,mm2
|
|
mov edx,D [esi+ edx*4]
|
|
mov D [edi],edx
|
|
// advance to next texture pixel
|
|
add ebx,D [slHeightMapStep]
|
|
add edi,4
|
|
paddd mm6,Q [mm0001]
|
|
dec ecx
|
|
jnz pixLoop
|
|
// advance to next texture row
|
|
pop edx
|
|
add ebx,D [slHeightRowStep]
|
|
paddd mm6,Q [mm0010]
|
|
dec edx
|
|
jnz rowLoop
|
|
emms
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
PIX pixPos, pixDU, pixDV;
|
|
slHeightMapStep = _pixBufferWidth/pixBaseWidth
|
|
slHeightRowStep = (slHeightMapStep-1)*_pixBufferWidth;
|
|
mmShift = DISTORSION+ FastLog2(slHeightMapStep) +2;
|
|
for( PIX pixV=0; pixV<_pixTexHeight; pixV++)
|
|
{ // row loop
|
|
for( PIX pixU=0; pixU<_pixTexWidth; pixU++)
|
|
{ // texel loop
|
|
pixPos = pswHeightMap[0];
|
|
pixDU = (pswHeightMap[1] - pixPos) >>(SLONG&)mmShift;
|
|
pixDV = (pswHeightMap[_pixBufferWidth] - pixPos) >>(SLONG&)mmShift;
|
|
pixDU = (pixU +pixDU) & (SLONG&)mmBaseWidthMask;
|
|
pixDV = (pixV +pixDV) & (SLONG&)mmBaseHeightMask;
|
|
*pulTexture++ = pulTextureBase[pixDV*pixBaseWidth + pixDU];
|
|
// advance to next texel in height map
|
|
pswHeightMap += slHeightMapStep;
|
|
}
|
|
pswHeightMap += slHeightRowStep;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
else if( _pixBufferWidth*2 == _pixTexWidth)
|
|
{ // BILINEAR SUPER-SAMPLING 2
|
|
|
|
#if ASMOPT == 1
|
|
|
|
__asm {
|
|
push ebx
|
|
bsf eax,D [pixBaseWidth]
|
|
mov edx,32
|
|
sub edx,eax
|
|
mov D [mmBaseWidthShift],edx
|
|
|
|
movq mm0,Q [mmBaseHeightMask]
|
|
psllq mm0,32
|
|
por mm0,Q [mmBaseWidthMask]
|
|
movq Q [mmBaseMasks],mm0
|
|
|
|
pxor mm6,mm6 // MM6 = pixV|pixU
|
|
mov ebx,D [pswHeightMap]
|
|
mov esi,D [pulTextureBase]
|
|
mov edi,D [pulTexture]
|
|
mov edx,D [_pixBufferHeight]
|
|
rowLoop2:
|
|
push edx
|
|
mov edx,D [_pixTexWidth]
|
|
mov ecx,D [_pixBufferWidth]
|
|
pixLoop2:
|
|
mov eax,D [_pixBufferWidth]
|
|
|
|
movd mm1,D [ebx+ 2]
|
|
movd mm0,D [ebx+ eax*2]
|
|
psllq mm0,32
|
|
por mm1,mm0
|
|
movd mm0,D [ebx]
|
|
punpckldq mm0,mm0
|
|
psubd mm1,mm0
|
|
movq mm0,mm6
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm1,mm0 // MM1 = slV_00 | slU_00
|
|
|
|
movd mm2,D [ebx+ 4]
|
|
movd mm0,D [ebx+ eax*2 +2]
|
|
psllq mm0,32
|
|
por mm2,mm0
|
|
movd mm0,D [ebx+ 2]
|
|
punpckldq mm0,mm0
|
|
psubd mm2,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1LO]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm2,mm0 // MM2 = slV_01 | slU_01
|
|
|
|
movd mm3,D [ebx+ eax*2 +2]
|
|
movd mm0,D [ebx+ eax*4]
|
|
psllq mm0,32
|
|
por mm3,mm0
|
|
movd mm0,D [ebx+ eax*2]
|
|
punpckldq mm0,mm0
|
|
psubd mm3,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1HI]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm3,mm0 // MM3 = slV_10 | slU_10
|
|
|
|
movd mm4,D [ebx+ eax*2 +4]
|
|
movd mm0,D [ebx+ eax*4 +2]
|
|
psllq mm0,32
|
|
por mm4,mm0
|
|
movd mm0,D [ebx+ eax*2 +2]
|
|
punpckldq mm0,mm0
|
|
psubd mm4,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1HILO]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm4,mm0 // MM4 = slV_11 | slU_11
|
|
|
|
movq mm0,mm1
|
|
psrad mm0,DISTORSION+1+0
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi],eax
|
|
|
|
movq mm0,mm1
|
|
paddd mm0,mm2
|
|
psrad mm0,DISTORSION+1+1
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ 4],eax
|
|
|
|
movq mm0,mm1
|
|
paddd mm0,mm3
|
|
psrad mm0,DISTORSION+1+1
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4],eax
|
|
|
|
paddd mm1,mm2
|
|
paddd mm1,mm3
|
|
paddd mm1,mm4
|
|
psrad mm1,DISTORSION+1+2
|
|
pand mm1,Q [mmBaseMasks]
|
|
movq mm7,mm1
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm1,mm7
|
|
movd eax,mm1
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +4],eax
|
|
|
|
// advance to next texture pixels
|
|
paddd mm6,Q [mm1LO]
|
|
add edi,8
|
|
add ebx,2
|
|
dec ecx
|
|
jnz pixLoop2
|
|
// advance to next texture row
|
|
lea edi,[edi+ edx*4]
|
|
pop edx
|
|
paddd mm6,Q [mm1HI]
|
|
dec edx
|
|
jnz rowLoop2
|
|
emms
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
SLONG slU_00, slU_01, slU_10, slU_11;
|
|
SLONG slV_00, slV_01, slV_10, slV_11;
|
|
for( PIX pixV=0; pixV<_pixBufferHeight; pixV++)
|
|
{ // row loop
|
|
for( PIX pixU=0; pixU<_pixBufferWidth; pixU++)
|
|
{ // texel loop
|
|
slU_00 = pswHeightMap[_pixBufferWidth*0+1] - pswHeightMap[_pixBufferWidth*0+0] + ((pixU+0)<<(DISTORSION+1+1));
|
|
slV_00 = pswHeightMap[_pixBufferWidth*1+0] - pswHeightMap[_pixBufferWidth*0+0] + ((pixV+0)<<(DISTORSION+1+1));
|
|
slU_01 = pswHeightMap[_pixBufferWidth*0+2] - pswHeightMap[_pixBufferWidth*0+1] + ((pixU+1)<<(DISTORSION+1+1));
|
|
slV_01 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*0+1] + ((pixV+0)<<(DISTORSION+1+1));
|
|
slU_10 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*1+0] + ((pixU+0)<<(DISTORSION+1+1));
|
|
slV_10 = pswHeightMap[_pixBufferWidth*2+0] - pswHeightMap[_pixBufferWidth*1+0] + ((pixV+1)<<(DISTORSION+1+1));
|
|
slU_11 = pswHeightMap[_pixBufferWidth*1+2] - pswHeightMap[_pixBufferWidth*1+1] + ((pixU+1)<<(DISTORSION+1+1));
|
|
slV_11 = pswHeightMap[_pixBufferWidth*2+1] - pswHeightMap[_pixBufferWidth*1+1] + ((pixV+1)<<(DISTORSION+1+1));
|
|
|
|
pulTexture[_pixTexWidth*0+0] = PIXEL( (slU_00 ) >>(DISTORSION+1 ), (slV_00 ) >>(DISTORSION+1 ) );
|
|
pulTexture[_pixTexWidth*0+1] = PIXEL( (slU_00+slU_01 ) >>(DISTORSION+1+1), (slV_00+slV_01 ) >>(DISTORSION+1+1) );
|
|
pulTexture[_pixTexWidth*1+0] = PIXEL( (slU_00 +slU_10 ) >>(DISTORSION+1+1), (slV_00 +slV_10 ) >>(DISTORSION+1+1) );
|
|
pulTexture[_pixTexWidth*1+1] = PIXEL( (slU_00+slU_01+slU_10+slU_11) >>(DISTORSION+1+2), (slV_00+slV_01+slV_10+slV_11) >>(DISTORSION+1+2) );
|
|
|
|
// advance to next texel
|
|
pulTexture+=2;
|
|
pswHeightMap++;
|
|
}
|
|
pulTexture+=_pixTexWidth;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
else if( _pixBufferWidth*4 == _pixTexWidth)
|
|
{ // BILINEAR SUPER-SAMPLING 4
|
|
|
|
#if ASMOPT == 1
|
|
|
|
__asm {
|
|
push ebx
|
|
bsf eax,D [pixBaseWidth]
|
|
mov edx,32
|
|
sub edx,eax
|
|
mov D [mmBaseWidthShift],edx
|
|
|
|
movq mm0,Q [mmBaseHeightMask]
|
|
psllq mm0,32
|
|
por mm0,Q [mmBaseWidthMask]
|
|
movq Q [mmBaseMasks],mm0
|
|
|
|
pxor mm6,mm6 // MM6 = pixV|pixU
|
|
mov ebx,D [pswHeightMap]
|
|
mov esi,D [pulTextureBase]
|
|
mov edi,D [pulTexture]
|
|
mov edx,D [_pixBufferHeight]
|
|
rowLoop4:
|
|
push edx
|
|
mov ecx,D [_pixBufferWidth]
|
|
pixLoop4:
|
|
mov eax,D [_pixBufferWidth]
|
|
mov edx,D [_pixTexWidth]
|
|
|
|
movd mm1,D [ebx+ 2]
|
|
movd mm0,D [ebx+ eax*2]
|
|
psllq mm0,32
|
|
por mm1,mm0
|
|
movd mm0,D [ebx]
|
|
punpckldq mm0,mm0
|
|
psubd mm1,mm0
|
|
movq mm0,mm6
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm1,mm0 // MM1 = slV_00 | slU_00
|
|
|
|
movd mm2,D [ebx+ 4]
|
|
movd mm0,D [ebx+ eax*2 +2]
|
|
psllq mm0,32
|
|
por mm2,mm0
|
|
movd mm0,D [ebx+ 2]
|
|
punpckldq mm0,mm0
|
|
psubd mm2,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1LO]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm2,mm0 // MM2 = slV_01 | slU_01
|
|
|
|
movd mm3,D [ebx+ eax*2 +2]
|
|
movd mm0,D [ebx+ eax*4]
|
|
psllq mm0,32
|
|
por mm3,mm0
|
|
movd mm0,D [ebx+ eax*2]
|
|
punpckldq mm0,mm0
|
|
psubd mm3,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1HI]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm3,mm0 // MM3 = slV_10 | slU_10
|
|
|
|
movd mm4,D [ebx+ eax*2 +4]
|
|
movd mm0,D [ebx+ eax*4 +2]
|
|
psllq mm0,32
|
|
por mm4,mm0
|
|
movd mm0,D [ebx+ eax*2 +2]
|
|
punpckldq mm0,mm0
|
|
psubd mm4,mm0
|
|
movq mm0,mm6
|
|
paddd mm0,Q [mm1HILO]
|
|
pslld mm0,DISTORSION+1+1
|
|
paddd mm4,mm0 // MM4 = slV_11 | slU_11
|
|
|
|
// texel 00
|
|
movq mm0,mm1
|
|
psrad mm0,DISTORSION
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi],eax
|
|
// texel 01
|
|
movq mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
psrad mm0,DISTORSION+2
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi +4],eax
|
|
// texel 02
|
|
movq mm0,mm1
|
|
paddd mm0,mm2
|
|
psrad mm0,DISTORSION+1
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi +8],eax
|
|
// texel 03
|
|
movq mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
psrad mm0,DISTORSION+2
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi +12],eax
|
|
|
|
// texel 10
|
|
movq mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm3
|
|
psrad mm0,DISTORSION+2
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4],eax
|
|
// texel 11
|
|
movq mm0,mm1
|
|
pslld mm0,3
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+4
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +4],eax
|
|
// texel 12
|
|
movq mm0,mm1
|
|
paddd mm0,mm0
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+3
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +8],eax
|
|
// texel 13
|
|
movq mm0,mm2
|
|
pslld mm0,3
|
|
paddd mm0,mm2
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+4
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +12],eax
|
|
|
|
// texel 20
|
|
movq mm0,mm1
|
|
paddd mm0,mm3
|
|
psrad mm0,DISTORSION+1
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*8],eax
|
|
// texel 21
|
|
movq mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+3
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*8 +4],eax
|
|
// texel 22
|
|
movq mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+2
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*8 +8],eax
|
|
// texel 23
|
|
movq mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+3
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*8 +12],eax
|
|
|
|
imul edx,3 // _pixTexWidth*=3
|
|
// texel 30
|
|
movq mm0,mm1
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
psrad mm0,DISTORSION+2
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4],eax
|
|
// texel 31
|
|
movq mm0,mm3
|
|
pslld mm0,3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
paddd mm0,mm4
|
|
psrad mm0,DISTORSION+4
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +4],eax
|
|
// texel 32
|
|
movq mm0,mm4
|
|
paddd mm0,mm0
|
|
paddd mm0,mm4
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm2
|
|
paddd mm0,mm1
|
|
psrad mm0,DISTORSION+3
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +8],eax
|
|
// texel 33
|
|
movq mm0,mm4
|
|
pslld mm0,3
|
|
paddd mm0,mm4
|
|
paddd mm0,mm1
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm2
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
paddd mm0,mm3
|
|
psrad mm0,DISTORSION+4
|
|
pand mm0,Q [mmBaseMasks]
|
|
movq mm7,mm0
|
|
psrlq mm7,Q [mmBaseWidthShift]
|
|
paddd mm0,mm7
|
|
movd eax,mm0
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi+ edx*4 +12],eax
|
|
|
|
// advance to next texture pixels
|
|
paddd mm6,Q [mm1LO]
|
|
add edi,16
|
|
add ebx,2
|
|
dec ecx
|
|
jnz pixLoop4
|
|
// advance to next texture row
|
|
lea edi,[edi+ edx*4] // +=[_pixTexWidth]*3
|
|
pop edx
|
|
paddd mm6,Q [mm1HI]
|
|
dec edx
|
|
jnz rowLoop4
|
|
emms
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
SLONG slU_00, slU_01, slU_10, slU_11;
|
|
SLONG slV_00, slV_01, slV_10, slV_11;
|
|
mmBaseWidthShift = FastLog2( pixBaseWidth); // faster multiplying with shift
|
|
for( PIX pixV=0; pixV<_pixBufferHeight; pixV++)
|
|
{ // row loop
|
|
for( PIX pixU=0; pixU<_pixBufferWidth; pixU++)
|
|
{ // texel loop
|
|
slU_00 = pswHeightMap[_pixBufferWidth*0+1] - pswHeightMap[_pixBufferWidth*0+0] + ((pixU+0)<<(DISTORSION+2));
|
|
slV_00 = pswHeightMap[_pixBufferWidth*1+0] - pswHeightMap[_pixBufferWidth*0+0] + ((pixV+0)<<(DISTORSION+2));
|
|
slU_01 = pswHeightMap[_pixBufferWidth*0+2] - pswHeightMap[_pixBufferWidth*0+1] + ((pixU+1)<<(DISTORSION+2));
|
|
slV_01 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*0+1] + ((pixV+0)<<(DISTORSION+2));
|
|
slU_10 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*1+0] + ((pixU+0)<<(DISTORSION+2));
|
|
slV_10 = pswHeightMap[_pixBufferWidth*2+0] - pswHeightMap[_pixBufferWidth*1+0] + ((pixV+1)<<(DISTORSION+2));
|
|
slU_11 = pswHeightMap[_pixBufferWidth*1+2] - pswHeightMap[_pixBufferWidth*1+1] + ((pixU+1)<<(DISTORSION+2));
|
|
slV_11 = pswHeightMap[_pixBufferWidth*2+1] - pswHeightMap[_pixBufferWidth*1+1] + ((pixV+1)<<(DISTORSION+2));
|
|
|
|
pulTexture[_pixTexWidth*0+0] = PIXEL( (slU_00 ) >>(DISTORSION ), (slV_00 ) >>(DISTORSION ) );
|
|
pulTexture[_pixTexWidth*0+1] = PIXEL( (slU_00* 3+slU_01* 1 ) >>(DISTORSION+2), (slV_00* 3+slV_01* 1 ) >>(DISTORSION+2) );
|
|
pulTexture[_pixTexWidth*0+2] = PIXEL( (slU_00 +slU_01 ) >>(DISTORSION+1), (slV_00 +slV_01 ) >>(DISTORSION+1) );
|
|
pulTexture[_pixTexWidth*0+3] = PIXEL( (slU_00* 1+slU_01* 3 ) >>(DISTORSION+2), (slV_00* 1+slV_01* 3 ) >>(DISTORSION+2) );
|
|
|
|
pulTexture[_pixTexWidth*1+0] = PIXEL( (slU_00* 3 +slU_10* 1 ) >>(DISTORSION+2), (slV_00* 3 +slV_10 ) >>(DISTORSION+2) );
|
|
pulTexture[_pixTexWidth*1+1] = PIXEL( (slU_00* 9+slU_01* 3+slU_10* 3+slU_11* 1) >>(DISTORSION+4), (slV_00* 9+slV_01* 3+slV_10* 3+slV_11* 1) >>(DISTORSION+4) );
|
|
pulTexture[_pixTexWidth*1+2] = PIXEL( (slU_00* 3+slU_01* 3+slU_10* 1+slU_11* 1) >>(DISTORSION+3), (slV_00* 3+slV_01* 3+slV_10* 1+slV_11* 1) >>(DISTORSION+3) );
|
|
pulTexture[_pixTexWidth*1+3] = PIXEL( (slU_00* 3+slU_01* 9+slU_10* 1+slU_11* 3) >>(DISTORSION+4), (slV_00* 3+slV_01* 9+slV_10* 1+slV_11* 3) >>(DISTORSION+4) );
|
|
|
|
pulTexture[_pixTexWidth*2+0] = PIXEL( (slU_00 +slU_10 ) >>(DISTORSION+1), (slV_00 +slV_10 ) >>(DISTORSION+1) );
|
|
pulTexture[_pixTexWidth*2+1] = PIXEL( (slU_00* 3+slU_01* 1+slU_10* 3+slU_11* 1) >>(DISTORSION+3), (slV_00* 3+slV_01* 1+slV_10* 3+slV_11* 1) >>(DISTORSION+3) );
|
|
pulTexture[_pixTexWidth*2+2] = PIXEL( (slU_00 +slU_01 +slU_10 +slU_11 ) >>(DISTORSION+2), (slV_00 +slV_01 +slV_10 +slV_11 ) >>(DISTORSION+2) );
|
|
pulTexture[_pixTexWidth*2+3] = PIXEL( (slU_00* 1+slU_01* 3+slU_10* 1+slU_11* 3) >>(DISTORSION+3), (slV_00* 1+slV_01* 3+slV_10* 1+slV_11* 3) >>(DISTORSION+3) );
|
|
|
|
pulTexture[_pixTexWidth*3+0] = PIXEL( (slU_00* 1 +slU_10* 3 ) >>(DISTORSION+2), (slV_00* 1 +slV_10* 3 ) >>(DISTORSION+2) );
|
|
pulTexture[_pixTexWidth*3+1] = PIXEL( (slU_00* 3+slU_01* 1+slU_10* 9+slU_11* 3) >>(DISTORSION+4), (slV_00* 3+slV_01* 1+slV_10* 9+slV_11* 3) >>(DISTORSION+4) );
|
|
pulTexture[_pixTexWidth*3+2] = PIXEL( (slU_00* 1+slU_01* 1+slU_10* 3+slU_11* 3) >>(DISTORSION+3), (slV_00* 1+slV_01* 1+slV_10* 3+slV_11* 3) >>(DISTORSION+3) );
|
|
pulTexture[_pixTexWidth*3+3] = PIXEL( (slU_00* 1+slU_01* 3+slU_10* 3+slU_11* 9) >>(DISTORSION+4), (slV_00* 1+slV_01* 3+slV_10* 3+slV_11* 9) >>(DISTORSION+4) );
|
|
|
|
// advance to next texel
|
|
pulTexture+=4;
|
|
pHeightMap++;
|
|
}
|
|
pulTexture+=_pixTexWidth*3;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{ // DO NOTHING
|
|
ASSERTALWAYS( "Effect textures larger than 256 pixels aren't supported");
|
|
}
|
|
|
|
_sfStats.StopTimer(CStatForm::STI_EFFECTRENDER);
|
|
}
|
|
#pragma warning(default: 4731)
|
|
|
|
|
|
|
|
///////////////// Fire
|
|
|
|
|
|
void InitializeFire(void)
|
|
{
|
|
Randomize( (ULONG)(_pTimer->GetHighPrecisionTimer().GetMilliseconds()));
|
|
}
|
|
|
|
enum PlasmaType {
|
|
ptNormal = 0,
|
|
ptUp,
|
|
ptUpTile,
|
|
ptDown,
|
|
ptDownTile
|
|
};
|
|
|
|
/*******************************
|
|
Plasma Animation
|
|
********************************/
|
|
static void AnimatePlasma( SLONG slDensity, PlasmaType eType)
|
|
{
|
|
_sfStats.StartTimer(CStatForm::STI_EFFECTRENDER);
|
|
|
|
/////////////////////////////////// move plasma
|
|
|
|
UBYTE *pNew = (UBYTE*)_ptdEffect->td_pubBuffer1;
|
|
UBYTE *pOld = (UBYTE*)_ptdEffect->td_pubBuffer2;
|
|
|
|
PIX pixV, pixU;
|
|
PIX pixOffset;
|
|
SLONG slLineAbove, slLineBelow, slLineLeft, slLineRight;
|
|
ULONG ulNew;
|
|
|
|
// --------------------------
|
|
// Normal plasma
|
|
// --------------------------
|
|
if (eType == ptNormal) {
|
|
// inner rectangle (without 1 pixel border)
|
|
pixOffset = _pixBufferWidth;
|
|
for( pixV=1; pixV<_pixBufferHeight-1; pixV++) {
|
|
for( pixU=0; pixU<_pixBufferWidth; pixU++) {
|
|
ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset + _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset - 1] +
|
|
(ULONG)pOld[pixOffset + 1]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[pixOffset] = ulNew - (ulNew >> slDensity);
|
|
pixOffset++;
|
|
}
|
|
}
|
|
// upper horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
slLineBelow = _pixBufferWidth + 1;
|
|
slLineLeft = 0;
|
|
slLineRight = 2;
|
|
pixOffset = 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[pixOffset] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// lower horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1;
|
|
slLineBelow = 1;
|
|
slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth;
|
|
slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2;
|
|
pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[pixOffset] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// corner ( 0, 0)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[1] +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>2) +
|
|
(ULONG)pOld[0]
|
|
)>>1;
|
|
pNew[0] = ulNew - (ulNew >> slDensity);
|
|
// corner ( 0, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[0] +
|
|
(ULONG)pOld[_pixBufferWidth-2]
|
|
)>>2) +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>1;
|
|
pNew[_pixBufferWidth-1] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, 0)
|
|
ulNew = ((((ULONG)pOld[0] +
|
|
(ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth]
|
|
)>>1;
|
|
pNew[(_pixBufferHeight-1)*_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth-1] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>1;
|
|
pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity);
|
|
|
|
|
|
// --------------------------
|
|
// Plasma going up
|
|
// --------------------------
|
|
} else if (eType==ptUp || eType==ptUpTile) {
|
|
// inner rectangle (without 1 pixel border)
|
|
pixOffset = _pixBufferWidth;
|
|
for( pixV=1; pixV<_pixBufferHeight-1; pixV++) {
|
|
for( pixU=0; pixU<_pixBufferWidth; pixU++) {
|
|
ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset + _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset - 1] +
|
|
(ULONG)pOld[pixOffset + 1]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[pixOffset-_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
pixOffset++;
|
|
}
|
|
}
|
|
// tile
|
|
if (eType==ptUpTile) {
|
|
// upper horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
slLineBelow = _pixBufferWidth + 1;
|
|
slLineLeft = 0;
|
|
slLineRight = 2;
|
|
pixOffset = 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[slLineAbove] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// lower horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1;
|
|
slLineBelow = 1;
|
|
slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth;
|
|
slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2;
|
|
pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[slLineAbove] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// corner ( 0, 0)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[1] +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>2) +
|
|
(ULONG)pOld[0]
|
|
)>>1;
|
|
pNew[(_pixBufferHeight-1)*_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
// corner ( 0, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[0] +
|
|
(ULONG)pOld[_pixBufferWidth-2]
|
|
)>>2) +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>1;
|
|
pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, 0)
|
|
ulNew = ((((ULONG)pOld[0] +
|
|
(ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth]
|
|
)>>1;
|
|
pNew[(_pixBufferHeight-2)*_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth-1] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>1;
|
|
pNew[((_pixBufferHeight-1)*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity);
|
|
}
|
|
|
|
|
|
// --------------------------
|
|
// Plasma going down
|
|
// --------------------------
|
|
} else if (eType==ptDown || eType==ptDownTile) {
|
|
// inner rectangle (without 1 pixel border)
|
|
pixOffset = _pixBufferWidth;
|
|
for( pixV=1; pixV<_pixBufferHeight-1; pixV++) {
|
|
for( pixU=0; pixU<_pixBufferWidth; pixU++) {
|
|
ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset + _pixBufferWidth] +
|
|
(ULONG)pOld[pixOffset - 1] +
|
|
(ULONG)pOld[pixOffset + 1]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[pixOffset+_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
pixOffset++;
|
|
}
|
|
}
|
|
// tile
|
|
if (eType==ptDownTile) {
|
|
// upper horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
slLineBelow = _pixBufferWidth + 1;
|
|
slLineLeft = 0;
|
|
slLineRight = 2;
|
|
pixOffset = 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[slLineBelow] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// lower horizontal border (without corners)
|
|
slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1;
|
|
slLineBelow = 1;
|
|
slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth;
|
|
slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2;
|
|
pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1;
|
|
for( pixU=_pixBufferWidth-2; pixU>0; pixU--) {
|
|
ulNew = ((((ULONG)pOld[slLineAbove] +
|
|
(ULONG)pOld[slLineBelow] +
|
|
(ULONG)pOld[slLineLeft] +
|
|
(ULONG)pOld[slLineRight]
|
|
)>>2) +
|
|
(ULONG)pOld[pixOffset]
|
|
)>>1;
|
|
pNew[slLineBelow] = ulNew - (ulNew >> slDensity);
|
|
slLineAbove++;
|
|
slLineBelow++;
|
|
slLineLeft++;
|
|
slLineRight++;
|
|
pixOffset++;
|
|
}
|
|
// corner ( 0, 0)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[1] +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>2) +
|
|
(ULONG)pOld[0]
|
|
)>>1;
|
|
pNew[_pixBufferWidth] = ulNew - (ulNew >> slDensity);
|
|
// corner ( 0, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[0] +
|
|
(ULONG)pOld[_pixBufferWidth-2]
|
|
)>>2) +
|
|
(ULONG)pOld[_pixBufferWidth-1]
|
|
)>>1;
|
|
pNew[(2*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, 0)
|
|
ulNew = ((((ULONG)pOld[0] +
|
|
(ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth]
|
|
)>>1;
|
|
pNew[0] = ulNew - (ulNew >> slDensity);
|
|
// corner ( _pixBufferHeight, _pixBufferWidth)
|
|
ulNew = ((((ULONG)pOld[_pixBufferWidth-1] +
|
|
(ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] +
|
|
(ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2]
|
|
)>>2) +
|
|
(ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1]
|
|
)>>1;
|
|
pNew[_pixBufferWidth-1] = ulNew - (ulNew >> slDensity);
|
|
}
|
|
}
|
|
|
|
// swap buffers
|
|
Swap( _ptdEffect->td_pubBuffer1, _ptdEffect->td_pubBuffer2);
|
|
|
|
_sfStats.StopTimer(CStatForm::STI_EFFECTRENDER);
|
|
}
|
|
|
|
|
|
/*******************************
|
|
Fire Animation
|
|
********************************/
|
|
static void AnimateFire( SLONG slDensity)
|
|
{
|
|
// _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER);
|
|
|
|
/////////////////////////////////// move fire
|
|
|
|
// use only one buffer (otherwise it's not working)
|
|
UBYTE *pubNew = (UBYTE*)_ptdEffect->td_pubBuffer2;
|
|
SLONG slBufferMask = _pixBufferWidth*_pixBufferHeight -1;
|
|
SLONG slColumnModulo = _pixBufferWidth*(_pixBufferHeight-2) -1;
|
|
|
|
#if ASMOPT == 1
|
|
|
|
__asm {
|
|
push ebx
|
|
mov edi,D [ulRNDSeed] ;// EDI = randomizer
|
|
mov esi,D [pubNew]
|
|
xor ebx,ebx
|
|
|
|
colLoopFM:
|
|
mov ecx,D [_pixBufferHeight]
|
|
sub ecx,2
|
|
|
|
rowLoopFM:
|
|
mov edx,D [_pixBufferWidth]
|
|
add edx,esi
|
|
movzx eax,B [ebx+ edx]
|
|
add edx,D [_pixBufferWidth]
|
|
movzx edx,B [ebx+ edx]
|
|
add eax,edx
|
|
shr eax,1
|
|
cmp eax,D [slDensity]
|
|
jg doCalc
|
|
mov B [esi+ebx],0
|
|
jmp pixDone
|
|
doCalc:
|
|
mov edx,edi
|
|
sar edx,16
|
|
and edx,D [slDensity]
|
|
sub eax,edx
|
|
movsx edx,B [asbMod3Sub1Table +edx]
|
|
add edx,ebx
|
|
and edx,D [slBufferMask]
|
|
mov B [esi+edx],al
|
|
imul edi,262147
|
|
|
|
pixDone:
|
|
// advance to next row
|
|
add ebx,D [_pixBufferWidth]
|
|
dec ecx
|
|
jnz rowLoopFM
|
|
|
|
// advance to next column
|
|
sub ebx,D [slColumnModulo]
|
|
cmp ebx,D [_pixBufferWidth]
|
|
jl colLoopFM
|
|
|
|
// all done
|
|
mov D [ulRNDSeed],edi
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
// inner rectangle (without 1 pixel border)
|
|
for( PIX pixU=0; pixU<_pixBufferWidth; pixU++)
|
|
{
|
|
SLONG slOffset = pixU;
|
|
for( PIX pixV=1; pixV<_pixBufferHeight-1; pixV++)
|
|
{
|
|
ULONG ulNew = ((ULONG)pubNew[_pixBufferWidth+slOffset] + (ULONG)pubNew[_pixBufferWidth*2+slOffset]) >>1;
|
|
if( ulNew>slDensity) {
|
|
ULONG ulNewDensity = RNDW&slDensity;
|
|
ulNew -= ulNewDensity;
|
|
SLONG slDifusion = (SLONG)asbMod3Sub1Table[ulNewDensity]; // (SLONG)(ulNewDensity%3-1);
|
|
SLONG slPos = (slDifusion+slOffset) & slBufferMask;
|
|
pubNew[slPos] = ulNew;
|
|
} else {
|
|
pubNew[slOffset] = 0;
|
|
}
|
|
slOffset += _pixBufferWidth;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER);
|
|
}
|
|
|
|
//////////////////////////// displace texture
|
|
|
|
static void RenderPlasmaFire(void)
|
|
{
|
|
// _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER);
|
|
|
|
// get and adjust textures' parameters
|
|
PIX pixBaseWidth = _ptdBase->GetPixWidth();
|
|
ULONG *pulTextureBase = _ptdBase->td_pulFrames;
|
|
ULONG *pulTexture = _ptdEffect->td_pulFrames;
|
|
|
|
ASSERT( _ptdEffect->td_pulFrames!=NULL && _ptdBase->td_pulFrames!=NULL && pixBaseWidth<=256);
|
|
UBYTE *pubHeat = (UBYTE*)_ptdEffect->td_pubBuffer2; // heat map pointer
|
|
SLONG slHeatMapStep = _pixBufferWidth/_pixTexWidth;
|
|
SLONG slHeatRowStep = (slHeatMapStep-1)*_pixBufferWidth;
|
|
SLONG slBaseMipShift = 8 - FastLog2(pixBaseWidth);
|
|
|
|
#if ASMOPT == 1
|
|
|
|
__asm {
|
|
push ebx
|
|
mov ebx,D [pubHeat]
|
|
mov esi,D [pulTextureBase]
|
|
mov edi,D [pulTexture]
|
|
mov ecx,D [_pixTexHeight]
|
|
rowLoopF:
|
|
push ecx
|
|
mov edx,D [_pixTexWidth]
|
|
mov ecx,D [slBaseMipShift]
|
|
pixLoopF:
|
|
movzx eax,B [ebx]
|
|
shr eax,cl
|
|
mov eax,D [esi+ eax*4]
|
|
mov D [edi],eax
|
|
// advance to next pixel
|
|
add ebx,D [slHeatMapStep]
|
|
add edi,4
|
|
dec edx
|
|
jnz pixLoopF
|
|
// advance to next row
|
|
pop ecx
|
|
add ebx,D [slHeatRowStep]
|
|
dec ecx
|
|
jnz rowLoopF
|
|
pop ebx
|
|
}
|
|
|
|
#else
|
|
|
|
INDEX iPalette;
|
|
for( INDEX pixV=0; pixV<_pixTexHeight; pixV++) {
|
|
// for every pixel in horizontal line
|
|
for( INDEX pixU=0; pixU<_pixTexWidth; pixU++) {
|
|
iPalette = (*pubHeat)>>slBaseMipShift;
|
|
*pulTexture++ = pulTextureBase[iPalette];
|
|
pubHeat += slHeatMapStep;
|
|
}
|
|
pubHeat += slHeatRowStep;
|
|
}
|
|
|
|
#endif
|
|
|
|
// _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// EFFECT TABLES
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
struct TextureEffectSourceType atestWater[] = {
|
|
{
|
|
"Raindrops",
|
|
InitializeRaindropsStandard,
|
|
AnimateRaindropsStandard
|
|
},
|
|
{
|
|
"RaindropsBig",
|
|
InitializeRaindropsBig,
|
|
AnimateRaindropsBig
|
|
},
|
|
{
|
|
"RaindropsSmall",
|
|
InitializeRaindropsSmall,
|
|
AnimateRaindropsSmall
|
|
},
|
|
{
|
|
"Random Surfer",
|
|
InitializeRandomSurfer,
|
|
AnimateRandomSurfer
|
|
},
|
|
{
|
|
"Oscilator",
|
|
InitializeOscilator,
|
|
AnimateOscilator
|
|
},
|
|
{
|
|
"Vertical Line",
|
|
InitializeVertLine,
|
|
AnimateVertLine
|
|
},
|
|
{
|
|
"Horizontal Line",
|
|
InitializeHortLine,
|
|
AnimateHortLine
|
|
},
|
|
};
|
|
|
|
struct TextureEffectSourceType atestFire[] = {
|
|
{
|
|
"Point",
|
|
InitializeFirePoint,
|
|
AnimateFirePoint
|
|
},
|
|
{
|
|
"Random Point",
|
|
InitializeRandomFirePoint,
|
|
AnimateRandomFirePoint
|
|
},
|
|
{
|
|
"Shake Point",
|
|
InitializeFireShakePoint,
|
|
AnimateFireShakePoint
|
|
},
|
|
{
|
|
"Fire Place",
|
|
InitializeFirePlace,
|
|
AnimateFirePlace
|
|
},
|
|
{
|
|
"Roler",
|
|
InitializeFireRoler,
|
|
AnimateFireRoler
|
|
},
|
|
{
|
|
"Fall",
|
|
InitializeFireFall,
|
|
AnimateFireFall
|
|
},
|
|
{
|
|
"Fountain",
|
|
InitializeFireFountain,
|
|
AnimateFireFountain
|
|
},
|
|
{
|
|
"Side Fountain",
|
|
InitializeFireSideFountain,
|
|
AnimateFireSideFountain
|
|
},
|
|
{
|
|
"Lightning",
|
|
InitializeFireLightning,
|
|
AnimateFireLightning
|
|
},
|
|
{
|
|
"Lightning Ball",
|
|
InitializeFireLightningBall,
|
|
AnimateFireLightningBall
|
|
},
|
|
{
|
|
"Smoke",
|
|
InitializeFireSmoke,
|
|
AnimateFireSmoke
|
|
},
|
|
};
|
|
|
|
|
|
void AWaterFast(void) { AnimateWater(2); };
|
|
void AWaterMedium(void) { AnimateWater(3); };
|
|
void AWaterSlow(void) { AnimateWater(5); };
|
|
|
|
void APlasma(void) { AnimatePlasma(4, ptNormal); };
|
|
void APlasmaUp(void) { AnimatePlasma(4, ptUp); };
|
|
void APlasmaUpTile(void) { AnimatePlasma(4, ptUpTile); };
|
|
void APlasmaDown(void) { AnimatePlasma(5, ptDown); };
|
|
void APlasmaDownTile(void) { AnimatePlasma(5, ptDownTile); };
|
|
void APlasmaUpSlow(void) { AnimatePlasma(6, ptUp); };
|
|
|
|
void AFire(void) { AnimateFire(15); };
|
|
|
|
|
|
struct TextureEffectGlobalType _ategtTextureEffectGlobalPresets[] = {
|
|
{
|
|
"Water Fast",
|
|
InitializeWater,
|
|
AWaterFast,
|
|
sizeof(atestWater)/sizeof(atestWater[0]),
|
|
atestWater
|
|
},
|
|
{
|
|
"Water Medium",
|
|
InitializeWater,
|
|
AWaterMedium,
|
|
sizeof(atestWater)/sizeof(atestWater[0]),
|
|
atestWater
|
|
},
|
|
{
|
|
"Water Slow",
|
|
InitializeWater,
|
|
AWaterSlow,
|
|
sizeof(atestWater)/sizeof(atestWater[0]),
|
|
atestWater
|
|
},
|
|
{
|
|
"",
|
|
InitializeWater,
|
|
AWaterSlow,
|
|
sizeof(atestWater)/sizeof(atestWater[0]),
|
|
atestWater
|
|
},
|
|
{
|
|
"Plasma Tile",
|
|
InitializeFire,
|
|
APlasma,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Plasma Up",
|
|
InitializeFire,
|
|
APlasmaUp,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Plasma Up Tile",
|
|
InitializeFire,
|
|
APlasmaUpTile,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Plasma Down",
|
|
InitializeFire,
|
|
APlasmaDown,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Plasma Down Tile",
|
|
InitializeFire,
|
|
APlasmaDownTile,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Plasma Up Slow",
|
|
InitializeFire,
|
|
APlasmaUpSlow,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
{
|
|
"Fire",
|
|
InitializeFire,
|
|
AFire,
|
|
sizeof(atestFire)/sizeof(atestFire[0]),
|
|
atestFire
|
|
},
|
|
};
|
|
|
|
INDEX _ctTextureEffectGlobalPresets = sizeof(_ategtTextureEffectGlobalPresets)
|
|
/ sizeof(_ategtTextureEffectGlobalPresets[0]);
|
|
|
|
|
|
// get effect type (TRUE if water type effect, FALSE if plasma or fire effect)
|
|
BOOL CTextureEffectGlobal::IsWater(void)
|
|
{
|
|
return( _ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Initialize == InitializeWater);
|
|
}
|
|
|
|
// default constructor
|
|
CTextureEffectGlobal::CTextureEffectGlobal(CTextureData *ptdTexture, ULONG ulGlobalEffect)
|
|
{
|
|
// remember global effect's texture data for cross linking
|
|
teg_ptdTexture = ptdTexture;
|
|
teg_ulEffectType = ulGlobalEffect;
|
|
// init for animating
|
|
_ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Initialize();
|
|
// make sure the texture will be updated next time when used
|
|
teg_updTexture.Invalidate();
|
|
}
|
|
|
|
// add new effect source.
|
|
void CTextureEffectGlobal::AddEffectSource( ULONG ulEffectSourceType, PIX pixU0, PIX pixV0,
|
|
PIX pixU1, PIX pixV1)
|
|
{
|
|
CTextureEffectSource* ptesNew = teg_atesEffectSources.New(1);
|
|
ptesNew->Initialize(this, ulEffectSourceType, pixU0, pixV0, pixU1, pixV1);
|
|
}
|
|
|
|
// animate effect texture
|
|
void CTextureEffectGlobal::Animate(void)
|
|
{
|
|
// if not set yet (funny word construction:)
|
|
if( !bTableSet) {
|
|
// set table for fast modulo 3 minus 1
|
|
for( INDEX i=0; i<256; i++) asbMod3Sub1Table[i]=(SBYTE)((i%3)-1);
|
|
bTableSet = TRUE;
|
|
}
|
|
|
|
// setup some internal vars
|
|
_ptdEffect = teg_ptdTexture;
|
|
_pixBufferWidth = _ptdEffect->td_pixBufferWidth;
|
|
_pixBufferHeight = _ptdEffect->td_pixBufferHeight;
|
|
_ulBufferMask = _pixBufferHeight*_pixBufferWidth -1;
|
|
|
|
// remember buffer pointers
|
|
_pubDrawBuffer=(UBYTE*)_ptdEffect->td_pubBuffer2;
|
|
_pswDrawBuffer=(SWORD*)_ptdEffect->td_pubBuffer2;
|
|
|
|
// for each effect source
|
|
FOREACHINDYNAMICARRAY( teg_atesEffectSources, CTextureEffectSource, itEffectSource) {
|
|
// let it animate itself
|
|
itEffectSource->Animate();
|
|
}
|
|
// use animation function for this global effect type
|
|
_ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Animate();
|
|
// remember that it was calculated
|
|
teg_updTexture.MarkUpdated();
|
|
}
|
|
|
|
#pragma warning(disable: 4731)
|
|
// render effect texture
|
|
void CTextureEffectGlobal::Render( INDEX iWantedMipLevel, PIX pixTexWidth, PIX pixTexHeight)
|
|
{
|
|
// setup some internal vars
|
|
_ptdEffect = teg_ptdTexture;
|
|
_ptdBase = teg_ptdTexture->td_ptdBaseTexture;
|
|
_pixBufferWidth = _ptdEffect->td_pixBufferWidth;
|
|
_pixBufferHeight = _ptdEffect->td_pixBufferHeight;
|
|
|
|
if( IsWater()) {
|
|
// use water rendering routine
|
|
_pixTexWidth = pixTexWidth;
|
|
_pixTexHeight = pixTexHeight;
|
|
_iWantedMipLevel = iWantedMipLevel;
|
|
RenderWater();
|
|
} else {
|
|
// use plasma & fire rendering routine
|
|
_pixTexWidth = _ptdEffect->GetWidth() >>iWantedMipLevel;
|
|
_pixTexHeight = _ptdEffect->GetHeight() >>iWantedMipLevel;
|
|
RenderPlasmaFire();
|
|
}
|
|
}
|
|
#pragma warning(default: 4731)
|
|
|
|
// returns number of second it took to render effect texture
|
|
DOUBLE CTextureEffectGlobal::GetRenderingTime(void)
|
|
{
|
|
return( _sfStats.sf_astTimers[CStatForm::STI_EFFECTRENDER].st_tvElapsed.GetSeconds());
|
|
}
|
|
|
|
|