]> git.mxchange.org Git - simgear.git/blobdiff - simgear/io/sg_binobj.cxx
HTTP: Rename urlretrieve/urlload to save/load.
[simgear.git] / simgear / io / sg_binobj.cxx
index e01a52865f0f71188ab13dfde738e6eb7c858c0b..69cdd477c61fb23dfcba21b66b97dd718b3b9c01 100644 (file)
@@ -43,6 +43,7 @@
 #include <simgear/bucket/newbucket.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/math/SGGeometry.hxx>
+#include <simgear/structure/exception.hxx>
 
 #include "lowlevel.hxx"
 #include "sg_binobj.hxx"
@@ -319,15 +320,18 @@ void SGBinObject::read_object( gzFile fp,
     }
 
     if ( sgReadError() ) {
-        cout << "We detected an error reading object properties"  << endl;
-        return;
+        throw sg_exception("Error reading object properties");
+    }
+    
+    size_t indexCount = std::bitset<32>(idx_mask).count();
+    if (indexCount == 0) {
+        throw sg_exception("object index mask has no bits set");
     }
     
     for ( j = 0; j < nelements; ++j ) {
         sgReadUInt( fp, &nbytes );
         if ( sgReadError() ) {
-            cout << "We detected an error reading element size for :" << j << endl;
-            return;
+            throw sg_exception("Error reading element size");
         }
         
         buf.resize( nbytes );
@@ -335,8 +339,7 @@ void SGBinObject::read_object( gzFile fp,
         sgReadBytes( fp, nbytes, ptr );
         
         if ( sgReadError() ) {
-            cout << "We detected an error reading object element:" << j << "bytes="<< nbytes  << endl;
-            return;
+            throw sg_exception("Error reading element bytes");
         }
                 
         int_list vs;
@@ -405,7 +408,7 @@ bool SGBinObject::read_bin( const string& file ) {
             SG_LOG( SG_EVENT, SG_ALERT,
                "ERROR: opening " << file << " or " << filegz << " for reading!");
 
-            return false;
+            throw sg_io_exception("Error opening for reading (and .gz)", sg_location(file));
         }
     }
 
@@ -423,10 +426,9 @@ bool SGBinObject::read_bin( const string& file ) {
     } else {
         // close the file before we return
         gzclose(fp);
-
-        return false;
+        throw sg_io_exception("Bad BTG magic/version", sg_location(file));
     }
-
+    
     // read creation time
     unsigned int foo_calendar_time;
     sgReadUInt( fp, &foo_calendar_time );
@@ -461,8 +463,7 @@ bool SGBinObject::read_bin( const string& file ) {
      //cout << "Total objects to read = " << nobjects << endl;
 
     if ( sgReadError() ) {
-        cout << "We detected an error while reading the file header" << endl;
-        return false;
+        throw sg_io_exception("Error reading BTG file header", sg_location(file));
     }
     
     // read in objects
@@ -612,19 +613,13 @@ bool SGBinObject::read_bin( const string& file ) {
         }
         
         if ( sgReadError() ) {
-            cout << "We detected an error while reading object:" << i << endl;
-            return false;
+            throw sg_io_exception("Error while reading object", sg_location(file, i));
         }
     }
 
     // close the file
     gzclose(fp);
 
-    if ( sgReadError() ) {
-        cout << "We detected an error while reading the file." << endl;
-        return false;
-    }
-
     return true;
 }
 
@@ -664,7 +659,7 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts,
     if (verts.empty()) {
         return;
     }
-    
+        
     unsigned int start = 0, end = 1;
     string m;
     int_list emptyList;
@@ -687,6 +682,13 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts,
         if ( !normals.empty() && !normals.front().empty()) idx_mask |= SG_IDX_NORMALS;
         if ( !colors.empty() && !colors.front().empty()) idx_mask |= SG_IDX_COLORS;
         if ( !texCoords.empty() && !texCoords.front().empty()) idx_mask |= SG_IDX_TEXCOORDS;
+        
+        if (idx_mask == 0) {
+            SG_LOG(SG_IO, SG_ALERT, "SGBinObject::write_objects: object with material:"
+                << m << "has no indices set");
+        }
+    
+    
         sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
         sgWriteUInt( fp, 1 );                        // nbytes
         sgWriteChar( fp, idx_mask );
@@ -721,6 +723,26 @@ bool SGBinObject::write_bin( const string& base, const string& name,
     return write_bin_file(file);
 }
 
+static unsigned int max_object_size( const string_list& materials )
+{
+    unsigned int max_size = 0;
+
+    for (unsigned int start=0; start < materials.size();) {
+        string m = materials[start];
+        unsigned int end = start + 1;
+        // find range of objects with identical material, calc its size
+        for (; (end < materials.size()) && (m == materials[end]); ++end) {}
+
+        unsigned int cur_size = end - start;
+        max_size = std::max(max_size, cur_size);
+        start = end;
+    }
+
+    return max_size;
+}
+
+const unsigned int VERSION_7_MATERIAL_LIMIT = 0x7fff;
+
 bool SGBinObject::write_bin_file(const SGPath& file)
 {
     int i;
@@ -752,7 +774,16 @@ bool SGBinObject::write_bin_file(const SGPath& file)
     cout << "tex coords = " << texcoords.size() << endl;
 
     version = 10;
-    if (wgs84_nodes.size() < 0xffff) {
+    bool shortMaterialsRanges = 
+        (max_object_size(pt_materials) < VERSION_7_MATERIAL_LIMIT) &&
+        (max_object_size(fan_materials) < VERSION_7_MATERIAL_LIMIT) &&
+        (max_object_size(strip_materials) < VERSION_7_MATERIAL_LIMIT) &&
+        (max_object_size(tri_materials) < VERSION_7_MATERIAL_LIMIT);
+                    
+    if ((wgs84_nodes.size() < 0xffff) &&
+        (normals.size() < 0xffff) &&
+        (texcoords.size() < 0xffff) &&
+        shortMaterialsRanges) {
         version = 7; // use smaller indices if possible
     }
 
@@ -827,7 +858,7 @@ bool SGBinObject::write_bin_file(const SGPath& file)
     gzclose(fp);
 
     if ( sgWriteError() ) {
-        cout << "We detected an error while writing the file." << endl;
+        cout << "Error while writing file " << file.str() << endl;
         return false;
     }
 
@@ -904,7 +935,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
     fprintf(fp, "\n");
 
     // dump individual triangles if they exist
-    if ( tris_v.size() > 0 ) {
+    if ( ! tris_v.empty() ) {
         fprintf(fp, "# triangle groups\n");
 
         int start = 0;
@@ -952,7 +983,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
     }
 
     // dump triangle groups
-    if ( strips_v.size() > 0 ) {
+    if ( ! strips_v.empty() ) {
         fprintf(fp, "# triangle strips\n");
 
         int start = 0;
@@ -1004,9 +1035,13 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
     fclose(fp);
 
     string command = "gzip --force --best " + file.str();
-    system(command.c_str());
+    int err = system(command.c_str());
+    if (err)
+    {
+        cout << "ERROR: gzip " << file.str() << " failed!" << endl;
+    }
 
-    return true;
+    return (err == 0);
 }
 
 void SGBinObject::read_properties(gzFile fp, int nproperties)