257 lines
6.5 KiB
C++
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
|
|
}
|