JD2022-TU1/main/extern/Camcam/Fast2D/Fast2D.cpp

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);
}