388 lines
9.7 KiB
C++
388 lines
9.7 KiB
C++
// Fast2D.cpp : Defines the entry point for the DLL application.
|
|
//
|
|
#include "Fast2D.h"
|
|
#include "memory.h"
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
//#include "Rrasters.h"
|
|
|
|
#ifdef _MANAGED
|
|
#pragma managed(push, off)
|
|
#endif
|
|
|
|
#ifdef FAST2D_DLL_MODE
|
|
BOOL APIENTRY DllMain( HMODULE hModule,
|
|
DWORD ul_reason_for_call,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
switch (ul_reason_for_call)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _MANAGED
|
|
#pragma managed(pop)
|
|
#endif
|
|
|
|
// This is the constructor of a class that has been exported.
|
|
// see Fast2D.h for the class definition
|
|
u32 CFast2D::FirstInit = 0;
|
|
s32 CFast2D::LeveledSize[F2DTLevels] = {F2DT8Size,F2DT8Size1,F2DT8Size2};
|
|
s32 CFast2D::LeveledDelta[F2DTLevels];
|
|
|
|
MAP16 CFast2D::MWork[F2DTLevels];
|
|
MAP16 CFast2D::MWork_Help[F2DTLevels];
|
|
MAP16 CFast2D::MWork_Help2[F2DTLevels];
|
|
|
|
FAST2DTRACKSTACK CFast2D::TRACKSTACK[MAX_F2DT];
|
|
|
|
|
|
CFast2D::CFast2D()
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
void CFast2D::DoFirstInit()
|
|
{
|
|
memset(MWork,0,sizeof(MWork));
|
|
memset(TRACKSTACK,0,sizeof(TRACKSTACK));
|
|
LeveledDelta[0] = 0;
|
|
for (int i=1;i<F2DTLevels;i++) LeveledDelta[i] = LeveledDelta[i-1] + LeveledSize[i-1] * LeveledSize[i-1];
|
|
FirstInit = 1;
|
|
}
|
|
|
|
float CFast2D::CopyData(MAP16 *WORKMAP, s16 *pDst , s32 X , s32 Y , u32 Size , u32 ModeMule)
|
|
{
|
|
s16 *pBase;
|
|
float SqrValue = 0,DotProduct = 0,Counter = 0;
|
|
if (!ModeMule) DotProduct = 1.0f;
|
|
/* Perform dot product */
|
|
for (int LY = Y - ( Size >> 1 ) ; LY < Y + ( Size >> 1 ) ; LY++)
|
|
{
|
|
s32 LocalY;
|
|
LocalY = LY;
|
|
if ((LocalY >= 0) && (LocalY < WORKMAP->SY))
|
|
{
|
|
pBase = WORKMAP->GetBase() + LocalY * WORKMAP->PITCH;
|
|
for (int LX = X - ( Size >> 1 ) ; LX < X + ( Size >> 1 ) ; LX++)
|
|
{
|
|
s32 LocalX;
|
|
float Base = 0;
|
|
LocalX = LX;
|
|
if ((LocalX >= 0)&&(LocalX < WORKMAP->SX))
|
|
Base = (float)pBase[LocalX];
|
|
|
|
|
|
|
|
//if (Base > 0) Base = Base * 0.125f; // Black is more important
|
|
//if ((Base * Base) < 1024.0) Base = 0;
|
|
if (ModeMule)
|
|
{
|
|
DotProduct += (float)*(pDst) * (float)Base;
|
|
SqrValue += (float)Base * (float)Base;
|
|
}
|
|
else
|
|
{
|
|
SqrValue += (float)Base * (float)Base;
|
|
*pDst = (s16)Base;
|
|
}
|
|
pDst++;
|
|
}
|
|
}
|
|
}
|
|
if (SqrValue == 0.0f) return 0.0f;
|
|
|
|
|
|
if (ModeMule)
|
|
return ((float)(DotProduct * FastInvSqrt(SqrValue )));/* == Global denoise kiil flat*/
|
|
else
|
|
return ((float)(DotProduct * FastInvSqrt(SqrValue)));
|
|
}
|
|
|
|
void CFast2D::BuildOneTrackData(MAP16 *WORKMAP , FAST2DTRACKSTACK *pDt , s32 X ,s32 Y)
|
|
{
|
|
s16 *Pdst;
|
|
Pdst = pDt->InitMap;
|
|
for (int i = 0 ; i < F2DTLevels; i++ )
|
|
{
|
|
pDt->Norm[i] = CopyData(&WORKMAP[i], Pdst , X>>i , Y>>i , LeveledSize[i]);
|
|
Pdst += LeveledSize[i] * LeveledSize[i];
|
|
}
|
|
pDt->X = (float)X;
|
|
pDt->Y = (float)Y;
|
|
}
|
|
void CFast2D::UpdateData(u32 Index,float Factor)
|
|
{
|
|
if (Index < MAX_F2DT)
|
|
BuildOneTrackData((MAP16*)MWork, &TRACKSTACK[Index],(int)(TRACKSTACK[Index].X+0.5f),(int)(TRACKSTACK[Index].Y+0.5f));
|
|
}
|
|
|
|
void CFast2D::Destroy(u32 Index)
|
|
{
|
|
if (Index < MAX_F2DT) TRACKSTACK[Index].Init = 0;
|
|
}
|
|
|
|
u32 CFast2D::New(float X ,float Y )
|
|
{
|
|
if (!FirstInit) DoFirstInit();
|
|
u32 IDToCreate = 0;
|
|
while (IDToCreate < MAX_F2DT)
|
|
{
|
|
if (TRACKSTACK[IDToCreate].Init == 0)
|
|
break;
|
|
IDToCreate++;
|
|
}
|
|
if (IDToCreate == MAX_F2DT) IDToCreate = MAX_F2DT -1;
|
|
|
|
memset(&TRACKSTACK[IDToCreate],0,sizeof(FAST2DTRACKSTACK));
|
|
X = (float)((int)X);
|
|
Y = (float)((int)Y);
|
|
TRACKSTACK[IDToCreate].X = X;
|
|
TRACKSTACK[IDToCreate].Y = Y;
|
|
TRACKSTACK[IDToCreate].Init = 1;
|
|
BuildOneTrackData((MAP16*)MWork, &TRACKSTACK[IDToCreate],(int)TRACKSTACK[IDToCreate].X,(int)TRACKSTACK[IDToCreate].Y);
|
|
return IDToCreate;
|
|
}
|
|
|
|
void CFast2D::CopyDataRGBA(MAP *WORKMAP, s16 *pDst , s32 X , s32 Y , u32 Size , float Factor)
|
|
{
|
|
s32 *pBase;
|
|
for (int LY = Y - ( Size >> 1 ) ; LY < (Y + ( Size >> 1 )) ; LY++)
|
|
{
|
|
s32 LocalY;
|
|
LocalY = LY;
|
|
if (LocalY < 0) LocalY = 0;
|
|
if (LocalY >= (int)WORKMAP->SY) LocalY = WORKMAP->SY-1;
|
|
pBase = WORKMAP->GetBase() + LocalY * WORKMAP->PITCH;
|
|
for (int LX = X - ( Size >> 1 ) ; LX < X + ( Size >> 1 ) ; LX++)
|
|
{
|
|
s32 LocalX;
|
|
LocalX = LX;
|
|
if (LocalX < 0) LocalX = 0;
|
|
if (LocalX >= WORKMAP->SX) LocalX = WORKMAP->SX-1;
|
|
{
|
|
s32 VpBase = (s32)(Factor * (float)Size * (float)Size * (float)(*pDst)) + 128;
|
|
if (*pDst == 0)
|
|
{}
|
|
else
|
|
{
|
|
pBase[LocalX] = VpBase;
|
|
if (pBase[LocalX] < 0) pBase[LocalX] = 0;
|
|
if (pBase[LocalX] > 255) pBase[LocalX] = 255;
|
|
pBase[LocalX] |= pBase[LocalX] << 8;
|
|
pBase[LocalX] |= pBase[LocalX] << 8;
|
|
}
|
|
|
|
}
|
|
pDst++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFast2D::ComputeTrack(MAP16 *WORKMAP , FAST2DTRACKSTACK *pTrack,u32 BigSearch)
|
|
{
|
|
int LevelDec = F2DTLevels;
|
|
pTrack->LastError = 0.0f;
|
|
float Pond = 0;
|
|
float Weight = 1;
|
|
while (LevelDec--)
|
|
{
|
|
float Max = -10000000000000.0f;
|
|
s32 XM,YM;
|
|
s16 *Pdst = pTrack->InitMap;
|
|
Pdst += LeveledDelta[LevelDec];
|
|
s32 Delta;
|
|
if (LevelDec >= F2DTLevels - 1)
|
|
{
|
|
Delta = (1<<(LevelDec + BigSearch));
|
|
if (BigSearch >= 8)
|
|
{
|
|
for (int X = pTrack->X-Delta ; X <= pTrack->X+Delta ; X += (2<<LevelDec) )
|
|
for (int Y = pTrack->Y-Delta ; Y <= pTrack->Y+Delta ; Y += (2<<LevelDec) )
|
|
{
|
|
float Norm = CopyData(&WORKMAP[LevelDec], Pdst , X>>LevelDec , Y>>LevelDec , LeveledSize[LevelDec],1);
|
|
if (Norm > Max)
|
|
{
|
|
XM = X;
|
|
YM = Y;
|
|
Max = Norm;
|
|
}
|
|
}
|
|
pTrack->X = XM;
|
|
pTrack->Y = YM;
|
|
Delta = (1<<LevelDec);
|
|
}
|
|
for (int X = pTrack->X-Delta ; X <= pTrack->X+Delta ; X += (1<<LevelDec) )
|
|
for (int Y = pTrack->Y-Delta ; Y <= pTrack->Y+Delta ; Y += (1<<LevelDec) )
|
|
{
|
|
float Norm = CopyData(&WORKMAP[LevelDec], Pdst , X>>LevelDec , Y>>LevelDec , LeveledSize[LevelDec],1);
|
|
if (Norm > Max)
|
|
{
|
|
XM = X;
|
|
YM = Y;
|
|
Max = Norm;
|
|
}
|
|
}
|
|
pTrack->X = XM;
|
|
pTrack->Y = YM;//*/
|
|
|
|
} else
|
|
{
|
|
Delta = (1<<LevelDec);
|
|
//Delta = 0;
|
|
for (int X = pTrack->X-Delta ; X <= pTrack->X+Delta ; X += (1<<LevelDec) )
|
|
for (int Y = pTrack->Y-Delta ; Y <= pTrack->Y+Delta ; Y += (1<<LevelDec) )
|
|
{
|
|
float Norm = CopyData(&WORKMAP[LevelDec], Pdst , X>>LevelDec , Y>>LevelDec , LeveledSize[LevelDec],1);
|
|
if (Norm > Max)
|
|
{
|
|
XM = X;
|
|
YM = Y;
|
|
Max = Norm;
|
|
}
|
|
}
|
|
}//*/
|
|
pTrack->LastError += Weight * Max * pTrack->Norm[LevelDec];
|
|
Pond += Weight;
|
|
//Weight = 0;
|
|
pTrack->X = XM;
|
|
pTrack->Y = YM;
|
|
//LevelDec = 0;
|
|
}
|
|
pTrack->LastError /= Pond;
|
|
pTrack->Init |= 4;
|
|
}
|
|
|
|
void CFast2D::ComputeTrack(u32 i,u32 BigSearch)
|
|
{
|
|
if (TRACKSTACK[i].Init) ComputeTrack((MAP16*)MWork, &TRACKSTACK[i],BigSearch);
|
|
}
|
|
|
|
|
|
|
|
void CFast2D::Set(u32 ID, Vector *pResult)
|
|
{
|
|
if (ID == -1) return;
|
|
if ((ID < MAX_F2DT) && (TRACKSTACK[ID].Init))
|
|
{
|
|
TRACKSTACK[ID].X = pResult->x;
|
|
TRACKSTACK[ID].Y = pResult->y;
|
|
TRACKSTACK[ID].LastError = pResult->z;
|
|
}
|
|
}
|
|
|
|
u32 CFast2D::Get(u32 ID, Vector *pResult)
|
|
{
|
|
if (ID == -1) return 0;
|
|
if ((ID < MAX_F2DT) && (TRACKSTACK[ID].Init))
|
|
{
|
|
pResult->x = TRACKSTACK[ID].X;
|
|
pResult->y = TRACKSTACK[ID].Y;
|
|
pResult->z = TRACKSTACK[ID].LastError;
|
|
return 1;
|
|
}
|
|
pResult->z = 0.0f;
|
|
return 0;
|
|
}
|
|
float CFast2D::GetError(u32 ID)
|
|
{
|
|
if (ID == -1) return 0;
|
|
if ((ID < MAX_F2DT) && (TRACKSTACK[ID].Init))
|
|
return TRACKSTACK[ID].LastError;
|
|
else return 0;
|
|
}
|
|
float CFast2D::GetNorm(u32 ID, u32 LVL)
|
|
{
|
|
if (ID == -1) return 0;
|
|
if ((ID < MAX_F2DT) && (TRACKSTACK[ID].Init) && (LVL < F2DTLevels))
|
|
{
|
|
return TRACKSTACK[ID].Norm[LVL];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
s32 CFast2D::GetSign(MAP *CurrentMap)
|
|
{
|
|
s32 *Base,Res = 0;
|
|
for (int Y = 16 ; Y < (CurrentMap->SY )-16 ; Y ++)
|
|
{
|
|
Base = CurrentMap->GetBase() + Y * CurrentMap->PITCH + (CurrentMap->SX >> 1)-16;
|
|
for (int X = 16 ; X < (CurrentMap->SX)-16 ; X ++ )
|
|
Res += (*(Base++)) & 0xff;
|
|
}
|
|
return Res;
|
|
}
|
|
|
|
u32 CFast2D::Compute(MAP *CurrentMap,MAP16 *ZMap,u32 Option)
|
|
{
|
|
#ifdef TEST_PHILIPPE
|
|
|
|
if (Option == 123456789)
|
|
{
|
|
void DanceDance_NoiseMap(MAP *CurrentMap);
|
|
DanceDance_NoiseMap(CurrentMap);
|
|
return 1;
|
|
}
|
|
#endif
|
|
static u32 LastSign;
|
|
u32 ReturnValue = 1;
|
|
|
|
if (!FirstInit) DoFirstInit(); if (CurrentMap->SX*CurrentMap->SY > MWork[0].SX*MWork[0].SY)
|
|
{
|
|
MWork[0].SetSize(CurrentMap->SX*6, CurrentMap->SY);
|
|
MWork[0].PITCH = MWork[0].SX = CurrentMap->SX;
|
|
MWork[0].SY = CurrentMap->SY;
|
|
for (int i = 1 ; i < F2DTLevels; i++ ) {MWork[i].PITCH = MWork[i].SX = MWork[i-1].SX >> 1;MWork[i].SY = MWork[i-1].SY >> 1;MWork[i].SetBase(MWork[i-1].GetBase() + MWork[i-1].SX * MWork[i-1].SY * 4);};
|
|
for (int i = 0 ; i < F2DTLevels; i++ ) {MWork_Help[i] = MWork[i];MWork_Help[i].staticBase = 1;MWork_Help[i].MoveBase(MWork_Help[i].SX * MWork_Help[i].SY) ;};
|
|
for (int i = 0 ; i < F2DTLevels; i++ ) {MWork_Help2[i] = MWork_Help[i];MWork_Help2[i].staticBase = 1;MWork_Help2[i].MoveBase(MWork_Help2[i].SX * MWork_Help2[i].SY) ;};
|
|
}
|
|
|
|
/* Compute working maps */
|
|
MAP_2_MAP16(CurrentMap,&MWork[0],14);
|
|
|
|
for (int i = 0 ; i < F2DTLevels ; i++ )
|
|
{
|
|
void MAP16_PowerBLUR_XY(MAP16 *pSrc,MAP16 *pTmp,u8 Alpha, u32 Power, u32 Iteration);
|
|
if (i < F2DTLevels - 1 )MAP16_Copy_O2(&MWork[i],&MWork[i+1]);
|
|
MAP16_Copy(&MWork[i] , &MWork_Help[i]);
|
|
MAP16_BLUR_Inplace(&MWork_Help[i],2 ,3);
|
|
MAP16_Sub(&MWork_Help[i],&MWork[i]);//*/
|
|
}
|
|
//START_RASTER(FAST2D);
|
|
/* Track particules */
|
|
FeatureBoxFrame(Option ? CurrentMap : 0,0);
|
|
if (Option)
|
|
{
|
|
for (int i = 0 ; i < MAX_F2DT; i++ )
|
|
{
|
|
if ((TRACKSTACK[i].Init) && (TRACKSTACK[i].LastError > 0.6f))
|
|
{
|
|
if (Option&2) CopyDataRGBA(CurrentMap, TRACKSTACK[i].InitMap , TRACKSTACK[i].X , TRACKSTACK[i].Y , F2DT8Size ,TRACKSTACK[i].Norm[0]);
|
|
}
|
|
}
|
|
LastSign = GetSign(CurrentMap);
|
|
}
|
|
|
|
CurrentMap->SetValue(1, 0xc0deFFEF);
|
|
CurrentMap->SetValue(2, rand()%321654);
|
|
MAP_2_MAP16(CurrentMap,&MWork_Help[0],16);
|
|
//MAP16_BLUR_Inplace(&MWork_Help[0],1,1);
|
|
//STOP_RASTER(FAST2D);
|
|
|
|
return 1;
|
|
}
|
|
|
|
u32 CFast2D::Compute(MAP *CurrentMap,u32 options)
|
|
{
|
|
return Compute(CurrentMap,0,options);
|
|
}
|