#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 }