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.
This commit is contained in:
James Turner 2012-11-07 21:10:00 +00:00
parent 183d3749f0
commit 851a307c23
2 changed files with 104 additions and 1 deletions

View File

@ -722,6 +722,26 @@ bool SGBinObject::write_bin( const string& base, const string& name,
return write_bin_file(file); 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) bool SGBinObject::write_bin_file(const SGPath& file)
{ {
int i; int i;
@ -753,9 +773,16 @@ bool SGBinObject::write_bin_file(const SGPath& file)
cout << "tex coords = " << texcoords.size() << endl; cout << "tex coords = " << texcoords.size() << endl;
version = 10; 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) && if ((wgs84_nodes.size() < 0xffff) &&
(normals.size() < 0xffff) && (normals.size() < 0xffff) &&
(texcoords.size() < 0xffff)) { (texcoords.size() < 0xffff) &&
shortMaterialsRanges) {
version = 7; // use smaller indices if possible version = 7; // use smaller indices if possible
} }

View File

@ -250,12 +250,88 @@ void test_big()
compareTris(basic, rd); 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[]) int main(int argc, char* argv[])
{ {
test_empty(); test_empty();
test_basic(); test_basic();
test_many_tcs(); test_many_tcs();
test_big(); test_big();
test_some_objects();
test_many_objects();
return 0; return 0;
} }