]> git.mxchange.org Git - simgear.git/commitdiff
Test for, and fix, materials handling in BTG code.
authorJames Turner <zakalawe@mac.com>
Wed, 7 Nov 2012 21:10:00 +0000 (21:10 +0000)
committerJames Turner <zakalawe@mac.com>
Wed, 7 Nov 2012 21:10:00 +0000 (21:10 +0000)
It's possible (and happens!) to have less than 2^16 vertices or tex-coords, but more than 2^15 objects (tris) with the same materials. This was breaking our version 7 vs version 10 detection logic. Pete found the issue, I'm simply committing a version of his fix.

simgear/io/sg_binobj.cxx
simgear/io/test_binobj.cxx

index 3deaacc19972348f51d884b90ee6ab1ce663e383..994f3dbe643018e016a83768c48343d15a35c0df 100644 (file)
@@ -722,6 +722,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;
@@ -753,9 +773,16 @@ bool SGBinObject::write_bin_file(const SGPath& file)
     cout << "tex coords = " << texcoords.size() << endl;
 
     version = 10;
+    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)) {
+        (texcoords.size() < 0xffff) &&
+        shortMaterialsRanges) {
         version = 7; // use smaller indices if possible
     }
 
index 2ca1edf149bdd02e474fb1e210b94ed8e2d22194..00b697906c1cabbe5c2fb22263fc97b8123b74ee 100644 (file)
@@ -250,12 +250,88 @@ void test_big()
    compareTris(basic, rd);
 }
 
+void test_some_objects()
+{
+    SGBinObject basic;
+    SGPath path(simgear::Dir::current().file("some_objects.btg.gz"));
+    
+    SGVec3d center(1, 2, 3);
+    basic.set_gbs_center(center);
+    basic.set_gbs_radius(12345);
+    
+    std::vector<SGVec3d> points;
+    generate_points(10000, points);
+    std::vector<SGVec3f> normals;
+    generate_normals(1024, normals);
+    std::vector<SGVec2f> texCoords;
+    generate_tcs(20000, texCoords);
+    
+    basic.set_wgs84_nodes(points);
+    basic.set_normals(normals);
+    basic.set_texcoords(texCoords);
+    
+    generate_tris(basic, 30000); // a number smaller than 2^15!
+    
+    bool ok = basic.write_bin_file(path);
+    VERIFY( ok );
+    
+    SGBinObject rd;
+    ok = rd.read_bin(path.str()) ;
+    VERIFY( ok);
+    COMPARE(rd.get_version(), 7); // since we have less than 2^15 tris
+    COMPARE(rd.get_wgs84_nodes().size(), points.size());
+    COMPARE(rd.get_texcoords().size(), texCoords.size());
+   
+    comparePoints(rd, points);
+    compareTexCoords(rd, texCoords);
+    compareTris(basic, rd);
+}
+
+void test_many_objects()
+{
+    SGBinObject basic;
+    SGPath path(simgear::Dir::current().file("many_objects.btg.gz"));
+    
+    SGVec3d center(1, 2, 3);
+    basic.set_gbs_center(center);
+    basic.set_gbs_radius(12345);
+    
+    std::vector<SGVec3d> points;
+    generate_points(10000, points);
+    std::vector<SGVec3f> normals;
+    generate_normals(1024, normals);
+    std::vector<SGVec2f> texCoords;
+    generate_tcs(20000, texCoords);
+    
+    basic.set_wgs84_nodes(points);
+    basic.set_normals(normals);
+    basic.set_texcoords(texCoords);
+    
+    generate_tris(basic, 200000);
+    
+    bool ok = basic.write_bin_file(path);
+    VERIFY( ok );
+    
+    SGBinObject rd;
+    ok = rd.read_bin(path.str()) ;
+    VERIFY( ok);
+    COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16
+    COMPARE(rd.get_wgs84_nodes().size(), points.size());
+    COMPARE(rd.get_texcoords().size(), texCoords.size());
+   
+    comparePoints(rd, points);
+    compareTexCoords(rd, texCoords);
+    compareTris(basic, rd);
+}
+
 int main(int argc, char* argv[])
 {
     test_empty();
     test_basic();
     test_many_tcs();
     test_big();
+    test_some_objects();
+    test_many_objects();
     
     return 0;
 }