@@ -24,10 +24,25 @@ struct Bounds
24
24
{
25
25
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 ];
26
26
}
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
+ }
27
41
};
28
42
29
- static void updateAttributeBounds (const Mesh& mesh, cgltf_attribute_type type, Bounds& b )
43
+ static Bounds computeBounds (const Mesh& mesh, cgltf_attribute_type type)
30
44
{
45
+ Bounds b;
31
46
Attr pad = {};
32
47
33
48
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
73
88
b.min .f [k] -= pad.f [k];
74
89
b.max .f [k] += pad.f [k];
75
90
}
91
+
92
+ return b;
76
93
}
77
94
78
95
QuantizationPosition prepareQuantizationPosition (const std::vector<Mesh>& meshes, const Settings& settings)
@@ -82,19 +99,34 @@ QuantizationPosition prepareQuantizationPosition(const std::vector<Mesh>& meshes
82
99
result.bits = settings.pos_bits ;
83
100
result.normalized = settings.pos_normalized ;
84
101
85
- Bounds b ;
102
+ std::vector< Bounds> bounds (meshes. size ()) ;
86
103
87
104
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]);
91
110
92
111
if (b.isValid ())
93
112
{
94
113
result.offset [0 ] = b.min .f [0 ];
95
114
result.offset [1 ] = b.min .f [1 ];
96
115
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 );
98
130
}
99
131
100
132
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
154
186
continue ;
155
187
156
188
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);
158
192
}
159
193
160
194
// update all material data using canonical bounds
0 commit comments