Files
firestorm/Gameleap/code/mw4/Tools/TCTb/TCTd.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1364 lines
33 KiB
C++

// TCTd.cpp : super multizone tool !
//
#include <Stuff\StuffHeaders.hpp>
#include <MLR\MLRTexturePool.hpp>
#include <DLLPlatform\DLLPlatform.hpp>
#include <ElementRenderer\ElementRenderer.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\ListElement.hpp>
#include <ElementRenderer\SwitchElement.hpp>
#include <ElementRenderer\ShapeElement.hpp>
#include <ElementRenderer\GridElement.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <MLR\MLRHeaders.hpp>
#include <gosFX\gosFX.hpp>
#include "ImageLib\image.h"
#include "HFslimMZ.hpp"
#include <GameOS\ToolOS.hpp>
//#define NON_DEBUG_BUG 1
HFSlimMZ *theTerrain;
void
MakeBSP(
Stuff::DynamicArrayOf<Stuff::Plane> *planes,
WORD *plane_count,
ElementRenderer::GroupElement *tile,
MemoryStream *stream
);
char theName[1024];
char contentPath[1024];
char inputPath[1024];
char texturePath[1024];
char outputPath[1024];
void FileExport(HFSlimMZ*, const char *fname);
void FileExportMaster(int, int, Scalar, Scalar, Scalar, Scalar, const char
*fname);
void ImportMegabasetexture(Page *page);
void ImportExportCulturalMeshs(Page *map_to_convert, const char*, const
char*, Scalar, Scalar, Scalar, Scalar);
FILE *analyzeFile;
bool doCulturalsOnly = false;
const int culturalLocationMax = 64*1024; // this is INSANE
CulturalLoc culturalLoc[culturalLocationMax];
int culturalLocCount = 0;
bool culturalBillboarding[9];
void __stdcall InitializeGameEngine()
{
//
//---------------------
// Initialize libraries
//---------------------
//
Stuff::InitializeClasses();
MidLevelRenderer::InitializeClasses(NULL, 32768*16);
gosFX::InitializeClasses();
ElementRenderer::InitializeClasses();
Stuff::ArmorLevel=1;
theTerrain = new HFSlimMZ;
Register_Pointer(theTerrain);
analyzeFile = fopen("analyze.txt", "wt");
Verify(analyzeFile);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall DoGameLogic()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall UpdateDisplay()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void __stdcall TerminateGameEngine()
{
Unregister_Pointer(theTerrain);
delete theTerrain;
fclose(analyzeFile);
//
//-------------------
// Turn off libraries
//-------------------
//
ElementRenderer::TerminateClasses();
gosFX::TerminateClasses();
MidLevelRenderer::TerminateClasses();
Stuff::TerminateClasses();
}
//
// Setup the GameOS structure
//
void __stdcall GetGameOSEnvironment( char* CommandLine )
{
CommandLine = CommandLine;
Environment.applicationName = "TCT";
Environment.directoryPath = "\\Tools\\TCTb";
Environment.screenWidth = 640;
Environment.screenHeight = 480;
Environment.fullScreen = FALSE;
Environment.bitDepth = 16;
Environment.debugLog = "TCTLog.txt";
Environment.spew = ""; //"GameOS*";
Environment.UpdateRenderers = UpdateDisplay;
Environment.DoGameLogic = DoGameLogic;
Environment.InitializeGameEngine = InitializeGameEngine;
Environment.TerminateGameEngine = TerminateGameEngine;
Environment.Renderer = 0;
Environment.FullScreenDevice = 0;
Environment.AntiAlias = 0; // true/false - Enable full screen antialiasing
//
// Texture infomation
//
Environment.Texture_S_256 = 13;
Environment.Texture_S_128 = 12;
Environment.Texture_S_64 = 1;
Environment.Texture_S_32 = 1;
Environment.Texture_S_16 = 1;
Environment.Texture_K_256 = 1;
Environment.Texture_K_128 = 1;
Environment.Texture_K_64 = 1;
Environment.Texture_K_32 = 1;
Environment.Texture_K_16 = 1;
Environment.Texture_A_256 = 1;
Environment.Texture_A_128 = 1;
Environment.Texture_A_64 = 1;
Environment.Texture_A_32 = 1;
Environment.Texture_A_16 = 1;
}
int
__cdecl main(int argc, char *argv[])
{
InitGameOS(NULL, NULL, "blabla");
InitializeGameEngine();
const char *notation_file_name;
char default_notation_file_name[] = "TCTd.ini";
notation_file_name = default_notation_file_name;
for(int i=1;i<argc;i++)
{
if(NULL!=strstr(argv[i], "-h") || NULL!=strstr(argv[i], "/h"))
{
fprintf(stdout, "%s - Terrain Creation Tool\n", argv[0]);
fprintf(stdout, "If no commandline options are specified TCT is looking for a TCTd.ini in\n");
fprintf(stdout, "the working directory and none of the options below are true.\n\n");
fprintf(stdout, "Commandline options:\n");
fprintf(stdout, "/h - show this help\n");
fprintf(stdout, "/c - stops after creating Cultural.mlr\n");
fprintf(stdout, "/p - create a precise, seamless terrain (takes much longer!)\n");
fprintf(stdout, "/uid - use interest data, height field must be 24-bit\n\tred channel - height info\n\tgreen channel - interest data\n");
fprintf(stdout, "/bsp - create bsp-files\n");
fprintf(stdout, "/f filename - use specified file as TCTd.ini file\n");
fprintf(stdout, "/s - cap the number of points on a per tile base \n");
fprintf(stdout, "/y - cap the number of points on a per tile base including the surrounding tiles \n");
fprintf(stdout, "/m - saves density map\n\tred channel - tile density\n\t green channel - order of insertion\n\tblue chanel - number of neighbors \n");
fprintf(stdout, "/i - sIlent mode - no more PAUSEs \n");
exit(0);
}
if(NULL!=strstr(argv[i], "-p") || NULL!=strstr(argv[i], "/p"))
{
fprintf(stdout, "Precise Mode requested.\n");
doPrecise = true;
}
if(NULL!=strstr(argv[i], "-uid") || NULL!=strstr(argv[i], "/uid"))
{
fprintf(stdout, "Use interest data Mode requested.\n");
doInterest = true;
}
if(NULL!=strstr(argv[i], "-s") || NULL!=strstr(argv[i], "/s"))
{
fprintf(stdout, "Cap triangle count Mode requested.\n");
doTileCap = true;
}
if(NULL!=strstr(argv[i], "-c") || NULL!=strstr(argv[i], "/c"))
{
fprintf(stdout, "Stops executing after creation of Cultural.mlr.\n");
doCulturalsOnly = true;
}
if(NULL!=strstr(argv[i], "-y") || NULL!=strstr(argv[i], "/y"))
{
fprintf(stdout, "Cap triangle count Mode 2 requested.\n");
doTileCapYovin = true;
}
if(NULL!=strstr(argv[i], "-m") || NULL!=strstr(argv[i], "/m"))
{
fprintf(stdout, "Create density map requested. Programm will exit after bitmap creation.\n");
doDensityMap = true;
}
if(NULL!=strstr(argv[i], "-i") || NULL!=strstr(argv[i], "/i"))
{
fprintf(stdout, "Silent mode requested. Program won't be pausing anymore.\n");
silentMode = true;
}
if(NULL!=strstr(argv[i], "-bsp") || NULL!=strstr(argv[i], "/bsp"))
{
fprintf(stdout, "Bsp-file creation requested.\n");
doBSP = true;
}
if(NULL!=strstr(argv[i], "-f") || NULL!=strstr(argv[i], "/f"))
{
notation_file_name = argv[++i];
fprintf(stdout, "TCTd will use following file as ini-file: %s.\n", notation_file_name);
}
}
//
//--------------------------------------------------------------
// Open up the .ini file, and figure out how many map to convert
//--------------------------------------------------------------
//
{
NotationFile config_file(notation_file_name);
NotationFile::PageIterator *maps = config_file.MakePageIterator();
Check_Object(maps);
//
//----------------------------
// Convert the maps one by one
//----------------------------
//
Page *map_to_convert;
while ((map_to_convert = maps->ReadAndNext()) != NULL)
{
Check_Object(map_to_convert);
const char* map = map_to_convert->GetName();
Check_Pointer(map);
const char *path;
strcpy(contentPath, "Content\\");
strcpy(texturePath, "Textures\\");
const char *default_path = "\\";
if(!map_to_convert->GetEntry("InputPath", &path))
{
path = default_path;
}
strncpy(inputPath, path, 1024);
fprintf(stdout, "Inputpath: %s\n", inputPath);
gos_PushCurrentHeap(MidLevelRenderer::TexturePoolHeap);
MidLevelRenderer::TGAFilePool *pool = new MidLevelRenderer::TGAFilePool(texturePath);
Check_Object(pool);
MidLevelRenderer::MLRTexturePool::Instance =
new MidLevelRenderer::MLRTexturePool(pool);
Check_Object(MidLevelRenderer::MLRTexturePool::Instance);
gos_PopCurrentHeap();
path = map;
strncpy(theName, path, 1024);
fprintf(stdout, "Mapname: %s\n", theName);
float dX, dY, dZ;
if(!map_to_convert->GetEntry("DeltaX", &dX))
{
dX = 5.0f;
}
if(!map_to_convert->GetEntry("DeltaY", &dY))
{
dY = 5.0f;
}
if(!map_to_convert->GetEntry("DeltaZ", &dZ))
{
dZ = 5.0f;
}
fprintf(stdout, "Heighfield size: %f %f %f\n", dX, dY, dZ);
theTerrain->SetScale(dX, dY, dZ);
const char *map_center;
Stuff::Scalar map_center_x, map_center_z;
map_center_x = 0.0f;
map_center_z = 0.0f;
if(map_to_convert->GetEntry("MapCenter", &map_center))
{
sscanf(map_center, "%f %f", &map_center_x, &map_center_z);
theTerrain->SetCenter(map_center_x, map_center_z);
}
else
{
theTerrain->SetCenter(0.0f, 0.0f);
}
ImportExportCulturalMeshs(map_to_convert, inputPath, theName, dX, dZ, map_center_x, map_center_z);
if(doCulturalsOnly==false)
{
fprintf(stdout, "Start importing the mega texture.\n");
if(doBSP==false)
{
if(!map_to_convert->GetEntry("WaterLevel", &waterLevel))
{
doWater = false;
}
else
{
doWater = true;
fprintf(stdout, "Waterlevel found at: %f.\n", waterLevel);
}
}
else
{
doWater = false;
}
ImportMegabasetexture(map_to_convert);
}
else
{
fprintf(stdout,"Culturals done I am going home.");
}
}
}
TerminateGameEngine();
ExitGameOS();
return 0;
}
bool
ImportBitmap(Image &timg, int iRBX, int optPolys, int bucketSize, int
smooth, const char *density_map_name)
{
if(timg.GetBpp()<8)
{
STOP(("Bitmap Must Be At Least 8 bit - Depth Error\n"));
return false;
}
else
{
if(timg.GetBpp()>8) //Not a Bitmapped Image Resolve
{
if(doInterest==true)
{
theTerrain->FillInterestDataFromImage(timg);
iRBX = 0;
}
RMETHOD rmd;
switch(iRBX)
{
case 0:
rmd=RMD_REDC;
break;
case 1:
rmd=RMD_GREENC;
break;
case 2:
rmd=RMD_BLUEC;
break;
case 3:
rmd=RMD_ALPHAC;
break;
case 4:
rmd=RMD_MAX;
break;
case 5:
rmd=RMD_BHT;
break;
default:
rmd=RMD_MAX;
}
timg.ReduceTo8Bit(rmd);
}
else
{
doInterest = false;
}
Verify(timg.GetWidth() % 256 == 0);
Verify(timg.GetHeight() % 256 == 0);
theTerrain->FillFromImage(timg, smooth);
fprintf(stdout, "Heightfield image loaded.\n");
int xDim, zDim;
theTerrain->GetZoneDimensions(&xDim, &zDim);
Verify((optPolys > 0) && (bucketSize > 0));
theTerrain->OptimizeHField(xDim*zDim*optPolys/2, bucketSize, density_map_name);
fprintf(stdout, "Terrain optimized.\n");
}
return true;
}
bool
ImportCulturalLocationBitmap(Image &timg, int iRBX, Scalar dX, Scalar dZ,
Scalar xOffset, Scalar zOffset, int max, int min)
{
if(timg.GetWidth()!=timg.GetHeight())
{
fprintf(stdout, "Bitmap Must Be Square - Dimension Error\n");
return false;
}
if(timg.GetBpp()<8)
{
fprintf(stdout, "Bitmap Must Be At Least 8 bit - Depth Error\n");
return false;
}
else
{
if(timg.GetBpp()>8) //Not a Bitmapped Image Resolve
{
RMETHOD rmd;
switch(iRBX)
{
case 0:
rmd=RMD_REDC;
break;
case 1:
rmd=RMD_GREENC;
break;
case 2:
rmd=RMD_BLUEC;
break;
case 3:
rmd=RMD_ALPHAC;
break;
case 4:
rmd=RMD_MAX;
break;
case 5:
rmd=RMD_BHT;
break;
default:
rmd=RMD_MAX;
}
timg.ReduceTo8Bit(rmd);
}
Verify(timg.GetWidth() % 256 == 0);
Verify(timg.GetHeight() % 256 == 0);
}
BYTE *img = timg.Lock();
int w = timg.GetHeight();
int h = timg.GetWidth();
for(int j=0;j<w;j++)
{
for(int i=0;i<h;i++)
{
if(img[j*timg.GetPitch() + i] > 0x80)
{
if(culturalLocCount>=culturalLocationMax)
{
return true;
}
culturalLoc[culturalLocCount].loc.x = (w-i-1)*dX +
4.0f*(Random::GetFraction() - 0.5f) - xOffset;
culturalLoc[culturalLocCount].loc.y = 0.0f;
culturalLoc[culturalLocCount].loc.z = (h-j-1)*dZ +
4.0f*(Random::GetFraction() - 0.5f) - zOffset;
culturalLoc[culturalLocCount].nr = min + Random::GetLessThan(max);
culturalLoc[culturalLocCount].yaw =
culturalBillboarding[culturalLoc[culturalLocCount].nr] ? 0xff :
Random::GetLessThan(180);
culturalLocCount++;
}
}
}
return true;
}
MLRShape*
TraversErfBranch(ElementRenderer::Element *elmt)
{
if(elmt->GetClassID() == ElementRenderer::CameraElementClassID)
{
return NULL;
}
switch(elmt->GetClassID())
{
case ElementRenderer::GroupElementClassID:
{
ElementRenderer::GroupElement *group =
Cast_Pointer(ElementRenderer::GroupElement *, elmt);
Stuff::ChainIteratorOf<ElementRenderer::Element*> *children =
group->MakeIterator();
Register_Object(children);
ElementRenderer::Element *child = NULL;
while ((child = children->ReadAndNext()) != NULL)
{
TraversErfBranch(child);
}
Unregister_Object(children);
delete children;
}
break;
case ElementRenderer::ListElementClassID:
{
ElementRenderer::ListElement *group =
Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
TraversErfBranch(group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::GridElementClassID:
{
ElementRenderer::GridElement *group =
Cast_Pointer(ElementRenderer::GridElement *, elmt);
BYTE xSize, zSize;
group->GetSize(&xSize, &zSize);
for(BYTE i=0;i<zSize;i++)
for(BYTE j=0;j<xSize;j++)
{
TraversErfBranch( group->GetIndexedElement(i, j));
}
}
break;
case ElementRenderer::LODElementClassID:
{
ElementRenderer::ListElement *group =
Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
TraversErfBranch(group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::PointCloudElementClassID:
{
}
break;
case ElementRenderer::ScalableShapeElementClassID:
{
ElementRenderer::ShapeElement *group =
Cast_Pointer(ElementRenderer::ShapeElement *, elmt);
return group->GetMLRShape();
}
break;
case ElementRenderer::ScreenQuadsElementClassID:
{
}
break;
case ElementRenderer::ShapeElementClassID:
{
ElementRenderer::ShapeElement *group =
Cast_Pointer(ElementRenderer::ShapeElement *, elmt);
return group->GetMLRShape();
}
break;
case ElementRenderer::SwitchElementClassID:
{
ElementRenderer::ListElement *group =
Cast_Pointer(ElementRenderer::ListElement *, elmt);
for(int i=0;i<group->GetActiveCount();i++)
{
TraversErfBranch(group->GetIndexedElement(i));
}
}
break;
case ElementRenderer::TriangleCloudElementClassID:
{
}
break;
}
return NULL;
}
void
ImportExportCulturalMeshs(
Page *map_to_convert,
const char *dir,
const char *missionName,
Scalar dX, Scalar dZ,
Scalar xOffset, Scalar zOffset
)
{
gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
MLRShape *outShape = new MLRShape(9);
gos_PopCurrentHeap();
ElementRenderer::Element *elm[3] = {NULL, NULL, NULL};
FileStream fs[3];
int count=0, primCount=0, primCounts[3];
char name[1024];
const char *fadeValues;
if(map_to_convert->GetEntry("CulturalFadeValues", &fadeValues))
{
Scalar fadeIn = 50.0f, fadeOut = 80.0f;
sscanf(fadeValues, "%f %f", &fadeIn, &fadeOut);
theTerrain->SetCulturalFadeValues(fadeIn, fadeOut);
}
const char *culAname;
if(map_to_convert->GetEntry("CulturalALocations", &culAname))
{
ChainOf<Note*> *nc = map_to_convert->MakeNoteChain("CulturalAObject");
ChainIteratorOf<Note*> nci(nc);
Note *innote;
while (innote = nci.ReadAndNext())
{
const char *value;
innote->GetEntry(&value);
int billboarded;
sscanf(value, "%s %d", name, &billboarded);
MString fname(dir);
fname += "Culturals\\";
fname += name;
fs[0].Open(fname);
if(fs[0].IsFileOpened()==true)
{
gos_PushCurrentHeap(ElementRenderer::g_Heap);
elm[0] = ElementRenderer::Element::Create(&fs[0], ElementRenderer::ReadERFVersion(&fs[0]));
gos_PopCurrentHeap();
MLRShape *shape = TraversErfBranch(elm[0]);
if(shape!=NULL)
{
MLRPrimitiveBase *prim = shape->Find(0);
MLRState state = prim->GetReferenceState();
state.SetFogMode(0);
prim->SetReferenceState(state);
outShape->Add(prim);
culturalBillboarding[count++] = billboarded>0 ? true : false;
}
}
}
delete nc;
primCounts[0] = outShape->GetNum() - primCount;
if(primCounts[0]>0)
{
MString fname(dir);
fname += "Culturals\\";
fname += culAname;
Image timg;
timg.Load(fname);
if(false==ImportCulturalLocationBitmap(timg, 4, dX, dZ, xOffset, zOffset, primCounts[0], primCount))
{
STOP(("Cannot find %s!", fname));
}
}
primCount = primCounts[0];
}
const char *culBname;
if(map_to_convert->GetEntry("CulturalBLocations", &culBname))
{
ChainOf<Note*> *nc = map_to_convert->MakeNoteChain("CulturalBObject");
ChainIteratorOf<Note*> nci(nc);
Note *innote;
while (innote = nci.ReadAndNext())
{
MString fname(dir);
fname += "Culturals\\";
const char *value;
innote->GetEntry(&value);
int billboarded;
sscanf(value, "%s %d", name, &billboarded);
fname += name;
fs[1].Open(fname);
if(fs[1].IsFileOpened()==true)
{
gos_PushCurrentHeap(ElementRenderer::g_Heap);
elm[1] = ElementRenderer::Element::Create(&fs[1], ElementRenderer::ReadERFVersion(&fs[1]));
gos_PopCurrentHeap();
MLRShape *shape = TraversErfBranch(elm[1]);
if(shape!=NULL)
{
MLRPrimitiveBase *prim = shape->Find(0);
MLRState state = prim->GetReferenceState();
state.SetFogMode(0);
prim->SetReferenceState(state);
outShape->Add(prim);
culturalBillboarding[count++] = billboarded>0 ? true : false;
}
}
}
delete nc;
primCounts[1] = outShape->GetNum() - primCount;
if(primCounts[1]>0)
{
MString fname(dir);
fname += "Culturals\\";
fname += culBname;
Image timg;
timg.Load(fname);
if(false==ImportCulturalLocationBitmap(timg, 4, dX, dZ, xOffset, zOffset, primCounts[1], primCount))
{
STOP(("Cannot find %s!", fname));
}
}
primCount += primCounts[1];
}
const char *culCname;
if(map_to_convert->GetEntry("CulturalCLocations", &culCname))
{
ChainOf<Note*> *nc = map_to_convert->MakeNoteChain("CulturalCObject");
ChainIteratorOf<Note*> nci(nc);
Note *innote;
while (innote = nci.ReadAndNext())
{
const char *value;
innote->GetEntry(&value);
int billboarded;
sscanf(value, "%s %d", name, &billboarded);
MString fname(dir);
fname += "Culturals\\";
fname += name;
fs[2].Open(fname);
if(fs[2].IsFileOpened()==true)
{
gos_PushCurrentHeap(ElementRenderer::g_Heap);
elm[2] = ElementRenderer::Element::Create(&fs[2], ElementRenderer::ReadERFVersion(&fs[2]));
gos_PopCurrentHeap();
MLRShape *shape = TraversErfBranch(elm[2]);
if(shape!=NULL)
{
MLRPrimitiveBase *prim = shape->Find(0);
MLRState state = prim->GetReferenceState();
state.SetFogMode(0);
prim->SetReferenceState(state);
outShape->Add(prim);
culturalBillboarding[count++] = billboarded>0 ? true : false;
}
}
}
delete nc;
primCounts[2] = outShape->GetNum() - primCount;
if(primCounts[2]>0)
{
MString fname(dir);
fname += "Culturals\\";
fname += culCname;
Image timg;
timg.Load(fname);
if(false==ImportCulturalLocationBitmap(timg, 4, dX, dZ, xOffset, zOffset, primCounts[2], primCount))
{
STOP(("Cannot find %s!", fname));
}
}
primCount += primCounts[2];
}
if(primCount>0)
{
MString fname(dir);
fname += missionName;
fname += "Culturals.mlr";
if(gos_FileReadOnly(fname)==false)
{
FileStream fs(fname, FileStream::WriteOnly);
if(fs.IsFileOpened()==true)
{
WriteMLRVersion(&fs);
OBB obb;
obb = OBB::Identity;
obb.sphereRadius = 5.0f;
fs << obb;
fs << outShape->GetClassID();
fs << (BYTE)outShape->GetNum();
int i;
MLRPrimitiveBase *prim;
// MLR_I_TMesh *tmesh;
for(i=0;i<outShape->GetNum();i++)
{
prim = outShape->Find(i);
prim->Save(&fs);
// tmesh = Cast_Object(MLR_I_TMesh*, prim);
// tmesh->MLR_I_TMesh::Save(&fs);
}
char mapDataFileName[1024];
sprintf(mapDataFileName, "Content\\Maps\\%s\\%s.data", theName, theName);
NotationFile mapData(mapDataFileName);
Page *page = mapData.FindPage("GameData");
if(page!=NULL)
{
sprintf(mapDataFileName, "Content\\Maps\\%s\\%sCulturals.mlr", missionName, missionName);
page->SetEntry("CulturalData", mapDataFileName);
mapData.Save();
}
}
}
else
{
STOP(("File %s is read-only!", fname));
}
}
if(elm[0]!=NULL)
{
delete elm[0];
}
if(elm[1]!=NULL)
{
delete elm[1];
}
if(elm[2]!=NULL)
{
delete elm[2];
}
}
bool
ImportBitmap(const char *fname, int iRBX, int optPolys, int bucketSize, int smooth, const char *density_map_name)
{
Image timg;
char tfn[MAX_PATH];
strcpy(tfn, fname);
timg.Load(tfn);
return ImportBitmap(timg, iRBX, optPolys, bucketSize, smooth, density_map_name);
}
void
ImportMegabasetexture(
Page *map_to_convert
)
{
char buf[MAX_PATH];
GetCurrentDirectory(MAX_PATH, buf);
Check_Object(map_to_convert);
const char *hf_name;
if(!map_to_convert->GetEntry("HeightField", &hf_name))
{
SetCurrentDirectory(buf);
return;
}
int polyCount = 5000;
map_to_convert->GetEntry("PolyCount", &polyCount);
int bucketSize = 64;
map_to_convert->GetEntry("BucketSize", &bucketSize);
if(bucketSize>Limits::Max_Number_Vertices_Per_Mesh/2)
{
bucketSize = Limits::Max_Number_Vertices_Per_Mesh/2;
}
int smoothPass = 2;
map_to_convert->GetEntry("SmoothingPasses", &smoothPass);
int xDim, zDim;
char hf_path[1024], density_map_name[1024];
strcpy(hf_path, inputPath);
strcat(hf_path, hf_name);
sprintf(density_map_name, "%sdensity_%s", inputPath, hf_name);
if(false==ImportBitmap(hf_path, 0, polyCount, bucketSize, smoothPass, density_map_name))
{
SetCurrentDirectory(buf);
return;
}
int borderPix = 0;
map_to_convert->GetEntry("BorderPixels", &borderPix);
int nrOfLevels = 3;
map_to_convert->GetEntry("NumberOfLevels", &nrOfLevels);
fprintf(stdout, "HF: %s pc: %d bs: %d l: %d\n", hf_name, polyCount, bucketSize, nrOfLevels);
theTerrain->SetAllDepth(nrOfLevels);
theTerrain->GetZoneDimensions(&xDim, &zDim);
const char *mega_detail_name;
if(!map_to_convert->GetEntry("DetailTexture", &mega_detail_name))
{
SetCurrentDirectory(buf);
return;
}
char detailName[1024];
// sprintf(detailName, "Maps\\%s\\%s", theName, mega_detail_name);
strncpy(detailName, mega_detail_name, 1023);
char underWaterDetailName[1024];
char waterTextureName[1024];
char waterDetailName[1024];
const char *under_water_detail_name = NULL;
const char *water_texture_name = NULL;
const char *water_detail_texture_name = NULL;
Scalar waterTextureRatio = 4.0f;
Scalar waterDetailTextureRatio = 4.0f;
int waterMovieFrames = 1;
int waterDetailMovieFrames = 1;
if(doWater==true)
{
if(map_to_convert->GetEntry("UnderwaterdetailTexture", &under_water_detail_name))
{
// sprintf(underWaterDetailName, "Maps\\%s\\%s", theName, under_water_detail_name);
strncpy(underWaterDetailName, under_water_detail_name, 1023);
under_water_detail_name = underWaterDetailName;
}
else
{
under_water_detail_name = NULL;
}
if(map_to_convert->GetEntry("WaterTexture", &water_texture_name))
{
// sprintf(waterTextureName, "Maps\\%s\\%s", theName, water_texture_name);
strncpy(waterTextureName, water_texture_name, 1023);
water_texture_name = waterTextureName;
}
else
{
water_texture_name = NULL;
}
map_to_convert->GetEntry("WaterTextureMovieFrames", &waterMovieFrames);
if(map_to_convert->GetEntry("WaterDetailTexture", &water_detail_texture_name))
{
// sprintf(waterDetailName, "Maps\\%s\\%s", theName, water_detail_texture_name);
strncpy(waterDetailName, water_detail_texture_name, 1023);
water_detail_texture_name = waterDetailName;
}
else
{
water_detail_texture_name = NULL;
}
map_to_convert->GetEntry("WaterDetailTextureMovieFrames", &waterDetailMovieFrames);
char mapDataFileName[1024];
sprintf(mapDataFileName, "Content\\Maps\\%s\\%s.data", theName, theName);
NotationFile mapData(mapDataFileName);
Page *page = mapData.FindPage("GameData");
if(page!=NULL)
{
page->SetEntry("WaterLevel", waterLevel);
if(under_water_detail_name!=NULL)
{
page->SetEntry("UnderWaterTexture", under_water_detail_name);
}
if(water_texture_name!=NULL)
{
page->SetEntry("WaterTexture", water_texture_name);
}
if(water_detail_texture_name!=NULL)
{
page->SetEntry("WaterDetailTexture", water_detail_texture_name);
}
mapData.Save();
}
map_to_convert->GetEntry("WaterTextureRatio", &waterTextureRatio);
map_to_convert->GetEntry("WaterDetailRatio", &waterDetailTextureRatio);
theTerrain->SetWaterInfo(water_texture_name, waterTextureRatio, waterMovieFrames);
}
Scalar ratio = 16.0f;
map_to_convert->GetEntry("DetailRatio", &ratio);
Scalar dStart = 32.0f;
map_to_convert->GetEntry("DetailFadeBegin", &dStart);
Scalar dEnd = 64.0f;
map_to_convert->GetEntry("DetailFadeEnd", &dEnd);
const char *mega_alpha_name;
MLRState::AlphaMode alpha;
if(map_to_convert->GetEntry("DetailAlphaMode", &mega_alpha_name))
{
if(!strncmp(mega_alpha_name, "oneone", sizeof("oneone")))
{
alpha = MLRState::OneOneMode;
} else
if(!strncmp(mega_alpha_name, "alphainvalpha", sizeof("alphainvalpha")))
{
alpha = MLRState::AlphaInvAlphaMode;
} else
if(!strncmp(mega_alpha_name, "oneinvalpha", sizeof("oneinvalpha")))
{
alpha = MLRState::OneInvAlphaMode;
} else {
alpha = MLRState::AlphaOneMode;
}
}
else
{
alpha = MLRState::AlphaInvAlphaMode;
}
theTerrain->SetWaterDetailTextureInfo(
water_detail_texture_name,
0.0f,
0.0f,
waterDetailTextureRatio,
waterDetailTextureRatio,
dStart,
dEnd,
alpha,
waterDetailMovieFrames
);
theTerrain->SetBorderPixels(borderPix);
theTerrain->SetDetailTextureInfo(
detailName,
under_water_detail_name,
0.0f,
0.0f,
ratio,
ratio,
dStart,
dEnd,
alpha
);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalling SetMegaTexture");
#endif
if(true == theTerrain->SetMegaTexture(
nrOfLevels,
bucketSize,
theName,
outputPath)
)
{
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalling SetMegaTexture (tctd) (returned TRUE)");
#endif
theTerrain->SetCulturals(culturalLoc, culturalLocCount);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalling SetMegaTexture (SetCulturals)");
#endif
FileExport(theTerrain, outputPath);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalling SetMegaTexture (FileExport)");
#endif
}
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\nCalling SetMegaTexture (done)");
#endif
sprintf(outputPath, "%sMaps\\%s\\%s.erf", contentPath, theName, theName);
#ifdef NON_DEBUG_BUG
fprintf(stdout, "\n%s", outputPath);
#endif
FileExportMaster(
xDim, zDim,
theTerrain->GetCenterX(), theTerrain->GetCenterZ(),
theTerrain->GetXScale(), theTerrain->GetZScale(),
outputPath
);
SetCurrentDirectory(buf);
}
bool Debug_Tile=false;
bool Debug_Zone=false;
void
ZoneExport(
ElementRenderer::GridElement *terrain,
const char* zone_filename
)
{
Check_Object(terrain);
Check_Pointer(zone_filename);
//
//--------------------------------------------------------
// Make a memory stream array to avoid reallocating memory
//--------------------------------------------------------
//
DynamicArrayOf<DynamicMemoryStream *> tile_streams(64);
int triangle_count = terrain->CountTriangles();
Verify(triangle_count < 32768);
DynamicArrayOf<Plane> planes(triangle_count*2);
WORD plane_count = 0;
//
//---------------------------
// Step through all the tiles
//---------------------------
//
int t;
for (t=0; t<64; ++t)
{
tile_streams[t] = new DynamicMemoryStream;
Check_Object(tile_streams[t]);
ElementRenderer::GroupElement *tile =
Cast_Object(
ElementRenderer::GroupElement*,
terrain->GetIndexedElement(t)
);
Check_Object(tile);
//
//-----------------------------------------------
// For each tile, run the collision process on it
//-----------------------------------------------
//
fprintf(stdout, "\r Working on tile %d", t);
MakeBSP(&planes, &plane_count, tile, tile_streams[t]);
}
fprintf(stdout, "\r Used %d planes \n", plane_count);
//
//------------------------------------------
// Copy the stream info into the output file
//------------------------------------------
//
Stuff::FileStream zone_stream(zone_filename, Stuff::FileStream::WriteOnly);
zone_stream << plane_count;
zone_stream.WriteBytes(planes.GetData(), plane_count * sizeof(Plane));
for (t=0; t<64; ++t)
{
Check_Object(tile_streams[t]);
tile_streams[t]->Rewind();
zone_stream << tile_streams[t]->GetSize() << *tile_streams[t];
Check_Object(tile_streams[t]);
delete tile_streams[t];
}
}
void
FileExport(HFSlimMZ *tT, const char *output_path)
{
//
//---------------------------------------------------
// Analyze the set file and extract the useful pieces
//---------------------------------------------------
//
int i, j, xDim, zDim;
tT->GetZoneDimensions(&xDim, &zDim);
Stuff::DynamicArrayOf<ElementRenderer::GridElement*> *terrainArray;
terrainArray = tT->GetTerrainArray();
ElementRenderer::GridElement *terrain;
for(j=0;j<zDim;j++)
{
for(i=0;i<xDim;i++)
{
terrain = (*terrainArray)[j*xDim+i];
Check_Object(terrain);
if(doBSP==true)
{
fprintf(stdout, "Processing zone %c%c\n", 'A'+j, 'A'+i);
sprintf(outputPath, "%sMaps\\%s\\%c%c.bsp", contentPath, theName, 'A'+j, 'A'+i);
ZoneExport(terrain, outputPath);
}
else
{
sprintf(outputPath, "%sMaps\\%s\\%c%c.erf", contentPath, theName, 'A'+j, 'A'+i);
Stuff::FileStream element_stream(output_path, Stuff::FileStream::WriteOnly);
if(element_stream.IsFileOpened()==true)
{
fprintf(stdout, "Saving file %s.\n", outputPath);
}
else
{
fprintf(stdout, "Couldn't open file %s.\n", outputPath);
}
ElementRenderer::WriteERFVersion(&element_stream);
int row, col;
for (row=0; row<8; ++row)
{
for (col=0; col<8; ++col)
{
ElementRenderer::GroupElement *group =
Cast_Object(
ElementRenderer::GroupElement*,
terrain->GetIndexedElement(row, col)
);
Stuff::ChainIteratorOf<ElementRenderer::Element*>* iterator = group->MakeIterator();
Check_Object(iterator);
ElementRenderer::Element *element = iterator->GetCurrent();
Check_Object(element);
Verify(element->GetLocalToWorld() == Stuff::LinearMatrix4D::Identity);
ElementRenderer::StateChange *state = new ElementRenderer::StateChange;
state->SetLightingMode(MidLevelRenderer::MLRState::TerrainLightingMode);
element->AdoptStateChange(state);
element->Save(&element_stream);
Check_Object(iterator);
delete iterator;
}
}
}
}
}
}
void
FileExportMaster(int xDim, int zDim, Scalar mapCenterX, Scalar mapCenterZ, Scalar xGrid, Scalar zGrid, const char *output_path)
{
gos_PushCurrentHeap(ElementRenderer::GridElement::s_Heap);
ElementRenderer::GridElement *terrain =
new ElementRenderer::GridElement(
zDim, xDim,
-mapCenterZ, -mapCenterX,
zDim*256*zGrid, xDim*256*xGrid
);
terrain->SetSize(0);
gos_PopCurrentHeap();
//
//---------------------------------------------------
// Analyze the set file and extract the useful pieces
//---------------------------------------------------
//
terrain->SetRootMode();
Stuff::FileStream element_stream(output_path,
Stuff::FileStream::WriteOnly);
ElementRenderer::WriteERFVersion(&element_stream);
terrain->Save(&element_stream);
} // end of export