root/cafu/trunk/CaBSP/CaBSP.cpp

Revision 455, 10.3 KB (checked in by Carsten, 4 months ago)

Updated copyright banners (in C++ files).

Line 
1/*
2=================================================================================
3This file is part of Cafu, the open-source game engine and graphics engine
4for multiplayer, cross-platform, real-time 3D action.
5Copyright (C) 2002-2012 Carsten Fuchs Software.
6
7Cafu is free software: you can redistribute it and/or modify it under the terms
8of the GNU General Public License as published by the Free Software Foundation,
9either version 3 of the License, or (at your option) any later version.
10
11Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with Cafu. If not, see <http://www.gnu.org/licenses/>.
17
18For support and more information about Cafu, visit us at <http://www.cafu.de>.
19=================================================================================
20*/
21
22/**********************************************/
23/***                                        ***/
24/*** Cafu Binary Space Partitioning Utility ***/
25/***                                        ***/
26/***     I think that I shall never see     ***/
27/***         a poem lovely as a tree        ***/
28/***                                        ***/
29/**********************************************/
30
31#ifdef _WIN32
32#define WIN32_LEAN_AND_MEAN
33#include <windows.h>
34#else
35#include <stdarg.h>
36#include <unistd.h>
37#include <string.h>
38#define _stricmp strcasecmp
39#endif
40
41#include <time.h>
42#include <ctype.h>
43#include <stdio.h>
44
45#include "ConsoleCommands/Console.hpp"
46#include "ConsoleCommands/ConsoleInterpreter.hpp"
47#include "ConsoleCommands/ConsoleStdout.hpp"
48#include "FileSys/FileManImpl.hpp"
49#include "Templates/Array.hpp"
50#include "MaterialSystem/Material.hpp"
51#include "MaterialSystem/MaterialManager.hpp"
52#include "MaterialSystem/MaterialManagerImpl.hpp"
53#include "ClipSys/CollisionModelMan_impl.hpp"
54
55#include "BspTreeBuilder/BspTreeBuilder.hpp"
56
57#if defined(_WIN32)
58    #if defined(_MSC_VER)
59        #define vsnprintf _vsnprintf
60        #if (_MSC_VER<1300)
61        #define for if (false) ; else for
62    #endif
63    #endif
64#endif
65
66
67static cf::ConsoleStdoutT ConsoleStdout(true);      // Enable auto-flushing the stdout stream for CaBSP.
68cf::ConsoleI* Console=&ConsoleStdout;
69
70static cf::FileSys::FileManImplT FileManImpl;
71cf::FileSys::FileManI* cf::FileSys::FileMan=&FileManImpl;
72
73static cf::ClipSys::CollModelManImplT CCM;
74cf::ClipSys::CollModelManI* cf::ClipSys::CollModelMan=&CCM;
75
76ConsoleInterpreterI* ConsoleInterpreter=NULL;
77MaterialManagerI*    MaterialManager   =NULL;
78
79
80const time_t ProgramStartTime=time(NULL);
81
82// Returns a string with the elapsed time since program start.
83// The string is in the format "hh:mm:ss".
84const char* GetTimeSinceProgramStart()
85{
86    const unsigned long TotalSec=(unsigned long)difftime(time(NULL), ProgramStartTime);
87    const unsigned long Sec     =TotalSec % 60;
88    const unsigned long Min     =(TotalSec/60) % 60;
89    const unsigned long Hour    =TotalSec/3600;
90
91    static char TimeString[16];
92    sprintf(TimeString, "%2lu:%2lu:%2lu", Hour, Min, Sec);
93
94    return TimeString;
95}
96
97
98static void Error(const char* ErrorText, ...)
99{
100    va_list ArgList;
101    char    ErrorString[256];
102
103    if (ErrorText!=NULL)
104    {
105        va_start(ArgList, ErrorText);
106            vsnprintf(ErrorString, 256, ErrorText, ArgList);
107        va_end(ArgList);
108
109        Console->Print(cf::va("\nFATAL ERROR: %s\n", ErrorString));
110    }
111
112    Console->Print("Program aborted.\n\n");
113    exit(1);
114}
115
116
117static void WriteLogFileEntry(const char* WorldPathName)
118{
119    char          DateTime [256]="unknown";
120    char          HostName [256]="unknown";
121    char          WorldName[256]="unknown";
122    time_t        Time          =time(NULL);
123    unsigned long RunningSec    =(unsigned long)difftime(Time, ProgramStartTime);
124    FILE*         LogFile       =fopen("CaBSP.log", "a");
125
126    if (!LogFile) return;
127
128    strftime(DateTime, 256, "%d.%m.%Y %H:%M", localtime(&Time));
129    DateTime[255]=0;
130
131#ifdef _WIN32
132    unsigned long Dummy=256;
133    if (!GetComputerName(HostName, &Dummy)) sprintf(HostName, "unknown (look-up failed).");
134#else
135    // This function also works on Windows, but sadly requires calls to 'WSAStartup()' and 'WSACleanup()'.
136    if (gethostname(HostName, 256)) sprintf(HostName, "unknown (look-up failed).");
137#endif
138    HostName[255]=0;
139
140    if (WorldPathName)
141    {
142        // Dateinamen abtrennen (mit Extension).
143        size_t i=strlen(WorldPathName);
144
145        while (i>0 && WorldPathName[i-1]!='/' && WorldPathName[i-1]!='\\') i--;
146        strncpy(WorldName, WorldPathName+i, 256);
147        WorldName[255]=0;
148
149        // Extension abtrennen.
150        i=strlen(WorldName);
151
152        while (i>0 && WorldName[i-1]!='.') i--;
153        if (i>0) WorldName[i-1]=0;
154    }
155
156    // Date, Time, WorldName, TimeForCompletion on [HostName]
157    fprintf(LogFile, "%-16s %-16s%3lu:%02lu:%02lu [%-16s]\n", DateTime, WorldName, RunningSec/3600, (RunningSec/60) % 60, RunningSec % 60, HostName);
158    fclose(LogFile);
159}
160
161
162void Usage()
163{
164    Console->Print("USAGE: CaBSP InFile.cmap OutFile.cw [OPTIONS]\n");
165    Console->Print("\n");
166 // Console->Print("OPTIONS:\n");
167 // Console->Print("-putWadInCW WadFile   : Place textures used from WAD specified into CW.\n");
168 // Console->Print("-p WadFile            : Short form of '-putWadInCW'. Recommended when the\n");
169 // Console->Print("                        limited length of the command line is a problem.\n");
170 // Console->Print("\n");
171    Console->Print("Please note that all file names must include their paths and suffixes!\n");
172 // Console->Print("WAD file names are partially name-matched, case insensitive.\n");
173
174    // The most simple tree means that there is no leak detection and no attempt to fill the world.
175
176    exit(1);
177}
178
179
180#include "../Common/World.hpp"
181#include "LoadWorld.cpp"
182
183
184int main(int ArgC, const char* ArgV[])
185{
186    bool Option_MostSimpleTree    =false;
187    bool Option_MinimizeFaceSplits=false;
188
189    Console->Print(cf::va("\n*** Cafu Binary Space Partitioning Utility, Version 10a (%s) ***\n\n", __DATE__));
190
191
192    // Initialize the FileMan by mounting the default file system.
193    // Note that specifying "./" (instead of "") as the file system description effectively prevents the use of
194    // absolute paths like "D:\abc\someDir\someFile.xy" or "/usr/bin/xy". This however should be fine for this application.
195    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_LOCAL_PATH, "./", "");
196    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/TechDemo.zip", "Games/DeathMatch/Textures/TechDemo/", "Ca3DE");
197    cf::FileSys::FileMan->MountFileSystem(cf::FileSys::FS_TYPE_ZIP_ARCHIVE, "Games/DeathMatch/Textures/SkyDomes.zip", "Games/DeathMatch/Textures/SkyDomes/", "Ca3DE");
198
199    // Parse the command-line.
200    // Currently, no extension-checking or other comfort for file names is provided.
201    if (ArgC<3) Usage();
202
203    for (int ArgNr=3; ArgNr<ArgC; ArgNr++)
204    {
205        if (!_stricmp(ArgV[ArgNr], "-putWadInCW") || !_stricmp(ArgV[ArgNr], "-p"))
206        {
207            ArgNr++;
208            if (ArgNr>=ArgC) Usage();
209
210            Console->Print(cf::va("NOTE: %s is obsolete now. Ignored \"%s %s\".\n", ArgV[ArgNr-1], ArgV[ArgNr-1], ArgV[ArgNr]));
211        }
212        else if (!_stricmp(ArgV[ArgNr], "-mostSimpleTree"    ) || !_stricmp(ArgV[ArgNr], "-mst")) { Option_MostSimpleTree    =true; }
213        else if (!_stricmp(ArgV[ArgNr], "-minimizeFaceSplits") || !_stricmp(ArgV[ArgNr], "-mfs"))
214        {
215            Console->Print("\n*** WARNING: This option will cause the Cafu engine to render many faces\n");
216            Console->Print("*** *TWICE*! Therefore, it's use it currently highly discouraged.\n\n");
217            Option_MinimizeFaceSplits=true;
218        }
219        else if (ArgV[ArgNr][0]==0)
220        {
221            // The argument is "", the empty string.
222            // This can happen under Linux, when CaBSP is called via wxExecute() with white-space trailing the command string.
223        }
224        else
225        {
226            Console->Print(cf::va("Unknown option '%s'.\n", ArgV[ArgNr]));
227            Usage();
228        }
229    }
230
231
232    std::string GameDirectory=ArgV[2];
233
234    // Determine the game directory, cleverly assuming that the destination file is in "Worlds".
235    {
236        // Strip the file name and extention off.
237        size_t i=GameDirectory.find_last_of("/\\");
238
239        GameDirectory=GameDirectory.substr(0, i==std::string::npos ? 0 : i)+"/..";
240    }
241
242
243    // Setup the global MaterialManager pointer.
244    static MaterialManagerImplT MatManImpl;
245
246    MaterialManager=&MatManImpl;
247
248    if (MaterialManager->RegisterMaterialScriptsInDir(GameDirectory+"/Materials", GameDirectory+"/").Size()==0)
249    {
250        Console->Print(std::string("\nNo materials found in scripts in \"")+GameDirectory+"/Materials\".\n");
251        Error("No materials found.");
252    }
253
254
255    ModelManagerT   ModelMan;
256    WorldT          World;
257    ArrayT<VectorT> DrawWorldOutsidePointSamples;
258
259    LoadWorld(ArgV[1], GameDirectory, ModelMan, World, DrawWorldOutsidePointSamples);
260
261    // What we need:
262    // For each entity: The BspTree itself, OutsidePointSamples, FloodFillSources.
263    // One common instance, shared for all: LeakDetectMat
264    BspTreeBuilderT BspTreeBuilder(World.BspTree, Option_MostSimpleTree, Option_MinimizeFaceSplits);
265
266    ArrayT<Vector3dT> FloodFillSources;
267    for (unsigned long IPSNr=0; IPSNr<World.InfoPlayerStarts.Size(); IPSNr++)
268        FloodFillSources.PushBack(World.InfoPlayerStarts[IPSNr].Origin);
269
270    BspTreeBuilder.Build(true /*yes, this is the worldspawn entity*/, FloodFillSources, DrawWorldOutsidePointSamples, ArgV[1]);
271
272    try
273    {
274        Console->Print(cf::va("\n%-50s %s\n", "*** Save World ***", GetTimeSinceProgramStart()));
275        Console->Print(std::string(ArgV[2])+"\n");
276        World.SaveToDisk(ArgV[2]);
277
278        WriteLogFileEntry(ArgV[2]);
279        Console->Print(cf::va("\n%-50s %s\n", "COMPLETED.", GetTimeSinceProgramStart()));
280    }
281    catch (const WorldT::SaveErrorT& E) { Error(E.Msg); }
282
283    return 0;
284}
Note: See TracBrowser for help on using the browser.