00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <simgear_config.h>
00027 #endif
00028
00029 #include <simgear/compiler.h>
00030 #include <simgear/debug/logstream.hxx>
00031
00032 #include <stdio.h>
00033 #include <time.h>
00034
00035 #include <vector>
00036 #include <string>
00037 #include <iostream>
00038
00039 #include <simgear/bucket/newbucket.hxx>
00040 #include <simgear/misc/sg_path.hxx>
00041
00042 #include "lowlevel.hxx"
00043 #include "sg_binobj.hxx"
00044
00045
00046 using std::string;
00047 using std::vector;
00048 using std::cout;
00049 using std::endl;
00050
00051 enum sgObjectTypes {
00052 SG_BOUNDING_SPHERE = 0,
00053
00054 SG_VERTEX_LIST = 1,
00055 SG_COLOR_LIST = 4,
00056 SG_NORMAL_LIST = 2,
00057 SG_TEXCOORD_LIST = 3,
00058
00059 SG_POINTS = 9,
00060
00061 SG_TRIANGLE_FACES = 10,
00062 SG_TRIANGLE_STRIPS = 11,
00063 SG_TRIANGLE_FANS = 12
00064 };
00065
00066 enum sgIndexTypes {
00067 SG_IDX_VERTICES = 0x01,
00068 SG_IDX_NORMALS = 0x02,
00069 SG_IDX_COLORS = 0x04,
00070 SG_IDX_TEXCOORDS = 0x08
00071 };
00072
00073 enum sgPropertyTypes {
00074 SG_MATERIAL = 0,
00075 SG_INDEX_TYPES = 1
00076 };
00077
00078
00079 class sgSimpleBuffer {
00080
00081 private:
00082
00083 char *ptr;
00084 unsigned int size;
00085
00086 public:
00087
00088 inline sgSimpleBuffer( unsigned int s )
00089 {
00090 size = 1;
00091 while ( size < s ) {
00092 size *= 2;
00093 }
00094 SG_LOG(SG_EVENT, SG_DEBUG, "Creating a new buffer of size = " << size);
00095 ptr = new char[size];
00096 }
00097
00098 inline ~sgSimpleBuffer() {
00099 delete [] ptr;
00100 }
00101
00102 inline unsigned int get_size() const { return size; }
00103 inline char *get_ptr() const { return ptr; }
00104 inline void resize( unsigned int s ) {
00105 if ( s > size ) {
00106 if ( ptr != NULL ) {
00107 delete [] ptr;
00108 }
00109 while ( size < s ) {
00110 size *= 2;
00111 }
00112 SG_LOG(SG_EVENT, SG_DEBUG, "resizing buffer to size = " << size);
00113 ptr = new char[size];
00114 }
00115 }
00116 };
00117
00118
00119
00120
00121 Point3D sgCalcCenter( point_list& wgs84_nodes ) {
00122 Point3D p, min, max;
00123
00124 if ( wgs84_nodes.size() ) {
00125 min = max = wgs84_nodes[0];
00126 } else {
00127 min = max = Point3D( 0 );
00128 }
00129
00130 for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) {
00131 p = wgs84_nodes[i];
00132
00133 if ( p.x() < min.x() ) { min.setx( p.x() ); }
00134 if ( p.y() < min.y() ) { min.sety( p.y() ); }
00135 if ( p.z() < min.z() ) { min.setz( p.z() ); }
00136
00137 if ( p.x() > max.x() ) { max.setx( p.x() ); }
00138 if ( p.y() > max.y() ) { max.sety( p.y() ); }
00139 if ( p.z() > max.z() ) { max.setz( p.z() ); }
00140 }
00141
00142 return ( min + max ) / 2.0;
00143 }
00144
00145
00146
00147 double sgCalcBoundingRadius( Point3D center, point_list& wgs84_nodes ) {
00148 double dist_squared;
00149 double radius_squared = 0;
00150
00151 for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) {
00152 dist_squared = center.distance3Dsquared( wgs84_nodes[i] );
00153 if ( dist_squared > radius_squared ) {
00154 radius_squared = dist_squared;
00155 }
00156 }
00157
00158 return sqrt(radius_squared);
00159 }
00160
00161
00162
00163
00164 static void read_object( gzFile fp,
00165 int obj_type,
00166 int nproperties,
00167 int nelements,
00168 group_list *vertices,
00169 group_list *normals,
00170 group_list *colors,
00171 group_list *texcoords,
00172 string_list *materials )
00173 {
00174 unsigned int nbytes;
00175 unsigned char idx_mask;
00176 int idx_size;
00177 bool do_vertices, do_normals, do_colors, do_texcoords;
00178 int j, k, idx;
00179 sgSimpleBuffer buf( 32768 );
00180 char material[256];
00181
00182
00183 if ( obj_type == SG_POINTS ) {
00184 idx_size = 1;
00185 idx_mask = SG_IDX_VERTICES;
00186 do_vertices = true;
00187 do_normals = false;
00188 do_colors = false;
00189 do_texcoords = false;
00190 } else {
00191 idx_size = 2;
00192 idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS);
00193 do_vertices = true;
00194 do_normals = false;
00195 do_colors = false;
00196 do_texcoords = true;
00197 }
00198
00199 for ( j = 0; j < nproperties; ++j ) {
00200 char prop_type;
00201 sgReadChar( fp, &prop_type );
00202
00203 sgReadUInt( fp, &nbytes );
00204
00205 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00206 char *ptr = buf.get_ptr();
00207 sgReadBytes( fp, nbytes, ptr );
00208 if ( prop_type == SG_MATERIAL ) {
00209 strncpy( material, ptr, nbytes );
00210 material[nbytes] = '\0';
00211
00212 } else if ( prop_type == SG_INDEX_TYPES ) {
00213 idx_mask = ptr[0];
00214
00215 idx_size = 0;
00216 do_vertices = false;
00217 do_normals = false;
00218 do_colors = false;
00219 do_texcoords = false;
00220 if ( idx_mask & SG_IDX_VERTICES ) {
00221 do_vertices = true;
00222 ++idx_size;
00223 }
00224 if ( idx_mask & SG_IDX_NORMALS ) {
00225 do_normals = true;
00226 ++idx_size;
00227 }
00228 if ( idx_mask & SG_IDX_COLORS ) {
00229 do_colors = true;
00230 ++idx_size;
00231 }
00232 if ( idx_mask & SG_IDX_TEXCOORDS ) {
00233 do_texcoords = true;
00234 ++idx_size;
00235 }
00236 }
00237 }
00238
00239 for ( j = 0; j < nelements; ++j ) {
00240 sgReadUInt( fp, &nbytes );
00241
00242 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00243 char *ptr = buf.get_ptr();
00244 sgReadBytes( fp, nbytes, ptr );
00245 int count = nbytes / (idx_size * sizeof(unsigned short));
00246 unsigned short *sptr = (unsigned short *)ptr;
00247 int_list vs; vs.clear();
00248 int_list ns; ns.clear();
00249 int_list cs; cs.clear();
00250 int_list tcs; tcs.clear();
00251 for ( k = 0; k < count; ++k ) {
00252 if ( sgIsBigEndian() ) {
00253 for ( idx = 0; idx < idx_size; ++idx ) {
00254 sgEndianSwap( (uint16_t *)&(sptr[idx]) );
00255 }
00256 }
00257 idx = 0;
00258 if ( do_vertices ) {
00259 vs.push_back( sptr[idx++] );
00260 }
00261 if ( do_normals ) {
00262 ns.push_back( sptr[idx++] );
00263 }
00264 if ( do_colors ) {
00265 cs.push_back( sptr[idx++] );
00266 }
00267 if ( do_texcoords ) {
00268 tcs.push_back( sptr[idx++] );
00269 }
00270
00271 sptr += idx_size;
00272 }
00273
00274 vertices->push_back( vs );
00275 normals->push_back( ns );
00276 colors->push_back( cs );
00277 texcoords->push_back( tcs );
00278 materials->push_back( material );
00279 }
00280 }
00281
00282
00283
00284 bool SGBinObject::read_bin( const string& file ) {
00285 SGVec3d p;
00286 int i, j, k;
00287 unsigned int nbytes;
00288 sgSimpleBuffer buf( 32768 );
00289
00290
00291 gbs_center = SGVec3d(0, 0, 0);
00292 gbs_radius = 0.0;
00293
00294 wgs84_nodes.clear();
00295 normals.clear();
00296 texcoords.clear();
00297
00298 pts_v.clear();
00299 pts_n.clear();
00300 pts_c.clear();
00301 pts_tc.clear();
00302 pt_materials.clear();
00303
00304 tris_v.clear();
00305 tris_n.clear();
00306 tris_c.clear();
00307 tris_tc.clear();
00308 tri_materials.clear();
00309
00310 strips_v.clear();
00311 strips_n.clear();
00312 strips_c.clear();
00313 strips_tc.clear();
00314 strip_materials.clear();
00315
00316 fans_v.clear();
00317 fans_n.clear();
00318 fans_c.clear();
00319 fans_tc.clear();
00320 fan_materials.clear();
00321
00322 gzFile fp;
00323 if ( (fp = gzopen( file.c_str(), "rb" )) == NULL ) {
00324 string filegz = file + ".gz";
00325 if ( (fp = gzopen( filegz.c_str(), "rb" )) == NULL ) {
00326 SG_LOG( SG_EVENT, SG_ALERT,
00327 "ERROR: opening " << file << " or " << filegz << " for reading!");
00328
00329 return false;
00330 }
00331 }
00332
00333 sgClearReadError();
00334
00335
00336 unsigned int header;
00337 sgReadUInt( fp, &header );
00338 if ( ((header & 0xFF000000) >> 24) == 'S' &&
00339 ((header & 0x00FF0000) >> 16) == 'G' ) {
00340
00341
00342 version = (header & 0x0000FFFF);
00343
00344 } else {
00345
00346 gzclose(fp);
00347
00348 return false;
00349 }
00350
00351
00352 unsigned int foo_calendar_time;
00353 sgReadUInt( fp, &foo_calendar_time );
00354
00355 #if 0
00356 time_t calendar_time = foo_calendar_time;
00357
00358
00359
00360
00361 struct tm *local_tm;
00362 local_tm = localtime( &calendar_time );
00363 char time_str[256];
00364 strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
00365 SG_LOG( SG_EVENT, SG_DEBUG, "File created on " << time_str);
00366 #endif
00367
00368
00369 unsigned short nobjects;
00370 if ( version >= 7 ) {
00371 sgReadUShort( fp, &nobjects );
00372 } else {
00373 short tmp;
00374 sgReadShort( fp, &tmp );
00375 nobjects = tmp;
00376 }
00377
00378
00379
00380 for ( i = 0; i < nobjects; ++i ) {
00381
00382 char obj_type;
00383 unsigned short nproperties, nelements;
00384 sgReadChar( fp, &obj_type );
00385 if ( version >= 7 ) {
00386 sgReadUShort( fp, &nproperties );
00387 sgReadUShort( fp, &nelements );
00388 } else {
00389 short tmp;
00390 sgReadShort( fp, &tmp );
00391 nproperties = tmp;
00392 sgReadShort( fp, &tmp );
00393 nelements = tmp;
00394 }
00395
00396
00397
00398
00399 if ( obj_type == SG_BOUNDING_SPHERE ) {
00400
00401 for ( j = 0; j < nproperties; ++j ) {
00402 char prop_type;
00403 sgReadChar( fp, &prop_type );
00404
00405 sgReadUInt( fp, &nbytes );
00406
00407 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00408 char *ptr = buf.get_ptr();
00409 sgReadBytes( fp, nbytes, ptr );
00410 }
00411
00412
00413 for ( j = 0; j < nelements; ++j ) {
00414 sgReadUInt( fp, &nbytes );
00415
00416 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00417 char *ptr = buf.get_ptr();
00418 sgReadBytes( fp, nbytes, ptr );
00419
00420 double *dptr = (double *)ptr;
00421 if ( sgIsBigEndian() ) {
00422 sgEndianSwap( (uint64_t *)&(dptr[0]) );
00423 sgEndianSwap( (uint64_t *)&(dptr[1]) );
00424 sgEndianSwap( (uint64_t *)&(dptr[2]) );
00425 }
00426 gbs_center = SGVec3d( dptr[0], dptr[1], dptr[2] );
00427
00428 ptr += sizeof(double) * 3;
00429
00430 float *fptr = (float *)ptr;
00431 if ( sgIsBigEndian() ) {
00432 sgEndianSwap( (uint32_t *)fptr );
00433 }
00434 gbs_radius = fptr[0];
00435
00436 }
00437 } else if ( obj_type == SG_VERTEX_LIST ) {
00438
00439 for ( j = 0; j < nproperties; ++j ) {
00440 char prop_type;
00441 sgReadChar( fp, &prop_type );
00442
00443 sgReadUInt( fp, &nbytes );
00444
00445 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00446 char *ptr = buf.get_ptr();
00447 sgReadBytes( fp, nbytes, ptr );
00448 }
00449
00450
00451 for ( j = 0; j < nelements; ++j ) {
00452 sgReadUInt( fp, &nbytes );
00453
00454 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00455 char *ptr = buf.get_ptr();
00456 sgReadBytes( fp, nbytes, ptr );
00457 int count = nbytes / (sizeof(float) * 3);
00458 float *fptr = (float *)ptr;
00459 wgs84_nodes.reserve( count );
00460 for ( k = 0; k < count; ++k ) {
00461 if ( sgIsBigEndian() ) {
00462 sgEndianSwap( (uint32_t *)&(fptr[0]) );
00463 sgEndianSwap( (uint32_t *)&(fptr[1]) );
00464 sgEndianSwap( (uint32_t *)&(fptr[2]) );
00465 }
00466 wgs84_nodes.push_back( SGVec3d(fptr[0], fptr[1], fptr[2]) );
00467 fptr += 3;
00468 }
00469 }
00470 } else if ( obj_type == SG_COLOR_LIST ) {
00471
00472 for ( j = 0; j < nproperties; ++j ) {
00473 char prop_type;
00474 sgReadChar( fp, &prop_type );
00475
00476 sgReadUInt( fp, &nbytes );
00477
00478 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00479 char *ptr = buf.get_ptr();
00480 sgReadBytes( fp, nbytes, ptr );
00481 }
00482
00483
00484 for ( j = 0; j < nelements; ++j ) {
00485 sgReadUInt( fp, &nbytes );
00486
00487 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00488 char *ptr = buf.get_ptr();
00489 sgReadBytes( fp, nbytes, ptr );
00490 int count = nbytes / (sizeof(float) * 4);
00491 float *fptr = (float *)ptr;
00492 colors.reserve(count);
00493 for ( k = 0; k < count; ++k ) {
00494 if ( sgIsBigEndian() ) {
00495 sgEndianSwap( (uint32_t *)&(fptr[0]) );
00496 sgEndianSwap( (uint32_t *)&(fptr[1]) );
00497 sgEndianSwap( (uint32_t *)&(fptr[2]) );
00498 sgEndianSwap( (uint32_t *)&(fptr[3]) );
00499 }
00500 SGVec4f color( fptr[0], fptr[1], fptr[2], fptr[3] );
00501 colors.push_back( color );
00502 fptr += 4;
00503 }
00504 }
00505 } else if ( obj_type == SG_NORMAL_LIST ) {
00506
00507 for ( j = 0; j < nproperties; ++j ) {
00508 char prop_type;
00509 sgReadChar( fp, &prop_type );
00510
00511 sgReadUInt( fp, &nbytes );
00512
00513 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00514 char *ptr = buf.get_ptr();
00515 sgReadBytes( fp, nbytes, ptr );
00516 }
00517
00518
00519 for ( j = 0; j < nelements; ++j ) {
00520 sgReadUInt( fp, &nbytes );
00521
00522 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00523 unsigned char *ptr = (unsigned char *)(buf.get_ptr());
00524 sgReadBytes( fp, nbytes, ptr );
00525 int count = nbytes / 3;
00526 normals.reserve( count );
00527 for ( k = 0; k < count; ++k ) {
00528 SGVec3f normal((ptr[0]) / 127.5 - 1.0,
00529 (ptr[1]) / 127.5 - 1.0,
00530 (ptr[2]) / 127.5 - 1.0);
00531
00532 normals.push_back(normalize(normal));
00533 ptr += 3;
00534 }
00535 }
00536 } else if ( obj_type == SG_TEXCOORD_LIST ) {
00537
00538 for ( j = 0; j < nproperties; ++j ) {
00539 char prop_type;
00540 sgReadChar( fp, &prop_type );
00541
00542 sgReadUInt( fp, &nbytes );
00543
00544 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00545 char *ptr = buf.get_ptr();
00546 sgReadBytes( fp, nbytes, ptr );
00547 }
00548
00549
00550 for ( j = 0; j < nelements; ++j ) {
00551 sgReadUInt( fp, &nbytes );
00552
00553 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00554 char *ptr = buf.get_ptr();
00555 sgReadBytes( fp, nbytes, ptr );
00556 int count = nbytes / (sizeof(float) * 2);
00557 float *fptr = (float *)ptr;
00558 texcoords.reserve(count);
00559 for ( k = 0; k < count; ++k ) {
00560 if ( sgIsBigEndian() ) {
00561 sgEndianSwap( (uint32_t *)&(fptr[0]) );
00562 sgEndianSwap( (uint32_t *)&(fptr[1]) );
00563 }
00564 texcoords.push_back( SGVec2f( fptr[0], fptr[1] ) );
00565 fptr += 2;
00566 }
00567 }
00568 } else if ( obj_type == SG_POINTS ) {
00569
00570 read_object( fp, SG_POINTS, nproperties, nelements,
00571 &pts_v, &pts_n, &pts_c, &pts_tc, &pt_materials );
00572 } else if ( obj_type == SG_TRIANGLE_FACES ) {
00573
00574 read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
00575 &tris_v, &tris_n, &tris_c, &tris_tc, &tri_materials );
00576 } else if ( obj_type == SG_TRIANGLE_STRIPS ) {
00577
00578 read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
00579 &strips_v, &strips_n, &strips_c, &strips_tc,
00580 &strip_materials );
00581 } else if ( obj_type == SG_TRIANGLE_FANS ) {
00582
00583 read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
00584 &fans_v, &fans_n, &fans_c, &fans_tc, &fan_materials );
00585 } else {
00586
00587
00588
00589 for ( j = 0; j < nproperties; ++j ) {
00590 char prop_type;
00591 sgReadChar( fp, &prop_type );
00592
00593 sgReadUInt( fp, &nbytes );
00594
00595 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00596 char *ptr = buf.get_ptr();
00597 sgReadBytes( fp, nbytes, ptr );
00598 }
00599
00600
00601 for ( j = 0; j < nelements; ++j ) {
00602 sgReadUInt( fp, &nbytes );
00603
00604 if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
00605 char *ptr = buf.get_ptr();
00606 sgReadBytes( fp, nbytes, ptr );
00607 }
00608 }
00609 }
00610
00611
00612 gzclose(fp);
00613
00614 if ( sgReadError() ) {
00615 cout << "We detected an error while reading the file." << endl;
00616 return false;
00617 }
00618
00619 return true;
00620 }
00621
00622
00623
00624
00625
00626 bool SGBinObject::write_bin( const string& base, const string& name,
00627 const SGBucket& b )
00628 {
00629 int i, j;
00630 unsigned char idx_mask;
00631 int idx_size;
00632
00633 SGPath file = base + "/" + b.gen_base_path() + "/" + name + ".gz";
00634 file.create_dir( 0755 );
00635 cout << "Output file = " << file.str() << endl;
00636
00637 gzFile fp;
00638 if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
00639 cout << "ERROR: opening " << file.str() << " for writing!" << endl;
00640 return false;
00641 }
00642
00643 sgClearWriteError();
00644
00645 cout << "points size = " << pts_v.size() << " pt_materials = "
00646 << pt_materials.size() << endl;
00647 cout << "triangles size = " << tris_v.size() << " tri_materials = "
00648 << tri_materials.size() << endl;
00649 cout << "strips size = " << strips_v.size() << " strip_materials = "
00650 << strip_materials.size() << endl;
00651 cout << "fans size = " << fans_v.size() << " fan_materials = "
00652 << fan_materials.size() << endl;
00653
00654 cout << "nodes = " << wgs84_nodes.size() << endl;
00655 cout << "colors = " << colors.size() << endl;
00656 cout << "normals = " << normals.size() << endl;
00657 cout << "tex coords = " << texcoords.size() << endl;
00658
00659
00660 sgWriteUInt( fp, SG_FILE_MAGIC_NUMBER );
00661 time_t calendar_time = time(NULL);
00662 sgWriteLong( fp, (int32_t)calendar_time );
00663
00664
00665 string material;
00666 int start;
00667 int end;
00668 unsigned short nobjects = 0;
00669 nobjects++;
00670 nobjects++;
00671 nobjects++;
00672 nobjects++;
00673 nobjects++;
00674
00675
00676 unsigned short npts = 0;
00677 start = 0; end = 1;
00678 while ( start < (int)pt_materials.size() ) {
00679 material = pt_materials[start];
00680 while ( (end < (int)pt_materials.size()) &&
00681 (material == pt_materials[end]) ) {
00682 end++;
00683 }
00684 npts++;
00685 start = end; end = start + 1;
00686 }
00687 nobjects += npts;
00688
00689
00690 unsigned short ntris = 0;
00691 start = 0; end = 1;
00692 while ( start < (int)tri_materials.size() ) {
00693 material = tri_materials[start];
00694 while ( (end < (int)tri_materials.size()) &&
00695 (material == tri_materials[end]) ) {
00696 end++;
00697 }
00698 ntris++;
00699 start = end; end = start + 1;
00700 }
00701 nobjects += ntris;
00702
00703
00704 unsigned short nstrips = 0;
00705 start = 0; end = 1;
00706 while ( start < (int)strip_materials.size() ) {
00707 material = strip_materials[start];
00708 while ( (end < (int)strip_materials.size()) &&
00709 (material == strip_materials[end]) ) {
00710 end++;
00711 }
00712 nstrips++;
00713 start = end; end = start + 1;
00714 }
00715 nobjects += nstrips;
00716
00717
00718 unsigned short nfans = 0;
00719 start = 0; end = 1;
00720 while ( start < (int)fan_materials.size() ) {
00721 material = fan_materials[start];
00722 while ( (end < (int)fan_materials.size()) &&
00723 (material == fan_materials[end]) ) {
00724 end++;
00725 }
00726 nfans++;
00727 start = end; end = start + 1;
00728 }
00729 nobjects += nfans;
00730
00731 cout << "total top level objects = " << nobjects << endl;
00732 sgWriteUShort( fp, nobjects );
00733
00734
00735 sgWriteChar( fp, (char)SG_BOUNDING_SPHERE );
00736 sgWriteUShort( fp, 0 );
00737 sgWriteUShort( fp, 1 );
00738
00739 sgWriteUInt( fp, sizeof(double) * 3 + sizeof(float) );
00740 sgdVec3 center;
00741 sgdSetVec3( center, gbs_center.x(), gbs_center.y(), gbs_center.z() );
00742 sgWritedVec3( fp, center );
00743 sgWriteFloat( fp, gbs_radius );
00744
00745
00746 sgWriteChar( fp, (char)SG_VERTEX_LIST );
00747 sgWriteUShort( fp, 0 );
00748 sgWriteUShort( fp, 1 );
00749 sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 );
00750 for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
00751 SGVec3f p = toVec3f(wgs84_nodes[i] - gbs_center);
00752 sgWriteVec3( fp, p.data() );
00753 }
00754
00755
00756 sgWriteChar( fp, (char)SG_COLOR_LIST );
00757 sgWriteUShort( fp, 0 );
00758 sgWriteUShort( fp, 1 );
00759 sgWriteUInt( fp, colors.size() * sizeof(float) * 4 );
00760 for ( i = 0; i < (int)colors.size(); ++i ) {
00761 sgWriteVec4( fp, colors[i].data() );
00762 }
00763
00764
00765 sgWriteChar( fp, (char)SG_NORMAL_LIST );
00766 sgWriteUShort( fp, 0 );
00767 sgWriteUShort( fp, 1 );
00768 sgWriteUInt( fp, normals.size() * 3 );
00769 char normal[3];
00770 for ( i = 0; i < (int)normals.size(); ++i ) {
00771 SGVec3f p = normals[i];
00772 normal[0] = (unsigned char)((p.x() + 1.0) * 127.5);
00773 normal[1] = (unsigned char)((p.y() + 1.0) * 127.5);
00774 normal[2] = (unsigned char)((p.z() + 1.0) * 127.5);
00775 sgWriteBytes( fp, 3, normal );
00776 }
00777
00778
00779 sgWriteChar( fp, (char)SG_TEXCOORD_LIST );
00780 sgWriteUShort( fp, 0 );
00781 sgWriteUShort( fp, 1 );
00782 sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 );
00783 for ( i = 0; i < (int)texcoords.size(); ++i ) {
00784 sgWriteVec2( fp, texcoords[i].data() );
00785 }
00786
00787
00788 if ( pts_v.size() > 0 ) {
00789 int start = 0;
00790 int end = 1;
00791 string material;
00792 while ( start < (int)pt_materials.size() ) {
00793
00794 material = pt_materials[start];
00795 while ( (end < (int)pt_materials.size()) &&
00796 (material == pt_materials[end]) )
00797 {
00798
00799 end++;
00800 }
00801
00802
00803
00804 sgWriteChar( fp, (char)SG_POINTS );
00805 sgWriteUShort( fp, 2 );
00806 sgWriteUShort( fp, end - start );
00807
00808 sgWriteChar( fp, (char)SG_MATERIAL );
00809 sgWriteUInt( fp, material.length() );
00810 sgWriteBytes( fp, material.length(), material.c_str() );
00811
00812 idx_mask = 0;
00813 idx_size = 0;
00814 if ( pts_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
00815 if ( pts_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
00816 if ( pts_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
00817 if ( pts_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
00818 sgWriteChar( fp, (char)SG_INDEX_TYPES );
00819 sgWriteUInt( fp, 1 );
00820 sgWriteChar( fp, idx_mask );
00821
00822
00823 for ( i = start; i < end; ++i ) {
00824
00825 sgWriteUInt( fp, pts_v[i].size() * idx_size
00826 * sizeof(unsigned short) );
00827 for ( j = 0; j < (int)pts_v[i].size(); ++j ) {
00828 if ( pts_v.size() ) {
00829 sgWriteUShort( fp, (unsigned short)pts_v[i][j] );
00830 }
00831 if ( pts_n.size() ) {
00832 sgWriteUShort( fp, (unsigned short)pts_n[i][j] );
00833 }
00834 if ( pts_c.size() ) {
00835 sgWriteUShort( fp, (unsigned short)pts_c[i][j] );
00836 }
00837 if ( pts_tc.size() ) {
00838 sgWriteUShort( fp, (unsigned short)pts_tc[i][j] );
00839 }
00840 }
00841 }
00842
00843 start = end;
00844 end = start + 1;
00845 }
00846 }
00847
00848
00849 if ( tris_v.size() > 0 ) {
00850 int start = 0;
00851 int end = 1;
00852 string material;
00853 while ( start < (int)tri_materials.size() ) {
00854
00855 material = tri_materials[start];
00856 while ( (end < (int)tri_materials.size()) &&
00857 (material == tri_materials[end]) &&
00858 3*(end-start) < 32760 )
00859 {
00860
00861 end++;
00862 }
00863
00864
00865
00866 sgWriteChar( fp, (char)SG_TRIANGLE_FACES );
00867 sgWriteUShort( fp, 2 );
00868 sgWriteUShort( fp, 1 );
00869
00870 sgWriteChar( fp, (char)SG_MATERIAL );
00871 sgWriteUInt( fp, material.length() );
00872 sgWriteBytes( fp, material.length(), material.c_str() );
00873
00874 idx_mask = 0;
00875 idx_size = 0;
00876 if ( tris_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
00877 if ( tris_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
00878 if ( tris_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
00879 if ( tris_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
00880 sgWriteChar( fp, (char)SG_INDEX_TYPES );
00881 sgWriteUInt( fp, 1 );
00882 sgWriteChar( fp, idx_mask );
00883
00884
00885 sgWriteUInt( fp, (end - start) * 3 * idx_size
00886 * sizeof(unsigned short) );
00887
00888
00889 for ( i = start; i < end; ++i ) {
00890 for ( j = 0; j < 3; ++j ) {
00891 if ( tris_v.size() ) {
00892 sgWriteUShort( fp, (unsigned short)tris_v[i][j] );
00893 }
00894 if ( tris_n.size() ) {
00895 sgWriteUShort( fp, (unsigned short)tris_n[i][j] );
00896 }
00897 if ( tris_c.size() ) {
00898 sgWriteUShort( fp, (unsigned short)tris_c[i][j] );
00899 }
00900 if ( tris_tc.size() ) {
00901 sgWriteUShort( fp, (unsigned short)tris_tc[i][j] );
00902 }
00903 }
00904 }
00905
00906 start = end;
00907 end = start + 1;
00908 }
00909 }
00910
00911
00912 if ( strips_v.size() > 0 ) {
00913 int start = 0;
00914 int end = 1;
00915 string material;
00916 while ( start < (int)strip_materials.size() ) {
00917
00918 material = strip_materials[start];
00919 while ( (end < (int)strip_materials.size()) &&
00920 (material == strip_materials[end]) )
00921 {
00922
00923 end++;
00924 }
00925
00926
00927
00928 sgWriteChar( fp, (char)SG_TRIANGLE_STRIPS );
00929 sgWriteUShort( fp, 2 );
00930 sgWriteUShort( fp, end - start );
00931
00932 sgWriteChar( fp, (char)SG_MATERIAL );
00933 sgWriteUInt( fp, material.length() );
00934 sgWriteBytes( fp, material.length(), material.c_str() );
00935
00936 idx_mask = 0;
00937 idx_size = 0;
00938 if ( strips_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
00939 if ( strips_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
00940 if ( strips_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
00941 if ( strips_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size;}
00942 sgWriteChar( fp, (char)SG_INDEX_TYPES );
00943 sgWriteUInt( fp, 1 );
00944 sgWriteChar( fp, idx_mask );
00945
00946
00947 for ( i = start; i < end; ++i ) {
00948
00949 sgWriteUInt( fp, strips_v[i].size() * idx_size
00950 * sizeof(unsigned short));
00951 for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
00952 if ( strips_v.size() ) {
00953 sgWriteUShort( fp, (unsigned short)strips_v[i][j] );
00954 }
00955 if ( strips_n.size() ) {
00956 sgWriteUShort( fp, (unsigned short)strips_n[i][j] );
00957 }
00958 if ( strips_c.size() ) {
00959 sgWriteUShort( fp, (unsigned short)strips_c[i][j] );
00960 }
00961 if ( strips_tc.size() ) {
00962 sgWriteUShort( fp, (unsigned short)strips_tc[i][j] );
00963 }
00964 }
00965 }
00966
00967 start = end;
00968 end = start + 1;
00969 }
00970 }
00971
00972
00973 if ( fans_v.size() > 0 ) {
00974 int start = 0;
00975 int end = 1;
00976 string material;
00977 while ( start < (int)fan_materials.size() ) {
00978
00979 material = fan_materials[start];
00980 while ( (end < (int)fan_materials.size()) &&
00981 (material == fan_materials[end]) )
00982 {
00983
00984 end++;
00985 }
00986
00987
00988
00989 sgWriteChar( fp, (char)SG_TRIANGLE_FANS );
00990 sgWriteUShort( fp, 2 );
00991 sgWriteUShort( fp, end - start );
00992
00993 sgWriteChar( fp, (char)SG_MATERIAL );
00994 sgWriteUInt( fp, material.length() );
00995 sgWriteBytes( fp, material.length(), material.c_str() );
00996
00997 idx_mask = 0;
00998 idx_size = 0;
00999 if ( fans_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
01000 if ( fans_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
01001 if ( fans_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
01002 if ( fans_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
01003 sgWriteChar( fp, (char)SG_INDEX_TYPES );
01004 sgWriteUInt( fp, 1 );
01005 sgWriteChar( fp, idx_mask );
01006
01007
01008 for ( i = start; i < end; ++i ) {
01009
01010 sgWriteUInt( fp, fans_v[i].size() * idx_size
01011 * sizeof(unsigned short) );
01012 for ( j = 0; j < (int)fans_v[i].size(); ++j ) {
01013 if ( fans_v.size() ) {
01014 sgWriteUShort( fp, (unsigned short)fans_v[i][j] );
01015 }
01016 if ( fans_n.size() ) {
01017 sgWriteUShort( fp, (unsigned short)fans_n[i][j] );
01018 }
01019 if ( fans_c.size() ) {
01020 sgWriteUShort( fp, (unsigned short)fans_c[i][j] );
01021 }
01022 if ( fans_tc.size() ) {
01023 sgWriteUShort( fp, (unsigned short)fans_tc[i][j] );
01024 }
01025 }
01026 }
01027
01028 start = end;
01029 end = start + 1;
01030 }
01031 }
01032
01033
01034 gzclose(fp);
01035
01036 if ( sgWriteError() ) {
01037 cout << "We detected an error while writing the file." << endl;
01038 return false;
01039 }
01040
01041 return true;
01042 }
01043
01044
01045
01046
01047
01048 bool SGBinObject::write_ascii( const string& base, const string& name,
01049 const SGBucket& b )
01050 {
01051 int i, j;
01052
01053 SGPath file = base + "/" + b.gen_base_path() + "/" + name;
01054 file.create_dir( 0755 );
01055 cout << "Output file = " << file.str() << endl;
01056
01057 FILE *fp;
01058 if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
01059 cout << "ERROR: opening " << file.str() << " for writing!" << endl;
01060 return false;
01061 }
01062
01063 cout << "triangles size = " << tris_v.size() << " tri_materials = "
01064 << tri_materials.size() << endl;
01065 cout << "strips size = " << strips_v.size() << " strip_materials = "
01066 << strip_materials.size() << endl;
01067 cout << "fans size = " << fans_v.size() << " fan_materials = "
01068 << fan_materials.size() << endl;
01069
01070 cout << "points = " << wgs84_nodes.size() << endl;
01071 cout << "tex coords = " << texcoords.size() << endl;
01072
01073 fprintf(fp, "# FGFS Scenery\n");
01074 fprintf(fp, "# Version %s\n", SG_SCENERY_FILE_FORMAT);
01075
01076 time_t calendar_time = time(NULL);
01077 struct tm *local_tm;
01078 local_tm = localtime( &calendar_time );
01079 char time_str[256];
01080 strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm);
01081 fprintf(fp, "# Created %s\n", time_str );
01082 fprintf(fp, "\n");
01083
01084
01085 fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
01086 gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
01087 fprintf(fp, "\n");
01088
01089
01090 fprintf(fp, "# vertex list\n");
01091 for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
01092 SGVec3d p = wgs84_nodes[i] - gbs_center;
01093
01094 fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
01095 }
01096 fprintf(fp, "\n");
01097
01098 fprintf(fp, "# vertex normal list\n");
01099 for ( i = 0; i < (int)normals.size(); ++i ) {
01100 SGVec3f p = normals[i];
01101 fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
01102 }
01103 fprintf(fp, "\n");
01104
01105
01106 fprintf(fp, "# texture coordinate list\n");
01107 for ( i = 0; i < (int)texcoords.size(); ++i ) {
01108 SGVec2f p = texcoords[i];
01109 fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() );
01110 }
01111 fprintf(fp, "\n");
01112
01113
01114 if ( tris_v.size() > 0 ) {
01115 fprintf(fp, "# triangle groups\n");
01116
01117 int start = 0;
01118 int end = 1;
01119 string material;
01120 while ( start < (int)tri_materials.size() ) {
01121
01122 material = tri_materials[start];
01123 while ( (end < (int)tri_materials.size()) &&
01124 (material == tri_materials[end]) )
01125 {
01126
01127 end++;
01128 }
01129
01130
01131
01132 point_list group_nodes;
01133 group_nodes.clear();
01134 SGVec3d bs_center;
01135 double bs_radius = 0;
01136 for ( i = start; i < end; ++i ) {
01137 for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
01138 group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ tris_v[i][j] ]) );
01139 bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
01140 bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
01141 }
01142 }
01143
01144
01145 fprintf(fp, "\n");
01146 fprintf(fp, "# usemtl %s\n", material.c_str());
01147 fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
01148 bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
01149
01150
01151 for ( i = start; i < end; ++i ) {
01152 fprintf(fp, "f");
01153 for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
01154 fprintf(fp, " %d/%d", tris_v[i][j], tris_tc[i][j] );
01155 }
01156 fprintf(fp, "\n");
01157 }
01158
01159 start = end;
01160 end = start + 1;
01161 }
01162 }
01163
01164
01165 if ( strips_v.size() > 0 ) {
01166 fprintf(fp, "# triangle strips\n");
01167
01168 int start = 0;
01169 int end = 1;
01170 string material;
01171 while ( start < (int)strip_materials.size() ) {
01172
01173 material = strip_materials[start];
01174 while ( (end < (int)strip_materials.size()) &&
01175 (material == strip_materials[end]) )
01176 {
01177
01178 end++;
01179 }
01180
01181
01182
01183 point_list group_nodes;
01184 group_nodes.clear();
01185 SGVec3d bs_center;
01186 double bs_radius = 0;
01187 for ( i = start; i < end; ++i ) {
01188 for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
01189 group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ strips_v[i][j] ]) );
01190 bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
01191 bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
01192 }
01193 }
01194
01195
01196 fprintf(fp, "\n");
01197 fprintf(fp, "# usemtl %s\n", material.c_str());
01198 fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
01199 bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
01200
01201
01202 for ( i = start; i < end; ++i ) {
01203 fprintf(fp, "ts");
01204 for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
01205 fprintf(fp, " %d/%d", strips_v[i][j], strips_tc[i][j] );
01206 }
01207 fprintf(fp, "\n");
01208 }
01209
01210 start = end;
01211 end = start + 1;
01212 }
01213 }
01214
01215
01216 fclose(fp);
01217
01218 string command = "gzip --force --best " + file.str();
01219 system(command.c_str());
01220
01221 return true;
01222 }