/*********************/ /*** MkLevel Class ***/ /*********************/ #include "stdio.h" #include <misc.hpp> #include <GFName.hpp> #include <conio.h> #include <iostream.h> #include <vector> #include <DaveLib.h> #include "MkLevel.h" #include "Layers\MkLevelLayer.h" #include "Layers\MkLevelLayerTile.h" #include "Layers\MkLevelLayer3d.h" #include "Layers\MkLevelLayerShade.h" #include "Layers\MkLevelLayerCollision.h" #include "Layers\MkLevelLayerActor.h" #include "Layers\MkLevelLayerItem.h" #include "Layers\MkLevelLayerPlatform.h" #include "Layers\MkLevelLayerFX.h" #include "Layers\MkLevelLayerTrigger.h" #include "Layers\MkLevelLayerHazard.h" //*************************************************************************** const GString ConfigFilename="MkLevel.ini"; sExpLayerTile BlankTile2d={-1,-1}; sExpLayerTile BlankTile3d={0,0}; //*************************************************************************** CMkLevel::CMkLevel() { memset(&LevelHdr,0,sizeof(sLevelHdr)); Tile2dList.Add(BlankTile2d); Tile3dList.Add(BlankTile3d); OutTile3dList.resize(1); OutTile3dList[0].TriCount=0; OutTile3dList[0].QuadCount=0; } //*************************************************************************** CMkLevel::~CMkLevel() { } //*************************************************************************** void CMkLevel::SetAppDir(const char *AppPath) { #ifdef _DEBUG AppDir="\\spongebob\\tools\\data\\bin\\"; #else GFName Path=AppPath; Path.File(""); Path.Ext(""); AppDir=Path.FullName(); #endif } //*************************************************************************** void CMkLevel::Init(const char *Filename,const char *OutFilename,int TPBase,int TPW,int TPH) { // Setup filenames and paths GFName Path; InFilename=Filename; Path=Filename; LevelName=Path.File(); Path.File(""); Path.Ext(""); InPath=Path.FullName(); Path=OutFilename; Path.Ext(""); OutName=Path.FullName(); // Load ini file Config.LoadAndImport(GString(AppDir+ConfigFilename)); // Setup Texgrab if (TPBase==-1 || TPW==-1 || TPH==-1) GObject::Error(ERR_FATAL,"TPage not set\n"); TexGrab.SetTPage(TPBase,TPW,TPH); TexGrab.SetOutFile(GString(OutName+".Tex")); TexGrab.SetDebug(DebugOn); TexGrab.SetDebugOut(GString(OutName+".Lbm")); TexGrab.NoSort(); TexGrab.AnimatedHeadersOnly(true); TexGrab.DontOutputBoxes(true); //!!! TexGrab.AllowRotate(true); TexGrab.AllowRotate(false); //!!! TexGrab.ShrinkToFit(true); TexGrab.ShrinkToFit(false); // Setup TriList OutFaceList.SetTexGrab(TexGrab); // Set up other stuph FlatFace[0].vtx[0].x=+0.5f; FlatFace[0].vtx[0].y=+1.0f; FlatFace[0].vtx[0].z=-4.0f; FlatFace[0].vtx[1].x=-0.5f; FlatFace[0].vtx[1].y= 0.0f; FlatFace[0].vtx[1].z=-4.0f; FlatFace[0].vtx[2].x=+0.5f; FlatFace[0].vtx[2].y= 0.0f; FlatFace[0].vtx[2].z=-4.0f; FlatFace[0].uv[0][0]=1; FlatFace[0].uv[0][1]=1; FlatFace[0].uv[1][0]=0; FlatFace[0].uv[1][1]=0; FlatFace[0].uv[2][0]=1; FlatFace[0].uv[2][1]=0; FlatFace[0].Flags=0; FlatFace[1].vtx[0].x=-0.5f; FlatFace[1].vtx[0].y= 0.0f; FlatFace[1].vtx[0].z=-4.0f; FlatFace[1].vtx[1].x=+0.5f; FlatFace[1].vtx[1].y=+1.0f; FlatFace[1].vtx[1].z=-4.0f; FlatFace[1].vtx[2].x=-0.5f; FlatFace[1].vtx[2].y=+1.0f; FlatFace[1].vtx[2].z=-4.0f; FlatFace[1].uv[0][0]=0; FlatFace[1].uv[0][1]=0; FlatFace[1].uv[1][0]=1; FlatFace[1].uv[1][1]=1; FlatFace[1].uv[2][0]=0; FlatFace[1].uv[2][1]=1; FlatFace[1].Flags=0; } //*************************************************************************** int CMkLevel::AddModel(GString &Filename) { GFName Path=Filename; sMkLevelModel ThisModel; int Idx; CScene Scene; ThisModel.Name=GFName(Filename).File(); Idx=ModelList.Find(ThisModel); if (Idx!=-1) { return(Idx); } Idx=ModelList.size(); Path.File(""); Path.Ext(""); GString RootPath=Path.FullName(); // Load Model and add int TriStart=ModelFaceList.GetFaceCount();; Scene.Load(Filename); BuildModel(Scene,RootPath,0); ThisModel.TriStart=TriStart; ThisModel.TriCount=ModelFaceList.GetFaceCount()-TriStart; ModelList.Add(ThisModel); return(Idx); } //*************************************************************************** void CMkLevel::BuildModel(CScene &Scene,GString &RootPath,int Node) { CNode &ThisNode=Scene.GetNode(Node); vector<sGinTri> const &NodeTriList = ThisNode.GetTris(); vector<Vector3> const &NodeVtxList = ThisNode.GetPts(); vector<int> const &NodeMatList = ThisNode.GetTriMaterial(); vector<sUVTri> const &NodeUVList = ThisNode.GetUVTris(); vector<GString> const &SceneTexList= Scene.GetTexList(); vector<int> const &SceneUsedMatList=Scene.GetUsedMaterialIdx(); vector<Material> const &SceneMaterials=Scene.GetMaterials(); int TriCount=NodeTriList.size(); for (int T=0; T<TriCount; T++) { int Mat=SceneUsedMatList[NodeMatList[T]]; if (Mat>SceneTexList.size()) GObject::Error(ERR_FATAL,"Crap Material ID, wanted %i, only have %i\n",Mat,SceneTexList.size()); GString TexName=RootPath+SceneTexList[Mat]; CFace &F=ModelFaceList.AddFace( NodeVtxList, NodeTriList[T], NodeUVList[T], TexName,SceneMaterials[Mat].Flags,false); } int ChildCount=ThisNode.GetPruneChildCount(); for (int Loop=0;Loop<ChildCount ; Loop++) BuildModel(Scene,RootPath,ThisNode.PruneChildList[Loop]); } //*************************************************************************** int CMkLevel::AddModel(const char *Name,int TriStart,int TriCount) { sMkLevelModel ThisModel; int Idx; ThisModel.Name=Name; Idx=ModelList.Find(ThisModel); if (Idx!=-1) { return(Idx); } Idx=ModelList.size(); ThisModel.TriStart=ModelFaceList.GetFaceCount(); ThisModel.TriCount=TriCount; // Add tri data for (int i=0;i<TriCount; i++) { sExpTri &ThisTri=InTriList[TriStart+i]; CFace F; ExpTri2Face(ThisTri,F); ModelFaceList.SetTPageFlag(F,ThisTri.Flags*0); ModelFaceList.AddFace(F,false); } ModelList.Add(ThisModel); return(Idx); } //*************************************************************************** void CMkLevel::ProcessModels() { int i,ListSize; int TriStart=OutFaceList.GetFaceCount(); // Add faces ListSize=ModelFaceList.GetFaceCount(); for (i=0; i<ListSize; i++) { OutFaceList.AddFace(ModelFaceList[i],true); } // Update models ListSize=ModelList.size(); for (i=0; i<ListSize; i++) { // printf("%s = %i %i\n",ModelList[i].Name,ModelList[i].TriStart,ModelList[i].TriCount); ModelList[i].TriStart+=TriStart; } } //*************************************************************************** //*** Load ****************************************************************** //*************************************************************************** void CMkLevel::Load() { FILE *File; sExpFileHdr *FileHdr; int Size; printf("Load %s\n",LevelName); File=fopen(InFilename,"rb"); if (!File) GObject::Error(ERR_FATAL,"%s Not found\n",InFilename); // Calc File Size fseek(File,0,SEEK_END); Size=ftell(File); fseek(File,0,SEEK_SET); FileHdr=(sExpFileHdr*)malloc(Size); // Load It fread(FileHdr,Size,1,File); fclose(File); LoadTiles(FileHdr); LoadLayers(FileHdr); free(FileHdr); } //*************************************************************************** void CMkLevel::LoadStrList(CList<GString> &List,char *TexPtr,int Count) { char FullName[1024]; GString FilePath; for (int i=0; i<Count; i++) { GString InName=InPath; InName+=TexPtr; // sprintf(FullName,"%s",InName); _fullpath( FullName, InName, 1024); // GFName::makeabsolute(InPath,InName,FullName); // InName=FullName; // _fullpath( FullName, FullName, 1024); List.push_back(GString(FullName)); TexPtr+=strlen(TexPtr)+1; } } //*************************************************************************** void CMkLevel::LoadTiles(sExpFileHdr *FileHdr) { u8 *ByteHdr=(u8*)FileHdr; int i,ListSize; int RGBSize; TileW=FileHdr->TileW; TileH=FileHdr->TileH; RGBSize=TileW*TileH*3; // Load SetNames LoadStrList(InSetNameList,(char*) &ByteHdr[FileHdr->SetNameOfs],FileHdr->SetNameCount); // Load TexNames LoadStrList(InTexNameList,(char*) &ByteHdr[FileHdr->TexNameOfs],FileHdr->TexNameCount); // Load Tiles u8 *TilePtr=(u8*) &ByteHdr[FileHdr->TileOfs]; InTileList.resize(FileHdr->TileCount); for (i=0; i<FileHdr->TileCount; i++) { sExpTile *ThisTilePtr=(sExpTile*)TilePtr; sExpTile &InTile=InTileList[i]; InTile=*ThisTilePtr; // Skip RGB Image, not needed (and too buggy) // InTile.RGB=(u8*)malloc(RGBSize); // memcpy(InTile.RGB,TilePtr+sizeof(sExpTile),RGBSize); InTile.RGB=0; TilePtr+=RGBSize+sizeof(sExpTile); } // Load Tris sExpTri *TriPtr=(sExpTri*) &ByteHdr[FileHdr->TriOfs]; InTriList.resize(FileHdr->TriCount); for (i=0; i<FileHdr->TriCount; i++) { InTriList[i]=TriPtr[i]; } // Load 2d bitmaps ListSize=InSetNameList.size(); BmpList.resize(ListSize); for (i=0; i<ListSize; i++) { GString Ext=GFName(InSetNameList[i]).Ext(); if (Ext=="BMP") { BmpList[i].LoadBMP(InSetNameList[i]); } } } //*************************************************************************** void CMkLevel::LoadLayers(sExpFileHdr *FileHdr) { u8 *ByteHdr=(u8*)FileHdr; for (int i=0; i<FileHdr->LayerCount; i++) { sExpLayerHdr *LayerHdr=(sExpLayerHdr *)&ByteHdr[FileHdr->LayerOfs[i]]; switch(LayerHdr->Type) { case LAYER_TYPE_TILE: switch (LayerHdr->SubType) { case LAYER_SUBTYPE_ACTION: LayerList.push_back(new CMkLevelLayer3d(LayerHdr)); break; case LAYER_SUBTYPE_MID: LayerList.push_back(new CMkLevelLayerTile(LayerHdr)); break; case LAYER_SUBTYPE_BACK: default: break; } break; case LAYER_TYPE_COLLISION: LayerList.push_back(new CMkLevelLayerCollision(LayerHdr)); break; case LAYER_TYPE_SHADE: LayerList.push_back(new CMkLevelLayerShade(LayerHdr)); break; case LAYER_TYPE_ACTOR: LayerList.push_back(new CMkLevelLayerActor(LayerHdr)); break; case LAYER_TYPE_ITEM: LayerList.push_back(new CMkLevelLayerItem(LayerHdr)); break; case LAYER_TYPE_PLATFORM: LayerList.push_back(new CMkLevelLayerPlatform(LayerHdr)); break; case LAYER_TYPE_TRIGGER: LayerList.push_back(new CMkLevelLayerTrigger(LayerHdr)); break; case LAYER_TYPE_FX: LayerList.push_back(new CMkLevelLayerFX(LayerHdr)); break; case LAYER_TYPE_HAZARD: LayerList.push_back(new CMkLevelLayerHazard(LayerHdr)); break; default: GObject::Error(ERR_FATAL,"Unknown Layer Type\n"); } } } //*************************************************************************** //*** Process *************************************************************** //*************************************************************************** void CMkLevel::Process() { printf("PreProcess Layers\n"); PreProcessLayers(); printf("Process Models\n"); ProcessModels(); printf("Process Tilebank\n"); ProcessTileBanks(); printf("Process Layers\n"); ProcessLayers(); OutFaceList.Process(); } //*************************************************************************** void CMkLevel::PreProcessLayers() { int LayerCount=LayerList.size(); for (int i=0; i<LayerCount; i++) { LayerList[i]->PreProcess(this); } } //*************************************************************************** void CMkLevel::ProcessLayers() { int LayerCount=LayerList.size(); for (int i=0; i<LayerCount; i++) { LayerList[i]->Process(this); } } //*************************************************************************** void CMkLevel::ProcessTileBanks() { PreProcessTileBank2d(); PreProcessTileBank3d(); TexGrab.Process(); ProcessTileBank2d(); ProcessTileBank3d(); } //*************************************************************************** void CMkLevel::PreProcessTileBank2d() { int i,ListSize=Tile2dList.size(); Tile2dList[0].Tile=-1; // Extract Tex data from list for (i=1; i<ListSize; i++) { // Skip blank sExpLayerTile &ThisTile=Tile2dList[i]; ThisTile.Tile=Create2dTex(ThisTile.Tile,ThisTile.Flags); } } //*************************************************************************** void CMkLevel::ProcessTileBank2d() { int i,ListSize=Tile2dList.size(); vector<sTexOutInfo> &TexInfo=TexGrab.GetTexInfo(); OutTile2dList.resize(ListSize); for (i=1; i<ListSize; i++) { // Skip blank sExpLayerTile &InTile=Tile2dList[i]; sTile2d &OutTile=OutTile2dList[i]; SetUpTileUV(OutTile,TexInfo[InTile.Tile]); } } //*************************************************************************** void CMkLevel::PreProcessTileBank3d() { int i,ListSize=Tile3dList.size(); for (i=1; i<ListSize; i++) { // Skip Blank sExpLayerTile &ThisTile=Tile3dList[i]; ThisTile.Tile=Create3dTile(ThisTile); } } //*************************************************************************** void CMkLevel::ProcessTileBank3d() { int i,ListSize=Tile3dList.size(); for (i=0; i<ListSize; i++) { } } //*************************************************************************** void CMkLevel::SetUpTileUV(sTile2d &Out, sTexOutInfo &Info) { int W = Info.w-1; int H = Info.h-1; float Inx0, Iny0; u8 Outx0, Outy0; // Allow for upside textures now :oP Inx0=0; Iny0=1-0; if (Info.Rotated) { GObject::Error(ERR_FATAL,"Rotated Texure, cant cope!\n"); } Outx0 = Info.u + round(Inx0 * W); Outy0 = (Info.v + H) - round(Iny0 * H); Out.u0=Outx0; Out.v0=Outy0; Out.TPage=Info.Tpage; Out.Clut=Info.Clut; } //*************************************************************************** //*************************************************************************** //*************************************************************************** void CMkLevel::ExpTri2Face(sExpTri &ThisTri,CFace &F,bool ImportTex) { if (ImportTex) { F.TexName=InTexNameList[ThisTri.TexID]; F.Mat=-1; } else { F.Mat=ThisTri.TexID; } for (int p=0; p<3; p++) { F.vtx[p]=ThisTri.vtx[p]; F.vtx[p].y=F.vtx[p].y; F.uvs[p].u=ThisTri.uv[p][0]; F.uvs[p].v=ThisTri.uv[p][1]; } } //*************************************************************************** CMkLevelLayer *CMkLevel::FindLayer(int Type,int SubType) { int ListSize=LayerList.size(); for (int i=0; i<ListSize; i++) { if (LayerList[i]->IsType(Type,SubType)) return(LayerList[i]); } return(0); } //*************************************************************************** int CMkLevel::Create3dTile(sExpLayerTile &InTile) { sExpTile &SrcTile=InTileList[InTile.Tile]; CFace F; int i,ListSize,p; CList<sExpTri> SortList; CList<float> ZPosList; sTile3d ThisTile; int TileID=OutTile3dList.size(); ThisTile.TriStart=OutFaceList.GetFaceCount(); ThisTile.QuadCount=0; ThisTile.QuadStart=0; if (SrcTile.TriCount) { ThisTile.TriCount=SrcTile.TriCount; for (i=0; i<SrcTile.TriCount; i++) { int ListPos; sExpTri &ThisTri=InTriList[SrcTile.TriStart+i]; float ThisZPos; ThisZPos=ThisTri.vtx[0].z; if (ThisZPos<ThisTri.vtx[1].z) ThisZPos=ThisTri.vtx[1].z; if (ThisZPos<ThisTri.vtx[2].z) ThisZPos=ThisTri.vtx[2].z; ListSize=SortList.size(); for (ListPos=0; ListPos<ListSize; ListPos++) { if (ZPosList[ListPos]>ThisZPos) break; } SortList.insert(ListPos,ThisTri); ZPosList.insert(ListPos,ThisZPos); } } else { // create flat tile (This is WRONG, flip tex are gen, need to flip goem) // int TexID=Create2dTex(InTile.Tile,InTile.Flags); int TexID=Create2dTex(InTile.Tile,0); ThisTile.TriCount=2; for (int i=0; i<2; i++) { FlatFace[i].Flags=0; FlatFace[i].TexID=TexID; SortList.push_back(FlatFace[i]); } // InTile.Flags=0; } // Add sorted list to main list ListSize=SortList.size(); for (i=0; i<ListSize; i++) { sExpTri &ThisTri=SortList[i]; CFace F; bool SwapPnt=false; if (SrcTile.TriCount) { F.TexName=InTexNameList[ThisTri.TexID]; F.Mat=-1; } else { F.Mat=ThisTri.TexID; } for (p=0; p<3; p++) { F.vtx[p]=ThisTri.vtx[p]; F.vtx[p].y=F.vtx[p].y; F.uvs[p].u=ThisTri.uv[p][0]; F.uvs[p].v=ThisTri.uv[p][1]; } if (InTile.Flags & PC_TILE_FLAG_MIRROR_X) { F.vtx[0].x=-F.vtx[0].x; F.vtx[1].x=-F.vtx[1].x; F.vtx[2].x=-F.vtx[2].x; SwapPnt^=1; } if (InTile.Flags & PC_TILE_FLAG_MIRROR_Y) { F.vtx[0].y =1.0-F.vtx[0].y; F.vtx[1].y =1.0-F.vtx[1].y; F.vtx[2].y =1.0-F.vtx[2].y; SwapPnt^=1; } if (SwapPnt) { Vector3 TmpV=F.vtx[0]; F.vtx[0]=F.vtx[1]; F.vtx[1]=TmpV; sUV TmpUV=F.uvs[0]; F.uvs[0]=F.uvs[1]; F.uvs[1]=TmpUV; } OutFaceList.SetTPageFlag(F,ThisTri.Flags); OutFaceList.AddFace(F,true); } OutTile3dList.push_back(ThisTile); return(TileID); } //*************************************************************************** int CMkLevel::Create2dTex(int Tile,int Flags) { sExpTile &SrcTile=InTileList[Tile]; sMkLevelTex InTex; int Idx; // Must be new, add it // InTex.Set=SrcTile.Set; // InTex.XOfs=SrcTile.XOfs; // InTex.YOfs=SrcTile.YOfs; InTex.Tile=Tile; InTex.Flags=Flags; Idx=Tex2dList.Find(InTex); if (Idx!=-1) { return(Tex2dList[Idx].TexID); } InTex.TexID=BuildTileTex(SrcTile,Flags); Tex2dList.push_back(InTex); return(InTex.TexID); } //*************************************************************************** int CMkLevel::BuildTileTex(sExpTile &SrcTile,int Flags) { Frame &InFrame=BmpList[SrcTile.Set]; Frame ThisFrame; Rect ThisRect; GString Name=GFName(InSetNameList[SrcTile.Set]).File(); GString TexName; int BmpW=InFrame.GetWidth(); int BmpH=InFrame.GetHeight(); int TexID; TexGrab.ShrinkToFit(false); TexGrab.AllowRotate(false); if (SrcTile.XOfs*16>BmpW) { printf("AARGH!!! %s(%i) wants X=%i,tile is only %i Wide\n",Name,SrcTile.Set,SrcTile.XOfs*16,BmpW); SrcTile.XOfs=0; } if (SrcTile.YOfs*16>BmpH) { printf("AARGH!!! %s(%i) wants Y=%i,tile is only %i High\n",Name,SrcTile.Set,SrcTile.YOfs*16,BmpH); SrcTile.YOfs=0; } MakeTexName(SrcTile,Flags,TexName); ThisRect.X=SrcTile.XOfs*16; ThisRect.Y=SrcTile.YOfs*16; ThisRect.W=16; ThisRect.H=16; ThisFrame.Grab(InFrame,ThisRect); if (Flags& PC_TILE_FLAG_MIRROR_X) ThisFrame.FlipX(); if (Flags & PC_TILE_FLAG_MIRROR_Y) ThisFrame.FlipY(); TexID=TexGrab.AddMemFrame(TexName,ThisFrame); #ifdef _DEBUG if (0) { if (!ThisFrame.IsBlank()) { char DbgName[256]; sprintf(DbgName,"/x/%s.lbm",TexName); ThisFrame.SaveLbm(DbgName); } } #endif return(TexID); } //*************************************************************************** void CMkLevel::MakeTexName(sExpTile &SrcTile,int Flags,GString &OutStr) { char NewName[256]; GString Name=GFName(InSetNameList[SrcTile.Set]).File(); sprintf(NewName,"%s_%02d_%02d_%01d_",Name,SrcTile.XOfs,SrcTile.YOfs,Flags&PC_TILE_FLAG_MIRROR_XY); OutStr=NewName; } //*************************************************************************** /* int CMkLevel::FindRGBMatch(sMkLevelTex &ThisTex) { int i,ListSize=Tex2dList.size(); int Size=TileW*TileH; u8 *RGBPtr=ThisTex.RGB; if (!RGBPtr) printf("HA HA\n"); // Create Checksum for this tile ThisTex.RChk=0; ThisTex.GChk=0; ThisTex.BChk=0; for (i=0; i<Size; i++) { ThisTex.RChk+=*RGBPtr++; ThisTex.GChk+=*RGBPtr++; ThisTex.BChk+=*RGBPtr++; } // Check all others for match for (i=0; i<ListSize; i++) { sMkLevelTex &ChkTex=Tex2dList[i]; if (ChkTex.RGB) { // Checksum first if (ThisTex.RChk==ChkTex.RChk && ThisTex.GChk==ChkTex.GChk && ThisTex.BChk==ChkTex.BChk) { if (ThisTex.Flags==ChkTex.Flags) { if (IsRGBSame(ThisTex,ChkTex)) return(i); } } } } return(-1); } */ //*************************************************************************** /* bool CMkLevel::IsRGBSame(const sMkLevelTex &Tex0,const sMkLevelTex &Tex1) { int Size=TileW*TileH*3; int H=TileH; u8 *RGB0=Tex0.RGB; u8 *RGB1=Tex1.RGB; int Res=memcmp(RGB0,RGB1,Size); return(Res==0); } */ /* bool CMkLevel::IsRGBSame(const sMkLevelTex &Tex0,const sMkLevelTex &Tex1) { int W=TileW; int H=TileH; int XOfs0,YOfs0; int XOfs1,YOfs1; u8 *RGB0=Tex0.RGB; u8 *RGB1=Tex1.RGB; XOfs0=YOfs0=0; XOfs1=YOfs1=0; if (Tex0.Flags & PC_TILE_FLAG_MIRROR_X) XOfs0=W-1; if (Tex0.Flags & PC_TILE_FLAG_MIRROR_Y) YOfs0=H-1; if (Tex1.Flags & PC_TILE_FLAG_MIRROR_X) XOfs1=W-1; if (Tex1.Flags & PC_TILE_FLAG_MIRROR_Y) YOfs1=H-1; for (int Y=0; Y<H; Y++) { for (int X=0; X<W; X++) { int X0=abs(XOfs0-X); int Y0=abs(YOfs0-Y); int X1=abs(XOfs1-X); int Y1=abs(YOfs1-Y); int Idx0=X0+(Y0*W); int Idx1=X1+(Y1*W); if (RGB0[Idx0+0]!=RGB1[Idx1+0]) return(false); if (RGB0[Idx0+1]!=RGB1[Idx1+1]) return(false); if (RGB0[Idx0+2]!=RGB1[Idx1+2]) return(false); } } return(true); } */ //*************************************************************************** //*** Write ***************************************************************** //*************************************************************************** void CMkLevel::Write() { GString OutFilename=OutName+".Lvl"; File=fopen(OutFilename,"wb"); fwrite(&LevelHdr,1,sizeof(sLevelHdr),File); WriteLevel(); WriteTileBank(); // rewrite header fseek(File,0,SEEK_SET); fwrite(&LevelHdr,1,sizeof(sLevelHdr),File); fclose(File); } //*************************************************************************** int MinOT=123456,MaxOT=0; void CMkLevel::WriteTileBank() { int i,ListSize; // 2d Tilebank LevelHdr.TileBank2d=(sTile2d*)ftell(File); ListSize=OutTile2dList.size(); printf("%i 2d tiles\n",ListSize); for (i=0; i<ListSize; i++) { sTile2d &OutTile=OutTile2dList[i]; fwrite(&OutTile,1,sizeof(sTile2d),File); } // 3d Tilebank LevelHdr.TileBank3d=(sTile3d*)ftell(File); ListSize=OutTile3dList.size(); printf("%i 3d tiles\n",ListSize); for (i=0; i<ListSize; i++) { sTile3d &OutTile=OutTile3dList[i]; fwrite(&OutTile,1,sizeof(sTile3d),File); } // TriList LevelHdr.TriList=(sTri*)WriteTriList(); // QuadList LevelHdr.QuadList=(sQuad*)WriteQuadList(); printf("OT %i -> %i\n",MinOT,MaxOT); // VtxList LevelHdr.VtxList=(sVtx*)WriteVtxList(); // LevelHdr.VtxList=(sVtx*)OutFaceList.WriteVtxList(File); } //*************************************************************************** int ZMin=9999,ZMax=0; int CMkLevel::WriteTriList() { vector<sTri> &TriList=OutFaceList.GetOutTriList(); vector<sVtx> const &VtxList=OutFaceList.GetVtxList(); int ThisPos=ftell(File); int i,ListSize=TriList.size(); int ZOfs=+4*Scale; for (i=0;i<ListSize;i++) { sTri &T=TriList[i]; int OtOfs=0; int Z[3]; // Calc OtOfs Z[0]=VtxList[T.P0].vz+ZOfs; Z[1]=VtxList[T.P1].vz+ZOfs; Z[2]=VtxList[T.P2].vz+ZOfs; for (int p=0; p<3; p++) { if (ZMin>Z[p]) ZMin=Z[p]; if (ZMax<Z[p]) ZMax=Z[p]; OtOfs+=Z[p]*Z[p]; } OtOfs=(int)sqrt(OtOfs/3); OtOfs/=8; // printf("%i\n",OtOfs); if (MinOT>OtOfs) MinOT=OtOfs; if (MaxOT<OtOfs) MaxOT=OtOfs; if (OtOfs>15) OtOfs=15; if (OtOfs<0) OtOfs=0; // if (OtOfs>15) OtOfs=15; T.OTOfs=OtOfs; // Write It fwrite(&T,1,sizeof(sTri),File); } printf("Tri %i\n",ListSize); printf("ZMin %i ZMax %i\n",ZMin,ZMax); return(ThisPos); } //*************************************************************************** int CMkLevel::WriteQuadList() { vector<sQuad> &QuadList=OutFaceList.GetOutQuadList(); vector<sVtx> const &VtxList=OutFaceList.GetVtxList(); int ThisPos=ftell(File); int i,ListSize=QuadList.size(); for (i=0;i<ListSize;i++) { sQuad &Q=QuadList[i]; int Z[4]; int OtOfs=0; // Calc OtOfs Z[0]=abs(VtxList[Q.P0].vz); Z[1]=abs(VtxList[Q.P1].vz); Z[2]=abs(VtxList[Q.P2].vz); Z[3]=abs(VtxList[Q.P3].vz); for (int p=0; p<4; p++) { if (OtOfs<Z[p]) OtOfs=Z[p]; } if (MinOT>OtOfs) MinOT=OtOfs; if (MaxOT<OtOfs) MaxOT=OtOfs; if (OtOfs>63) OtOfs=63; // Write It fwrite(&Q,1,sizeof(sQuad),File); } printf("Quad %i\n",ListSize); return(ThisPos); } //*************************************************************************** int CMkLevel::WriteVtxList() { vector<sVtx> const &VtxList=OutFaceList.GetVtxList(); int i,ListSize=VtxList.size(); int Pos=ftell(File); //sVtx Ofs; // Ofs.vx=-0; // Ofs.vy=-0; // Ofs.vz=-4*Scale; for (i=0; i<ListSize; i++) { sVtx const &In=VtxList[i]; sVtx Out; Out.vx=+In.vx; Out.vy=-In.vy; Out.vz=+In.vz; // printf("%i\n",Out.vz); fwrite(&Out,1,sizeof(sVtx),File); } return(Pos); } //*************************************************************************** //*** Write ***************************************************************** //*************************************************************************** void CMkLevel::WriteLevel() { WriteLayers(); } //*************************************************************************** void CMkLevel::WriteLayers() { // Back (Shade) LevelHdr.BackLayer=WriteLayer(LAYER_TYPE_SHADE,LAYER_SUBTYPE_BACK,0);//"Shade"); // Mid LevelHdr.MidLayer=WriteLayer(LAYER_TYPE_TILE,LAYER_SUBTYPE_MID,"Mid"); // Action LevelHdr.ActionLayer=WriteLayer(LAYER_TYPE_TILE,LAYER_SUBTYPE_ACTION,"Action"); // Collision LevelHdr.CollisionLayer=WriteLayer(LAYER_TYPE_COLLISION,LAYER_SUBTYPE_NONE,"Collision"); // Things LevelHdr.ActorList=WriteThings(LAYER_TYPE_ACTOR,"Actor List"); LevelHdr.ItemList=WriteThings(LAYER_TYPE_ITEM,"Item List"); LevelHdr.PlatformList=WriteThings(LAYER_TYPE_PLATFORM,"Platform List"); LevelHdr.TriggerList=WriteThings(LAYER_TYPE_TRIGGER,"Trigger List"); LevelHdr.FXList=WriteThings(LAYER_TYPE_FX,"FX List"); LevelHdr.HazardList=WriteThings(LAYER_TYPE_HAZARD,"Hazard List"); LevelHdr.ModelList=(sModel*)WriteModelList(); } //*************************************************************************** int CMkLevel::WriteLayer(int Type,int SubType,const char *LayerName) { CMkLevelLayer *ThisLayer=FindLayer(Type,SubType); int Ofs; if (!ThisLayer) { if (LayerName) GObject::Error(ERR_WARNING,"No %s Layer Found in %s!!\n",LayerName,LevelName); return(0); } Ofs=ThisLayer->Write(File,LayerName,LevelName); PadFile(File); return(Ofs); } //*************************************************************************** int CMkLevel::WriteThings(int Type,const char *LayerName) { CMkLevelLayer *ThisLayer=FindLayer(Type,LAYER_SUBTYPE_NONE); int Ofs; if (!ThisLayer) { GFName Name=InFilename; if (LayerName) GObject::Error(ERR_WARNING,"No %s Layer Found in %s!!\n",LayerName,Name.File()); return(0); } Ofs=ThisLayer->Write(File,LayerName,LevelName); // printf("%s %i\n",LayerName,Ofs); PadFile(File); return(Ofs); } //*************************************************************************** int CMkLevel::WriteModelList() { int i,ListSize=ModelList.size(); int Ofs=ftell(File); for (i=0; i<ListSize; i++) { sModel Out; sMkLevelModel &ThisModel=ModelList[i]; Out.TriCount=ThisModel.TriCount; Out.TriStart=ThisModel.TriStart; CalcModelBBox(ThisModel,Out.BBox); printf("Writing Model %s (%i/%i) (%i Tris) (BBox %i,%i->%i,%i)\n",ThisModel.Name,i+1,ListSize,Out.TriCount,Out.BBox.XMin,Out.BBox.YMin,Out.BBox.XMax,Out.BBox.YMax); fwrite(&Out,1,sizeof(sModel),File); } return(Ofs); } //*************************************************************************** void CMkLevel::CalcModelBBox(sMkLevelModel &ThisModel,sBBox &BBox) { vector<sTri> &TriList=OutFaceList.GetOutTriList(); vector<sVtx> const &VtxList=OutFaceList.GetVtxList(); int Vtx[3]; BBox.XMin=+32000; BBox.XMax=-32000; BBox.YMin=+32000; BBox.YMax=-32000; for (int T=0; T<ThisModel.TriCount; T++) { sTri &ThisTri=TriList[T+ThisModel.TriStart]; Vtx[0]=ThisTri.P0; Vtx[1]=ThisTri.P1; Vtx[2]=ThisTri.P2; for (int V=0; V<3; V++) { sVtx const &ThisVtx=VtxList[Vtx[V]]; if (BBox.XMin>+ThisVtx.vx) BBox.XMin=+ThisVtx.vx; if (BBox.XMax<+ThisVtx.vx) BBox.XMax=+ThisVtx.vx; if (BBox.YMin>-ThisVtx.vy) BBox.YMin=-ThisVtx.vy; if (BBox.YMax<-ThisVtx.vy) BBox.YMax=-ThisVtx.vy; } } }