head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.39; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.56; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.03; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.22.00; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# sg_binobj.cxx

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

@ 1.3 log @Oops, try again. @ text @d1240 1 a1240 1