doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dmap.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../../../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "dmap.h"
33 
35 
36 /*
37 ============
38 ProcessModel
39 ============
40 */
41 bool ProcessModel( uEntity_t *e, bool floodFill ) {
42  bspface_t *faces;
43 
44  // build a bsp tree using all of the sides
45  // of all of the structural brushes
47  e->tree = FaceBSP( faces );
48 
49  // create portals at every leaf intersection
50  // to allow flood filling
51  MakeTreePortals( e->tree );
52 
53  // classify the leafs as opaque or areaportal
55 
56  // see if the bsp is completely enclosed
57  if ( floodFill && !dmapGlobals.noFlood ) {
58  if ( FloodEntities( e->tree ) ) {
59  // set the outside leafs to opaque
60  FillOutside( e );
61  } else {
62  common->Printf ( "**********************\n" );
63  common->Warning( "******* leaked *******" );
64  common->Printf ( "**********************\n" );
65  LeakFile( e->tree );
66  // bail out here. If someone really wants to
67  // process a map that leaks, they should use
68  // -noFlood
69  return false;
70  }
71  }
72 
73  // get minimum convex hulls for each visible side
74  // this must be done before creating area portals,
75  // because the visible hull is used as the portal
76  ClipSidesByTree( e );
77 
78  // determine areas before clipping tris into the
79  // tree, so tris will never cross area boundaries
80  FloodAreas( e );
81 
82  // we now have a BSP tree with solid and non-solid leafs marked with areas
83  // all primitives will now be clipped into this, throwing away
84  // fragments in the solid areas
86 
87  // now build shadow volumes for the lights and split
88  // the optimize lists by the light beam trees
89  // so there won't be unneeded overdraw in the static
90  // case
91  Prelight( e );
92 
93  // optimizing is a superset of fixing tjunctions
94  if ( !dmapGlobals.noOptimize ) {
95  OptimizeEntity( e );
96  } else if ( !dmapGlobals.noTJunc ) {
98  }
99 
100  // now fix t junctions across areas
101  FixGlobalTjunctions( e );
102 
103  return true;
104 }
105 
106 /*
107 ============
108 ProcessModels
109 ============
110 */
111 bool ProcessModels( void ) {
112  bool oldVerbose;
113  uEntity_t *entity;
114 
115  oldVerbose = dmapGlobals.verbose;
116 
117  for ( dmapGlobals.entityNum = 0 ; dmapGlobals.entityNum < dmapGlobals.num_entities ; dmapGlobals.entityNum++ ) {
118 
119  entity = &dmapGlobals.uEntities[dmapGlobals.entityNum];
120  if ( !entity->primitives ) {
121  continue;
122  }
123 
124  common->Printf( "############### entity %i ###############\n", dmapGlobals.entityNum );
125 
126  // if we leaked, stop without any more processing
127  if ( !ProcessModel( entity, (bool)(dmapGlobals.entityNum == 0 ) ) ) {
128  return false;
129  }
130 
131  // we usually don't want to see output for submodels unless
132  // something strange is going on
133  if ( !dmapGlobals.verboseentities ) {
134  dmapGlobals.verbose = false;
135  }
136  }
137 
138  dmapGlobals.verbose = oldVerbose;
139 
140  return true;
141 }
142 
143 /*
144 ============
145 DmapHelp
146 ============
147 */
148 void DmapHelp( void ) {
149  common->Printf(
150 
151  "Usage: dmap [options] mapfile\n"
152  "Options:\n"
153  "noCurves = don't process curves\n"
154  "noCM = don't create collision map\n"
155  "noAAS = don't create AAS files\n"
156 
157  );
158 }
159 
160 /*
161 ============
162 ResetDmapGlobals
163 ============
164 */
165 void ResetDmapGlobals( void ) {
166  dmapGlobals.mapFileBase[0] = '\0';
167  dmapGlobals.dmapFile = NULL;
168  dmapGlobals.mapPlanes.Clear();
169  dmapGlobals.num_entities = 0;
170  dmapGlobals.uEntities = NULL;
171  dmapGlobals.entityNum = 0;
172  dmapGlobals.mapLights.Clear();
173  dmapGlobals.verbose = false;
174  dmapGlobals.glview = false;
175  dmapGlobals.noOptimize = false;
176  dmapGlobals.verboseentities = false;
177  dmapGlobals.noCurves = false;
178  dmapGlobals.fullCarve = false;
179  dmapGlobals.noModelBrushes = false;
180  dmapGlobals.noTJunc = false;
181  dmapGlobals.nomerge = false;
182  dmapGlobals.noFlood = false;
183  dmapGlobals.noClipSides = false;
184  dmapGlobals.noLightCarve = false;
185  dmapGlobals.noShadow = false;
186  dmapGlobals.shadowOptLevel = SO_NONE;
187  dmapGlobals.drawBounds.Clear();
188  dmapGlobals.drawflag = false;
189  dmapGlobals.totalShadowTriangles = 0;
190  dmapGlobals.totalShadowVerts = 0;
191 }
192 
193 /*
194 ============
195 Dmap
196 ============
197 */
198 void Dmap( const idCmdArgs &args ) {
199  int i;
200  int start, end;
201  char path[1024];
202  idStr passedName;
203  bool leaked = false;
204  bool noCM = false;
205  bool noAAS = false;
206 
208 
209  if ( args.Argc() < 2 ) {
210  DmapHelp();
211  return;
212  }
213 
214  common->Printf("---- dmap ----\n");
215 
216  dmapGlobals.fullCarve = true;
217  dmapGlobals.shadowOptLevel = SO_MERGE_SURFACES; // create shadows by merging all surfaces, but no super optimization
218 // dmapGlobals.shadowOptLevel = SO_CLIP_OCCLUDERS; // remove occluders that are completely covered
219 // dmapGlobals.shadowOptLevel = SO_SIL_OPTIMIZE;
220 // dmapGlobals.shadowOptLevel = SO_CULL_OCCLUDED;
221 
222  dmapGlobals.noLightCarve = true;
223 
224  for ( i = 1 ; i < args.Argc() ; i++ ) {
225  const char *s;
226 
227  s = args.Argv(i);
228  if ( s[0] == '-' ) {
229  s++;
230  if ( s[0] == '\0' ) {
231  continue;
232  }
233  }
234 
235  if ( !idStr::Icmp( s,"glview" ) ) {
236  dmapGlobals.glview = true;
237  } else if ( !idStr::Icmp( s, "v" ) ) {
238  common->Printf( "verbose = true\n" );
239  dmapGlobals.verbose = true;
240  } else if ( !idStr::Icmp( s, "draw" ) ) {
241  common->Printf( "drawflag = true\n" );
242  dmapGlobals.drawflag = true;
243  } else if ( !idStr::Icmp( s, "noFlood" ) ) {
244  common->Printf( "noFlood = true\n" );
245  dmapGlobals.noFlood = true;
246  } else if ( !idStr::Icmp( s, "noLightCarve" ) ) {
247  common->Printf( "noLightCarve = true\n" );
248  dmapGlobals.noLightCarve = true;
249  } else if ( !idStr::Icmp( s, "lightCarve" ) ) {
250  common->Printf( "noLightCarve = false\n" );
251  dmapGlobals.noLightCarve = false;
252  } else if ( !idStr::Icmp( s, "noOpt" ) ) {
253  common->Printf( "noOptimize = true\n" );
254  dmapGlobals.noOptimize = true;
255  } else if ( !idStr::Icmp( s, "verboseentities" ) ) {
256  common->Printf( "verboseentities = true\n");
257  dmapGlobals.verboseentities = true;
258  } else if ( !idStr::Icmp( s, "noCurves" ) ) {
259  common->Printf( "noCurves = true\n");
260  dmapGlobals.noCurves = true;
261  } else if ( !idStr::Icmp( s, "noModels" ) ) {
262  common->Printf( "noModels = true\n" );
263  dmapGlobals.noModelBrushes = true;
264  } else if ( !idStr::Icmp( s, "noClipSides" ) ) {
265  common->Printf( "noClipSides = true\n" );
266  dmapGlobals.noClipSides = true;
267  } else if ( !idStr::Icmp( s, "noCarve" ) ) {
268  common->Printf( "noCarve = true\n" );
269  dmapGlobals.fullCarve = false;
270  } else if ( !idStr::Icmp( s, "shadowOpt" ) ) {
271  dmapGlobals.shadowOptLevel = (shadowOptLevel_t)atoi( args.Argv( i+1 ) );
272  common->Printf( "shadowOpt = %i\n",dmapGlobals.shadowOptLevel );
273  i += 1;
274  } else if ( !idStr::Icmp( s, "noTjunc" ) ) {
275  // triangle optimization won't work properly without tjunction fixing
276  common->Printf ("noTJunc = true\n" );
277  dmapGlobals.noTJunc = true;
278  dmapGlobals.noOptimize = true;
279  common->Printf ("forcing noOptimize = true\n" );
280  } else if ( !idStr::Icmp( s, "noCM" ) ) {
281  noCM = true;
282  common->Printf( "noCM = true\n" );
283  } else if ( !idStr::Icmp( s, "noAAS" ) ) {
284  noAAS = true;
285  common->Printf( "noAAS = true\n" );
286  } else if ( !idStr::Icmp( s, "editorOutput" ) ) {
287 #ifdef _WIN32
288  com_outputMsg = true;
289 #endif
290  } else {
291  break;
292  }
293  }
294 
295  if ( i >= args.Argc() ) {
296  common->Error( "usage: dmap [options] mapfile" );
297  }
298 
299  passedName = args.Argv(i); // may have an extension
300  passedName.BackSlashesToSlashes();
301  if ( passedName.Icmpn( "maps/", 4 ) != 0 ) {
302  passedName = "maps/" + passedName;
303  }
304 
305  idStr stripped = passedName;
306  stripped.StripFileExtension();
307  idStr::Copynz( dmapGlobals.mapFileBase, stripped, sizeof(dmapGlobals.mapFileBase) );
308 
309  bool region = false;
310  // if this isn't a regioned map, delete the last saved region map
311  if ( passedName.Right( 4 ) != ".reg" ) {
312  sprintf( path, "%s.reg", dmapGlobals.mapFileBase );
313  fileSystem->RemoveFile( path );
314  } else {
315  region = true;
316  }
317 
318 
319  passedName = stripped;
320 
321  // delete any old line leak files
322  sprintf( path, "%s.lin", dmapGlobals.mapFileBase );
323  fileSystem->RemoveFile( path );
324 
325 
326  //
327  // start from scratch
328  //
329  start = Sys_Milliseconds();
330 
331  if ( !LoadDMapFile( passedName ) ) {
332  return;
333  }
334 
335  if ( ProcessModels() ) {
336  WriteOutputFile();
337  } else {
338  leaked = true;
339  }
340 
341  FreeDMapFile();
342 
343  common->Printf( "%i total shadow triangles\n", dmapGlobals.totalShadowTriangles );
344  common->Printf( "%i total shadow verts\n", dmapGlobals.totalShadowVerts );
345 
346  end = Sys_Milliseconds();
347  common->Printf( "-----------------------\n" );
348  common->Printf( "%5.0f seconds for dmap\n", ( end - start ) * 0.001f );
349 
350  if ( !leaked ) {
351 
352  if ( !noCM ) {
353 
354  // make sure the collision model manager is not used by the game
355  cmdSystem->BufferCommandText( CMD_EXEC_NOW, "disconnect" );
356 
357  // create the collision map
358  start = Sys_Milliseconds();
359 
360  collisionModelManager->LoadMap( dmapGlobals.dmapFile );
362 
363  end = Sys_Milliseconds();
364  common->Printf( "-------------------------------------\n" );
365  common->Printf( "%5.0f seconds to create collision map\n", ( end - start ) * 0.001f );
366  }
367 
368  if ( !noAAS && !region ) {
369  // create AAS files
370  RunAAS_f( args );
371  }
372  }
373 
374  // free the common .map representation
375  delete dmapGlobals.dmapFile;
376 
377  // clear the map plane list
378  dmapGlobals.mapPlanes.Clear();
379 
380 #ifdef _WIN32
381  if ( com_outputMsg && com_hwndMsg != NULL ) {
382  unsigned int msg = ::RegisterWindowMessage( DMAP_DONE );
383  ::PostMessage( com_hwndMsg, msg, 0, 0 );
384  }
385 #endif
386 }
387 
388 /*
389 ============
390 Dmap_f
391 ============
392 */
393 void Dmap_f( const idCmdArgs &args ) {
394 
395  common->ClearWarnings( "running dmap" );
396 
397  // refresh the screen each time we print so it doesn't look
398  // like it is hung
399  common->SetRefreshOnPrint( true );
400  Dmap( args );
401  common->SetRefreshOnPrint( false );
402 
404 }
virtual void FreeMap(void)=0
void MakeTreePortals(tree_t *tree)
Definition: portals.cpp:498
void FixGlobalTjunctions(uEntity_t *e)
void FreeDMapFile(void)
Definition: map.cpp:599
bool LoadDMapFile(const char *filename)
Definition: map.cpp:513
void Dmap_f(const idCmdArgs &args)
Definition: dmap.cpp:393
void PutPrimitivesInAreas(uEntity_t *e)
Definition: usurface.cpp:589
primitive_t * primitives
Definition: dmap.h:50
bool noOptimize
Definition: dmap.h:251
virtual void LoadMap(const idMapFile *mapFile)=0
char mapFileBase[1024]
Definition: dmap.h:235
void ResetDmapGlobals(void)
Definition: dmap.cpp:165
idList< mapLight_t * > mapLights
Definition: dmap.h:246
int Sys_Milliseconds(void)
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
tree_t * FaceBSP(bspface_t *list)
Definition: facebsp.cpp:375
bool noClipSides
Definition: dmap.h:259
bool fullCarve
Definition: dmap.h:254
shadowOptLevel_t shadowOptLevel
Definition: dmap.h:261
void Clear(void)
Definition: Bounds.h:201
idCmdSystem * cmdSystem
Definition: CmdSystem.cpp:116
bool verbose
Definition: dmap.h:248
void Prelight(uEntity_t *e)
Definition: usurface.cpp:996
GLdouble s
Definition: glext.h:2935
idMapFile * dmapFile
Definition: dmap.h:237
int i
Definition: process.py:33
void FixEntityTjunctions(uEntity_t *e)
bool glview
Definition: dmap.h:250
idPlaneSet mapPlanes
Definition: dmap.h:239
int Icmp(const char *text) const
Definition: Str.h:667
idStr & BackSlashesToSlashes(void)
Definition: Str.cpp:727
int totalShadowVerts
Definition: dmap.h:268
shadowOptLevel_t
Definition: dmap.h:224
int Icmpn(const char *text, int n) const
Definition: Str.h:672
virtual void RemoveFile(const char *relativePath)=0
void Clear(void)
Definition: PlaneSet.h:43
virtual void BufferCommandText(cmdExecution_t exec, const char *text)=0
bool noCurves
Definition: dmap.h:253
void Dmap(const idCmdArgs &args)
Definition: dmap.cpp:198
Definition: dmap.h:89
void FloodAreas(uEntity_t *e)
Definition: portals.cpp:924
idStr & StripFileExtension(void)
Definition: Str.cpp:757
bool noFlood
Definition: dmap.h:258
GLuint GLuint end
Definition: glext.h:2845
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
bspface_t * MakeStructuralBspFaceList(primitive_t *list)
Definition: facebsp.cpp:420
bool drawflag
Definition: dmap.h:265
static void Copynz(char *dest, const char *src, int destsize)
Definition: Str.cpp:1376
virtual void virtual void virtual void virtual void PrintWarnings(void)=0
const char * path
Definition: sws.c:117
int totalShadowTriangles
Definition: dmap.h:267
int Argc(void) const
Definition: CmdArgs.h:48
const char * Right(int len, idStr &result) const
Definition: Str.h:896
idBounds drawBounds
Definition: dmap.h:264
virtual void Printf(const char *fmt,...) id_attribute((format(printf
bool noLightCarve
Definition: dmap.h:260
bool noModelBrushes
Definition: dmap.h:255
int entityNum
Definition: dmap.h:244
uEntity_t * uEntities
Definition: dmap.h:242
bool verboseentities
Definition: dmap.h:252
struct tree_s * tree
Definition: dmap.h:51
bool ProcessModel(uEntity_t *e, bool floodFill)
Definition: dmap.cpp:41
void RunAAS_f(const idCmdArgs &args)
Definition: AASBuild.cpp:879
void DmapHelp(void)
Definition: dmap.cpp:148
bool ProcessModels(void)
Definition: dmap.cpp:111
tuple f
Definition: idal.py:89
Definition: dmap.h:46
int num_entities
Definition: dmap.h:241
Definition: dmap.h:225
bool FloodEntities(tree_t *tree)
Definition: portals.cpp:580
Definition: Str.h:116
void LeakFile(tree_t *tree)
Definition: leakfile.cpp:53
const char * Argv(int arg) const
Definition: CmdArgs.h:50
void WriteOutputFile(void)
Definition: output.cpp:636
void ClipSidesByTree(uEntity_t *e)
Definition: usurface.cpp:324
void FilterBrushesIntoTree(uEntity_t *e)
Definition: ubrush.cpp:439
virtual void ClearWarnings(const char *reason)=0
virtual void SetRefreshOnPrint(bool set)=0
bool nomerge
Definition: dmap.h:257
dmapGlobals_t dmapGlobals
Definition: dmap.cpp:34
void OptimizeEntity(uEntity_t *e)
Definition: optimize.cpp:1983
virtual void Error(const char *fmt,...) id_attribute((format(printf
void FillOutside(uEntity_t *e)
Definition: portals.cpp:990
bool noTJunc
Definition: dmap.h:256
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
idCollisionModelManager * collisionModelManager
GLuint start
Definition: glext.h:2845
bool noShadow
Definition: dmap.h:262
void Clear(void)
Definition: List.h:184