doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MapFile.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 "precompiled.h"
30 #pragma hdrstop
31 
32 
33 /*
34 ===============
35 FloatCRC
36 ===============
37 */
38 ID_INLINE unsigned int FloatCRC( float f ) {
39  return *(unsigned int *)&f;
40 }
41 
42 /*
43 ===============
44 StringCRC
45 ===============
46 */
47 ID_INLINE unsigned int StringCRC( const char *str ) {
48  unsigned int i, crc;
49  const unsigned char *ptr;
50 
51  crc = 0;
52  ptr = reinterpret_cast<const unsigned char*>(str);
53  for ( i = 0; str[i]; i++ ) {
54  crc ^= str[i] << (i & 3);
55  }
56  return crc;
57 }
58 
59 /*
60 =================
61 ComputeAxisBase
62 
63 WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0
64 rotation by (0,RotY,RotZ) assigns X to normal
65 =================
66 */
67 static void ComputeAxisBase( const idVec3 &normal, idVec3 &texS, idVec3 &texT ) {
68  float RotY, RotZ;
69  idVec3 n;
70 
71  // do some cleaning
72  n[0] = ( idMath::Fabs( normal[0] ) < 1e-6f ) ? 0.0f : normal[0];
73  n[1] = ( idMath::Fabs( normal[1] ) < 1e-6f ) ? 0.0f : normal[1];
74  n[2] = ( idMath::Fabs( normal[2] ) < 1e-6f ) ? 0.0f : normal[2];
75 
76  RotY = -atan2( n[2], idMath::Sqrt( n[1] * n[1] + n[0] * n[0]) );
77  RotZ = atan2( n[1], n[0] );
78  // rotate (0,1,0) and (0,0,1) to compute texS and texT
79  texS[0] = -sin(RotZ);
80  texS[1] = cos(RotZ);
81  texS[2] = 0;
82  // the texT vector is along -Z ( T texture coorinates axis )
83  texT[0] = -sin(RotY) * cos(RotZ);
84  texT[1] = -sin(RotY) * sin(RotZ);
85  texT[2] = -cos(RotY);
86 }
87 
88 /*
89 =================
90 idMapBrushSide::GetTextureVectors
91 =================
92 */
94  int i;
95  idVec3 texX, texY;
96 
97  ComputeAxisBase( plane.Normal(), texX, texY );
98  for ( i = 0; i < 2; i++ ) {
99  v[i][0] = texX[0] * texMat[i][0] + texY[0] * texMat[i][1];
100  v[i][1] = texX[1] * texMat[i][0] + texY[1] * texMat[i][1];
101  v[i][2] = texX[2] * texMat[i][0] + texY[2] * texMat[i][1];
102  v[i][3] = texMat[i][2] + ( origin * v[i].ToVec3() );
103  }
104 }
105 
106 /*
107 =================
108 idMapPatch::Parse
109 =================
110 */
111 idMapPatch *idMapPatch::Parse( idLexer &src, const idVec3 &origin, bool patchDef3, float version ) {
112  float info[7];
113  idDrawVert *vert;
114  idToken token;
115  int i, j;
116 
117  if ( !src.ExpectTokenString( "{" ) ) {
118  return NULL;
119  }
120 
121  // read the material (we had an implicit 'textures/' in the old format...)
122  if ( !src.ReadToken( &token ) ) {
123  src.Error( "idMapPatch::Parse: unexpected EOF" );
124  return NULL;
125  }
126 
127  // Parse it
128  if (patchDef3) {
129  if ( !src.Parse1DMatrix( 7, info ) ) {
130  src.Error( "idMapPatch::Parse: unable to Parse patchDef3 info" );
131  return NULL;
132  }
133  } else {
134  if ( !src.Parse1DMatrix( 5, info ) ) {
135  src.Error( "idMapPatch::Parse: unable to parse patchDef2 info" );
136  return NULL;
137  }
138  }
139 
140  idMapPatch *patch = new idMapPatch( info[0], info[1] );
141  patch->SetSize( info[0], info[1] );
142  if ( version < 2.0f ) {
143  patch->SetMaterial( "textures/" + token );
144  } else {
145  patch->SetMaterial( token );
146  }
147 
148  if ( patchDef3 ) {
149  patch->SetHorzSubdivisions( info[2] );
150  patch->SetVertSubdivisions( info[3] );
151  patch->SetExplicitlySubdivided( true );
152  }
153 
154  if ( patch->GetWidth() < 0 || patch->GetHeight() < 0 ) {
155  src.Error( "idMapPatch::Parse: bad size" );
156  delete patch;
157  return NULL;
158  }
159 
160  // these were written out in the wrong order, IMHO
161  if ( !src.ExpectTokenString( "(" ) ) {
162  src.Error( "idMapPatch::Parse: bad patch vertex data" );
163  delete patch;
164  return NULL;
165  }
166  for ( j = 0; j < patch->GetWidth(); j++ ) {
167  if ( !src.ExpectTokenString( "(" ) ) {
168  src.Error( "idMapPatch::Parse: bad vertex row data" );
169  delete patch;
170  return NULL;
171  }
172  for ( i = 0; i < patch->GetHeight(); i++ ) {
173  float v[5];
174 
175  if ( !src.Parse1DMatrix( 5, v ) ) {
176  src.Error( "idMapPatch::Parse: bad vertex column data" );
177  delete patch;
178  return NULL;
179  }
180 
181  vert = &((*patch)[i * patch->GetWidth() + j]);
182  vert->xyz[0] = v[0] - origin[0];
183  vert->xyz[1] = v[1] - origin[1];
184  vert->xyz[2] = v[2] - origin[2];
185  vert->st[0] = v[3];
186  vert->st[1] = v[4];
187  }
188  if ( !src.ExpectTokenString( ")" ) ) {
189  delete patch;
190  src.Error( "idMapPatch::Parse: unable to parse patch control points" );
191  return NULL;
192  }
193  }
194  if ( !src.ExpectTokenString( ")" ) ) {
195  src.Error( "idMapPatch::Parse: unable to parse patch control points, no closure" );
196  delete patch;
197  return NULL;
198  }
199 
200  // read any key/value pairs
201  while( src.ReadToken( &token ) ) {
202  if ( token == "}" ) {
203  src.ExpectTokenString( "}" );
204  break;
205  }
206  if ( token.type == TT_STRING ) {
207  idStr key = token;
208  src.ExpectTokenType( TT_STRING, 0, &token );
209  patch->epairs.Set( key, token );
210  }
211  }
212 
213  return patch;
214 }
215 
216 /*
217 ============
218 idMapPatch::Write
219 ============
220 */
221 bool idMapPatch::Write( idFile *fp, int primitiveNum, const idVec3 &origin ) const {
222  int i, j;
223  const idDrawVert *v;
224 
225  if ( GetExplicitlySubdivided() ) {
226  fp->WriteFloatString( "// primitive %d\n{\n patchDef3\n {\n", primitiveNum );
227  fp->WriteFloatString( " \"%s\"\n ( %d %d %d %d 0 0 0 )\n", GetMaterial(), GetWidth(), GetHeight(), GetHorzSubdivisions(), GetVertSubdivisions());
228  } else {
229  fp->WriteFloatString( "// primitive %d\n{\n patchDef2\n {\n", primitiveNum );
230  fp->WriteFloatString( " \"%s\"\n ( %d %d 0 0 0 )\n", GetMaterial(), GetWidth(), GetHeight());
231  }
232 
233  fp->WriteFloatString( " (\n" );
234  for ( i = 0; i < GetWidth(); i++ ) {
235  fp->WriteFloatString( " ( " );
236  for ( j = 0; j < GetHeight(); j++ ) {
237  v = &verts[ j * GetWidth() + i ];
238  fp->WriteFloatString( " ( %f %f %f %f %f )", v->xyz[0] + origin[0],
239  v->xyz[1] + origin[1], v->xyz[2] + origin[2], v->st[0], v->st[1] );
240  }
241  fp->WriteFloatString( " )\n" );
242  }
243  fp->WriteFloatString( " )\n }\n}\n" );
244 
245  return true;
246 }
247 
248 /*
249 ===============
250 idMapPatch::GetGeometryCRC
251 ===============
252 */
253 unsigned int idMapPatch::GetGeometryCRC( void ) const {
254  int i, j;
255  unsigned int crc;
256 
258  for ( i = 0; i < GetWidth(); i++ ) {
259  for ( j = 0; j < GetHeight(); j++ ) {
260  crc ^= FloatCRC( verts[j * GetWidth() + i].xyz.x );
261  crc ^= FloatCRC( verts[j * GetWidth() + i].xyz.y );
262  crc ^= FloatCRC( verts[j * GetWidth() + i].xyz.z );
263  }
264  }
265 
266  crc ^= StringCRC( GetMaterial() );
267 
268  return crc;
269 }
270 
271 /*
272 =================
273 idMapBrush::Parse
274 =================
275 */
276 idMapBrush *idMapBrush::Parse( idLexer &src, const idVec3 &origin, bool newFormat, float version ) {
277  int i;
278  idVec3 planepts[3];
279  idToken token;
281  idMapBrushSide *side;
282  idDict epairs;
283 
284  if ( !src.ExpectTokenString( "{" ) ) {
285  return NULL;
286  }
287 
288  do {
289  if ( !src.ReadToken( &token ) ) {
290  src.Error( "idMapBrush::Parse: unexpected EOF" );
291  sides.DeleteContents( true );
292  return NULL;
293  }
294  if ( token == "}" ) {
295  break;
296  }
297 
298  // here we may have to jump over brush epairs ( only used in editor )
299  do {
300  // if token is a brace
301  if ( token == "(" ) {
302  break;
303  }
304  // the token should be a key string for a key/value pair
305  if ( token.type != TT_STRING ) {
306  src.Error( "idMapBrush::Parse: unexpected %s, expected ( or epair key string", token.c_str() );
307  sides.DeleteContents( true );
308  return NULL;
309  }
310 
311  idStr key = token;
312 
313  if ( !src.ReadTokenOnLine( &token ) || token.type != TT_STRING ) {
314  src.Error( "idMapBrush::Parse: expected epair value string not found" );
315  sides.DeleteContents( true );
316  return NULL;
317  }
318 
319  epairs.Set( key, token );
320 
321  // try to read the next key
322  if ( !src.ReadToken( &token ) ) {
323  src.Error( "idMapBrush::Parse: unexpected EOF" );
324  sides.DeleteContents( true );
325  return NULL;
326  }
327  } while (1);
328 
329  src.UnreadToken( &token );
330 
331  side = new idMapBrushSide();
332  sides.Append(side);
333 
334  if ( newFormat ) {
335  if ( !src.Parse1DMatrix( 4, side->plane.ToFloatPtr() ) ) {
336  src.Error( "idMapBrush::Parse: unable to read brush side plane definition" );
337  sides.DeleteContents( true );
338  return NULL;
339  }
340  } else {
341  // read the three point plane definition
342  if (!src.Parse1DMatrix( 3, planepts[0].ToFloatPtr() ) ||
343  !src.Parse1DMatrix( 3, planepts[1].ToFloatPtr() ) ||
344  !src.Parse1DMatrix( 3, planepts[2].ToFloatPtr() ) ) {
345  src.Error( "idMapBrush::Parse: unable to read brush side plane definition" );
346  sides.DeleteContents( true );
347  return NULL;
348  }
349 
350  planepts[0] -= origin;
351  planepts[1] -= origin;
352  planepts[2] -= origin;
353 
354  side->plane.FromPoints( planepts[0], planepts[1], planepts[2] );
355  }
356 
357  // read the texture matrix
358  // this is odd, because the texmat is 2D relative to default planar texture axis
359  if ( !src.Parse2DMatrix( 2, 3, side->texMat[0].ToFloatPtr() ) ) {
360  src.Error( "idMapBrush::Parse: unable to read brush side texture matrix" );
361  sides.DeleteContents( true );
362  return NULL;
363  }
364  side->origin = origin;
365 
366  // read the material
367  if ( !src.ReadTokenOnLine( &token ) ) {
368  src.Error( "idMapBrush::Parse: unable to read brush side material" );
369  sides.DeleteContents( true );
370  return NULL;
371  }
372 
373  // we had an implicit 'textures/' in the old format...
374  if ( version < 2.0f ) {
375  side->material = "textures/" + token;
376  } else {
377  side->material = token;
378  }
379 
380  // Q2 allowed override of default flags and values, but we don't any more
381  if ( src.ReadTokenOnLine( &token ) ) {
382  if ( src.ReadTokenOnLine( &token ) ) {
383  if ( src.ReadTokenOnLine( &token ) ) {
384  }
385  }
386  }
387  } while( 1 );
388 
389  if ( !src.ExpectTokenString( "}" ) ) {
390  sides.DeleteContents( true );
391  return NULL;
392  }
393 
394  idMapBrush *brush = new idMapBrush();
395  for ( i = 0; i < sides.Num(); i++ ) {
396  brush->AddSide( sides[i] );
397  }
398 
399  brush->epairs = epairs;
400 
401  return brush;
402 }
403 
404 /*
405 =================
406 idMapBrush::ParseQ3
407 =================
408 */
410  int i, shift[2], rotate;
411  float scale[2];
412  idVec3 planepts[3];
413  idToken token;
415  idMapBrushSide *side;
416  idDict epairs;
417 
418  do {
419  if ( src.CheckTokenString( "}" ) ) {
420  break;
421  }
422 
423  side = new idMapBrushSide();
424  sides.Append( side );
425 
426  // read the three point plane definition
427  if (!src.Parse1DMatrix( 3, planepts[0].ToFloatPtr() ) ||
428  !src.Parse1DMatrix( 3, planepts[1].ToFloatPtr() ) ||
429  !src.Parse1DMatrix( 3, planepts[2].ToFloatPtr() ) ) {
430  src.Error( "idMapBrush::ParseQ3: unable to read brush side plane definition" );
431  sides.DeleteContents( true );
432  return NULL;
433  }
434 
435  planepts[0] -= origin;
436  planepts[1] -= origin;
437  planepts[2] -= origin;
438 
439  side->plane.FromPoints( planepts[0], planepts[1], planepts[2] );
440 
441  // read the material
442  if ( !src.ReadTokenOnLine( &token ) ) {
443  src.Error( "idMapBrush::ParseQ3: unable to read brush side material" );
444  sides.DeleteContents( true );
445  return NULL;
446  }
447 
448  // we have an implicit 'textures/' in the old format
449  side->material = "textures/" + token;
450 
451  // read the texture shift, rotate and scale
452  shift[0] = src.ParseInt();
453  shift[1] = src.ParseInt();
454  rotate = src.ParseInt();
455  scale[0] = src.ParseFloat();
456  scale[1] = src.ParseFloat();
457  side->texMat[0] = idVec3( 0.03125f, 0.0f, 0.0f );
458  side->texMat[1] = idVec3( 0.0f, 0.03125f, 0.0f );
459  side->origin = origin;
460 
461  // Q2 allowed override of default flags and values, but we don't any more
462  if ( src.ReadTokenOnLine( &token ) ) {
463  if ( src.ReadTokenOnLine( &token ) ) {
464  if ( src.ReadTokenOnLine( &token ) ) {
465  }
466  }
467  }
468  } while( 1 );
469 
470  idMapBrush *brush = new idMapBrush();
471  for ( i = 0; i < sides.Num(); i++ ) {
472  brush->AddSide( sides[i] );
473  }
474 
475  brush->epairs = epairs;
476 
477  return brush;
478 }
479 
480 /*
481 ============
482 idMapBrush::Write
483 ============
484 */
485 bool idMapBrush::Write( idFile *fp, int primitiveNum, const idVec3 &origin ) const {
486  int i;
487  idMapBrushSide *side;
488 
489  fp->WriteFloatString( "// primitive %d\n{\n brushDef3\n {\n", primitiveNum );
490 
491  // write brush epairs
492  for ( i = 0; i < epairs.GetNumKeyVals(); i++) {
493  fp->WriteFloatString( " \"%s\" \"%s\"\n", epairs.GetKeyVal(i)->GetKey().c_str(), epairs.GetKeyVal(i)->GetValue().c_str());
494  }
495 
496  // write brush sides
497  for ( i = 0; i < GetNumSides(); i++ ) {
498  side = GetSide( i );
499  fp->WriteFloatString( " ( %f %f %f %f ) ", side->plane[0], side->plane[1], side->plane[2], side->plane[3] );
500  fp->WriteFloatString( "( ( %f %f %f ) ( %f %f %f ) ) \"%s\" 0 0 0\n",
501  side->texMat[0][0], side->texMat[0][1], side->texMat[0][2],
502  side->texMat[1][0], side->texMat[1][1], side->texMat[1][2],
503  side->material.c_str() );
504  }
505 
506  fp->WriteFloatString( " }\n}\n" );
507 
508  return true;
509 }
510 
511 /*
512 ===============
513 idMapBrush::GetGeometryCRC
514 ===============
515 */
516 unsigned int idMapBrush::GetGeometryCRC( void ) const {
517  int i, j;
518  idMapBrushSide *mapSide;
519  unsigned int crc;
520 
521  crc = 0;
522  for ( i = 0; i < GetNumSides(); i++ ) {
523  mapSide = GetSide(i);
524  for ( j = 0; j < 4; j++ ) {
525  crc ^= FloatCRC( mapSide->GetPlane()[j] );
526  }
527  crc ^= StringCRC( mapSide->GetMaterial() );
528  }
529 
530  return crc;
531 }
532 
533 /*
534 ================
535 idMapEntity::Parse
536 ================
537 */
538 idMapEntity *idMapEntity::Parse( idLexer &src, bool worldSpawn, float version ) {
539  idToken token;
540  idMapEntity *mapEnt;
541  idMapPatch *mapPatch;
542  idMapBrush *mapBrush;
543  bool worldent;
544  idVec3 origin;
545  double v1, v2, v3;
546 
547  if ( !src.ReadToken(&token) ) {
548  return NULL;
549  }
550 
551  if ( token != "{" ) {
552  src.Error( "idMapEntity::Parse: { not found, found %s", token.c_str() );
553  return NULL;
554  }
555 
556  mapEnt = new idMapEntity();
557 
558  if ( worldSpawn ) {
559  mapEnt->primitives.Resize( 1024, 256 );
560  }
561 
562  origin.Zero();
563  worldent = false;
564  do {
565  if ( !src.ReadToken(&token) ) {
566  src.Error( "idMapEntity::Parse: EOF without closing brace" );
567  return NULL;
568  }
569  if ( token == "}" ) {
570  break;
571  }
572 
573  if ( token == "{" ) {
574  // parse a brush or patch
575  if ( !src.ReadToken( &token ) ) {
576  src.Error( "idMapEntity::Parse: unexpected EOF" );
577  return NULL;
578  }
579 
580  if ( worldent ) {
581  origin.Zero();
582  }
583 
584  // if is it a brush: brush, brushDef, brushDef2, brushDef3
585  if ( token.Icmpn( "brush", 5 ) == 0 ) {
586  mapBrush = idMapBrush::Parse( src, origin, ( !token.Icmp( "brushDef2" ) || !token.Icmp( "brushDef3" ) ), version );
587  if ( !mapBrush ) {
588  return NULL;
589  }
590  mapEnt->AddPrimitive( mapBrush );
591  }
592  // if is it a patch: patchDef2, patchDef3
593  else if ( token.Icmpn( "patch", 5 ) == 0 ) {
594  mapPatch = idMapPatch::Parse( src, origin, !token.Icmp( "patchDef3" ), version );
595  if ( !mapPatch ) {
596  return NULL;
597  }
598  mapEnt->AddPrimitive( mapPatch );
599  }
600  // assume it's a brush in Q3 or older style
601  else {
602  src.UnreadToken( &token );
603  mapBrush = idMapBrush::ParseQ3( src, origin );
604  if ( !mapBrush ) {
605  return NULL;
606  }
607  mapEnt->AddPrimitive( mapBrush );
608  }
609  } else {
610  idStr key, value;
611 
612  // parse a key / value pair
613  key = token;
614  src.ReadTokenOnLine( &token );
615  value = token;
616 
617  // strip trailing spaces that sometimes get accidentally
618  // added in the editor
619  value.StripTrailingWhitespace();
621 
622  mapEnt->epairs.Set( key, value );
623 
624  if ( !idStr::Icmp( key, "origin" ) ) {
625  // scanf into doubles, then assign, so it is idVec size independent
626  v1 = v2 = v3 = 0;
627  sscanf( value, "%lf %lf %lf", &v1, &v2, &v3 );
628  origin.x = v1;
629  origin.y = v2;
630  origin.z = v3;
631  }
632  else if ( !idStr::Icmp( key, "classname" ) && !idStr::Icmp( value, "worldspawn" ) ) {
633  worldent = true;
634  }
635  }
636  } while( 1 );
637 
638  return mapEnt;
639 }
640 
641 /*
642 ============
643 idMapEntity::Write
644 ============
645 */
646 bool idMapEntity::Write( idFile *fp, int entityNum ) const {
647  int i;
648  idMapPrimitive *mapPrim;
649  idVec3 origin;
650 
651  fp->WriteFloatString( "// entity %d\n{\n", entityNum );
652 
653  // write entity epairs
654  for ( i = 0; i < epairs.GetNumKeyVals(); i++) {
655  fp->WriteFloatString( "\"%s\" \"%s\"\n", epairs.GetKeyVal(i)->GetKey().c_str(), epairs.GetKeyVal(i)->GetValue().c_str());
656  }
657 
658  epairs.GetVector( "origin", "0 0 0", origin );
659 
660  // write pritimives
661  for ( i = 0; i < GetNumPrimitives(); i++ ) {
662  mapPrim = GetPrimitive( i );
663 
664  switch( mapPrim->GetType() ) {
666  static_cast<idMapBrush*>(mapPrim)->Write( fp, i, origin );
667  break;
669  static_cast<idMapPatch*>(mapPrim)->Write( fp, i, origin );
670  break;
671  }
672  }
673 
674  fp->WriteFloatString( "}\n" );
675 
676  return true;
677 }
678 
679 /*
680 ===============
681 idMapEntity::RemovePrimitiveData
682 ===============
683 */
686 }
687 
688 /*
689 ===============
690 idMapEntity::GetGeometryCRC
691 ===============
692 */
693 unsigned int idMapEntity::GetGeometryCRC( void ) const {
694  int i;
695  unsigned int crc;
696  idMapPrimitive *mapPrim;
697 
698  crc = 0;
699  for ( i = 0; i < GetNumPrimitives(); i++ ) {
700  mapPrim = GetPrimitive( i );
701 
702  switch( mapPrim->GetType() ) {
704  crc ^= static_cast<idMapBrush*>(mapPrim)->GetGeometryCRC();
705  break;
707  crc ^= static_cast<idMapPatch*>(mapPrim)->GetGeometryCRC();
708  break;
709  }
710  }
711 
712  return crc;
713 }
714 
715 /*
716 ===============
717 idMapFile::Parse
718 ===============
719 */
720 bool idMapFile::Parse( const char *filename, bool ignoreRegion, bool osPath ) {
721  // no string concatenation for epairs and allow path names for materials
723  idToken token;
724  idStr fullName;
725  idMapEntity *mapEnt;
726  int i, j, k;
727 
728  name = filename;
729  name.StripFileExtension();
730  fullName = name;
731  hasPrimitiveData = false;
732 
733  if ( !ignoreRegion ) {
734  // try loading a .reg file first
735  fullName.SetFileExtension( "reg" );
736  src.LoadFile( fullName, osPath );
737  }
738 
739  if ( !src.IsLoaded() ) {
740  // now try a .map file
741  fullName.SetFileExtension( "map" );
742  src.LoadFile( fullName, osPath );
743  if ( !src.IsLoaded() ) {
744  // didn't get anything at all
745  return false;
746  }
747  }
748 
750  fileTime = src.GetFileTime();
751  entities.DeleteContents( true );
752 
753  if ( src.CheckTokenString( "Version" ) ) {
754  src.ReadTokenOnLine( &token );
755  version = token.GetFloatValue();
756  }
757 
758  while( 1 ) {
759  mapEnt = idMapEntity::Parse( src, ( entities.Num() == 0 ), version );
760  if ( !mapEnt ) {
761  break;
762  }
763  entities.Append( mapEnt );
764  }
765 
766  SetGeometryCRC();
767 
768  // if the map has a worldspawn
769  if ( entities.Num() ) {
770 
771  // "removeEntities" "classname" can be set in the worldspawn to remove all entities with the given classname
772  const idKeyValue *removeEntities = entities[0]->epairs.MatchPrefix( "removeEntities", NULL );
773  while ( removeEntities ) {
774  RemoveEntities( removeEntities->GetValue() );
775  removeEntities = entities[0]->epairs.MatchPrefix( "removeEntities", removeEntities );
776  }
777 
778  // "overrideMaterial" "material" can be set in the worldspawn to reset all materials
779  idStr material;
780  if ( entities[0]->epairs.GetString( "overrideMaterial", "", material ) ) {
781  for ( i = 0; i < entities.Num(); i++ ) {
782  mapEnt = entities[i];
783  for ( j = 0; j < mapEnt->GetNumPrimitives(); j++ ) {
784  idMapPrimitive *mapPrimitive = mapEnt->GetPrimitive( j );
785  switch( mapPrimitive->GetType() ) {
787  idMapBrush *mapBrush = static_cast<idMapBrush *>(mapPrimitive);
788  for ( k = 0; k < mapBrush->GetNumSides(); k++ ) {
789  mapBrush->GetSide( k )->SetMaterial( material );
790  }
791  break;
792  }
794  static_cast<idMapPatch *>(mapPrimitive)->SetMaterial( material );
795  break;
796  }
797  }
798  }
799  }
800  }
801 
802  // force all entities to have a name key/value pair
803  if ( entities[0]->epairs.GetBool( "forceEntityNames" ) ) {
804  for ( i = 1; i < entities.Num(); i++ ) {
805  mapEnt = entities[i];
806  if ( !mapEnt->epairs.FindKey( "name" ) ) {
807  mapEnt->epairs.Set( "name", va( "%s%d", mapEnt->epairs.GetString( "classname", "forcedName" ), i ) );
808  }
809  }
810  }
811 
812  // move the primitives of any func_group entities to the worldspawn
813  if ( entities[0]->epairs.GetBool( "moveFuncGroups" ) ) {
814  for ( i = 1; i < entities.Num(); i++ ) {
815  mapEnt = entities[i];
816  if ( idStr::Icmp( mapEnt->epairs.GetString( "classname" ), "func_group" ) == 0 ) {
817  entities[0]->primitives.Append( mapEnt->primitives );
818  mapEnt->primitives.Clear();
819  }
820  }
821  }
822  }
823 
824  hasPrimitiveData = true;
825  return true;
826 }
827 
828 /*
829 ============
830 idMapFile::Write
831 ============
832 */
833 bool idMapFile::Write( const char *fileName, const char *ext, bool fromBasePath ) {
834  int i;
835  idStr qpath;
836  idFile *fp;
837 
838  qpath = fileName;
839  qpath.SetFileExtension( ext );
840 
841  idLib::common->Printf( "writing %s...\n", qpath.c_str() );
842 
843  if ( fromBasePath ) {
844  fp = idLib::fileSystem->OpenFileWrite( qpath, "fs_devpath" );
845  }
846  else {
848  }
849 
850  if ( !fp ) {
851  idLib::common->Warning( "Couldn't open %s\n", qpath.c_str() );
852  return false;
853  }
854 
855  fp->WriteFloatString( "Version %f\n", (float) CURRENT_MAP_VERSION );
856 
857  for ( i = 0; i < entities.Num(); i++ ) {
858  entities[i]->Write( fp, i );
859  }
860 
862 
863  return true;
864 }
865 
866 /*
867 ===============
868 idMapFile::SetGeometryCRC
869 ===============
870 */
872  int i;
873 
874  geometryCRC = 0;
875  for ( i = 0; i < entities.Num(); i++ ) {
876  geometryCRC ^= entities[i]->GetGeometryCRC();
877  }
878 }
879 
880 /*
881 ===============
882 idMapFile::AddEntity
883 ===============
884 */
886  int ret = entities.Append( mapEnt );
887  return ret;
888 }
889 
890 /*
891 ===============
892 idMapFile::FindEntity
893 ===============
894 */
896  for ( int i = 0; i < entities.Num(); i++ ) {
897  idMapEntity *ent = entities[i];
898  if ( idStr::Icmp( ent->epairs.GetString( "name" ), name ) == 0 ) {
899  return ent;
900  }
901  }
902  return NULL;
903 }
904 
905 /*
906 ===============
907 idMapFile::RemoveEntity
908 ===============
909 */
911  entities.Remove( mapEnt );
912  delete mapEnt;
913 }
914 
915 /*
916 ===============
917 idMapFile::RemoveEntity
918 ===============
919 */
920 void idMapFile::RemoveEntities( const char *classname ) {
921  for ( int i = 0; i < entities.Num(); i++ ) {
922  idMapEntity *ent = entities[i];
923  if ( idStr::Icmp( ent->epairs.GetString( "classname" ), classname ) == 0 ) {
924  delete entities[i];
926  i--;
927  }
928  }
929 }
930 
931 /*
932 ===============
933 idMapFile::RemoveAllEntities
934 ===============
935 */
937  entities.DeleteContents( true );
938  hasPrimitiveData = false;
939 }
940 
941 /*
942 ===============
943 idMapFile::RemovePrimitiveData
944 ===============
945 */
947  for ( int i = 0; i < entities.Num(); i++ ) {
948  idMapEntity *ent = entities[i];
949  ent->RemovePrimitiveData();
950  }
951  hasPrimitiveData = false;
952 }
953 
954 /*
955 ===============
956 idMapFile::NeedsReload
957 ===============
958 */
960  if ( name.Length() ) {
961  ID_TIME_T time = (ID_TIME_T)-1;
962  if ( idLib::fileSystem->ReadFile( name, NULL, &time ) > 0 ) {
963  return ( time > fileTime );
964  }
965  }
966  return true;
967 }
int GetNumSides(void) const
Definition: MapFile.h:106
int CheckTokenString(const char *string)
Definition: Lexer.cpp:1007
const idPlane & GetPlane(void) const
Definition: MapFile.h:78
int GetType(void) const
Definition: MapFile.h:63
idList< idMapEntity * > entities
Definition: MapFile.h:221
int type
Definition: Token.h:77
GLsizei const GLfloat * value
Definition: glext.h:3614
idMapBrush(void)
Definition: MapFile.h:101
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
idList< idDrawVert > verts
Definition: Surface.h:96
void AddPrimitive(idMapPrimitive *p)
Definition: MapFile.h:175
bool FromPoints(const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate=true)
Definition: Plane.h:279
const idVec3 & Normal(void) const
Definition: Plane.h:239
idMapBrushSide * GetSide(int i) const
Definition: MapFile.h:108
int GetVertSubdivisions(void) const
Definition: MapFile.h:127
idMapEntity * FindEntity(const char *name)
Definition: MapFile.cpp:895
const GLdouble * v
Definition: glext.h:2936
int AddSide(idMapBrushSide *side)
Definition: MapFile.h:107
const idStr & GetKey(void) const
Definition: Dict.h:52
idVec3 origin
Definition: MapFile.h:88
unsigned int GetGeometryCRC(void) const
Definition: MapFile.cpp:253
const float * ToFloatPtr(void) const
Definition: Vector.h:719
void SetExplicitlySubdivided(bool b)
Definition: MapFile.h:131
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
int Parse1DMatrix(int x, float *m)
Definition: Lexer.cpp:1300
idVec3 xyz
Definition: DrawVert.h:42
const ID_TIME_T GetFileTime(void)
Definition: Lexer.h:290
void StripTrailingWhitespace(void)
Definition: Str.cpp:648
static idMapBrush * Parse(idLexer &src, const idVec3 &origin, bool newFormat=true, float version=CURRENT_MAP_VERSION)
Definition: MapFile.cpp:276
void ComputeAxisBase(idVec3 &normal, idVec3D &texS, idVec3D &texT)
unsigned int GetGeometryCRC(void) const
Definition: MapFile.cpp:516
GLenum GLsizei n
Definition: glext.h:3705
float z
Definition: Vector.h:320
bool Write(idFile *fp, int primitiveNum, const idVec3 &origin) const
Definition: MapFile.cpp:221
int GetHorzSubdivisions(void) const
Definition: MapFile.h:126
const float * ToFloatPtr(void) const
Definition: Plane.h:383
float GetFloatValue(void)
Definition: Token.h:138
Definition: Vector.h:316
static float Sqrt(float x)
Definition: Math.h:302
float version
Definition: MapFile.h:218
bool Write(idFile *fp, int primitiveNum, const idVec3 &origin) const
Definition: MapFile.cpp:485
const char * GetMaterial(void) const
Definition: MapFile.h:124
static idMapBrush * ParseQ3(idLexer &src, const idVec3 &origin)
Definition: MapFile.cpp:409
Definition: Token.h:71
ID_TIME_T fileTime
Definition: MapFile.h:219
#define TT_STRING
Definition: Token.h:41
void RemoveAllEntities()
Definition: MapFile.cpp:936
float ParseFloat(bool *errorFlag=NULL)
Definition: Lexer.cpp:1264
idPlane plane
Definition: MapFile.h:86
GLuint src
Definition: glext.h:5390
idList< idMapPrimitive * > primitives
Definition: MapFile.h:180
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
int ReadTokenOnLine(idToken *token)
Definition: Lexer.cpp:1172
float x
Definition: Vector.h:318
int i
Definition: process.py:33
const int CURRENT_MAP_VERSION
Definition: MapFile.h:47
int ParseInt(void)
Definition: Lexer.cpp:1227
idVec3 texMat[2]
Definition: MapFile.h:87
int Icmp(const char *text) const
Definition: Str.h:667
idDict epairs
Definition: MapFile.h:166
int GetHeight(void) const
struct version_s version
int Icmpn(const char *text, int n) const
Definition: Str.h:672
Definition: File.h:50
void RemovePrimitiveData()
Definition: MapFile.cpp:946
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
idVec2 st
Definition: DrawVert.h:43
Definition: Lexer.h:137
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
int ExpectTokenType(int type, int subtype, idToken *token)
Definition: Lexer.cpp:938
void RemoveEntities(const char *classname)
Definition: MapFile.cpp:920
static class idFileSystem * fileSystem
Definition: Lib.h:55
void SetMaterial(const char *p)
Definition: MapFile.h:77
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
unsigned int GetGeometryCRC(void) const
Definition: MapFile.cpp:693
Definition: Vector.h:808
static idMapEntity * Parse(idLexer &src, bool worldSpawn=false, float version=CURRENT_MAP_VERSION)
Definition: MapFile.cpp:538
bool Parse(const char *filename, bool ignoreRegion=false, bool osPath=false)
Definition: MapFile.cpp:720
static float Fabs(float f)
Definition: Math.h:779
Definition: Dict.h:65
#define NULL
Definition: Lib.h:88
bool Write(const char *fileName, const char *ext, bool fromBasePath=true)
Definition: MapFile.cpp:833
float y
Definition: Vector.h:319
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:260
idDict epairs
Definition: MapFile.h:59
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
bool GetExplicitlySubdivided(void) const
Definition: MapFile.h:128
const idStr & GetValue(void) const
Definition: Dict.h:53
void SetVertSubdivisions(int n)
Definition: MapFile.h:130
void DeleteContents(bool clear)
Definition: List.h:207
void SetMaterial(const char *p)
Definition: MapFile.h:125
ID_INLINE unsigned int FloatCRC(float f)
Definition: MapFile.cpp:38
virtual int WriteFloatString(const char *fmt,...) id_attribute((format(printf
Definition: File.cpp:294
void GetTextureVectors(idVec4 v[2]) const
Definition: MapFile.cpp:93
void UnreadToken(const idToken *token)
Definition: Lexer.cpp:1159
const idKeyValue * FindKey(const char *key) const
Definition: Dict.cpp:451
virtual void Printf(const char *fmt,...) id_attribute((format(printf
ID_INLINE unsigned int StringCRC(const char *str)
Definition: MapFile.cpp:47
GLfloat GLfloat v1
Definition: glext.h:3607
unsigned int geometryCRC
Definition: MapFile.h:220
idStr material
Definition: MapFile.h:85
void RemoveEntity(idMapEntity *mapEnt)
Definition: MapFile.cpp:910
bool NeedsReload()
Definition: MapFile.cpp:959
idStr name
Definition: MapFile.h:222
bool hasPrimitiveData
Definition: MapFile.h:223
idList< idMapBrushSide * > sides
Definition: MapFile.h:113
int ExpectTokenString(const char *string)
Definition: Lexer.cpp:919
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:3609
int Append(const type &obj)
Definition: List.h:646
idMapPrimitive * GetPrimitive(int i) const
Definition: MapFile.h:174
virtual idFile * OpenExplicitFileWrite(const char *OSPath)=0
tuple f
Definition: idal.py:89
int Num(void) const
Definition: List.h:265
bool RemoveIndex(int index)
Definition: List.h:849
const GLcharARB * name
Definition: glext.h:3629
idMapEntity(void)
Definition: MapFile.h:169
Definition: Str.h:116
const char * GetMaterial(void) const
Definition: MapFile.h:76
bool Write(idFile *fp, int entityNum) const
Definition: MapFile.cpp:646
const char * c_str(void) const
Definition: Str.h:487
void SetHorzSubdivisions(int n)
Definition: MapFile.h:129
const idKeyValue * GetKeyVal(int index) const
Definition: Dict.h:294
const idVec3 & ToVec3(void) const
Definition: Vector.h:1043
int Parse2DMatrix(int y, int x, float *m)
Definition: Lexer.cpp:1322
void RemovePrimitiveData()
Definition: MapFile.cpp:684
GLint j
Definition: qgl.h:264
idMapPatch(void)
Definition: MapFile.h:141
int IsLoaded(void)
Definition: Lexer.h:158
char * va(const char *fmt,...)
Definition: Str.cpp:1568
int AddEntity(idMapEntity *mapentity)
Definition: MapFile.cpp:885
virtual void CloseFile(idFile *f)=0
void SetGeometryCRC(void)
Definition: MapFile.cpp:871
static idMapPatch * Parse(idLexer &src, const idVec3 &origin, bool patchDef3=true, float version=CURRENT_MAP_VERSION)
Definition: MapFile.cpp:111
int GetNumPrimitives(void) const
Definition: MapFile.h:173
int GetNumKeyVals(void) const
Definition: Dict.h:290
void Zero(void)
Definition: Vector.h:415
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
void SetSize(int patchWidth, int patchHeight)
const int OLD_MAP_VERSION
Definition: MapFile.h:46
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
void Resize(int newsize)
Definition: List.h:360
bool Remove(const type &obj)
Definition: List.h:878
int GetWidth(void) const
int LoadFile(const char *filename, bool OSPath=false)
Definition: Lexer.cpp:1591
static class idCommon * common
Definition: Lib.h:53
void Clear(void)
Definition: List.h:184