Skip to content

Commit 4cee4aa

Browse files
authored
Merge pull request #848 from zeux/gltf-qerr
gltfpack: Warn when position quantization error is significant
2 parents fc45e05 + f1ae4f1 commit 4cee4aa

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed

gltf/stream.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@ struct Bounds
2424
{
2525
return min.f[0] <= max.f[0] && min.f[1] <= max.f[1] && min.f[2] <= max.f[2] && min.f[3] <= max.f[3];
2626
}
27+
28+
float getExtent() const
29+
{
30+
return std::max(max.f[0] - min.f[0], std::max(max.f[1] - min.f[1], max.f[2] - min.f[2]));
31+
}
32+
33+
void merge(const Bounds& other)
34+
{
35+
for (int k = 0; k < 4; ++k)
36+
{
37+
min.f[k] = std::min(min.f[k], other.min.f[k]);
38+
max.f[k] = std::max(max.f[k], other.max.f[k]);
39+
}
40+
}
2741
};
2842

29-
static void updateAttributeBounds(const Mesh& mesh, cgltf_attribute_type type, Bounds& b)
43+
static Bounds computeBounds(const Mesh& mesh, cgltf_attribute_type type)
3044
{
45+
Bounds b;
3146
Attr pad = {};
3247

3348
for (size_t j = 0; j < mesh.streams.size(); ++j)
@@ -73,6 +88,8 @@ static void updateAttributeBounds(const Mesh& mesh, cgltf_attribute_type type, B
7388
b.min.f[k] -= pad.f[k];
7489
b.max.f[k] += pad.f[k];
7590
}
91+
92+
return b;
7693
}
7794

7895
QuantizationPosition prepareQuantizationPosition(const std::vector<Mesh>& meshes, const Settings& settings)
@@ -82,19 +99,34 @@ QuantizationPosition prepareQuantizationPosition(const std::vector<Mesh>& meshes
8299
result.bits = settings.pos_bits;
83100
result.normalized = settings.pos_normalized;
84101

85-
Bounds b;
102+
std::vector<Bounds> bounds(meshes.size());
86103

87104
for (size_t i = 0; i < meshes.size(); ++i)
88-
{
89-
updateAttributeBounds(meshes[i], cgltf_attribute_type_position, b);
90-
}
105+
bounds[i] = computeBounds(meshes[i], cgltf_attribute_type_position);
106+
107+
Bounds b;
108+
for (size_t i = 0; i < meshes.size(); ++i)
109+
b.merge(bounds[i]);
91110

92111
if (b.isValid())
93112
{
94113
result.offset[0] = b.min.f[0];
95114
result.offset[1] = b.min.f[1];
96115
result.offset[2] = b.min.f[2];
97-
result.scale = std::max(b.max.f[0] - b.min.f[0], std::max(b.max.f[1] - b.min.f[1], b.max.f[2] - b.min.f[2]));
116+
result.scale = b.getExtent();
117+
}
118+
119+
if (b.isValid() && settings.quantize && !settings.pos_float)
120+
{
121+
float error = result.scale * 0.5f / (1 << (result.bits - 1));
122+
float max_rel_error = 0;
123+
124+
for (size_t i = 0; i < meshes.size(); ++i)
125+
if (bounds[i].isValid() && bounds[i].getExtent() > 1e-2f)
126+
max_rel_error = std::max(max_rel_error, error / bounds[i].getExtent());
127+
128+
if (max_rel_error > 5e-2f)
129+
fprintf(stderr, "Warning: position data has significant error (%.0f%%); consider using floating-point quantization (-vpf) or more bits (-vp N)\n", max_rel_error * 100);
98130
}
99131

100132
result.node_scale = result.scale / float((1 << result.bits) - 1) * (result.normalized ? 65535.f : 1.f);
@@ -154,7 +186,9 @@ void prepareQuantizationTexture(cgltf_data* data, std::vector<QuantizationTextur
154186
continue;
155187

156188
indices[i] = follow(parents, indices[i]);
157-
updateAttributeBounds(mesh, cgltf_attribute_type_texcoord, bounds[indices[i]]);
189+
190+
Bounds mb = computeBounds(mesh, cgltf_attribute_type_texcoord);
191+
bounds[indices[i]].merge(mb);
158192
}
159193

160194
// update all material data using canonical bounds

0 commit comments

Comments
 (0)