Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mesh_xml.cpp
Go to the documentation of this file.
1 #include "mesh.h"
2 #include "mesh_xml.h"
3 #include "aux_texture.h"
4 #include "aux_logo.h"
5 #include "vegastrike.h"
6 #include <iostream>
7 #include <fstream>
8 #include <expat.h>
9 #include <float.h>
10 #include <assert.h>
11 #include "ani_texture.h"
12 #ifndef _WIN32
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #else
17 #include <direct.h>
18 #include <process.h>
19 #endif
20 #if !defined (_WIN32) && !(defined (__APPLE__) || defined (MACOSX ) ) && !defined (BSD) && !defined(__HAIKU__)
21 #include <values.h>
22 #endif
23 #include "xml_support.h"
24 #include "vec.h"
25 #include "config_xml.h"
26 #include "vs_globals.h"
27 #include "cmd/script/mission.h"
28 #include "cmd/script/flightgroup.h"
29 #include "hashtable.h"
30 
31 #ifdef max
32 #undef max
33 #endif
34 
35 static inline float max( float x, float y )
36 {
37  if (x > y) return x;
38  else return y;
39 }
40 
41 #ifdef min
42 #undef min
43 #endif
44 
45 static inline float min( float x, float y )
46 {
47  if (x < y) return x;
48  else return y;
49 }
50 
57 struct GFXMaterial;
58 
60  EnumMap::Pair( "UNKNOWN", MeshXML::UNKNOWN ),
61  EnumMap::Pair( "Material", MeshXML::MATERIAL ),
62  EnumMap::Pair( "LOD", MeshXML::LOD ),
63  EnumMap::Pair( "Ambient", MeshXML::AMBIENT ),
64  EnumMap::Pair( "Diffuse", MeshXML::DIFFUSE ),
65  EnumMap::Pair( "Specular", MeshXML::SPECULAR ),
66  EnumMap::Pair( "Emissive", MeshXML::EMISSIVE ),
67  EnumMap::Pair( "Mesh", MeshXML::MESH ),
68  EnumMap::Pair( "Points", MeshXML::POINTS ),
69  EnumMap::Pair( "Point", MeshXML::POINT ),
70  EnumMap::Pair( "Location", MeshXML::LOCATION ),
71  EnumMap::Pair( "Normal", MeshXML::NORMAL ),
72  EnumMap::Pair( "Polygons", MeshXML::POLYGONS ),
73  EnumMap::Pair( "Line", MeshXML::LINE ),
74  EnumMap::Pair( "Tri", MeshXML::TRI ),
75  EnumMap::Pair( "Quad", MeshXML::QUAD ),
76  EnumMap::Pair( "Linestrip", MeshXML::LINESTRIP ),
77  EnumMap::Pair( "Tristrip", MeshXML::TRISTRIP ),
78  EnumMap::Pair( "Trifan", MeshXML::TRIFAN ),
79  EnumMap::Pair( "Quadstrip", MeshXML::QUADSTRIP ),
80  EnumMap::Pair( "Vertex", MeshXML::VERTEX ),
81  EnumMap::Pair( "Logo", MeshXML::LOGO ),
82  EnumMap::Pair( "Ref", MeshXML::REF ),
83  EnumMap::Pair( "DetailPlane", MeshXML::DETAILPLANE )
84 };
85 
87  EnumMap::Pair( "UNKNOWN", MeshXML::UNKNOWN ),
88  EnumMap::Pair( "Scale", MeshXML::SCALE ),
90  EnumMap::Pair( "alphatest", MeshXML::ALPHATEST ),
91  EnumMap::Pair( "texture", MeshXML::TEXTURE ),
92  EnumMap::Pair( "technique", MeshXML::TECHNIQUE ),
93  EnumMap::Pair( "alphamap", MeshXML::ALPHAMAP ),
94  EnumMap::Pair( "sharevertex", MeshXML::SHAREVERT ),
95  EnumMap::Pair( "red", MeshXML::RED ),
96  EnumMap::Pair( "green", MeshXML::GREEN ),
97  EnumMap::Pair( "blue", MeshXML::BLUE ),
98  EnumMap::Pair( "alpha", MeshXML::ALPHA ),
99  EnumMap::Pair( "power", MeshXML::POWER ),
100  EnumMap::Pair( "reflect", MeshXML::REFLECT ),
101  EnumMap::Pair( "x", MeshXML::X ),
102  EnumMap::Pair( "y", MeshXML::Y ),
103  EnumMap::Pair( "z", MeshXML::Z ),
104  EnumMap::Pair( "i", MeshXML::I ),
105  EnumMap::Pair( "j", MeshXML::J ),
106  EnumMap::Pair( "k", MeshXML::K ),
107  EnumMap::Pair( "Shade", MeshXML::FLATSHADE ),
108  EnumMap::Pair( "point", MeshXML::POINT ),
109  EnumMap::Pair( "s", MeshXML::S ),
110  EnumMap::Pair( "t", MeshXML::T ),
111  //Logo stuffs
112  EnumMap::Pair( "Type", MeshXML::TYPE ),
113  EnumMap::Pair( "Rotate", MeshXML::ROTATE ),
114  EnumMap::Pair( "Weight", MeshXML::WEIGHT ),
115  EnumMap::Pair( "Size", MeshXML::SIZE ),
116  EnumMap::Pair( "Offset", MeshXML::OFFSET ),
117  EnumMap::Pair( "meshfile", MeshXML::LODFILE ),
118  EnumMap::Pair( "Animation", MeshXML::ANIMATEDTEXTURE ),
119  EnumMap::Pair( "Reverse", MeshXML::REVERSE ),
120  EnumMap::Pair( "LightingOn", MeshXML::LIGHTINGON ),
121  EnumMap::Pair( "CullFace", MeshXML::CULLFACE ),
122  EnumMap::Pair( "ForceTexture", MeshXML::FORCETEXTURE ),
123  EnumMap::Pair( "UseNormals", MeshXML::USENORMALS ),
124  EnumMap::Pair( "UseTangents", MeshXML::USETANGENTS ),
125  EnumMap::Pair( "PolygonOffset", MeshXML::POLYGONOFFSET ),
126  EnumMap::Pair( "DetailTexture", MeshXML::DETAILTEXTURE ),
127  EnumMap::Pair( "FramesPerSecond", MeshXML::FRAMESPERSECOND )
128 };
129 
130 const EnumMap MeshXML::element_map( MeshXML::element_names, sizeof (MeshXML::element_names)/sizeof (MeshXML::element_names[0]) );
131 const EnumMap MeshXML::attribute_map( MeshXML::attribute_names,
132  sizeof (MeshXML::attribute_names)/sizeof (MeshXML::attribute_names[0]) );
133 
134 void Mesh::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
135 {
136  MeshXML *xml = (MeshXML*) userData;
137  xml->mesh->beginElement( xml, name, AttributeList( atts ) );
138 }
139 
140 void Mesh::endElement( void *userData, const XML_Char *name )
141 {
142  MeshXML *xml = (MeshXML*) userData;
143  xml->mesh->endElement( xml, std::string( name ) );
144 }
145 
146 enum BLENDFUNC parse_alpha( const char *tmp )
147 {
148  if (strcmp( tmp, "ZERO" ) == 0)
149  return ZERO;
150  if (strcmp( tmp, "ONE" ) == 0)
151  return ONE;
152  if (strcmp( tmp, "SRCCOLOR" ) == 0)
153  return SRCCOLOR;
154  if (strcmp( tmp, "INVSRCCOLOR" ) == 0)
155  return INVSRCCOLOR;
156  if (strcmp( tmp, "SRCALPHA" ) == 0)
157  return SRCALPHA;
158  if (strcmp( tmp, "INVSRCALPHA" ) == 0)
159  return INVSRCALPHA;
160  if (strcmp( tmp, "DESTALPHA" ) == 0)
161  return DESTALPHA;
162  if (strcmp( tmp, "INVDESTALPHA" ) == 0)
163  return INVDESTALPHA;
164  if (strcmp( tmp, "DESTCOLOR" ) == 0)
165  return DESTCOLOR;
166  if (strcmp( tmp, "INVDESTCOLOR" ) == 0)
167  return INVDESTCOLOR;
168  if (strcmp( tmp, "SRCALPHASAT" ) == 0)
169  return SRCALPHASAT;
170  if (strcmp( tmp, "CONSTALPHA" ) == 0)
171  return CONSTALPHA;
172  if (strcmp( tmp, "INVCONSTALPHA" ) == 0)
173  return INVCONSTALPHA;
174  if (strcmp( tmp, "CONSTCOLOR" ) == 0)
175  return CONSTCOLOR;
176  if (strcmp( tmp, "INVCONSTCOLOR" ) == 0)
177  return INVCONSTCOLOR;
178  return ZERO;
179 }
180 
181 #if 0
182 std::string parse_alpha( enum BLENDMODE tmp )
183 {
184  switch (tmp)
185  {
186  case ZERO:
187  return "ZERO";
188 
189  case ONE:
190  return "ONE";
191 
192  case SRCCOLOR:
193  return "SRCCOLOR";
194 
195  case INVSRCCOLOR:
196  return "INVSRCCOLOR";
197 
198  case SRCALPHA:
199  return "SRCALPHA";
200 
201  case INVSRCALPHA:
202  return "INVSRCALPHA";
203 
204  case DESTALPHA:
205  return "DESTALPHA";
206 
207  case INVDESTALPHA:
208  return "INVDESTALPHA";
209 
210  case DESTCOLOR:
211  return "DESTCOLOR";
212 
213  case INVDESTCOLOR:
214  return "INVDESTCOLOR";
215 
216  case SRCALPHASAT:
217  return "SRCALPHASAT";
218 
219  case CONSTALPHA:
220  return "CONSTALPHA";
221 
222  case INVCONSTALPHA:
223  return "INVCONSTALPHA";
224 
225  case CONSTCOLOR:
226  return "CONSTCOLOR";
227 
228  case INVCONSTCOLOR:
229  return "INVCONSTCOLOR";
230  }
231  return ZERO;
232 }
233 #endif
234 
235 /* Load stages:
236  *
237  * 0 - no tags seen
238  * 1 - waiting for points
239  * 2 - processing points
240  * 3 - done processing points, waiting for face data
241  *
242  * Note that this is only a debugging aid. Once DTD is written, there
243  * will be no need for this sort of checking
244  */
245 
246 bool shouldreflect( string r )
247 {
248  if (strtoupper( r ) == "FALSE")
249  return false;
250  int i;
251  for (i = 0; i < (int) r.length(); ++i)
252  if (r[i] != '0' && r[i] != '.' && r[i] != '+' && r[i] != 'e')
253  return true;
254  return false;
255 }
256 
257 void Mesh::beginElement( MeshXML *xml, const string &name, const AttributeList &attributes )
258 {
259  static bool use_detail_texture = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "use_detail_texture", "true" ) );
260  //static bool flatshadeit=false;
261  AttributeList::const_iterator iter;
262  float flotsize = 1;
263  MeshXML::Names elem = (MeshXML::Names) MeshXML::element_map.lookup( name );
264  MeshXML::Names top; //FIXME If state stack is empty, top is used uninitialized !!!
265  top = MeshXML::UNKNOWN; //FIXME this line temporarily added by chuck_starchaser
266  if (xml->state_stack.size() > 0)
267  top = *xml->state_stack.rbegin();
268  xml->state_stack.push_back( elem );
269  bool texture_found = false;
270  switch (elem)
271  {
273  if (use_detail_texture) {
274  Vector vec( detailPlanes.size() >= 2 ? 1 : 0, detailPlanes.size() == 1 ? 1 : 0, detailPlanes.size() == 0 ? 1 : 0 );
275  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
276  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
277  {
278  case MeshXML::X:
279  vec.i = XMLSupport::parse_float( iter->value );
280  break;
281  case MeshXML::Y:
282  vec.j = XMLSupport::parse_float( iter->value );
283  break;
284 
285  case MeshXML::Z:
286  vec.k = XMLSupport::parse_float( iter->value );
287  break;
288  }
289  }
290  static float detailscale = XMLSupport::parse_float( vs_config->getVariable( "graphics", "detail_texture_scale", "1" ) );
291  if (detailPlanes.size() < 6)
292  detailPlanes.push_back( vec*detailscale );
293  }
294  break;
295  case MeshXML::MATERIAL:
296  //assert(xml->load_stage==4);
297  xml->load_stage = 7;
298  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
299  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
300  {
301  case MeshXML::USENORMALS:
302  xml->usenormals = XMLSupport::parse_bool( iter->value );
303  break;
305  xml->usetangents = XMLSupport::parse_bool( iter->value );
306  break;
307  case MeshXML::POWER:
308  xml->material.power = XMLSupport::parse_float( (*iter).value );
309  break;
310  case MeshXML::REFLECT:
311  setEnvMap( shouldreflect( (*iter).value ) );
312  break;
313  case MeshXML::LIGHTINGON:
315  "ForceLighting",
316  "true" ) )
317  || XMLSupport::parse_bool( (*iter).value ) );
318  break;
319  case MeshXML::CULLFACE:
320  forceCullFace( XMLSupport::parse_bool( (*iter).value ) );
321  break;
322  }
323  }
324  break;
325  case MeshXML::DIFFUSE:
326  //assert(xml->load_stage==7);
327  xml->load_stage = 8;
328  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
329  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
330  {
331  case MeshXML::RED:
332  xml->material.dr = XMLSupport::parse_float( (*iter).value );
333  break;
334  case MeshXML::BLUE:
335  xml->material.db = XMLSupport::parse_float( (*iter).value );
336  break;
337  case MeshXML::ALPHA:
338  xml->material.da = XMLSupport::parse_float( (*iter).value );
339  break;
340  case MeshXML::GREEN:
341  xml->material.dg = XMLSupport::parse_float( (*iter).value );
342  break;
343  }
344  }
345  break;
346  case MeshXML::EMISSIVE:
347  //assert(xml->load_stage==7);
348  xml->load_stage = 8;
349  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
350  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
351  {
352  case MeshXML::RED:
353  xml->material.er = XMLSupport::parse_float( (*iter).value );
354  break;
355  case MeshXML::BLUE:
356  xml->material.eb = XMLSupport::parse_float( (*iter).value );
357  break;
358  case MeshXML::ALPHA:
359  xml->material.ea = XMLSupport::parse_float( (*iter).value );
360  break;
361  case MeshXML::GREEN:
362  xml->material.eg = XMLSupport::parse_float( (*iter).value );
363  break;
364  }
365  }
366  break;
367  case MeshXML::SPECULAR:
368  //assert(xml->load_stage==7);
369  xml->load_stage = 8;
370  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
371  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
372  {
373  case MeshXML::RED:
374  xml->material.sr = XMLSupport::parse_float( (*iter).value );
375  break;
376  case MeshXML::BLUE:
377  xml->material.sb = XMLSupport::parse_float( (*iter).value );
378  break;
379  case MeshXML::ALPHA:
380  xml->material.sa = XMLSupport::parse_float( (*iter).value );
381  break;
382  case MeshXML::GREEN:
383  xml->material.sg = XMLSupport::parse_float( (*iter).value );
384  break;
385  }
386  }
387  break;
388  case MeshXML::AMBIENT:
389  //assert(xml->load_stage==7);
390  xml->load_stage = 8;
391  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
392  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
393  {
394  case MeshXML::RED:
395  xml->material.ar = XMLSupport::parse_float( (*iter).value );
396  break;
397  case MeshXML::BLUE:
398  xml->material.ab = XMLSupport::parse_float( (*iter).value );
399  break;
400  case MeshXML::ALPHA:
401  xml->material.aa = XMLSupport::parse_float( (*iter).value );
402  break;
403  case MeshXML::GREEN:
404  xml->material.ag = XMLSupport::parse_float( (*iter).value );
405  break;
406  }
407  }
408  break;
409  case MeshXML::UNKNOWN:
410  VSFileSystem::vs_fprintf( stderr, "Unknown element start tag '%s' detected\n", name.c_str() );
411  break;
412  case MeshXML::MESH:
413  assert( xml->load_stage == 0 );
414  assert( xml->state_stack.size() == 1 );
415  xml->load_stage = 1;
416  //Read in texture attribute
417  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
418  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
419  {
420  case MeshXML::REVERSE:
421  xml->reverse = XMLSupport::parse_bool( (*iter).value );
422  break;
424  xml->force_texture = XMLSupport::parse_bool( (*iter).value );
425  break;
426  case MeshXML::SCALE:
427  xml->scale *= XMLSupport::parse_float( (*iter).value );
428  break;
429  case MeshXML::SHAREVERT:
430  xml->sharevert =
431  ( XMLSupport::parse_bool( (*iter).value )
432  && XMLSupport::parse_bool( vs_config->getVariable( "graphics", "SharedVertexArrays", "true" ) ) );
433  break;
435  this->polygon_offset = XMLSupport::parse_float( (*iter).value );
436  break;
437  case MeshXML::BLENDMODE:
438  {
439  char *csrc = strdup( (*iter).value.c_str() );
440  char *cdst = strdup( (*iter).value.c_str() );
441  sscanf( ( (*iter).value ).c_str(), "%s %s", csrc, cdst );
442  SetBlendMode( parse_alpha( csrc ), parse_alpha( cdst ) );
443  free( csrc );
444  free( cdst );
445  break;
446  }
447  case MeshXML::ALPHATEST:
448  {
449  float tmp = XMLSupport::parse_float( (*iter).value );
450  if (tmp > 1)
451  xml->mesh->alphatest = 255;
452  else if (tmp > 0 && tmp <= 1)
453  xml->mesh->alphatest = float_to_int( tmp*255.0f );
454  else xml->mesh->alphatest = 0;
455  break;
456  }
457  case MeshXML::TECHNIQUE:
458  xml->technique = iter->value;
459  break;
461  if (use_detail_texture)
462  detailTexture = TempGetTexture( xml, iter->value, FactionUtil::GetFaction( xml->faction ), GFXTRUE );
463  break;
464  case MeshXML::TEXTURE:
465  //NO BREAK..goes to next statement
466  case MeshXML::ALPHAMAP:
468  case MeshXML::UNKNOWN:
469  {
470  MeshXML::Names whichtype = MeshXML::UNKNOWN;
471  int strsize = 0;
472  if (strtoupper( iter->name ).find( "ANIMATION" ) == 0) {
473  whichtype = MeshXML::ANIMATEDTEXTURE;
474  strsize = strlen( "ANIMATION" );
475  }
476  if (strtoupper( iter->name ).find( "TEXTURE" ) == 0) {
477  whichtype = MeshXML::TEXTURE;
478  strsize = strlen( "TEXTURE" );
479  }
480  if (strtoupper( iter->name ).find( "ALPHAMAP" ) == 0) {
481  whichtype = MeshXML::ALPHAMAP;
482  strsize = strlen( "ALPHAMAP" );
483  }
484  if (whichtype != MeshXML::UNKNOWN) {
485  unsigned int texindex = 0;
486  string ind( iter->name.substr( strsize ) );
487  if ( !ind.empty() )
488  texindex = XMLSupport::parse_int( ind );
489  static bool per_pixel_lighting =
490  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "per_pixel_lighting", "true" ) );
491  if ( (texindex == 0) || per_pixel_lighting )
492  while (xml->decals.size() <= texindex)
493  xml->decals.push_back( MeshXML::ZeTexture() );
494  switch (whichtype)
495  {
497  xml->decals[texindex].animated_name = iter->value;
498  break;
499  case MeshXML::ALPHAMAP:
500  xml->decals[texindex].alpha_name = iter->value;
501  break;
502  default:
503  xml->decals[texindex].decal_name = iter->value;
504  }
505  if (texindex == 0)
506  texture_found = true;
507  }
508  break;
509  }
510  }
511  }
512  assert( texture_found );
513  break;
514  case MeshXML::POINTS:
515  assert( top == MeshXML::MESH ); //FIXME top was never initialized if state stack was empty
516  //assert(xml->load_stage == 1);
517  xml->load_stage = 2;
518  break;
519  case MeshXML::POINT:
520  assert( top == MeshXML::POINTS ); //FIXME top was never initialized if state stack was empty
521 
522  memset( &xml->vertex, 0, sizeof (xml->vertex) );
523  xml->point_state = 0; //Point state is used to check that all necessary attributes are recorded
524  break;
525  case MeshXML::LOCATION:
526  assert( top == MeshXML::POINT ); //FIXME top was never initialized if state stack was empty
527  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
528  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
529  {
530  case MeshXML::UNKNOWN:
531  VSFileSystem::vs_fprintf( stderr, "Unknown attribute '%s' encountered in Location tag\n", (*iter).name.c_str() );
532  break;
533  case MeshXML::X:
534  assert( !(xml->point_state&MeshXML::P_X) );
535  xml->vertex.x = XMLSupport::parse_float( (*iter).value );
536  xml->vertex.i = 0;
537  xml->point_state |= MeshXML::P_X;
538  break;
539  case MeshXML::Y:
540  assert( !(xml->point_state&MeshXML::P_Y) );
541  xml->vertex.y = XMLSupport::parse_float( (*iter).value );
542  xml->vertex.j = 0;
543  xml->point_state |= MeshXML::P_Y;
544  break;
545  case MeshXML::Z:
546  assert( !(xml->point_state&MeshXML::P_Z) );
547  xml->vertex.z = XMLSupport::parse_float( (*iter).value );
548  xml->vertex.k = 0;
549  xml->point_state |= MeshXML::P_Z;
550  break;
551  case MeshXML::S:
552  xml->vertex.s = XMLSupport::parse_float( (*iter).value );
553  break;
554  case MeshXML::T:
555  xml->vertex.t = XMLSupport::parse_float( (*iter).value );
556  break;
557  default:
558  assert( 0 );
559  }
560  }
561  assert( ( xml->point_state&(MeshXML::P_X
562  |MeshXML::P_Y
563  |MeshXML::P_Z) )
564  == (MeshXML::P_X
565  |MeshXML::P_Y
566  |MeshXML::P_Z) );
567  break;
568  case MeshXML::NORMAL:
569  assert( top == MeshXML::POINT );
570  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
571  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
572  {
573  case MeshXML::UNKNOWN:
574  VSFileSystem::vs_fprintf( stderr, "Unknown attribute '%s' encountered in Normal tag\n", (*iter).name.c_str() );
575  break;
576  case MeshXML::I:
577  assert( !(xml->point_state&MeshXML::P_I) );
578  xml->vertex.i = XMLSupport::parse_float( (*iter).value );
579  xml->point_state |= MeshXML::P_I;
580  break;
581  case MeshXML::J:
582  assert( !(xml->point_state&MeshXML::P_J) );
583  xml->vertex.j = XMLSupport::parse_float( (*iter).value );
584  xml->point_state |= MeshXML::P_J;
585  break;
586  case MeshXML::K:
587  assert( !(xml->point_state&MeshXML::P_K) );
588  xml->vertex.k = XMLSupport::parse_float( (*iter).value );
589  xml->point_state |= MeshXML::P_K;
590  break;
591  default:
592  assert( 0 );
593  }
594  }
595  if ( ( xml->point_state&(MeshXML::P_I
596  |MeshXML::P_J
597  |MeshXML::P_K) )
598  != (MeshXML::P_I
599  |MeshXML::P_J
600  |MeshXML::P_K) ) {
601  if (!xml->recalc_norm) {
602  xml->vertex.i = xml->vertex.j = xml->vertex.k = 0;
603  xml->recalc_norm = true;
604  }
605  }
606  break;
607  case MeshXML::POLYGONS:
608  assert( top == MeshXML::MESH );
609  //assert(xml->load_stage==3);
610  xml->load_stage = 4;
611  break;
612  case MeshXML::LINE:
613  assert( top == MeshXML::POLYGONS );
614  //assert(xml->load_stage==4);
615  xml->num_vertices = 2;
616  xml->active_list = &xml->lines;
617  xml->active_ind = &xml->lineind;
618  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
619  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
620  {
621  case MeshXML::UNKNOWN:
622 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
623  break;
624  case MeshXML::FLATSHADE:
625  if ( (*iter).value == "Flat" ) {
626  VSFileSystem::vs_fprintf( stderr, "Cannot Flatshade Lines\n" );
627  } else if ( (*iter).value == "Smooth" ) {
628  //ignored -- already done
629  }
630  break;
631  default:
632  assert( 0 );
633  }
634  }
635  break;
636  case MeshXML::TRI:
637  assert( top == MeshXML::POLYGONS );
638  //assert(xml->load_stage==4);
639  xml->num_vertices = 3;
640  xml->active_list = &xml->tris;
641  xml->active_ind = &xml->triind;
642  xml->trishade.push_back( 0 );
643  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
644  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
645  {
646  case MeshXML::UNKNOWN:
647 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
648  break;
649  case MeshXML::FLATSHADE:
650  if ( (*iter).value == "Flat" )
651  xml->trishade[xml->trishade.size()-1] = 1;
652  else if ( (*iter).value == "Smooth" )
653  xml->trishade[xml->trishade.size()-1] = 0;
654  break;
655  default:
656  assert( 0 );
657  }
658  }
659  break;
660  case MeshXML::LINESTRIP:
661  assert( top == MeshXML::POLYGONS );
662  //assert(xml->load_stage==4);
663  xml->num_vertices = 2;
664  xml->linestrips.push_back( vector< GFXVertex > () );
665  xml->active_list = &(xml->linestrips[xml->linestrips.size()-1]);
666  xml->lstrcnt = xml->linestripind.size();
667  xml->active_ind = &xml->linestripind;
668  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
669  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
670  {
671  case MeshXML::UNKNOWN:
672 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
673  break;
674  case MeshXML::FLATSHADE:
675  if ( (*iter).value == "Flat" ) {
676  VSFileSystem::vs_fprintf( stderr, "Cannot Flatshade Linestrips\n" );
677  } else if ( (*iter).value == "Smooth" ) {
678  //ignored -- already done
679  }
680  break;
681  default:
682  assert( 0 );
683  }
684  }
685  break;
686 
687  case MeshXML::TRISTRIP:
688  assert( top == MeshXML::POLYGONS );
689  //assert(xml->load_stage==4);
690  xml->num_vertices = 3; //minimum number vertices
691  xml->tristrips.push_back( vector< GFXVertex > () );
692  xml->active_list = &(xml->tristrips[xml->tristrips.size()-1]);
693  xml->tstrcnt = xml->tristripind.size();
694  xml->active_ind = &xml->tristripind;
695  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
696  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
697  {
698  case MeshXML::UNKNOWN:
699 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
700  break;
701  case MeshXML::FLATSHADE:
702  if ( (*iter).value == "Flat" ) {
703  VSFileSystem::vs_fprintf( stderr, "Cannot Flatshade Tristrips\n" );
704  } else if ( (*iter).value == "Smooth" ) {
705  //ignored -- already done
706  }
707  break;
708  default:
709  assert( 0 );
710  }
711  }
712  break;
713 
714  case MeshXML::TRIFAN:
715  assert( top == MeshXML::POLYGONS );
716  //assert(xml->load_stage==4);
717  xml->num_vertices = 3; //minimum number vertices
718  xml->trifans.push_back( vector< GFXVertex > () );
719  xml->active_list = &(xml->trifans[xml->trifans.size()-1]);
720  xml->tfancnt = xml->trifanind.size();
721  xml->active_ind = &xml->trifanind;
722  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
723  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
724  {
725  case MeshXML::UNKNOWN:
726 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
727  break;
728  case MeshXML::FLATSHADE:
729  if ( (*iter).value == "Flat" ) {
730  VSFileSystem::vs_fprintf( stderr, "Cannot Flatshade Trifans\n" );
731  } else if ( (*iter).value == "Smooth" ) {
732  //ignored -- already done
733  }
734  break;
735  default:
736  assert( 0 );
737  }
738  }
739  break;
740 
741  case MeshXML::QUADSTRIP:
742  assert( top == MeshXML::POLYGONS );
743  //assert(xml->load_stage==4);
744  xml->num_vertices = 4; //minimum number vertices
745  xml->quadstrips.push_back( vector< GFXVertex > () );
746  xml->active_list = &(xml->quadstrips[xml->quadstrips.size()-1]);
747  xml->qstrcnt = xml->quadstripind.size();
748  xml->active_ind = &xml->quadstripind;
749  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
750  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
751  {
752  case MeshXML::UNKNOWN:
753 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
754  break;
755  case MeshXML::FLATSHADE:
756  if ( (*iter).value == "Flat" ) {
757  VSFileSystem::vs_fprintf( stderr, "Cannot Flatshade Quadstrips\n" );
758  } else if ( (*iter).value == "Smooth" ) {
759  //ignored -- already done
760  }
761  break;
762  default:
763  assert( 0 );
764  }
765  }
766  break;
767 
768  case MeshXML::QUAD:
769  assert( top == MeshXML::POLYGONS );
770  //assert(xml->load_stage==4);
771  xml->num_vertices = 4;
772  xml->active_list = &xml->quads;
773  xml->active_ind = &xml->quadind;
774  xml->quadshade.push_back( 0 );
775  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
776  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
777  {
778  case MeshXML::UNKNOWN:
779 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
780  break;
781  case MeshXML::FLATSHADE:
782  if ( (*iter).value == "Flat" )
783  xml->quadshade[xml->quadshade.size()-1] = 1;
784  else if ( (*iter).value == "Smooth" )
785  xml->quadshade[xml->quadshade.size()-1] = 0;
786  break;
787  default:
788  assert( 0 );
789  }
790  }
791  break;
792  case MeshXML::LOD:
793  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
794  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
795  {
796  case MeshXML::UNKNOWN:
797  break;
799  framespersecond = XMLSupport::parse_float( (*iter).value );
800  break;
801  case MeshXML::LODFILE:
802  xml->lod.push_back( new Mesh( (*iter).value.c_str(), xml->lodscale, xml->faction, xml->fg, true ) ); //make orig mesh
803  break;
804  case MeshXML::SIZE:
805  flotsize = XMLSupport::parse_float( (*iter).value );
806  break;
807  }
808  }
809  if ( xml->lodsize.size() != xml->lod.size() )
810  xml->lodsize.push_back( flotsize );
811  break;
812  case MeshXML::VERTEX:
813  {
814  assert(
815  top == MeshXML::TRI || top == MeshXML::QUAD || top == MeshXML::LINE || top == MeshXML::TRISTRIP || top
816  == MeshXML::TRIFAN || top == MeshXML::QUADSTRIP || top == MeshXML::LINESTRIP );
817  //assert(xml->load_stage==4);
818 
819  xml->vertex_state = 0;
820  unsigned int index=0; //FIXME not all switch cases initialize index --"=0" added temporarily by chuck_starchaser
821  float s, t; //FIXME not all switch cases initialize s and t ...
822  s = t = 0.0f; //This initialization line to "=0.0f" added temporarily by chuck_starchaser
823  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
824  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
825  {
826  case MeshXML::UNKNOWN:
827 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
828  break;
829  case MeshXML::POINT:
830  assert( !(xml->vertex_state&MeshXML::V_POINT) );
832  index = XMLSupport::parse_int( (*iter).value );
833  break;
834  case MeshXML::S:
835  assert( !(xml->vertex_state&MeshXML::V_S) );
836  xml->vertex_state |= MeshXML::V_S;
837  s = XMLSupport::parse_float( (*iter).value );
838  break;
839  case MeshXML::T:
840  assert( !(xml->vertex_state&MeshXML::V_T) );
841  xml->vertex_state |= MeshXML::V_T;
842  t = XMLSupport::parse_float( (*iter).value );
843  break;
844  default:
845  assert( 0 );
846  }
847  }
848  assert( ( xml->vertex_state&(MeshXML::V_POINT
849  |MeshXML::V_S
850  |MeshXML::V_T) )
851  == (MeshXML::V_POINT
852  |MeshXML::V_S
853  |MeshXML::V_T) );
854  assert( index < xml->vertices.size() ); //FIXME not all switch cases initialize index
855 
856  memset( &xml->vertex, 0, sizeof (xml->vertex) );
857  xml->vertex = xml->vertices[index]; //FIXME not all switch cases initialize index
858  xml->vertexcount[index] += 1; //FIXME not all switch cases initialize index
859  if ( (!xml->vertex.i) && (!xml->vertex.j) && (!xml->vertex.k) )
860  if (!xml->recalc_norm)
861  xml->recalc_norm = true;
862  //xml->vertex.x*=scale;
863  //xml->vertex.y*=scale;
864  //xml->vertex.z*=scale;//FIXME
865  xml->vertex.s = s; //FIXME not all cases in switch above initialized s and t
866  xml->vertex.t = t; //FIXME not all cases in switch above initialized s and t
867  xml->active_list->push_back( xml->vertex );
868  xml->active_ind->push_back( index );
869  if (xml->reverse) {
870  unsigned int i;
871  for (i = xml->active_ind->size()-1; i > 0; i--)
872  (*xml->active_ind)[i] = (*xml->active_ind)[i-1];
873  (*xml->active_ind)[0] = index;
874  for (i = xml->active_list->size()-1; i > 0; i--)
875  (*xml->active_list)[i] = (*xml->active_list)[i-1];
876  (*xml->active_list)[0] = xml->vertex;
877  }
878  xml->num_vertices--;
879  break;
880  }
881  case MeshXML::LOGO:
882  {
883  assert( top == MeshXML::MESH );
884  //assert (xml->load_stage==4);
885  xml->load_stage = 5;
886  xml->vertex_state = 0;
887  unsigned int typ; //FIXME Not all cases below initialize typ
888  float rot, siz, offset; //FIXME Not all cases below initialize rot, siz or offset
889  typ = 0; //FIXME this line temporarily added by chuck_starchaser
890  rot = siz = offset = 0.0f; //FIXME this line temporarily added by chuck_starchaser
891  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
892  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
893  {
894  case MeshXML::UNKNOWN:
895 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
896  break;
897  case MeshXML::TYPE:
898  assert( !(xml->vertex_state&MeshXML::V_TYPE) );
900  typ = XMLSupport::parse_int( (*iter).value );
901 
902  break;
903  case MeshXML::ROTATE:
904  assert( !(xml->vertex_state&MeshXML::V_ROTATE) );
906  rot = XMLSupport::parse_float( (*iter).value );
907 
908  break;
909  case MeshXML::SIZE:
910  assert( !(xml->vertex_state&MeshXML::V_SIZE) );
912  siz = XMLSupport::parse_float( (*iter).value );
913  break;
914  case MeshXML::OFFSET:
915  assert( !(xml->vertex_state&MeshXML::V_OFFSET) );
917  offset = XMLSupport::parse_float( (*iter).value );
918  break;
919  default:
920  assert( 0 );
921  }
922  }
923  assert( ( xml->vertex_state&(MeshXML::V_TYPE
927  == (MeshXML::V_TYPE
930  |MeshXML::V_OFFSET) );
931  xml->logos.push_back( MeshXML::ZeLogo() );
932  xml->logos[xml->logos.size()-1].type = typ;
933  xml->logos[xml->logos.size()-1].rotate = rot;
934  xml->logos[xml->logos.size()-1].size = siz;
935  xml->logos[xml->logos.size()-1].offset = offset;
936  break;
937  }
938  case MeshXML::REF:
939  {
940  assert( top == MeshXML::LOGO );
941  //assert (xml->load_stage==5);
942  xml->load_stage = 6;
943  unsigned int ind = 0;
944  float indweight = 1;
945  bool foundindex = false;
946  int ttttttt;
947  ttttttt = 0;
948  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
949  switch ( MeshXML::attribute_map.lookup( (*iter).name ) )
950  {
951  case MeshXML::UNKNOWN:
952 //VSFileSystem::vs_fprintf (stderr,"Unknown attribute '%s' encountered in Vertex tag\n",(*iter).name.c_str() );
953  break;
954  case MeshXML::POINT:
955  assert( ttttttt < 2 );
957  ind = XMLSupport::parse_int( (*iter).value );
958  foundindex = true;
959  ttttttt += 2;
960  break;
961  case MeshXML::WEIGHT:
962  assert( (ttttttt&1) == 0 );
963  ttttttt += 1;
964  xml->vertex_state |= MeshXML::V_S;
965  indweight = XMLSupport::parse_float( (*iter).value );
966  break;
967  default:
968  assert( 0 );
969  }
970  }
971  assert( ttttttt == 3 );
972  if (!foundindex)
973  VSFileSystem::vs_fprintf( stderr, "mesh with uninitalized logo" );
974  xml->logos[xml->logos.size()-1].refpnt.push_back( ind );
975  xml->logos[xml->logos.size()-1].refweight.push_back( indweight );
977  break;
978  }
979  default:
980  assert( 0 );
981  }
982 }
983 
984 void Mesh::endElement( MeshXML *xml, const string &name )
985 {
986  //cerr << "End tag: " << name << endl;
987  MeshXML::Names elem = (MeshXML::Names) MeshXML::element_map.lookup( name );
988  assert( *xml->state_stack.rbegin() == elem );
989  xml->state_stack.pop_back();
990  unsigned int i;
991  switch (elem)
992  {
993  case MeshXML::UNKNOWN:
994  VSFileSystem::vs_fprintf( stderr, "Unknown element end tag '%s' detected\n", name.c_str() );
995  break;
996  case MeshXML::POINT:
997  assert( ( xml->point_state&(MeshXML::P_X
998  |MeshXML::P_Y
999  |MeshXML::P_Z
1000  |MeshXML::P_I
1001  |MeshXML::P_J
1002  |MeshXML::P_K) )
1003  == (MeshXML::P_X
1004  |MeshXML::P_Y
1005  |MeshXML::P_Z
1006  |MeshXML::P_I
1007  |MeshXML::P_J
1008  |MeshXML::P_K) );
1009  xml->vertices.push_back( xml->vertex );
1010  xml->vertexcount.push_back( 0 );
1011  break;
1012  case MeshXML::POINTS:
1013  xml->load_stage = 3;
1014  /*
1015  * cerr << xml->vertices.size() << " vertices\n";
1016  * for(int a=0; a<xml->vertices.size(); a++) {
1017  * clog << "Point: (" << xml->vertices[a].x << ", " << xml->vertices[a].y << ", " << xml->vertices[a].z << ") (" << xml->vertices[a].i << ", " << xml->vertices[a].j << ", " << xml->vertices[a].k << ")\n";
1018  * }
1019  * clog << endl;
1020  */
1021  break;
1022  case MeshXML::LINE:
1023  assert( xml->num_vertices == 0 );
1024  break;
1025  case MeshXML::TRI:
1026  assert( xml->num_vertices == 0 );
1027  break;
1028  case MeshXML::QUAD:
1029  assert( xml->num_vertices == 0 );
1030  break;
1031  case MeshXML::LINESTRIP:
1032  assert( xml->num_vertices <= 0 );
1033  for (i = xml->lstrcnt+1; i < xml->linestripind.size(); i++) {
1034  xml->nrmllinstrip.push_back( xml->linestripind[i-1] );
1035  xml->nrmllinstrip.push_back( xml->linestripind[i] );
1036  }
1037  break;
1038  case MeshXML::TRISTRIP:
1039  assert( xml->num_vertices <= 0 );
1040  for (i = xml->tstrcnt+2; i < xml->tristripind.size(); i++) {
1041  if ( (i-xml->tstrcnt)%2 ) {
1042  //normal order
1043  xml->nrmltristrip.push_back( xml->tristripind[i-2] );
1044  xml->nrmltristrip.push_back( xml->tristripind[i-1] );
1045  xml->nrmltristrip.push_back( xml->tristripind[i] );
1046  } else {
1047  //reverse order
1048  xml->nrmltristrip.push_back( xml->tristripind[i-1] );
1049  xml->nrmltristrip.push_back( xml->tristripind[i-2] );
1050  xml->nrmltristrip.push_back( xml->tristripind[i] );
1051  }
1052  }
1053  break;
1054  case MeshXML::TRIFAN:
1055  assert( xml->num_vertices <= 0 );
1056  for (i = xml->tfancnt+2; i < xml->trifanind.size(); i++) {
1057  xml->nrmltrifan.push_back( xml->trifanind[xml->tfancnt] );
1058  xml->nrmltrifan.push_back( xml->trifanind[i-1] );
1059  xml->nrmltrifan.push_back( xml->trifanind[i] );
1060  }
1061  break;
1062  case MeshXML::QUADSTRIP: //have to fix up nrmlquadstrip so that it 'looks' like a quad list for smooth shading
1063  assert( xml->num_vertices <= 0 );
1064  for (i = xml->qstrcnt+3; i < xml->quadstripind.size(); i += 2) {
1065  xml->nrmlquadstrip.push_back( xml->quadstripind[i-3] );
1066  xml->nrmlquadstrip.push_back( xml->quadstripind[i-2] );
1067  xml->nrmlquadstrip.push_back( xml->quadstripind[i] );
1068  xml->nrmlquadstrip.push_back( xml->quadstripind[i-1] );
1069  }
1070  break;
1071  case MeshXML::POLYGONS:
1072  assert( xml->tris.size()%3 == 0 );
1073  assert( xml->quads.size()%4 == 0 );
1074  break;
1075  case MeshXML::REF:
1076  //assert (xml->load_stage==6);
1077  xml->load_stage = 5;
1078  break;
1079  case MeshXML::LOGO:
1080  //assert (xml->load_stage==5);
1081  assert( xml->vertex_state >= MeshXML::V_REF*3 ); //make sure there are at least 3 reference points
1082  xml->load_stage = 4;
1083  break;
1084  case MeshXML::MATERIAL:
1085  //assert(xml->load_stage==7);
1086  xml->load_stage = 4;
1087  break;
1088  case MeshXML::DETAILPLANE:
1089 
1090  break;
1091  case MeshXML::DIFFUSE:
1092  //assert(xml->load_stage==8);
1093  xml->load_stage = 7;
1094  break;
1095  case MeshXML::EMISSIVE:
1096  //assert(xml->load_stage==8);
1097  xml->load_stage = 7;
1098  break;
1099  case MeshXML::SPECULAR:
1100  //assert(xml->load_stage==8);
1101  xml->load_stage = 7;
1102  break;
1103  case MeshXML::AMBIENT:
1104  //assert(xml->load_stage==8);
1105  xml->load_stage = 7;
1106  break;
1107  case MeshXML::MESH:
1108  //assert(xml->load_stage==4);//4 is done with poly, 5 is done with Logos
1109  xml->load_stage = 5;
1110  break;
1111  default:
1112  break;
1113  }
1114 }
1115 
1116 void updateMax( Vector &mn, Vector &mx, const GFXVertex &ver )
1117 {
1118  mn.i = min( ver.x, mn.i );
1119  mx.i = max( ver.x, mx.i );
1120  mn.j = min( ver.y, mn.j );
1121  mx.j = max( ver.y, mx.j );
1122  mn.k = min( ver.z, mn.k );
1123  mx.k = max( ver.z, mx.k );
1124 }
1125 
1126 using namespace VSFileSystem;
1127 
1128 void LaunchConverter( const char *input, const char *output, const char *args = "obc" )
1129 {
1130  string intmp = string( "\"" )+input+string( "\"" );
1131  string outtmp = string( "\"" )+output+string( "\"" );
1132 #ifndef _WIN32
1133  int pid = fork();
1134  if (!pid) {
1135  string soundserver_path = VSFileSystem::datadir+"/bin/mesher";
1136  string firstarg = string( "\"" )+soundserver_path+string( "\"" );
1137  pid = execlp( soundserver_path.c_str(), soundserver_path.c_str(), input, output, args, NULL );
1138  soundserver_path = VSFileSystem::datadir+"/mesher";
1139  firstarg = string( "\"" )+soundserver_path+string( "\"" );
1140  pid = execlp( soundserver_path.c_str(), soundserver_path.c_str(), input, output, args, NULL );
1141  VSFileSystem::vs_fprintf( stderr, "Unable to spawn converter\n" );
1142  exit( -1 );
1143  } else {
1144  if (pid == -1) {
1145  VSFileSystem::vs_fprintf( stderr, "Unable to spawn converter\n" );
1146  exit( -1 );
1147  }
1148  int mystat = 0;
1149  waitpid( pid, &mystat, 0 );
1150  }
1151 #else
1152  string ss_path = VSFileSystem::datadir+"\\bin\\mesher.exe";
1153  string firstarg = string( "\"" )+ss_path+string( "\"" );
1154  int pid = spawnl( P_WAIT, ss_path.c_str(), firstarg.c_str(), intmp.c_str(), outtmp.c_str(), args, NULL );
1155  if (pid == -1) {
1156  ss_path = VSFileSystem::datadir+"\\mesher.exe";
1157  firstarg = string( "\"" )+ss_path+string( "\"" );
1158  int pid = spawnl( P_WAIT, ss_path.c_str(), firstarg.c_str(), intmp.c_str(), outtmp.c_str(), args, NULL );
1159  if (pid == -1)
1160  VSFileSystem::vs_fprintf( stderr, "Unable to spawn obj converter Error (%d)\n", pid );
1161  }
1162 #endif
1163 }
1164 
1165 bool isBFXM( VSFile &f )
1166 {
1167  char bfxm[4];
1168  f.Read( &bfxm[0], 1 );
1169  f.Read( &bfxm[1], 1 );
1170  f.Read( &bfxm[2], 1 );
1171  f.Read( &bfxm[3], 1 );
1172  f.GoTo( 0 );
1173  return bfxm[0] == 'B' && bfxm[1] == 'F' && bfxm[2] == 'X' && bfxm[3] == 'M';
1174 }
1175 
1176 void CopyFile( VSFile &src, VSFile &dst )
1177 {
1178  size_t hm;
1179  size_t srcstruct;
1180  size_t *srcptr = &srcstruct;
1181  while ( ( hm = src.Read( srcptr, sizeof (srcstruct) ) ) )
1182  dst.Write( srcptr, hm );
1183 }
1184 /*
1185 
1186 bool loadObj( VSFile &f, std::string str )
1187 {
1188  string fullpath = f.GetFullPath();
1189  VSFile output;
1190  output.OpenCreateWrite( "output.bfxm", BSPFile );
1191  output.Close();
1192  output.OpenReadOnly( "output.bfxm", BSPFile );
1193  string outputpath = output.GetFullPath();
1194  output.Close();
1195  LaunchConverter( fullpath.c_str(), outputpath.c_str() );
1196  output.OpenReadOnly( "output.bfxm", BSPFile );
1197  if ( isBFXM( output ) ) {
1198  output.Close();
1199  f.Close();
1200  f.OpenReadOnly( "output.bfxm", BSPFile );
1201  return true;
1202  } else {
1203  output.Close();
1204  }
1205  VSFile input;
1206  input.OpenCreateWrite( "input.obj", BSPFile );
1207  f.GoTo( 0 );
1208  CopyFile( f, input );
1209  input.Close();
1210  input.OpenReadOnly( "input.obj", BSPFile );
1211  string inputpath = input.GetFullPath();
1212  input.Close();
1213 
1214  f.Close();
1215  int where = str.find_last_of( "." );
1216  str = str.substr( 0, where )+".mtl";
1217  f.OpenReadOnly( str, MeshFile );
1218  VSFile inputmtl;
1219  inputmtl.OpenCreateWrite( "input.mtl", BSPFile );
1220  CopyFile( f, inputmtl );
1221  f.Close();
1222  inputmtl.Close();
1223  LaunchConverter( inputpath.c_str(), outputpath.c_str() );
1224 
1225  output.OpenReadOnly( "output.bfxm", BSPFile );
1226  if ( isBFXM( output ) ) {
1227  output.Close();
1228  f.OpenReadOnly( "output.bfxm", BSPFile );
1229  return true;
1230  } else {
1231  output.Close();
1232  }
1233  return false;
1234 }
1235 */
1236 const bool USE_RECALC_NORM = true;
1237 const bool FLAT_SHADE = true;
1238 
1239 Mesh* Mesh::LoadMesh( const char *filename,
1240  const Vector &scale,
1241  int faction,
1242  Flightgroup *fg,
1243  const std::vector< std::string > &overridetextures )
1244 {
1245  vector< Mesh* >m = LoadMeshes( filename, scale, faction, fg, overridetextures );
1246  if ( m.empty() )
1247  return 0;
1248  if (m.size() > 1) {
1249  fprintf( stderr, "Mesh %s has %u subcomponents. Only first used!\n", filename, (unsigned int) m.size() );
1250  for (unsigned int i = 1; i < m.size(); ++i)
1251  delete m[i];
1252  }
1253  return m[0];
1254 }
1255 
1257 vector< Mesh* >Mesh::LoadMeshes( const char *filename,
1258  const Vector &scale,
1259  int faction,
1260  Flightgroup *fg,
1261  const std::vector< std::string > &overrideTextures )
1262 {
1263  /*
1264  * if (strstr(filename,".xmesh")) {
1265  * Mesh * m = new Mesh (filename,scale,faction,fg);
1266  * vector <Mesh*> ret;
1267  * ret.push_back(m);
1268  * return ret;
1269  * }*/
1270  string hash_name = VSFileSystem::GetHashName( filename, scale, faction );
1271  vector< Mesh* > *oldmesh = bfxmHashTable.Get( hash_name );
1272  if (oldmesh == 0) {
1273  hash_name = VSFileSystem::GetSharedMeshHashName( filename, scale, faction );
1274  oldmesh = bfxmHashTable.Get( hash_name );
1275  }
1276  if (0 != oldmesh) {
1277  vector< Mesh* >ret;
1278  for (unsigned int i = 0; i < oldmesh->size(); ++i) {
1279  ret.push_back( new Mesh() );
1280  Mesh *m = (*oldmesh)[i];
1281  ret.back()->LoadExistant( m->orig ? m->orig : m );
1282  }
1283  return ret;
1284  }
1285  VSFile f;
1286  VSError err = f.OpenReadOnly( filename, MeshFile );
1287  if (err > Ok) {
1288  VSFileSystem::vs_fprintf( stderr, "Cannot Open Mesh File %s\n", filename );
1289  return vector< Mesh* > ();
1290  }
1291  char bfxm[4];
1292  f.Read( &bfxm[0], sizeof(bfxm[0])*4 );
1293  bool isbfxm = (bfxm[0] == 'B' && bfxm[1] == 'F' && bfxm[2] == 'X' && bfxm[3] == 'M');
1294  if ( isbfxm || strstr( filename, ".obj" ) ) {
1295  if (!isbfxm) {
1296  // NOTE : Commented out following block, probably not needed anymore
1297 /* if ( !loadObj( f, filename ) ) {
1298  VSFileSystem::vs_fprintf( stderr, "Cannot Open Mesh File %s\n", filename );
1299 */
1300 //cleanexit=1;
1301 //winsys_exit(1);
1302  // return vector< Mesh* > ();
1303  // }
1304  }
1305  f.GoTo( 0 );
1306  hash_name =
1307  (err == VSFileSystem::Shared) ? VSFileSystem::GetSharedMeshHashName( filename, scale,
1308  faction ) : VSFileSystem::GetHashName(
1309  filename,
1310  scale,
1311  faction );
1312  vector< Mesh* > retval( LoadMeshes( f, scale, faction, fg, hash_name, overrideTextures ) );
1313  vector< Mesh* > *newvec = new vector< Mesh* > ( retval );
1314  for (unsigned int i = 0; i < retval.size(); ++i) {
1315  retval[i]->hash_name = hash_name;
1316  if (retval[i]->orig)
1317  retval[i]->orig->hash_name = hash_name;
1318  (*newvec)[i] = retval[i]->orig ? retval[i]->orig : retval[i];
1319  }
1320  bfxmHashTable.Put( hash_name, newvec );
1321  return retval;
1322  } else {
1323  f.Close();
1324  bool original = false;
1325  Mesh *m = new Mesh( filename, scale, faction, fg, original );
1326  vector< Mesh* >ret;
1327  ret.push_back( m );
1328  return ret;
1329  }
1330 }
1331 
1332 void Mesh::LoadXML( const char *filename,
1333  const Vector &scale,
1334  int faction,
1335  Flightgroup *fg,
1336  bool origthis,
1337  const vector< string > &textureOverride )
1338 {
1339  VSFile f;
1340  VSError err = f.OpenReadOnly( filename, MeshFile );
1341  if (err > Ok) {
1342  VSFileSystem::vs_fprintf( stderr, "Cannot Open Mesh File %s\n", filename );
1343 //cleanexit=1;
1344 //winsys_exit(1);
1345  return;
1346  }
1347  LoadXML( f, scale, faction, fg, origthis, textureOverride );
1348  f.Close();
1349 }
1350 
1351 void Mesh::LoadXML( VSFileSystem::VSFile &f,
1352  const Vector &scale,
1353  int faction,
1354  Flightgroup *fg,
1355  bool origthis,
1356  const vector< string > &textureOverride )
1357 {
1358  std::vector< unsigned int >ind;
1359  MeshXML *xml = new MeshXML;
1360  xml->mesh = this;
1361  xml->fg = fg;
1362  xml->usenormals = false;
1363  xml->usetangents = false;
1364  xml->force_texture = false;
1365  xml->reverse = false;
1366  xml->sharevert = false;
1367  xml->faction = faction;
1368  GFXGetMaterial( 0, xml->material ); //by default it's the default material;
1369  xml->load_stage = 0;
1370  xml->recalc_norm = false;
1371  xml->scale = scale;
1372  xml->lodscale = scale;
1373  XML_Parser parser = XML_ParserCreate( NULL );
1374  XML_SetUserData( parser, xml );
1375  XML_SetElementHandler( parser, &Mesh::beginElement, &Mesh::endElement );
1376  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
1377  XML_ParserFree( parser );
1378  //Now, copy everything into the mesh data structures
1379  if (xml->load_stage != 5) {
1380  VSFileSystem::vs_fprintf( stderr, "Warning: mesh load possibly failed\n" );
1381  exit( -1 );
1382  }
1383  PostProcessLoading( xml, textureOverride );
1384  numlods = xml->lod.size()+1;
1385  if (origthis) {
1386  orig = NULL;
1387  } else {
1388  orig = new Mesh[numlods];
1389  unsigned int i;
1390  for (i = 0; i < xml->lod.size(); i++) {
1391  orig[i+1] = *xml->lod[i];
1392  orig[i+1].lodsize = xml->lodsize[i];
1393  }
1394  }
1395  delete xml;
1396 }
1397 
1398 static void SumNormal( vector< GFXVertex > &vertices, int i1, int i2, int i3, vector< float > &weights )
1399 {
1400  Vector v1( vertices[i2].x-vertices[i1].x,
1401  vertices[i2].y-vertices[i1].y,
1402  vertices[i2].z-vertices[i1].z );
1403  Vector v2( vertices[i3].x-vertices[i1].x,
1404  vertices[i3].y-vertices[i1].y,
1405  vertices[i3].z-vertices[i1].z );
1406  v1.Normalize();
1407  v2.Normalize();
1408  Vector N = v1.Cross( v2 );
1409  float w = 1.f-0.9*fabsf( v1.Dot( v2 ) );
1410  N *= w;
1411 
1412  vertices[i1].i += N.i;
1413  vertices[i1].j += N.j;
1414  vertices[i1].k += N.k;
1415  weights[i1] += w;
1416 
1417  vertices[i2].i += N.i;
1418  vertices[i2].j += N.j;
1419  vertices[i2].k += N.k;
1420  weights[i2] += w;
1421 
1422  vertices[i3].i += N.i;
1423  vertices[i3].j += N.j;
1424  vertices[i3].k += N.k;
1425  weights[i3] += w;
1426 }
1427 
1428 static void SumLineNormal( vector< GFXVertex > &vertices, int i1, int i2, vector< float > &weights )
1429 {
1430  Vector v1( vertices[i2].x-vertices[i1].x,
1431  vertices[i2].y-vertices[i1].y,
1432  vertices[i2].z-vertices[i1].z );
1433  static Vector v2( 0.3408, 0.9401, 0.0005 );
1434  v1.Normalize();
1435  Vector N = v1.Cross( v2 );
1436 
1437  vertices[i1].i += N.i;
1438  vertices[i1].j += N.j;
1439  vertices[i1].k += N.k;
1440  weights[i1] += 1;
1441 
1442  vertices[i2].i += N.i;
1443  vertices[i2].j += N.j;
1444  vertices[i2].k += N.k;
1445  weights[i2] += 1;
1446 }
1447 
1448 static void SumNormals( vector< GFXVertex > &vertices,
1449  vector< int > &indices,
1450  size_t begin,
1451  size_t end,
1452  POLYTYPE polytype,
1453  vector< float > &weights )
1454 {
1455  int flip = 0;
1456  size_t i;
1457  switch (polytype)
1458  {
1459  case GFXTRI:
1460  if (end <= 2)
1461  break;
1462  end -= 2;
1463  for (; begin < end; begin += 3)
1464  SumNormal( vertices, indices[begin], indices[begin+1], indices[begin+2], weights );
1465  break;
1466  case GFXQUAD:
1467  if (end <= 3)
1468  break;
1469  end -= 3;
1470  for (; begin < end; begin += 4) {
1471  SumNormal( vertices, indices[begin], indices[begin+1], indices[begin+2], weights );
1472  SumNormal( vertices, indices[begin], indices[begin+2], indices[begin+3], weights );
1473  }
1474  break;
1475  case GFXTRISTRIP:
1476  case GFXQUADSTRIP:
1477  if (end <= 2)
1478  break;
1479  end -= 2;
1480  for (; begin < end; ++begin, flip ^= 1)
1481  SumNormal( vertices, indices[begin], indices[begin+1+flip], indices[begin+2-flip], weights );
1482  break;
1483  case GFXTRIFAN:
1484  if (end <= 2)
1485  break;
1486  end -= 2;
1487  for (i = begin; begin < end; ++begin)
1488  SumNormal( vertices, indices[i], indices[begin+1], indices[begin+2], weights );
1489  break;
1490  case GFXLINESTRIP:
1491  if (end <= 1)
1492  break;
1493  end -= 1;
1494  for (i = begin; begin < end; ++begin)
1495  SumLineNormal( vertices, indices[begin], indices[begin+1], weights );
1496  break;
1497  case GFXLINE:
1498  if (end <= 1)
1499  break;
1500  end -= 1;
1501  for (i = begin; begin < end; begin += 2)
1502  SumLineNormal( vertices, indices[begin], indices[begin+1], weights );
1503  break;
1504  case GFXPOLY:
1505  case GFXPOINT:
1506  break;
1507  }
1508 }
1509 
1510 static void ClearTangents( vector< GFXVertex > &vertices )
1511 {
1512  for (vector< GFXVertex >::iterator it = vertices.begin(); it != vertices.end(); ++it)
1513  it->SetTangent( Vector( 0, 0, 0 ), 0 );
1514 }
1515 
1516 static float faceTSPolarity( const Vector &T, const Vector &B, const Vector &N )
1517 {
1518  if (T.Cross( B ).Dot( N ) >= 0.f)
1519  return -1.f;
1520  else
1521  return 1.f;
1522 }
1523 
1524 static float faceTSWeight( vector< GFXVertex > &vertices, int i1, int i2, int i3 )
1525 {
1526  const GFXVertex &vtx1 = vertices[i1];
1527  const GFXVertex &vtx2 = vertices[i2];
1528  const GFXVertex &vtx3 = vertices[i3];
1529 
1530  Vector v1( vtx2.x-vtx1.x,
1531  vtx2.y-vtx1.y,
1532  vtx2.z-vtx1.z );
1533  Vector v2( vtx3.x-vtx1.x,
1534  vtx3.y-vtx1.y,
1535  vtx3.z-vtx1.z );
1536  v1.Normalize();
1537  v2.Normalize();
1538  return 1.f-fabsf( v1.Dot( v2 ) );
1539 }
1540 
1541 static void computeTangentspace( vector< GFXVertex > &vertices, int i1, int i2, int i3, Vector &T, Vector &B, Vector &N )
1542 {
1543  const GFXVertex &v1 = vertices[i1];
1544  const GFXVertex &v2 = vertices[i2];
1545  const GFXVertex &v3 = vertices[i3];
1546 
1547  //compute deltas. I think that the fact we use (*2-*1) and (*3-*1) is arbitrary, but I could be wrong
1548  Vector p0( v1.x, v1.y, v1.z );
1549  Vector p1( v2.x, v2.y, v2.z );
1550  Vector p2( v3.x, v3.y, v3.z );
1551  p1 -= p0;
1552  p2 -= p0;
1553 
1554  float s1, t1;
1555  float s2, t2;
1556  s1 = v2.s-v1.s;
1557  s2 = v3.s-v1.s;
1558  t1 = v2.t-v1.t;
1559  t2 = v3.t-v1.t;
1560 
1561  //and now a myracle happens...
1562  T = t2*p1-t1*p2;
1563  B = s1*p2-s2*p1;
1564  N = p1.Cross( p2 );
1565 
1566  //normalize
1567  T.Normalize();
1568  B.Normalize();
1569  N.Normalize();
1570 }
1571 
1572 static void SumTangent( vector< GFXVertex > &vertices, int i1, int i2, int i3, vector< float > &weights )
1573 {
1574  float w = faceTSWeight( vertices, i1, i2, i3 );
1575  Vector T, B, N;
1576  computeTangentspace( vertices, i1, i2, i3, T, B, N );
1577 
1578  float p = faceTSPolarity( T, B, N )*w;
1579  T *= w;
1580 
1581  GFXVertex &v1 = vertices[i1];
1582  GFXVertex &v2 = vertices[i2];
1583  GFXVertex &v3 = vertices[i3];
1584 
1585  v1.tx += T.x;
1586  v1.ty += T.y;
1587  v1.tz += T.z;
1588  v1.tw += p;
1589  weights[i1] += w;
1590 
1591  v2.tx += T.x;
1592  v2.ty += T.y;
1593  v2.tz += T.z;
1594  v2.tw += p;
1595  weights[i2] += w;
1596 
1597  v3.tx += T.x;
1598  v3.ty += T.y;
1599  v3.tz += T.z;
1600  v3.tw += p;
1601  weights[i3] += w;
1602 }
1603 
1604 static void SumTangents( vector< GFXVertex > &vertices,
1605  vector< int > &indices,
1606  size_t begin,
1607  size_t end,
1608  POLYTYPE polytype,
1609  vector< float > &weights )
1610 {
1611  int flip = 0;
1612  size_t i;
1613  switch (polytype)
1614  {
1615  case GFXTRI:
1616  if (end <= 2)
1617  break;
1618  end -= 2;
1619  for (; begin < end; begin += 3)
1620  SumTangent( vertices, indices[begin], indices[begin+1], indices[begin+2], weights );
1621  break;
1622  case GFXQUAD:
1623  if (end <= 3)
1624  break;
1625  end -= 3;
1626  for (; begin < end; begin += 4) {
1627  SumTangent( vertices, indices[begin], indices[begin+1], indices[begin+2], weights );
1628  SumTangent( vertices, indices[begin], indices[begin+2], indices[begin+3], weights );
1629  }
1630  break;
1631  case GFXTRISTRIP:
1632  case GFXQUADSTRIP:
1633  if (end <= 2)
1634  break;
1635  end -= 2;
1636  for (; begin < end; ++begin, flip ^= 1)
1637  SumTangent( vertices, indices[begin], indices[begin+1+flip], indices[begin+2-flip], weights );
1638  break;
1639  case GFXTRIFAN:
1640  if (end <= 2)
1641  break;
1642  end -= 2;
1643  for (i = begin; begin < end; ++begin)
1644  SumTangent( vertices, indices[i], indices[begin+1], indices[begin+2], weights );
1645  break;
1646  case GFXLINE:
1647  case GFXLINESTRIP:
1648  case GFXPOLY:
1649  case GFXPOINT:
1650  break;
1651  }
1652 }
1653 
1654 static void NormalizeTangents( vector< GFXVertex > &vertices, vector< float > &weights )
1655 {
1656  for (size_t i = 0, n = vertices.size(); i < n; ++i) {
1657  GFXVertex &v = vertices[i];
1658  float w = weights[i];
1659 
1660  if (w > 0) {
1661  //Average (shader will normalize)
1662  float iw = (w < 0.001) ? 1.f : (1.f / w);
1663  v.tx *= iw;
1664  v.ty *= iw;
1665  v.tz *= iw;
1666  v.tw *= iw;
1667  }
1668 
1669  // Don't let null vectors around (they create NaNs within shaders when normalized)
1670  // Since they happen regularly on sphere polar caps, replace them with a suitable value there (+x)
1671  if (Vector(v.tx, v.ty, v.tz).MagnitudeSquared() < 0.00001)
1672  v.tx = 0.001;
1673  }
1674 }
1675 
1676 static void NormalizeNormals( vector< GFXVertex > &vertices, vector< float > &weights )
1677 {
1678  for (size_t i = 0, n = vertices.size(); i < n; ++i) {
1679  GFXVertex &v = vertices[i];
1680  float w = weights[i];
1681 
1682  if (w > 0) {
1683  //Renormalize
1684  float mag = v.GetNormal().MagnitudeSquared();
1685  if (mag < 0.00001)
1686  mag = 1.f;
1687  else
1688  mag = 1.f/sqrt(mag);
1689  v.i *= mag;
1690  v.j *= mag;
1691  v.k *= mag;
1692  }
1693  }
1694 }
1695 
1696 void Mesh::PostProcessLoading( MeshXML *xml, const vector< string > &textureOverride )
1697 {
1698  unsigned int i;
1699  unsigned int a = 0;
1700  unsigned int j;
1701  //begin vertex normal calculations if necessary
1702  if (!xml->usenormals) {
1703  ClearTangents( xml->vertices );
1704 
1705  vector< float >weights;
1706  weights.resize( xml->vertices.size(), 0.f );
1707 
1708  size_t i, j, n;
1709 
1710  SumNormals( xml->vertices, xml->triind, 0, xml->triind.size(), GFXTRI, weights );
1711  SumNormals( xml->vertices, xml->quadind, 0, xml->quadind.size(), GFXQUAD, weights );
1712  SumNormals( xml->vertices, xml->lineind, 0, xml->lineind.size(), GFXLINE, weights );
1713  for ( i = j = 0, n = xml->tristrips.size(); i < n; j += xml->tristrips[i++].size() )
1714  SumNormals( xml->vertices, xml->tristripind, j, j+xml->tristrips[i].size(), GFXTRISTRIP, weights );
1715  for ( i = j = 0, n = xml->quadstrips.size(); i < n; j += xml->quadstrips[i++].size() )
1716  SumNormals( xml->vertices, xml->quadstripind, j, j+xml->quadstrips[i].size(), GFXQUADSTRIP, weights );
1717  for ( i = j = 0, n = xml->trifans.size(); i < n; j += xml->trifans[i++].size() )
1718  SumNormals( xml->vertices, xml->trifanind, j, j+xml->trifans[i].size(), GFXTRIFAN, weights );
1719  for ( i = j = 0, n = xml->linestrips.size(); i < n; j += xml->linestrips[i++].size() )
1720  SumNormals( xml->vertices, xml->linestripind, j, j+xml->linestrips[i].size(), GFXLINESTRIP, weights );
1721  NormalizeNormals( xml->vertices, weights );
1722  } else {
1723  //Flip normals - someone thought VS should flips normals, ask him why.
1724  for (i = 0; i < xml->vertices.size(); ++i) {
1725  GFXVertex &v = xml->vertices[i];
1726  v.i *= -1;
1727  v.j *= -1;
1728  v.k *= -1;
1729  }
1730  }
1731  a = 0;
1732  std::vector< unsigned int > ind;
1733  for (a = 0; a < xml->tris.size(); a += 3)
1734  for (j = 0; j < 3; j++) {
1735  int ix = xml->triind[a+j];
1736  ind.push_back( ix );
1737  xml->tris[a+j].SetNormal( xml->vertices[ix].GetNormal() );
1738  xml->tris[a+j].SetTangent( xml->vertices[ix].GetTangent(),
1739  xml->vertices[ix].GetTangentParity() );
1740  }
1741  a = 0;
1742  for (a = 0; a < xml->quads.size(); a += 4)
1743  for (j = 0; j < 4; j++) {
1744  int ix = xml->quadind[a+j];
1745  ind.push_back( ix );
1746  xml->quads[a+j].SetNormal( xml->vertices[ix].GetNormal() );
1747  xml->quads[a+j].SetTangent( xml->vertices[ix].GetTangent(),
1748  xml->vertices[ix].GetTangentParity() );
1749  }
1750  a = 0;
1751  for (a = 0; a < xml->lines.size(); a += 2)
1752  for (j = 0; j < 2; j++) {
1753  int ix = xml->lineind[a+j];
1754  ind.push_back( ix );
1755  xml->lines[a+j].SetNormal( xml->vertices[ix].GetNormal() );
1756  }
1757  a = 0;
1758  unsigned int k = 0;
1759  unsigned int l = 0;
1760  for (l = a = 0; a < xml->tristrips.size(); a++)
1761  for (k = 0; k < xml->tristrips[a].size(); k++, l++) {
1762  int ix = xml->tristripind[l];
1763  ind.push_back( ix );
1764  xml->tristrips[a][k].SetNormal( xml->vertices[ix].GetNormal() );
1765  xml->tristrips[a][k].SetTangent( xml->vertices[ix].GetTangent(),
1766  xml->vertices[ix].GetTangentParity() );
1767  }
1768  for (l = a = 0; a < xml->trifans.size(); a++)
1769  for (k = 0; k < xml->trifans[a].size(); k++, l++) {
1770  int ix = xml->trifanind[l];
1771  ind.push_back( ix );
1772  xml->trifans[a][k].SetNormal( xml->vertices[ix].GetNormal() );
1773  xml->trifans[a][k].SetTangent( xml->vertices[ix].GetTangent(),
1774  xml->vertices[ix].GetTangentParity() );
1775  }
1776  for (l = a = 0; a < xml->quadstrips.size(); a++)
1777  for (k = 0; k < xml->quadstrips[a].size(); k++, l++) {
1778  int ix = xml->quadstripind[l];
1779  ind.push_back( ix );
1780  xml->quadstrips[a][k].SetNormal( xml->vertices[ix].GetNormal() );
1781  xml->quadstrips[a][k].SetTangent( xml->vertices[ix].GetTangent(),
1782  xml->vertices[ix].GetTangentParity() );
1783  }
1784  for (l = a = 0; a < xml->linestrips.size(); a++)
1785  for (k = 0; k < xml->linestrips[a].size(); k++, l++) {
1786  int ix = xml->linestripind[l];
1787  ind.push_back( ix );
1788  xml->linestrips[a][k].SetNormal( xml->vertices[ix].GetNormal() );
1789  }
1790  //TODO: add alpha handling
1791 
1792  //check for per-polygon flat shading
1793  unsigned int trimax = xml->tris.size()/3;
1794  a = 0;
1795  i = 0;
1796  j = 0;
1797  if (!xml->usenormals) {
1798  for (i = 0; i < trimax; i++, a += 3)
1799  if (FLAT_SHADE || xml->trishade[i] == 1) {
1800  for (j = 0; j < 3; j++) {
1801  Vector Cur = xml->vertices[xml->triind[a+j]].GetPosition();
1802  Cur = (xml->vertices[xml->triind[a+( (j+1)%3 )]].GetPosition()-Cur)
1803  .Cross( xml->vertices[xml->triind[a+( (j+2)%3 )]].GetPosition()-Cur );
1804  Normalize( Cur );
1805  xml->tris[a+j].SetNormal( Cur );
1806  }
1807  }
1808  a = 0;
1809  trimax = xml->quads.size()/4;
1810  for (i = 0; i < trimax; i++, a += 4)
1811  if ( xml->quadshade[i] == 1 || (FLAT_SHADE) ) {
1812  for (j = 0; j < 4; j++) {
1813  Vector Cur = xml->vertices[xml->quadind[a+j]].GetPosition();
1814  Cur = (xml->vertices[xml->quadind[a+( (j+1)%4 )]].GetPosition()-Cur)
1815  .Cross( xml->vertices[xml->quadind[a+( (j+2)%4 )]].GetPosition()-Cur );
1816  Normalize( Cur );
1817  xml->quads[a+j].SetNormal( Cur );
1818  }
1819  }
1820  }
1821  string factionname = FactionUtil::GetFaction( xml->faction );
1822  for (unsigned int LC = 0; LC < textureOverride.size(); ++LC)
1823  if (textureOverride[LC] != "") {
1824  while (xml->decals.size() <= LC) {
1826  xml->decals.push_back( z );
1827  }
1828  if (textureOverride[LC].find( ".ani" ) != string::npos) {
1829  xml->decals[LC].decal_name = "";
1830  xml->decals[LC].animated_name = textureOverride[LC];
1831  xml->decals[LC].alpha_name = "";
1832  } else {
1833  xml->decals[LC].animated_name = "";
1834  xml->decals[LC].alpha_name = "";
1835  xml->decals[LC].decal_name = textureOverride[LC];
1836  }
1837  }
1838  while ( Decal.size() < xml->decals.size() )
1839  Decal.push_back( NULL );
1840  {
1841  for (unsigned int i = 0; i < xml->decals.size(); i++)
1842  Decal[i] = ( TempGetTexture( xml, i, factionname ) );
1843  }
1844  while (Decal.back() == NULL && Decal.size() > 1)
1845  Decal.pop_back();
1846  initTechnique( xml->technique );
1847 
1848  unsigned int index = 0;
1849 
1850  unsigned int totalvertexsize = xml->tris.size()+xml->quads.size()+xml->lines.size();
1851  for (index = 0; index < xml->tristrips.size(); index++)
1852  totalvertexsize += xml->tristrips[index].size();
1853  for (index = 0; index < xml->trifans.size(); index++)
1854  totalvertexsize += xml->trifans[index].size();
1855  for (index = 0; index < xml->quadstrips.size(); index++)
1856  totalvertexsize += xml->quadstrips[index].size();
1857  for (index = 0; index < xml->linestrips.size(); index++)
1858  totalvertexsize += xml->linestrips[index].size();
1859  index = 0;
1860  vector< GFXVertex > vertexlist( totalvertexsize );
1861 
1862  mn = Vector( FLT_MAX, FLT_MAX, FLT_MAX );
1863  mx = Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );
1864  radialSize = 0;
1865  vector< enum POLYTYPE >polytypes;
1866  polytypes.insert( polytypes.begin(), totalvertexsize, GFXTRI );
1867  //enum POLYTYPE * polytypes= new enum POLYTYPE[totalvertexsize];//overkill but what the hell
1868  vector< int >poly_offsets;
1869  poly_offsets.insert( poly_offsets.begin(), totalvertexsize, 0 );
1870  int o_index = 0;
1871  if ( xml->tris.size() ) {
1872  polytypes[o_index] = GFXTRI;
1873  poly_offsets[o_index] = xml->tris.size();
1874  o_index++;
1875  }
1876  if ( xml->quads.size() ) {
1877  polytypes[o_index] = GFXQUAD;
1878  poly_offsets[o_index] = xml->quads.size();
1879  o_index++;
1880  }
1881  if ( xml->lines.size() ) {
1882  polytypes[o_index] = GFXLINE;
1883  poly_offsets[o_index] = xml->lines.size();
1884  o_index++;
1885  }
1886  for (a = 0; a < xml->tris.size(); a++, index++)
1887  vertexlist[index] = xml->tris[a];
1888  for (a = 0; a < xml->quads.size(); a++, index++)
1889  vertexlist[index] = xml->quads[a];
1890  for (a = 0; a < xml->lines.size(); a++, index++)
1891  vertexlist[index] = xml->lines[a];
1892  for (a = 0; a < xml->tristrips.size(); a++) {
1893  for (unsigned int m = 0; m < xml->tristrips[a].size(); m++, index++)
1894  vertexlist[index] = xml->tristrips[a][m];
1895  polytypes[o_index] = GFXTRISTRIP;
1896  poly_offsets[o_index] = xml->tristrips[a].size();
1897  o_index++;
1898  }
1899  for (a = 0; a < xml->trifans.size(); a++) {
1900  for (unsigned int m = 0; m < xml->trifans[a].size(); m++, index++)
1901  vertexlist[index] = xml->trifans[a][m];
1902  polytypes[o_index] = GFXTRIFAN;
1903  poly_offsets[o_index] = xml->trifans[a].size();
1904  o_index++;
1905  }
1906  for (a = 0; a < xml->quadstrips.size(); a++) {
1907  for (unsigned int m = 0; m < xml->quadstrips[a].size(); m++, index++)
1908  vertexlist[index] = xml->quadstrips[a][m];
1909  polytypes[o_index] = GFXQUADSTRIP;
1910  poly_offsets[o_index] = xml->quadstrips[a].size();
1911  o_index++;
1912  }
1913  for (a = 0; a < xml->linestrips.size(); a++) {
1914  for (unsigned int m = 0; m < xml->linestrips[a].size(); m++, index++)
1915  vertexlist[index] = xml->linestrips[a][m];
1916  polytypes[o_index] = GFXLINESTRIP;
1917  poly_offsets[o_index] = xml->linestrips[a].size();
1918  o_index++;
1919  }
1920  for (i = 0; i < index; ++i)
1921  updateMax( mn, mx, vertexlist[i] );
1922  //begin tangent calculations if necessary
1923  if (!xml->usetangents) {
1924  ClearTangents( vertexlist );
1925 
1926  vector< float >weights;
1927  vector< int > indices( vertexlist.size() ); //Oops, someday we'll use real indices
1928  weights.resize( vertexlist.size(), 0.f );
1929 
1930  size_t i, j, n;
1931  for (i = 0, n = vertexlist.size(); i < n; ++i)
1932  indices[i] = i;
1933  for (i = j = 0, n = polytypes.size(); i < n; j += poly_offsets[i++])
1934  SumTangents( vertexlist, indices, j, j+poly_offsets[i], polytypes[i], weights );
1935  NormalizeTangents( vertexlist, weights );
1936  }
1937  if (mn.i == FLT_MAX && mn.j == FLT_MAX && mn.k == FLT_MAX)
1938  mx.i = mx.j = mx.k = mn.i = mn.j = mn.k = 0;
1939  mn.i *= xml->scale.i;
1940  mn.j *= xml->scale.j;
1941  mn.k *= xml->scale.k;
1942  mx.i *= xml->scale.i;
1943  mx.j *= xml->scale.j;
1944  mx.k *= xml->scale.k;
1945  float x_center = (mn.i+mx.i)/2.0,
1946  y_center = (mn.j+mx.j)/2.0,
1947  z_center = (mn.k+mx.k)/2.0;
1948  local_pos = Vector( x_center, y_center, z_center );
1949  for (a = 0; a < totalvertexsize; a++) {
1950  vertexlist[a].x *= xml->scale.i; //FIXME
1951  vertexlist[a].y *= xml->scale.j;
1952  vertexlist[a].z *= xml->scale.k;
1953  }
1954  for (a = 0; a < xml->vertices.size(); a++) {
1955  xml->vertices[a].x *= xml->scale.i; //FIXME
1956  xml->vertices[a].y *= xml->scale.j;
1957  xml->vertices[a].z *= xml->scale.k;
1958  xml->vertices[a].i *= -1;
1959  xml->vertices[a].k *= -1;
1960  xml->vertices[a].j *= -1;
1961  }
1962  if (o_index || index)
1963  radialSize = .5*(mx-mn).Magnitude();
1964  if (xml->sharevert) {
1965  vlist = new GFXVertexList(
1966  (polytypes.size() ? &polytypes[0] : 0),
1967  xml->vertices.size(),
1968  (xml->vertices.size() ? &xml->vertices[0] : 0), o_index,
1969  (poly_offsets.size() ? &poly_offsets[0] : 0), false,
1970  (ind.size() ? &ind[0] : 0) );
1971  } else {
1972  static bool usopttmp = ( XMLSupport::parse_bool( vs_config->getVariable( "graphics", "OptimizeVertexArrays", "false" ) ) );
1973  static float optvertexlimit =
1974  ( XMLSupport::parse_float( vs_config->getVariable( "graphics", "OptimizeVertexCondition", "1.0" ) ) );
1975  bool cachunk = false;
1976  if ( usopttmp && (vertexlist.size() > 0) ) {
1977  int numopt = totalvertexsize;
1978  GFXVertex *newv;
1979  unsigned int *ind;
1980  GFXOptimizeList( &vertexlist[0], totalvertexsize, &newv, &numopt, &ind );
1981  if (numopt < totalvertexsize*optvertexlimit) {
1982  vlist = new GFXVertexList(
1983  (polytypes.size() ? &polytypes[0] : 0),
1984  numopt, newv, o_index,
1985  (poly_offsets.size() ? &poly_offsets[0] : 0), false,
1986  ind );
1987  cachunk = true;
1988  }
1989  free( ind );
1990  free( newv );
1991  }
1992  if (!cachunk) {
1993  if (vertexlist.size() == 0)
1994  vertexlist.resize( 1 );
1995  vlist = new GFXVertexList(
1996  (polytypes.size() ? &polytypes[0] : 0),
1997  totalvertexsize, &vertexlist[0], o_index,
1998  (poly_offsets.size() ? &poly_offsets[0] : 0) );
1999  }
2000  }
2001  CreateLogos( xml, xml->faction, xml->fg );
2002  //Calculate bounding sphere
2003  if (mn.i == FLT_MAX) {
2004  mn = Vector( 0, 0, 0 );
2005  mx = Vector( 0, 0, 0 );
2006  }
2007  GFXSetMaterial( myMatNum, xml->material );
2008 }
2009