From 851a307c237a780de7573f53e0378b3127ecd785 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Nov 2012 21:10:00 +0000 Subject: [PATCH] Test for, and fix, materials handling in BTG code. 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 | 29 ++++++++++++++- simgear/io/test_binobj.cxx | 76 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 3deaacc1..994f3dbe 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -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 } diff --git a/simgear/io/test_binobj.cxx b/simgear/io/test_binobj.cxx index 2ca1edf1..00b69790 100644 --- a/simgear/io/test_binobj.cxx +++ b/simgear/io/test_binobj.cxx @@ -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 points; + generate_points(10000, points); + std::vector normals; + generate_normals(1024, normals); + std::vector 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 points; + generate_points(10000, points); + std::vector normals; + generate_normals(1024, normals); + std::vector 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; } -- 2.39.5