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
quadtree_xml.cpp
Go to the documentation of this file.
1 #include "quadtree.h"
2 #include "xml_support.h"
3 #include "gfxlib.h"
4 #include "ani_texture.h"
5 #include <assert.h>
6 #include "vsfilesystem.h"
7 #include "vsimage.h"
8 
9 using namespace VSFileSystem;
10 
11 extern enum BLENDFUNC parse_alpha( const char *tmp );
12 
14 {
15  int scale;
16  float OriginX;
17  float OriginY;
18  std::string file;
19  std::string terrainfile;
20 };
21 
22 struct TerraXML
23 {
24  float scales;
25  float scalet;
26  float radius;
27  float detail;
28  float SphereSizeX;
29  float SphereSizeZ;
30  std::vector< std::string >animation;
31 
32  std::vector< std::string >alpha;
33  std::vector< GFXMaterial >mat;
34  std::vector< TerrainData >data;
35 };
36 
37 void QuadTree::beginElement( void *userData, const XML_Char *name, const XML_Char **atts )
38 {
39  ( (QuadTree*) userData )->beginElement( name, XMLSupport::AttributeList( atts ) );
40 }
41 
42 void QuadTree::endElement( void *userData, const XML_Char *name )
43 {
44  ( (QuadTree*) userData )->endElement( name );
45 }
46 
48 
49 namespace TerrainXML
50 {
51 //
52 
53 enum Names
54 {
80  RED,
87 };
88 
89 const EnumMap::Pair element_names[] = {
90  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
91  EnumMap::Pair( "Terrain", TERRAIN ),
92  EnumMap::Pair( "Texture", TEXTURE ),
93  EnumMap::Pair( "Material", MATERIAL ),
94  EnumMap::Pair( "Data", DATA ),
95  EnumMap::Pair( "Ambient", TERRAINAMBIENT ),
96  EnumMap::Pair( "Diffuse", TERRAINDIFFUSE ),
97  EnumMap::Pair( "Specular", TERRAINSPECULAR ),
98  EnumMap::Pair( "Emissive", TERRAINEMISSIVE )
99 };
100 
101 const EnumMap::Pair attribute_names[] = {
102  EnumMap::Pair( "UNKNOWN", UNKNOWN ),
103  EnumMap::Pair( "Detail", DETAIL ),
104  EnumMap::Pair( "StaticDetail", STATICDETAIL ),
105  EnumMap::Pair( "Level", LEVEL ),
106  EnumMap::Pair( "Blend", BLEND ),
107  EnumMap::Pair( "File", FFILE ),
108  EnumMap::Pair( "AlphaFile", ALPHAFILE ),
109  EnumMap::Pair( "Animation", ANIMATIONFILE ),
110  EnumMap::Pair( "TerrainFile", TERRAINFILE ),
111  EnumMap::Pair( "Reflect", REFLECT ),
112  EnumMap::Pair( "Color", COLOR ),
113  EnumMap::Pair( "Scale", SCALE ),
114  EnumMap::Pair( "ScaleS", SCALES ),
115  EnumMap::Pair( "ScaleT", SCALET ),
116  EnumMap::Pair( "OriginX", ORIGINX ),
117  EnumMap::Pair( "OriginY", ORIGINY ),
118  EnumMap::Pair( "red", RED ),
119  EnumMap::Pair( "green", GREEN ),
120  EnumMap::Pair( "blue", BLUE ),
121  EnumMap::Pair( "alpha", ALPHA ),
122  EnumMap::Pair( "power", POWER ),
123  EnumMap::Pair( "radius", RADIUS ),
124  EnumMap::Pair( "SphereWidth", SPHERESIZEX ),
125  EnumMap::Pair( "SphereHeight", SPHERESIZEZ )
126 };
127 
128 const EnumMap element_map( element_names, 9 );
130 
131 //end namespace
132 }
133 
134 using XMLSupport::EnumMap;
140 using namespace TerrainXML;
141 
142 void QuadTree::beginElement( const string &name, const AttributeList &attributes )
143 {
144  Names elem = (Names) element_map.lookup( name );
145  AttributeList::const_iterator iter;
146  char csrc[128];
147  char cdst[128];
148  switch (elem)
149  {
150  case TERRAIN:
151  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
152  switch ( attribute_map.lookup( (*iter).name ) )
153  {
154  case DETAIL:
155  detail = parse_float( (*iter).value );
156  break;
157  case STATICDETAIL:
158  xml->detail = parse_float( (*iter).value );
159  break;
160  case LEVEL:
161  RootCornerData.Level = parse_int( (*iter).value );
162  break;
163  case SCALES:
164  xml->scales = parse_float( (*iter).value );
165  break;
166  case SCALET:
167  xml->scalet = parse_float( (*iter).value );
168  break;
169  case RADIUS:
170  xml->radius = parse_float( (*iter).value );
171  break;
172  case SPHERESIZEX:
173  xml->SphereSizeX = parse_float( (*iter).value );
174  break;
175  case SPHERESIZEZ:
176  xml->SphereSizeZ = parse_float( (*iter).value );
177  break;
178  }
179  }
180  break;
181  case TEXTURE:
182  textures.push_back( TerrainTexture() );
183  textures.back().color = textures.size()-1;
184  xml->mat.push_back( GFXMaterial() );
185  xml->alpha.push_back( std::string() );
186  xml->animation.push_back( std::string() );
187  GFXGetMaterial( 0, xml->mat.back() );
188  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
189  switch ( attribute_map.lookup( (*iter).name ) )
190  {
191  case FFILE:
192  textures.back().tex.filename = strdup( (*iter).value.c_str() );
193  break;
194  case ALPHAFILE:
195  xml->alpha.back() = (*iter).value.c_str();
196  break;
197  case ANIMATIONFILE:
198  xml->animation.back() = (*iter).value.c_str();
199  break;
200  case BLEND:
201  sscanf( ( (*iter).value ).c_str(), "%s %s", csrc, cdst );
202  textures.back().blendSrc = parse_alpha( csrc );
203  textures.back().blendDst = parse_alpha( cdst );
204  break;
205  case COLOR:
206  textures.back().color = parse_int( ( (*iter).value ) );
207  break;
208  }
209  }
210  break;
211  case MATERIAL:
212  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
213  switch ( attribute_map.lookup( (*iter).name ) )
214  {
215  case REFLECT:
216  textures.back().reflect = parse_bool( (*iter).value );
217  break;
218  case POWER:
219  xml->mat.back().power = parse_float( (*iter).value );
220  break;
221  }
222  }
223  break;
224  case TERRAINDIFFUSE:
225  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
226  switch ( attribute_map.lookup( (*iter).name ) )
227  {
228  case RED:
229  xml->mat.back().dr = parse_float( (*iter).value );
230  break;
231  case BLUE:
232  xml->mat.back().db = parse_float( (*iter).value );
233  break;
234  case ALPHA:
235  xml->mat.back().da = parse_float( (*iter).value );
236  break;
237  case GREEN:
238  xml->mat.back().dg = parse_float( (*iter).value );
239  break;
240  }
241  }
242  break;
243  case TERRAINEMISSIVE:
244  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
245  switch ( attribute_map.lookup( (*iter).name ) )
246  {
247  case RED:
248  xml->mat.back().er = parse_float( (*iter).value );
249  break;
250  case BLUE:
251  xml->mat.back().eb = parse_float( (*iter).value );
252  break;
253  case ALPHA:
254  xml->mat.back().ea = parse_float( (*iter).value );
255  break;
256  case GREEN:
257  xml->mat.back().eg = parse_float( (*iter).value );
258  break;
259  }
260  }
261  break;
262  case TERRAINSPECULAR:
263  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
264  switch ( attribute_map.lookup( (*iter).name ) )
265  {
266  case RED:
267  xml->mat.back().sr = parse_float( (*iter).value );
268  break;
269  case BLUE:
270  xml->mat.back().sb = parse_float( (*iter).value );
271  break;
272  case ALPHA:
273  xml->mat.back().sa = parse_float( (*iter).value );
274  break;
275  case GREEN:
276  xml->mat.back().sg = parse_float( (*iter).value );
277  break;
278  }
279  }
280  break;
281  case TERRAINAMBIENT:
282  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
283  switch ( attribute_map.lookup( (*iter).name ) )
284  {
285  case RED:
286  xml->mat.back().ar = parse_float( (*iter).value );
287  break;
288  case BLUE:
289  xml->mat.back().ab = parse_float( (*iter).value );
290  break;
291  case ALPHA:
292  xml->mat.back().aa = parse_float( (*iter).value );
293  break;
294  case GREEN:
295  xml->mat.back().ag = parse_float( (*iter).value );
296  break;
297  }
298  }
299  break;
300  case DATA:
301  xml->data.push_back( TerrainData() );
302  for (iter = attributes.begin(); iter != attributes.end(); iter++) {
303  switch ( attribute_map.lookup( (*iter).name ) )
304  {
305  case SCALE:
306  xml->data.back().scale = parse_int( (*iter).value );
307  break;
308  case ORIGINX:
309  xml->data.back().OriginX = parse_float( (*iter).value );
310  break;
311  case ORIGINY:
312  xml->data.back().OriginY = parse_float( (*iter).value );
313  break;
314  case FFILE:
315  xml->data.back().file = (*iter).value;
316  break;
317  case TERRAINFILE:
318  xml->data.back().terrainfile = (*iter).value;
319  break;
320  }
321  }
322  break;
323  case UNKNOWN:
324  default:
325  break;
326  }
327 }
328 
329 void QuadTree::endElement( const string &name ) {}
330 
331 void QuadTree::SetXSizes( int mX, unsigned int maxX )
332 {
333  if (mX < minX)
334  minX = mX;
335  if (maxX > this->maxX)
336  this->maxX = maxX;
337 }
338 
339 void QuadTree::SetZSizes( int mZ, unsigned int maxZ )
340 {
341  if (mZ < minZ)
342  minZ = mZ;
343  if (maxZ > this->maxZ)
344  this->maxZ = maxZ;
345 }
346 
347 void QuadTree::LoadXML( const char *filename, const Vector &Scales, const float Radius )
348 {
349  const int chunk_size = 16384;
350  std::vector< unsigned int >ind;
351  //FILE* inFile = VSFileSystem::vs_open (filename, "r");
352  VSFile f;
353  VSError err = f.OpenReadOnly( filename, UnknownFile );
354  if (err > Ok) {
355  assert( 0 );
356  return;
357  }
358  xml = new TerraXML;
359  xml->SphereSizeX = -1;
360  xml->SphereSizeZ = -1;
361  xml->scales = .001;
362  xml->scalet = .001;
363  xml->radius = 10000;
364  xml->detail = 20;
365  XML_Parser parser = XML_ParserCreate( NULL );
366  XML_SetUserData( parser, this );
367  XML_SetElementHandler( parser, &QuadTree::beginElement, &QuadTree::endElement );
368  XML_Parse( parser, ( f.ReadFull() ).c_str(), f.Size(), 1 );
369  /*
370  * do {
371  * #ifdef BIDBG
372  * char *buf = (XML_Char*)XML_GetBuffer(parser, chunk_size);
373  * #else
374  * char buf[chunk_size];
375  * #endif
376  * int length;
377  *
378  * length = VSFileSystem::vs_read(buf,1, chunk_size,inFile);
379  * //length = inFile.gcount();
380  * #ifdef BIDBG
381  * XML_ParseBuffer(parser, length, VSFileSystem::vs_feof(inFile));
382  * #else
383  * XML_Parse (parser,buf,length,VSFileSystem::vs_feof(inFile));
384  * #endif
385  * } while(!VSFileSystem::vs_feof(inFile));
386  */
387  f.Close();
388  XML_ParserFree( parser );
389  unsigned int i;
390  for (i = 0; i < textures.size(); i++) {
391  textures[i].scales = xml->scales;
392  textures[i].scalet = xml->scalet;
393  if (textures[i].tex.filename || xml->animation[i].length() > 0) {
394  Texture *tex;
395  if (xml->animation[i].length() > 0) {
396  tex = new AnimatedTexture( xml->animation[i].c_str(), 0, MIPMAP );
397  } else {
398  if (xml->alpha[i].length() > 0)
399  tex = new Texture( textures[i].tex.filename, xml->alpha[i].c_str() );
400  else
401  tex = new Texture( textures[i].tex.filename );
402  free( textures[i].tex.filename );
403  }
404  textures[i].tex.t = tex;
405  GFXSetMaterial( textures[i].material, xml->mat[i] );
406  } else {
407  textures[i].tex.t = NULL;
408  }
409  }
410  bool biggest = true;
411  for (i = 0; i < xml->data.size(); i++) {
412  HeightMapInfo hm;
413  hm.XOrigin = (int) xml->data[i].OriginX;
414  hm.ZOrigin = (int) xml->data[i].OriginY;
415  hm.Scale = xml->data[i].scale;
416  unsigned char *palette;
417  //FILE * fp;
418  //fp = VSFileSystem::vs_open (xml->data[i].file.c_str(),"rb");
419  Texture tex;
420  err = f.OpenReadOnly( xml->data[i].file.c_str(), UnknownFile );
421  if (err <= Ok) {
422  //hm.Data = (short *) readImage (fp,bpp, format, hm.XSize,hm.ZSize, palette, &heightmapTransform,false);
423  hm.Data = (short*) tex.ReadImage( &f, &heightmapTransform, false );
424  hm.XSize = tex.sizeX;
425  hm.ZSize = tex.sizeY;
426  f.Close();
427  }
428  //LoadData();
429  unsigned long xsize = 0;
430  unsigned long zsize = 0;
431  //fp = VSFileSystem::vs_open (xml->data[i].terrainfile.c_str(),"rb");
432  f.OpenReadOnly( xml->data[i].terrainfile.c_str(), UnknownFile );
433  if (err <= Ok) {
434  //hm.terrainmap = (unsigned char *)readImage (fp, bpp, format, xsize, zsize, palette, &terrainTransform,true);
435  hm.terrainmap = (unsigned char*) tex.ReadImage( &f, &terrainTransform, true );
436  xsize = tex.sizeX;
437  zsize = tex.sizeY;
438  f.Close();
439  }
440  if (hm.Data && hm.terrainmap) {
441  assert( xsize == hm.XSize && zsize == hm.ZSize );
442  SetXSizes( hm.XOrigin, hm.XSize<<hm.Scale );
443  SetZSizes( hm.ZOrigin, hm.ZSize<<hm.Scale );
444  hm.RowWidth = hm.XSize;
445  if (biggest) {
446  biggest = false;
447  if (Radius != 0 && xml->radius != 0) {
448  nonlinear_transform = new SphericalTransform( xml->SphereSizeX < 0 ? hm.XSize<<hm.Scale : xml->SphereSizeX,
449  Radius < 0 ? xml->radius : Radius,
450  xml->SphereSizeZ < 0 ? hm.ZSize<<hm.Scale : xml->SphereSizeZ );
451  } else {
452  nonlinear_transform = new IdentityTransform();
453  //only happens the first time!
454  }
455  GFXVertex *v = vertices.BeginMutate( 0 )->vertices;
456  float xmax = ( hm.XOrigin+(hm.XSize<<hm.Scale) );
457  float zmax = ( hm.ZOrigin+(hm.ZSize<<hm.Scale) );
458  v[0].SetVertex( nonlinear_transform->Transform( Vector( xmax, 0, hm.ZOrigin ) ) );
459  v[0].SetTexCoord( nonlinear_transform->TransformS( xmax,
460  xml->scales ),
461  nonlinear_transform->TransformT( hm.ZOrigin, xml->scalet ) );
462  Vector Norm0( nonlinear_transform->TransformNormal( v[0].GetConstVertex(), Vector( 0, 1, 0 ) ) );
463  v[0].SetNormal( Vector( Norm0.i*Scales.i, Norm0.j*Scales.j, Norm0.k*Scales.k ) );
464  v[1].SetVertex( nonlinear_transform->Transform( Vector( hm.XOrigin, 0, hm.ZOrigin ) ) );
465  v[1].SetTexCoord( nonlinear_transform->TransformS( hm.XOrigin,
466  xml->scales ),
467  nonlinear_transform->TransformT( hm.ZOrigin, xml->scalet ) );
468  Norm0 = ( nonlinear_transform->TransformNormal( v[1].GetConstVertex(), Vector( 0, 1, 0 ) ) );
469  v[1].SetNormal( Vector( Norm0.i*Scales.i, Norm0.j*Scales.j, Norm0.k*Scales.k ) );
470 
471  v[2].SetVertex( nonlinear_transform->Transform( Vector( hm.XOrigin, 0, zmax ) ) );
472  v[2].SetTexCoord( nonlinear_transform->TransformS( hm.XOrigin,
473  xml->scales ),
474  nonlinear_transform->TransformT( zmax, xml->scalet ) );
475  Norm0 = ( nonlinear_transform->TransformNormal( v[2].GetConstVertex(), Vector( 0, 1, 0 ) ) );
476  v[2].SetNormal( Vector( Norm0.i*Scales.i, Norm0.j*Scales.j, Norm0.k*Scales.k ) );
477 
478  v[3].SetVertex( nonlinear_transform->Transform( Vector( xmax, 0, zmax ) ) );
479  v[3].SetTexCoord( nonlinear_transform->TransformS( zmax,
480  xml->scales ),
481  nonlinear_transform->TransformT( zmax, xml->scalet ) );
482  Norm0 = ( nonlinear_transform->TransformNormal( v[3].GetConstVertex(), Vector( 0, 1, 0 ) ) );
483  v[3].SetNormal( Vector( Norm0.i*Scales.i, Norm0.j*Scales.j, Norm0.k*Scales.k ) );
484  vertices.EndMutate();
485  quadsquare::SetCurrentTerrain( &VertexAllocated,
486  &VertexCount,
487  &vertices,
488  &unusedvertices,
489  nonlinear_transform,
490  &textures,
491  Vector( 1.0F/Scales.i, 1.0F/Scales.j, 1.0F/Scales.k ),
492  neighbors );
493  root = new quadsquare( &RootCornerData );
494  }
495  root->AddHeightMap( RootCornerData, hm );
496  free( hm.Data );
497  free( hm.terrainmap );
498  }
499  }
500  if (biggest) {
501  quadsquare::SetCurrentTerrain( &VertexAllocated,
502  &VertexCount,
503  &vertices,
504  &unusedvertices,
505  nonlinear_transform,
506  &textures,
507  Vector( 1.0F/Scales.i, 1.0F/Scales.j, 1.0F/Scales.k ),
508  neighbors );
509  root = new quadsquare( &RootCornerData );
510  }
511  //root->StaticCullData (RootCornerData,xml->detail);
512  delete xml;
513 }
514