Skip to content

Commit 51b29e3

Browse files
authored
Fix rounding errors breaking buffer sizes of large gltf models (#810)
- Add uint64_t/int64_t types to the JsonObj class so that sizes never touch floats - In match graph diagrams, color nodes with obs-crossing boundary edges in red instead of in black
1 parent f66de61 commit 51b29e3

26 files changed

Lines changed: 194 additions & 139 deletions

src/stim/diagram/basic_3d_diagram.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ GltfScene Basic3dDiagram::to_gltf_scene() const {
6060
});
6161

6262
auto buf_purple_scattered_lines = std::shared_ptr<GltfBuffer<3>>(new GltfBuffer<3>{
63-
{"buf_blue_scattered_lines"},
63+
{"buf_purple_scattered_lines"},
6464
purple_line_data,
6565
});
6666

src/stim/diagram/gate_data_3d.cc

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_z_control_mesh() {
342342
return {"Z_CONTROL", mesh};
343343
}
344344

345-
std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh() {
345+
std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh(bool excited) {
346346
auto circle = make_circle_loop(8, CONTROL_RADIUS, true);
347347
auto circle2 = make_circle_loop(8, CONTROL_RADIUS, true);
348348
auto circle3 = make_circle_loop(8, CONTROL_RADIUS, true);
@@ -354,44 +354,44 @@ std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh() {
354354
std::swap(e.xyz[0], e.xyz[1]);
355355
std::swap(e.xyz[1], e.xyz[2]);
356356
}
357-
auto black_material = std::shared_ptr<GltfMaterial>(new GltfMaterial{
358-
{"black"},
359-
{0, 0, 0, 1},
357+
auto material = std::shared_ptr<GltfMaterial>(new GltfMaterial{
358+
{excited ? "det_red" : "det_black"},
359+
{excited ? 1.0f : 0.0f, excited ? 0.5f : 0.0f, excited ? 0.5f : 0.0f, 1},
360360
1,
361361
1,
362362
true,
363363
nullptr,
364364
});
365365
auto disc_interior = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
366-
{"detector_primitive_circle_interior"},
366+
{excited ? "excited_detector_primitive_circle_interior" : "detector_primitive_circle_interior"},
367367
GL_TRIANGLE_FAN,
368368
circle,
369369
nullptr,
370-
black_material,
370+
material,
371371
});
372372
auto disc_interior2 = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
373-
{"detector_primitive_circle_interior_2"},
373+
{excited ? "excited_detector_primitive_circle_interior_2" : "detector_primitive_circle_interior_2"},
374374
GL_TRIANGLE_FAN,
375375
circle2,
376376
nullptr,
377-
black_material,
377+
material,
378378
});
379379
auto disc_interior3 = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
380-
{"detector_primitive_circle_interior_3"},
380+
{excited ? "excited_detector_primitive_circle_interior_3" : "detector_primitive_circle_interior_3"},
381381
GL_TRIANGLE_FAN,
382382
circle3,
383383
nullptr,
384-
black_material,
384+
material,
385385
});
386386
auto mesh = std::shared_ptr<GltfMesh>(new GltfMesh{
387-
{"mesh_DETECTOR"},
387+
{excited ? "mesh_EXCITED_DETECTOR" : "mesh_DETECTOR"},
388388
{
389389
disc_interior,
390390
disc_interior2,
391391
disc_interior3,
392392
},
393393
});
394-
return {"DETECTOR", mesh};
394+
return {excited ? "EXCITED_DETECTOR" : "DETECTOR", mesh};
395395
}
396396

397397
std::map<std::string_view, std::shared_ptr<GltfMesh>> stim_draw_internal::make_gate_primitives() {
@@ -516,6 +516,7 @@ std::map<std::string_view, std::shared_ptr<GltfMesh>> stim_draw_internal::make_g
516516
make_z_control_mesh(),
517517
make_xswap_control_mesh(),
518518
make_zswap_control_mesh(),
519-
make_detector_mesh(),
519+
make_detector_mesh(false),
520+
make_detector_mesh(true),
520521
};
521522
}

src/stim/diagram/gltf.cc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ JsonObj GltfScene::_to_json_local() const {
3131
JsonObj GltfScene::to_json() {
3232
// Clear indices.
3333
visit([&](GltfId &item_id, const char *type, const std::function<JsonObj(void)> &to_json, uintptr_t abs_id) {
34-
item_id.index = SIZE_MAX;
34+
item_id.index = UINT64_MAX;
3535
});
3636

3737
// Re-index.
3838
std::map<std::string, size_t> counts;
3939
visit([&](GltfId &item_id, const char *type, const std::function<JsonObj(void)> &to_json, uintptr_t abs_id) {
4040
auto &c = counts[type];
41-
if (item_id.index == SIZE_MAX || item_id.index == c) {
41+
if (item_id.index == UINT64_MAX || item_id.index == c) {
4242
item_id.index = c;
4343
c++;
4444
} else if (item_id.index > c) {
@@ -97,7 +97,8 @@ void GltfImage::visit(const gltf_visit_callback &callback) {
9797

9898
JsonObj GltfImage::to_json() const {
9999
return std::map<std::string, JsonObj>{
100-
{"name", id.name},
100+
// Note: saving space by not including names.
101+
//{"name", id.name},
101102
{"uri", uri},
102103
};
103104
}
@@ -116,7 +117,8 @@ void GltfTexture::visit(const gltf_visit_callback &callback) {
116117

117118
JsonObj GltfTexture::to_json() const {
118119
return std::map<std::string, JsonObj>{
119-
{"name", id.name},
120+
// Note: saving space by not including names.
121+
// {"name", id.name},
120122
{"sampler", 0},
121123
{"source", 0},
122124
};
@@ -137,7 +139,7 @@ void GltfMaterial::visit(const gltf_visit_callback &callback) {
137139

138140
JsonObj GltfMaterial::to_json() const {
139141
JsonObj result = std::map<std::string, JsonObj>{
140-
{"name", id.name},
142+
// {"name", id.name},
141143
{"pbrMetallicRoughness",
142144
std::map<std::string, JsonObj>{
143145
{"baseColorFactor",

src/stim/diagram/gltf.h

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,23 @@
1111

1212
namespace stim_draw_internal {
1313

14-
constexpr size_t GL_FLOAT = 5126;
15-
constexpr size_t GL_ARRAY_BUFFER = 34962;
16-
constexpr size_t GL_UNSIGNED_SHORT = 5123;
17-
constexpr size_t GL_ELEMENT_ARRAY_BUFFER = 34963;
18-
constexpr size_t GL_TRIANGLE_STRIP = 5;
19-
constexpr size_t GL_TRIANGLES = 4;
20-
constexpr size_t GL_TRIANGLE_FAN = 6;
21-
22-
constexpr size_t GL_LINES = 1;
23-
constexpr size_t GL_LINE_STRIP = 3;
24-
constexpr size_t GL_LINE_LOOP = 2;
25-
26-
constexpr size_t GL_REPEAT = 10497;
27-
constexpr size_t GL_CLAMP = 10496;
28-
constexpr size_t GL_CLAMP_TO_EDGE = 33071;
29-
constexpr size_t GL_LINEAR = 9729;
30-
constexpr size_t GL_LINEAR_MIPMAP_NEAREST = 9987;
31-
constexpr size_t GL_NEAREST = 9728;
14+
constexpr uint64_t GL_FLOAT = 5126;
15+
constexpr uint64_t GL_ARRAY_BUFFER = 34962;
16+
constexpr uint64_t GL_TRIANGLES = 4;
17+
constexpr uint64_t GL_TRIANGLE_FAN = 6;
18+
19+
constexpr uint64_t GL_LINES = 1;
20+
constexpr uint64_t GL_LINE_STRIP = 3;
21+
constexpr uint64_t GL_LINE_LOOP = 2;
22+
23+
constexpr uint64_t GL_CLAMP_TO_EDGE = 33071;
24+
constexpr uint64_t GL_NEAREST = 9728;
3225

3326
struct GltfId {
3427
std::string name;
35-
size_t index;
28+
uint64_t index;
3629

37-
GltfId(std::string name) : name(name), index(SIZE_MAX) {
30+
GltfId(std::string name) : name(name), index(UINT64_MAX) {
3831
}
3932
GltfId() = delete;
4033
};
@@ -81,7 +74,7 @@ struct GltfBuffer {
8174
return std::map<std::string, JsonObj>{
8275
{"name", id.name},
8376
{"uri", ss.str()},
84-
{"byteLength", vertex_data_size},
77+
{"byteLength", (uint64_t)vertex_data_size},
8578
};
8679
}
8780

@@ -90,7 +83,7 @@ struct GltfBuffer {
9083
{"name", id.name},
9184
{"buffer", id.index},
9285
{"byteOffset", 0},
93-
{"byteLength", vertices.size() * sizeof(Coord<DIM>)},
86+
{"byteLength", (uint64_t)(vertices.size() * sizeof(Coord<DIM>))},
9487
{"target", GL_ARRAY_BUFFER},
9588
};
9689
}
@@ -115,7 +108,7 @@ struct GltfBuffer {
115108
{"bufferView", id.index},
116109
{"byteOffset", 0},
117110
{"componentType", GL_FLOAT},
118-
{"count", vertices.size()},
111+
{"count", (uint64_t)vertices.size()},
119112
{"type", "VEC" + std::to_string(DIM)},
120113
{"min", std::move(min_v)},
121114
{"max", std::move(max_v)},
@@ -125,10 +118,10 @@ struct GltfBuffer {
125118

126119
struct GltfSampler {
127120
GltfId id;
128-
size_t magFilter;
129-
size_t minFilter;
130-
size_t wrapS;
131-
size_t wrapT;
121+
uint64_t magFilter;
122+
uint64_t minFilter;
123+
uint64_t wrapS;
124+
uint64_t wrapT;
132125

133126
void visit(const gltf_visit_callback &callback);
134127
JsonObj to_json() const;
@@ -165,7 +158,7 @@ struct GltfMaterial {
165158

166159
struct GltfPrimitive {
167160
GltfId id;
168-
size_t element_type;
161+
uint64_t element_type;
169162
std::shared_ptr<GltfBuffer<3>> position_buffer;
170163
std::shared_ptr<GltfBuffer<2>> tex_coords_buffer;
171164
std::shared_ptr<GltfMaterial> material;

src/stim/diagram/graph/match_graph_3d_drawer.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
7979
auto minmax = Coord<3>::min_max(coords);
8080
auto center = (minmax.first + minmax.second) * 0.5;
8181

82+
std::set<uint64_t> boundary_observable_detectors;
8283
std::vector<Coord<3>> det_coords;
8384
auto handle_contiguous_targets = [&](SpanRef<const DemTarget> targets) {
8485
bool has_observables = false;
@@ -102,6 +103,13 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
102103
}
103104
auto a = det_coords[0];
104105
det_coords.push_back(a + d * 10);
106+
if (has_observables) {
107+
for (auto t : targets) {
108+
if (t.is_relative_detector_id()) {
109+
boundary_observable_detectors.insert(t.val());
110+
}
111+
}
112+
}
105113
}
106114
if (det_coords.size() == 2) {
107115
if (has_observables) {
@@ -129,10 +137,6 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
129137
}
130138
};
131139

132-
for (const auto &c : coords) {
133-
out.elements.push_back({"DETECTOR", c});
134-
}
135-
136140
dem.iter_flatten_error_instructions([&](const DemInstruction &op) {
137141
if (op.type != DemInstructionType::DEM_ERROR) {
138142
return;
@@ -148,5 +152,10 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
148152
handle_contiguous_targets({p + start, op.target_data.ptr_end});
149153
});
150154

155+
for (size_t k = 0; k < coords.size(); k++) {
156+
bool excited = boundary_observable_detectors.find(k) != boundary_observable_detectors.end();
157+
out.elements.push_back({excited ? "EXCITED_DETECTOR" : "DETECTOR", coords[k]});
158+
}
159+
151160
return out;
152161
}

0 commit comments

Comments
 (0)