SBSPSS/Utils/MkLevel/MkLevel.cpp

975 lines
24 KiB
C++
Raw Normal View History

2001-04-17 18:42:07 +02:00
/*********************/
/*** 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"
//***************************************************************************
2001-04-19 17:12:21 +02:00
const GString ConfigFilename="MkLevel.ini";
sExpLayerTile BlankTile2d={-1,-1};
sExpLayerTile BlankTile3d={0,0};
2001-04-17 18:42:07 +02:00
//***************************************************************************
CMkLevel::CMkLevel()
{
2001-04-19 17:12:21 +02:00
memset(&LevelHdr,0,sizeof(sLevelHdr));
Tile2dList.Add(BlankTile2d);
Tile3dList.Add(BlankTile3d);
OutTile3dList.resize(1);
OutTile3dList[0].TriCount=0;
OutTile3dList[0].QuadCount=0;
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
CMkLevel::~CMkLevel()
{
}
//***************************************************************************
2001-04-19 17:12:21 +02:00
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)
2001-04-17 18:42:07 +02:00
{
// Setup filenames and paths
2001-04-19 17:12:21 +02:00
GFName Path;
2001-04-17 18:42:07 +02:00
InFilename=Filename;
2001-04-19 17:12:21 +02:00
Path=Filename;
2001-04-17 18:42:07 +02:00
LevelName=Path.File();
Path.File("");
Path.Ext("");
InPath=Path.FullName();
2001-04-19 17:12:21 +02:00
Path=OutFilename;
Path.Ext("");
OutName=Path.FullName();
2001-04-17 18:42:07 +02:00
// Load ini file
2001-04-19 17:12:21 +02:00
Config.LoadAndImport(GString(AppDir+ConfigFilename));
2001-04-17 18:42:07 +02:00
// 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
2001-04-19 17:12:21 +02:00
OutFaceList.SetTexGrab(TexGrab);
2001-04-17 18:42:07 +02:00
// 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;
2001-04-19 17:12:21 +02:00
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;
2001-04-17 18:42:07 +02:00
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;
2001-04-19 17:12:21 +02:00
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;
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
//*** 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)
{
2001-04-23 16:51:44 +02:00
char FullName[1024];
2001-04-17 18:42:07 +02:00
GString FilePath;
for (int i=0; i<Count; i++)
{
2001-04-19 17:12:21 +02:00
GString InName=InPath;
InName+=TexPtr;
GFName::makeabsolute(InPath,InName,FullName);
2001-04-23 16:51:44 +02:00
InName=FullName;
_fullpath( FullName, FullName, 1024);
2001-04-17 18:42:07 +02:00
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;
InTile.RGB=(u8*)malloc(RGBSize);
memcpy(InTile.RGB,TilePtr+sizeof(sExpTile),RGBSize);
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")
{
2001-04-19 17:12:21 +02:00
BmpList[i].LoadBMP(InSetNameList[i]);
2001-04-17 18:42:07 +02:00
}
}
}
//***************************************************************************
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;
default:
GObject::Error(ERR_FATAL,"Unknown Layer Type\n");
}
}
}
2001-04-23 16:51:44 +02:00
2001-04-17 18:42:07 +02:00
//***************************************************************************
//*** Process ***************************************************************
//***************************************************************************
void CMkLevel::Process()
{
printf("PreProcess Layers\n");
PreProcessLayers();
printf("Process Tilebank\n");
ProcessTileBanks();
printf("Process Layers\n");
ProcessLayers();
2001-04-19 17:12:21 +02:00
OutFaceList.Process();
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
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];
2001-04-23 16:51:44 +02:00
ThisTile.Tile=Create2dTex(ThisTile.Tile,ThisTile.Flags);
2001-04-17 18:42:07 +02:00
}
}
//***************************************************************************
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();
2001-04-19 17:12:21 +02:00
for (i=1; i<ListSize; i++)
{ // Skip Blank
2001-04-17 18:42:07 +02:00
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;
}
2001-04-23 16:51:44 +02:00
//***************************************************************************
int CMkLevel::AddPlatform(sMkLevelLayerThing &ThisThing)
{
sMkLevelPlatform ThisPlatform;
int Idx;
ThisPlatform.Name=ThisThing.Name;
Idx=PlatformList.Find(ThisPlatform);
if (Idx!=-1)
{
return(Idx);
}
Idx=PlatformList.size();
ThisPlatform.TriStart=OutFaceList.GetFaceCount();
ThisPlatform.TriCount=ThisThing.Data.TriCount;
PlatformList.Add(ThisPlatform);
// Add tri data
for (int i=0;i<ThisPlatform.TriCount; i++)
{
// sExpTri &ThisTri=InTriList[ThisPlatform.TriStart+i];
sExpTri &ThisTri=InTriList[i];
CFace F;
ExpTri2Face(ThisTri,F);
OutFaceList.AddFace(F);
}
return(Idx);
}
//***************************************************************************
2001-04-17 18:42:07 +02:00
//***************************************************************************
//***************************************************************************
2001-04-23 16:51:44 +02:00
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];
}
}
2001-04-17 18:42:07 +02:00
//***************************************************************************
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;
2001-04-19 17:12:21 +02:00
int i,ListSize,p;
2001-04-17 18:42:07 +02:00
CList<sExpTri> SortList;
CList<float> ZPosList;
2001-04-19 17:12:21 +02:00
sTile3d ThisTile;
int TileID=OutTile3dList.size();
ThisTile.TriStart=OutFaceList.GetFaceCount();
ThisTile.QuadCount=0;
ThisTile.QuadStart=0;
2001-04-17 18:42:07 +02:00
if (SrcTile.TriCount)
{
2001-04-19 17:12:21 +02:00
ThisTile.TriCount=SrcTile.TriCount;
2001-04-17 18:42:07 +02:00
for (i=0; i<SrcTile.TriCount; i++)
{
int ListPos;
sExpTri ThisTri=InTriList[SrcTile.TriStart+i];
float ThisZPos;
ThisZPos=ThisTri.vtx[0].z;
2001-04-23 16:51:44 +02:00
if (ThisZPos<ThisTri.vtx[1].z) ThisZPos=ThisTri.vtx[1].z;
if (ThisZPos<ThisTri.vtx[2].z) ThisZPos=ThisTri.vtx[2].z;
2001-04-17 18:42:07 +02:00
ListSize=SortList.size();
for (ListPos=0; ListPos<ListSize; ListPos++)
{
2001-04-23 16:51:44 +02:00
if (ZPosList[ListPos]>ThisZPos) break;
2001-04-17 18:42:07 +02:00
}
2001-04-19 17:12:21 +02:00
SortList.insert(ListPos,ThisTri);
ZPosList.insert(ListPos,ThisZPos);
}
2001-04-17 18:42:07 +02:00
2001-04-19 17:12:21 +02:00
}
else
2001-04-23 16:51:44 +02:00
{ // create flat tile (This is WRONG, flip tex are gen, need to flip goem)
int TexID=Create2dTex(InTile.Tile,InTile.Flags);
2001-04-17 18:42:07 +02:00
2001-04-19 17:12:21 +02:00
ThisTile.TriCount=2;
for (int i=0; i<2; i++)
2001-04-17 18:42:07 +02:00
{
2001-04-19 17:12:21 +02:00
FlatFace[i].TexID=TexID;
SortList.push_back(FlatFace[i]);
2001-04-17 18:42:07 +02:00
}
2001-04-23 16:51:44 +02:00
InTile.Flags=0;
2001-04-19 17:12:21 +02:00
}
2001-04-17 18:42:07 +02:00
// Add sorted list to main list
2001-04-19 17:12:21 +02:00
ListSize=SortList.size();
for (i=0; i<ListSize; i++)
{
sExpTri &ThisTri=SortList[i];
CFace F;
bool SwapPnt=false;
2001-04-17 18:42:07 +02:00
2001-04-19 17:12:21 +02:00
if (SrcTile.TriCount)
2001-04-17 18:42:07 +02:00
{
F.TexName=InTexNameList[ThisTri.TexID];
F.Mat=-1;
2001-04-19 17:12:21 +02:00
}
else
{
F.Mat=ThisTri.TexID;
}
2001-04-17 18:42:07 +02:00
2001-04-19 17:12:21 +02:00
for (p=0; p<3; p++)
{
F.vtx[p]=ThisTri.vtx[p];
2001-04-23 16:51:44 +02:00
F.vtx[p].y=F.vtx[p].y;
2001-04-19 17:12:21 +02:00
F.uvs[p].u=ThisTri.uv[p][0];
F.uvs[p].v=ThisTri.uv[p][1];
2001-04-17 18:42:07 +02:00
}
2001-04-19 17:12:21 +02:00
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)
2001-04-17 18:42:07 +02:00
{
2001-04-19 17:12:21 +02:00
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;
2001-04-17 18:42:07 +02:00
}
2001-04-23 16:51:44 +02:00
2001-04-19 17:12:21 +02:00
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;
}
2001-04-23 16:51:44 +02:00
2001-04-19 17:12:21 +02:00
OutFaceList.AddFace(F,true);
2001-04-17 18:42:07 +02:00
}
2001-04-19 17:12:21 +02:00
OutTile3dList.push_back(ThisTile);
return(TileID);
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
2001-04-23 16:51:44 +02:00
int CMkLevel::Create2dTex(int Tile,int Flags)
2001-04-17 18:42:07 +02:00
{
2001-04-23 16:51:44 +02:00
sExpTile &SrcTile=InTileList[Tile];
2001-04-17 18:42:07 +02:00
int Idx;
sMkLevelTex InTex;
2001-04-23 16:51:44 +02:00
InTex.Set=SrcTile.Set;
InTex.Flags=Flags;
2001-04-17 18:42:07 +02:00
InTex.XOfs=SrcTile.XOfs;
InTex.YOfs=SrcTile.YOfs;
InTex.RGB=SrcTile.RGB;
Idx=Tex2dList.Find(InTex);
if (Idx!=-1) return(Idx);
// Try and find RGB data match
Idx=FindRGBMatch(InTex);
if (Idx!=-1) return(Idx);
// Must be new, add it
BuildTileTex(InTex);
Tex2dList.push_back(InTex);
return(InTex.TexID);
}
//***************************************************************************
int CMkLevel::BuildTileTex(sMkLevelTex &InTex)
{
Frame &InFrame=BmpList[InTex.Set];
Frame ThisFrame;
Rect ThisRect;
GString Name=GFName(InSetNameList[InTex.Set]).File();
GString TexName;
int BmpW=InFrame.GetWidth();
int BmpH=InFrame.GetHeight();
TexGrab.ShrinkToFit(false);
TexGrab.AllowRotate(false);
if (InTex.XOfs*16>BmpW)
{
printf("AARGH!!! %s(%i) wants X=%i,tile is only %i Wide\n",Name,InTex.Set,InTex.XOfs*16,BmpW);
InTex.XOfs=0;
}
if (InTex.YOfs*16>BmpH)
{
printf("AARGH!!! %s(%i) wants Y=%i,tile is only %i High\n",Name,InTex.Set,InTex.YOfs*16,BmpH);
InTex.YOfs=0;
}
MakeTexName(InTex,TexName);
ThisRect.X=InTex.XOfs*16;
ThisRect.Y=InTex.YOfs*16;
ThisRect.W=16;
ThisRect.H=16;
ThisFrame.Grab(InFrame,ThisRect);
if (InTex.Flags& PC_TILE_FLAG_MIRROR_X) ThisFrame.FlipX();
if (InTex.Flags & PC_TILE_FLAG_MIRROR_Y) ThisFrame.FlipY();
InTex.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(InTex.TexID);
}
//***************************************************************************
void CMkLevel::MakeTexName(sMkLevelTex &InTex,GString &OutStr)
{
char NewName[256];
GString Name=GFName(InSetNameList[InTex.Set]).File();
sprintf(NewName,"%s_%02d_%02d_%01d_",Name,InTex.XOfs,InTex.YOfs,InTex.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;
// 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 (IsRGBSame(ThisTex,ChkTex)) return(i);
}
}
}
return(-1);
}
//***************************************************************************
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()
{
2001-04-19 17:12:21 +02:00
GString OutFilename=OutName+".Lvl";
File=fopen(OutFilename,"wb");
fwrite(&LevelHdr,1,sizeof(sLevelHdr),File);
2001-04-17 18:42:07 +02:00
WriteLevel();
WriteTileBank();
2001-04-19 17:12:21 +02:00
// rewrite header
fseek(File,0,SEEK_SET);
fwrite(&LevelHdr,1,sizeof(sLevelHdr),File);
fclose(File);
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
2001-04-19 17:12:21 +02:00
int MinOT=123456,MaxOT=0;
2001-04-17 18:42:07 +02:00
void CMkLevel::WriteTileBank()
{
int i,ListSize;
// 2d Tilebank
2001-04-19 17:12:21 +02:00
LevelHdr.TileBank2d=(sTile2d*)ftell(File);
2001-04-17 18:42:07 +02:00
ListSize=OutTile2dList.size();
2001-04-19 17:12:21 +02:00
printf("%i 2d tiles\n",ListSize);
2001-04-17 18:42:07 +02:00
for (i=0; i<ListSize; i++)
{
sTile2d &OutTile=OutTile2dList[i];
fwrite(&OutTile,1,sizeof(sTile2d),File);
}
// 3d Tilebank
2001-04-19 17:12:21 +02:00
LevelHdr.TileBank3d=(sTile3d*)ftell(File);
2001-04-17 18:42:07 +02:00
ListSize=OutTile3dList.size();
2001-04-19 17:12:21 +02:00
printf("%i 3d tiles\n",ListSize);
2001-04-17 18:42:07 +02:00
for (i=0; i<ListSize; i++)
{
sTile3d &OutTile=OutTile3dList[i];
fwrite(&OutTile,1,sizeof(sTile3d),File);
}
// TriList
2001-04-19 17:12:21 +02:00
LevelHdr.TriList=(sTri*)WriteTriList();
2001-04-17 18:42:07 +02:00
// QuadList
2001-04-19 17:12:21 +02:00
LevelHdr.QuadList=(sQuad*)WriteQuadList();
printf("OT %i -> %i\n",MinOT,MaxOT);
2001-04-17 18:42:07 +02:00
// VtxList
2001-04-19 17:12:21 +02:00
LevelHdr.VtxList=(sVtx*)WriteVtxList();
2001-04-23 16:51:44 +02:00
// LevelHdr.VtxList=(sVtx*)OutFaceList.WriteVtxList(File);
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
int CMkLevel::WriteTriList()
{
2001-04-19 17:12:21 +02:00
vector<sTri> &TriList=OutFaceList.GetOutTriList();
vector<sVtx> const &VtxList=OutFaceList.GetVtxList();
2001-04-17 18:42:07 +02:00
int ThisPos=ftell(File);
int i,ListSize=TriList.size();
2001-04-19 17:12:21 +02:00
2001-04-17 18:42:07 +02:00
for (i=0;i<ListSize;i++)
{
sTri &T=TriList[i];
int Z[3];
int OtOfs=0;
// Calc OtOfs
Z[0]=abs(VtxList[T.P0].vz);
Z[1]=abs(VtxList[T.P1].vz);
Z[2]=abs(VtxList[T.P2].vz);
for (int p=0; p<3; p++)
{
if (OtOfs<Z[p]) OtOfs=Z[p];
}
2001-04-19 17:12:21 +02:00
OtOfs/=4;
if (MinOT>OtOfs) MinOT=OtOfs;
2001-04-17 18:42:07 +02:00
if (MaxOT<OtOfs) MaxOT=OtOfs;
2001-04-19 17:12:21 +02:00
if (OtOfs>15) OtOfs=15;
2001-04-17 18:42:07 +02:00
// Write It
fwrite(&T,1,sizeof(sTri),File);
}
2001-04-19 17:12:21 +02:00
printf("Tri %i\n",ListSize);
2001-04-17 18:42:07 +02:00
return(ThisPos);
}
//***************************************************************************
2001-04-19 17:12:21 +02:00
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,MaxOT);
return(ThisPos);
}
2001-04-17 18:42:07 +02:00
//***************************************************************************
2001-04-19 17:12:21 +02:00
int CMkLevel::WriteVtxList()
2001-04-17 18:42:07 +02:00
{
2001-04-19 17:12:21 +02:00
vector<sVtx> const &VtxList=OutFaceList.GetVtxList();
int i,ListSize=VtxList.size();
int Pos=ftell(File);
2001-04-23 16:51:44 +02:00
//sVtx Ofs;
2001-04-17 18:42:07 +02:00
2001-04-23 16:51:44 +02:00
// Ofs.vx=-0;
// Ofs.vy=-0;
// Ofs.vz=-4*Scale;
2001-04-17 18:42:07 +02:00
2001-04-19 17:12:21 +02:00
for (i=0; i<ListSize; i++)
{
sVtx const &In=VtxList[i];
sVtx Out;
2001-04-17 18:42:07 +02:00
2001-04-23 16:51:44 +02:00
Out.vx=+In.vx;
Out.vy=-In.vy;
Out.vz=+In.vz;
// printf("%i\n",Out.vz);
2001-04-19 17:12:21 +02:00
fwrite(&Out,1,sizeof(sVtx),File);
}
return(Pos);
}
//***************************************************************************
//*** Write *****************************************************************
//***************************************************************************
void CMkLevel::WriteLevel()
{
WriteLayers();
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
void CMkLevel::WriteLayers()
{
// Back (Shade)
2001-04-19 17:12:21 +02:00
LevelHdr.BackLayer=WriteLayer(LAYER_TYPE_SHADE,LAYER_SUBTYPE_BACK,0);//"Shade");
2001-04-17 18:42:07 +02:00
// Mid
2001-04-19 17:12:21 +02:00
LevelHdr.MidLayer=WriteLayer(LAYER_TYPE_TILE,LAYER_SUBTYPE_MID,"Mid");
2001-04-17 18:42:07 +02:00
// Action
2001-04-19 17:12:21 +02:00
LevelHdr.ActionLayer=WriteLayer(LAYER_TYPE_TILE,LAYER_SUBTYPE_ACTION,"Action");
2001-04-17 18:42:07 +02:00
// Collision
2001-04-19 17:12:21 +02:00
LevelHdr.CollisionLayer=WriteLayer(LAYER_TYPE_COLLISION,LAYER_SUBTYPE_NONE,"Collision");
2001-04-17 18:42:07 +02:00
// Things
2001-04-19 17:12:21 +02:00
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");
2001-04-23 16:51:44 +02:00
LevelHdr.PlatformGfx=(sModel*)WritePlatformGfx();
2001-04-17 18:42:07 +02:00
}
//***************************************************************************
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);
2001-04-19 17:12:21 +02:00
// printf("%s %i\n",LayerName,Ofs);
2001-04-17 18:42:07 +02:00
PadFile(File);
return(Ofs);
}
2001-04-23 16:51:44 +02:00
//***************************************************************************
int CMkLevel::WritePlatformGfx()
{
int i,ListSize=PlatformList.size();
int Ofs=ftell(File);
for (i=0; i<ListSize; i++)
{
sModel Out;
sMkLevelPlatform &ThisPlatform=PlatformList[i];
Out.TriCount=ThisPlatform.TriCount;
Out.TriStart=ThisPlatform.TriStart;
printf("Writing Platform %s (%i/%i)- %i Tris\n",ThisPlatform.Name,i+1,ListSize,Out.TriCount);
fwrite(&Out,1,sizeof(sModel),File);
}
return(Ofs);
}