JD2022-TU1/main/extern/Camcam/CCMesh/MapFunctions.cpp

257 lines
6.5 KiB
C++

#include "CCMesh.h"
#define RENDER
//#define RENDER_NORMALS
//#define NORMALE_CHECK
u32 OPT_Table_X[5000];
u32 OPT_Table_Y[5000];
Vector T_Table[MAX_POINT];
u32 FillFlag(u32 F)
{
u32 Base,INC,MASK;
Base = 0;
MASK = 0xffff;
INC = 16;
while (INC)
{
if (!(F & MASK))
{
Base += INC;
F >>= INC;
}
INC >>= 1;
MASK >>=INC;
}
INC = F;
F <<= Base;
while (INC)
{
F |= 1<<(Base++);
INC>>=1;
}
return F;
}
u32 GETScalarFlag(u32 Value,u32 ValueMax)
{
return 1<<((Value * 32)/ValueMax);
}
Vector Project2Map(Vector &V,MAP *RefMap, float focale)
{
Vector Ret;
float Ooz;
if (V.z > 0.001f)
{
Ooz = 1.0f / V.z;
Ret.x = 0.5f*(focale * V.x * Ooz * RefMap->SX + RefMap->SX);
Ret.y = 0.5f*(focale * V.y * Ooz * RefMap->SX + RefMap->SY);
Ret.z = Ooz;
} else Ret.z = -1.0f;
return Ret;
}
void Mesh::Tranform(MATRIX *Tr, MAP *RefMap)
{
int Counter;
Counter = NumberOfPoints;
MATCHMAX = Vector(-1000,-1000,0);
MATCHMIN = Vector(1000,1000,0);
if (!Focale)
Focale = 2.5;
while(Counter--)
{
T_Table[Counter] = Project2Map(*Tr * (Points[Counter]),RefMap, Focale);
MATCHMAX.Max(T_Table[Counter]);
MATCHMIN.Min(T_Table[Counter]);
}
Counter = NumberOfFaces;
while (Counter--)
{
OPT_Table_X[Counter] = GETScalarFlag(T_Table[Indexes[Counter].I[0]].x,RefMap->SX);
OPT_Table_X[Counter] |= GETScalarFlag(T_Table[Indexes[Counter].I[1]].x,RefMap->SX);
OPT_Table_X[Counter] |= GETScalarFlag(T_Table[Indexes[Counter].I[2]].x,RefMap->SX);
OPT_Table_X[Counter] = FillFlag(OPT_Table_X[Counter]);
OPT_Table_Y[Counter] = GETScalarFlag(T_Table[Indexes[Counter].I[0]].y,RefMap->SY);
OPT_Table_Y[Counter] |= GETScalarFlag(T_Table[Indexes[Counter].I[1]].y,RefMap->SY);
OPT_Table_Y[Counter] |= GETScalarFlag(T_Table[Indexes[Counter].I[2]].y,RefMap->SY);
OPT_Table_Y[Counter] = FillFlag(OPT_Table_Y[Counter]);
}
}
int Mesh::Collide(Vector &V, MAP *RefMap,CollideReport *pOptCol)
{
int Counter,MASK_X,MASK_Y,Ret;
float OozNearest;
Vector VR,NR;
VR = Vector(0,0,0);
if (V.x > MATCHMAX.x) return 0;
if (V.x < MATCHMIN.x) return 0;
if (V.y > MATCHMAX.y) return 0;
if (V.y < MATCHMIN.y) return 0;
MASK_X = GETScalarFlag(V.x,RefMap->SX);
MASK_Y = GETScalarFlag(V.y,RefMap->SY);
Ret = 0;
Counter = NumberOfFaces;
OozNearest = 1.0f / 10000000.0f;
while (Counter--)
{
if ((MASK_X & OPT_Table_X[Counter]) && (MASK_Y & OPT_Table_Y[Counter]))
{
int I1,I2,I3;
Vector B1,B2,CP;
I1 = Indexes[Counter].I[0];
I2 = Indexes[Counter].I[1];
I3 = Indexes[Counter].I[2];
B1 = T_Table[I2] - T_Table[I1];
B2 = T_Table[I3] - T_Table[I1];
B1.z = 0.0f;
B2.z = 0.0f;
CP = B1 ^ B2;
if (CP .z > 0)
{
if (V.isRightXY(T_Table[I2] , T_Table[I1]))
{
if (V.isRightXY(T_Table[I3] , T_Table[I2]))
{
if (V.isRightXY(T_Table[I1] , T_Table[I3]))
{
float P1,P2,P3;
P1 = V.DistanceToLineXY(T_Table[I2],T_Table[I3]);
if (P1)
{
P1 /= T_Table[I1].DistanceToLineXY(T_Table[I2],T_Table[I3]);
P2 = V.DistanceToLineXY(T_Table[I1],T_Table[I3]);
if (P2)
{
P2 /= T_Table[I2].DistanceToLineXY(T_Table[I1],T_Table[I3]);
P3 = V.DistanceToLineXY(T_Table[I1],T_Table[I2]);
if (P3)
{
Vector C1,C2,C3;
Vector N1,N2,N3;
float Ooz;
P3 /= T_Table[I3].DistanceToLineXY(T_Table[I1],T_Table[I2]);
Ooz = (T_Table[I1].z * P1) + (T_Table[I2].z * P2) + (T_Table[I3].z * P3);
/* OoZ corection */
if (Ooz > OozNearest)
{
C1 = (Points[I1]) * T_Table[I1].z;
C2 = (Points[I2]) * T_Table[I2].z;
C3 = (Points[I3]) * T_Table[I3].z;
#ifdef NORMALE_CHECK
N1 = (PointsN[I1]) * T_Table[I1].z;
N2 = (PointsN[I2]) * T_Table[I2].z;
N3 = (PointsN[I3]) * T_Table[I3].z;
NR = (N1 * P1) + (N2 * P2) + (N3 * P3);
NR *= 1.0f / Ooz;
#endif
{
VR = (C1 * P1) + (C2 * P2) + (C3 * P3);
VR *= 1.0f / Ooz;
Ret = 1;
OozNearest = Ooz;
if (pOptCol)
{
pOptCol->FaceIndex = Counter;
pOptCol->Ponderation.x = P1;
pOptCol->Ponderation.y = P2;
pOptCol->Ponderation.z = P3;
}
}
}
}
}
}
}
}
}
}
}
}
#ifdef NORMALE_CHECK
if (Ret)
{
MATRIX MS;
MS = MatrixSrc;
MS.T *= 0.0;
NR = MS * NR;
if (NR.z<0.4) Ret = 0;
}
#endif
if (Ret)
V = VR;
return Ret;
}
u32 IsBackFace(Mesh *pMyMesh, u32 T)
{
Vector B1,B2,CP;
u32 I1,I2,I3;
I1 = pMyMesh->Indexes[T].I[0];
I2 = pMyMesh->Indexes[T].I[1];
I3 = pMyMesh->Indexes[T].I[2];
B1 = T_Table[I2] - T_Table[I1];
B2 = T_Table[I3] - T_Table[I1];
B1.z = 0.0f;
B2.z = 0.0f;
CP = B1 ^ B2;
if (CP .z > 0) return 1;
else return 0;
}
void Mesh::Render(MAP &SOURCEMAP, u32 Color , u32 inside, u32 Render)
{
u32 Counter;
Tranform(&MatrixSrc,&SOURCEMAP);
if (!Render) return;
Counter = NumberOfFaces;
while (Counter--)
{
u32 I1,I2,I3;
if (IsBackFace(this,Counter))
{
I1 = Indexes[Counter].I[0];
I2 = Indexes[Counter].I[1];
I3 = Indexes[Counter].I[2];
if ((T_Table[I1].z > 0.0f) && (T_Table[I2].z > 0.0f) && (T_Table[I3].z > 0.0f))
{
if ((NeightBIndexes[Counter].I[0] == -1) || !IsBackFace(this,NeightBIndexes[Counter].I[0]))
{
DrawLine_Clip(&SOURCEMAP,T_Table[I1].x , T_Table[I1].y, T_Table[I2].x , T_Table[I2].y , Color);
}
else
{if ((inside) && (I1 > I2)) DrawLine_Clip(&SOURCEMAP,T_Table[I1].x , T_Table[I1].y, T_Table[I2].x , T_Table[I2].y , 0x80000000|Color);}
if ((NeightBIndexes[Counter].I[1] == -1) || !IsBackFace(this,NeightBIndexes[Counter].I[1]))
{
DrawLine_Clip(&SOURCEMAP,T_Table[I2].x , T_Table[I2].y, T_Table[I3].x , T_Table[I3].y , Color);
}
else
{if ((inside) && (I2 > I3)) DrawLine_Clip(&SOURCEMAP,T_Table[I2].x , T_Table[I2].y, T_Table[I3].x , T_Table[I3].y , 0x80000000|Color);}
if ((NeightBIndexes[Counter].I[2] == -1) || !IsBackFace(this,NeightBIndexes[Counter].I[2]))
{
DrawLine_Clip(&SOURCEMAP,T_Table[I3].x , T_Table[I3].y, T_Table[I1].x , T_Table[I1].y , Color);
}
else
{if ((inside) && (I3 > I1)) DrawLine_Clip(&SOURCEMAP,T_Table[I3].x , T_Table[I3].y, T_Table[I1].x , T_Table[I1].y , 0x80000000|Color);}
}
}
}
#ifdef RENDER_NORMALS
Counter = NumberOfPoints;
while (Counter--)
{
Vector V1,V1p;
V1 = Points[Counter] - (PointsN[Counter] * 4.0f);
V1p = Project2Map(MatrixSrc * V1,&SOURCEMAP, Focale);
DrawLine_Clip(&SOURCEMAP,T_Table[Counter].x , T_Table[Counter].y, V1p.x , V1p.y , 0x80000000|Color);
}
#endif
}