- // read object header
- char obj_type;
- short nproperties, nelements;
- sgReadChar( fp, &obj_type );
- sgReadShort( fp, &nproperties );
- sgReadShort( fp, &nelements );
-
- // cout << "object " << i << " = " << (int)obj_type << " props = "
- // << nproperties << " elements = " << nelements << endl;
-
- if ( obj_type == SG_BOUNDING_SPHERE ) {
- // read bounding sphere properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
-
- // read bounding sphere elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
-
- double *dptr = (double *)ptr;
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned long long *)&(dptr[0]) );
- sgEndianSwap( (unsigned long long *)&(dptr[1]) );
- sgEndianSwap( (unsigned long long *)&(dptr[2]) );
- }
- gbs_center = Point3D( dptr[0], dptr[1], dptr[2] );
- // cout << "Center = " << gbs_center << endl;
- ptr += sizeof(double) * 3;
-
- float *fptr = (float *)ptr;
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned int *)fptr );
- }
- gbs_radius = fptr[0];
- // cout << "Bounding radius = " << gbs_radius << endl;
- }
- } else if ( obj_type == SG_VERTEX_LIST ) {
- // read vertex list properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
-
- // read vertex list elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / (sizeof(float) * 3);
- float *fptr = (float *)ptr;
- for ( k = 0; k < count; ++k ) {
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned int *)&(fptr[0]) );
- sgEndianSwap( (unsigned int *)&(fptr[1]) );
- sgEndianSwap( (unsigned int *)&(fptr[2]) );
- }
- p = Point3D( fptr[0], fptr[1], fptr[2] );
- // cout << "node = " << p << endl;
- wgs84_nodes.push_back( p );
- fptr += 3;
- }
- }
- } else if ( obj_type == SG_NORMAL_LIST ) {
- // read normal list properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
-
- // read normal list elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- unsigned char *ptr = (unsigned char *)(buf.get_ptr());
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / 3;
- for ( k = 0; k < count; ++k ) {
- p = Point3D( ptr[0] / 128.0 - 1.0,
- ptr[1] / 128.0 - 1.0,
- ptr[2] / 128.0 - 1.0 );
- // cout << "normal = " << p << endl;
- normals.push_back( p );
- ptr += 3;
- }
- }
- } else if ( obj_type == SG_TEXCOORD_LIST ) {
- // read texcoord list properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
-
- // read texcoord list elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / (sizeof(float) * 2);
- float *fptr = (float *)ptr;
- for ( k = 0; k < count; ++k ) {
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned int *)&(fptr[0]) );
- sgEndianSwap( (unsigned int *)&(fptr[1]) );
- }
- p = Point3D( fptr[0], fptr[1], 0 );
- // cout << "texcoord = " << p << endl;
- texcoords.push_back( p );
- fptr += 2;
- }
- }
- } else if ( obj_type == SG_TRIANGLE_FACES ) {
- // read triangle face properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- if ( prop_type == SG_MATERIAL ) {
- strncpy( material, ptr, nbytes );
- material[nbytes] = '\0';
- // cout << "material type = " << material << endl;
- }
- }
-
- // read triangle face elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / (sizeof(short) * 2);
- short *sptr = (short *)ptr;
- int_list vs, tcs;
- vs.clear(); tcs.clear();
- for ( k = 0; k < count; ++k ) {
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned short *)&(sptr[0]) );
- sgEndianSwap( (unsigned short *)&(sptr[1]) );
- }
- vs.push_back( sptr[0] );
- tcs.push_back( sptr[1] );
- // cout << sptr[0] << "/" << sptr[1] << " ";
- sptr += 2;
- }
- // cout << endl;
- tris_v.push_back( vs );
- tris_tc.push_back( tcs );
- tri_materials.push_back( material );
- }
- } else if ( obj_type == SG_TRIANGLE_STRIPS ) {
- // read triangle strip properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- if ( prop_type == SG_MATERIAL ) {
- strncpy( material, ptr, nbytes );
- material[nbytes] = '\0';
- // cout << "material type = " << material << endl;
- }
- }
-
- // read triangle strip elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / (sizeof(short) * 2);
- short *sptr = (short *)ptr;
- int_list vs, tcs;
- vs.clear(); tcs.clear();
- for ( k = 0; k < count; ++k ) {
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned short *)&(sptr[0]) );
- sgEndianSwap( (unsigned short *)&(sptr[1]) );
- }
- vs.push_back( sptr[0] );
- tcs.push_back( sptr[1] );
- // cout << sptr[0] << "/" << sptr[1] << " ";
- sptr += 2;
- }
- // cout << endl;
- strips_v.push_back( vs );
- strips_tc.push_back( tcs );
- strip_materials.push_back( material );
- }
- } else if ( obj_type == SG_TRIANGLE_FANS ) {
- // read triangle fan properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- if ( prop_type == SG_MATERIAL ) {
- strncpy( material, ptr, nbytes );
- material[nbytes] = '\0';
- // cout << "material type = " << material << endl;
- }
- }
-
- // read triangle fan elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- int count = nbytes / (sizeof(short) * 2);
- short *sptr = (short *)ptr;
- int_list vs, tcs;
- vs.clear(); tcs.clear();
- for ( k = 0; k < count; ++k ) {
- if ( sgIsBigEndian() ) {
- sgEndianSwap( (unsigned short *)&(sptr[0]) );
- sgEndianSwap( (unsigned short *)&(sptr[1]) );
- }
- vs.push_back( sptr[0] );
- tcs.push_back( sptr[1] );
- // cout << sptr[0] << "/" << sptr[1] << " ";
- sptr += 2;
- }
- // cout << endl;
- fans_v.push_back( vs );
- fans_tc.push_back( tcs );
- fan_materials.push_back( material );
- }
- } else {
- // unknown object type, just skip
-
- // read properties
- for ( j = 0; j < nproperties; ++j ) {
- char prop_type;
- sgReadChar( fp, &prop_type );
-
- sgReadUInt( fp, &nbytes );
- // cout << "property size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
-
- // read elements
- for ( j = 0; j < nelements; ++j ) {
- sgReadUInt( fp, &nbytes );
- // cout << "element size = " << nbytes << endl;
- if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
- char *ptr = buf.get_ptr();
- sgReadBytes( fp, nbytes, ptr );
- }
- }
+ // read object header
+ char obj_type;
+ uint32_t nproperties, nelements;
+ sgReadChar( fp, &obj_type );
+ if ( version >= 10 ) {
+ sgReadUInt( fp, &nproperties );
+ sgReadUInt( fp, &nelements );
+ } else if ( version >= 7 ) {
+ uint16_t v;
+ sgReadUShort( fp, &v );
+ nproperties = v;
+ sgReadUShort( fp, &v );
+ nelements = v;
+ } else {
+ int16_t v;
+ sgReadShort( fp, &v );
+ nproperties = v;
+ sgReadShort( fp, &v );
+ nelements = v;
+ }
+
+ //cout << "object " << i << " = " << (int)obj_type << " props = "
+ // << nproperties << " elements = " << nelements << endl;
+
+ if ( obj_type == SG_BOUNDING_SPHERE ) {
+ // read bounding sphere properties
+ read_properties( fp, nproperties );
+
+ // read bounding sphere elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ buf.resize( nbytes );
+ buf.reset();
+ char *ptr = buf.get_ptr();
+ sgReadBytes( fp, nbytes, ptr );
+ gbs_center = buf.readVec3d();
+ gbs_radius = buf.readFloat();
+ }
+ } else if ( obj_type == SG_VERTEX_LIST ) {
+ // read vertex list properties
+ read_properties( fp, nproperties );
+
+ // read vertex list elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ buf.resize( nbytes );
+ buf.reset();
+ char *ptr = buf.get_ptr();
+ sgReadBytes( fp, nbytes, ptr );
+ int count = nbytes / (sizeof(float) * 3);
+ wgs84_nodes.reserve( count );
+ for ( k = 0; k < count; ++k ) {
+ SGVec3f v = buf.readVec3f();
+ // extend from float to double, hmmm
+ wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) );
+ }
+ }
+ } else if ( obj_type == SG_COLOR_LIST ) {
+ // read color list properties
+ read_properties( fp, nproperties );
+
+ // read color list elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ buf.resize( nbytes );
+ buf.reset();
+ char *ptr = buf.get_ptr();
+ sgReadBytes( fp, nbytes, ptr );
+ int count = nbytes / (sizeof(float) * 4);
+ colors.reserve(count);
+ for ( k = 0; k < count; ++k ) {
+ colors.push_back( buf.readVec4f() );
+ }
+ }
+ } else if ( obj_type == SG_NORMAL_LIST ) {
+ // read normal list properties
+ read_properties( fp, nproperties );
+
+ // read normal list elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ buf.resize( nbytes );
+ buf.reset();
+ unsigned char *ptr = (unsigned char *)(buf.get_ptr());
+ sgReadBytes( fp, nbytes, ptr );
+ int count = nbytes / 3;
+ normals.reserve( count );
+
+ for ( k = 0; k < count; ++k ) {
+ SGVec3f normal( (ptr[0]) / 127.5 - 1.0,
+ (ptr[1]) / 127.5 - 1.0,
+ (ptr[2]) / 127.5 - 1.0);
+ normals.push_back(normalize(normal));
+ ptr += 3;
+ }
+ }
+ } else if ( obj_type == SG_TEXCOORD_LIST ) {
+ // read texcoord list properties
+ read_properties( fp, nproperties );
+
+ // read texcoord list elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ buf.resize( nbytes );
+ buf.reset();
+ char *ptr = buf.get_ptr();
+ sgReadBytes( fp, nbytes, ptr );
+ int count = nbytes / (sizeof(float) * 2);
+ texcoords.reserve(count);
+ for ( k = 0; k < count; ++k ) {
+ texcoords.push_back( buf.readVec2f() );
+ }
+ }
+ } else if ( obj_type == SG_POINTS ) {
+ // read point elements
+ read_object( fp, SG_POINTS, nproperties, nelements,
+ pts_v, pts_n, pts_c, pts_tc, pt_materials );
+ } else if ( obj_type == SG_TRIANGLE_FACES ) {
+ // read triangle face properties
+ read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
+ tris_v, tris_n, tris_c, tris_tc, tri_materials );
+ } else if ( obj_type == SG_TRIANGLE_STRIPS ) {
+ // read triangle strip properties
+ read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
+ strips_v, strips_n, strips_c, strips_tc,
+ strip_materials );
+ } else if ( obj_type == SG_TRIANGLE_FANS ) {
+ // read triangle fan properties
+ read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
+ fans_v, fans_n, fans_c, fans_tc, fan_materials );
+ } else {
+ // unknown object type, just skip
+ read_properties( fp, nproperties );
+
+ // read elements
+ for ( j = 0; j < nelements; ++j ) {
+ sgReadUInt( fp, &nbytes );
+ // cout << "element size = " << nbytes << endl;
+ if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
+ char *ptr = buf.get_ptr();
+ sgReadBytes( fp, nbytes, ptr );
+ }
+ }
+
+ if ( sgReadError() ) {
+ cout << "We detected an error while reading object:" << i << endl;
+ return false;
+ }