Skip to content

Commit

Permalink
Fix rounding errors breaking buffer sizes of large gltf models
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Strilanc committed Aug 2, 2024
1 parent f66de61 commit 8106795
Show file tree
Hide file tree
Showing 25 changed files with 156 additions and 109 deletions.
2 changes: 1 addition & 1 deletion src/stim/diagram/basic_3d_diagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ GltfScene Basic3dDiagram::to_gltf_scene() const {
});

auto buf_purple_scattered_lines = std::shared_ptr<GltfBuffer<3>>(new GltfBuffer<3>{
{"buf_blue_scattered_lines"},
{"buf_purple_scattered_lines"},
purple_line_data,
});

Expand Down
27 changes: 14 additions & 13 deletions src/stim/diagram/gate_data_3d.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_z_control_mesh() {
return {"Z_CONTROL", mesh};
}

std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh() {
std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh(bool excited) {
auto circle = make_circle_loop(8, CONTROL_RADIUS, true);
auto circle2 = make_circle_loop(8, CONTROL_RADIUS, true);
auto circle3 = make_circle_loop(8, CONTROL_RADIUS, true);
Expand All @@ -354,44 +354,44 @@ std::pair<std::string_view, std::shared_ptr<GltfMesh>> make_detector_mesh() {
std::swap(e.xyz[0], e.xyz[1]);
std::swap(e.xyz[1], e.xyz[2]);
}
auto black_material = std::shared_ptr<GltfMaterial>(new GltfMaterial{
{"black"},
{0, 0, 0, 1},
auto material = std::shared_ptr<GltfMaterial>(new GltfMaterial{
{excited ? "det_red" : "det_black"},
{excited ? 1.0f : 0.0f, excited ? 0.5f : 0.0f, excited ? 0.5f : 0.0f, 1},
1,
1,
true,
nullptr,
});
auto disc_interior = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
{"detector_primitive_circle_interior"},
{excited ? "excited_detector_primitive_circle_interior" : "detector_primitive_circle_interior"},
GL_TRIANGLE_FAN,
circle,
nullptr,
black_material,
material,
});
auto disc_interior2 = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
{"detector_primitive_circle_interior_2"},
{excited ? "excited_detector_primitive_circle_interior_2" : "detector_primitive_circle_interior_2"},
GL_TRIANGLE_FAN,
circle2,
nullptr,
black_material,
material,
});
auto disc_interior3 = std::shared_ptr<GltfPrimitive>(new GltfPrimitive{
{"detector_primitive_circle_interior_3"},
{excited ? "excited_detector_primitive_circle_interior_3" : "detector_primitive_circle_interior_3"},
GL_TRIANGLE_FAN,
circle3,
nullptr,
black_material,
material,
});
auto mesh = std::shared_ptr<GltfMesh>(new GltfMesh{
{"mesh_DETECTOR"},
{excited ? "mesh_EXCITED_DETECTOR" : "mesh_DETECTOR"},
{
disc_interior,
disc_interior2,
disc_interior3,
},
});
return {"DETECTOR", mesh};
return {excited ? "EXCITED_DETECTOR" : "DETECTOR", mesh};
}

std::map<std::string_view, std::shared_ptr<GltfMesh>> stim_draw_internal::make_gate_primitives() {
Expand Down Expand Up @@ -516,6 +516,7 @@ std::map<std::string_view, std::shared_ptr<GltfMesh>> stim_draw_internal::make_g
make_z_control_mesh(),
make_xswap_control_mesh(),
make_zswap_control_mesh(),
make_detector_mesh(),
make_detector_mesh(false),
make_detector_mesh(true),
};
}
8 changes: 5 additions & 3 deletions src/stim/diagram/gltf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ void GltfImage::visit(const gltf_visit_callback &callback) {

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

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

JsonObj GltfMaterial::to_json() const {
JsonObj result = std::map<std::string, JsonObj>{
{"name", id.name},
// {"name", id.name},
{"pbrMetallicRoughness",
std::map<std::string, JsonObj>{
{"baseColorFactor",
Expand Down
17 changes: 13 additions & 4 deletions src/stim/diagram/graph/match_graph_3d_drawer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
auto minmax = Coord<3>::min_max(coords);
auto center = (minmax.first + minmax.second) * 0.5;

std::set<uint64_t> boundary_observable_detectors;
std::vector<Coord<3>> det_coords;
auto handle_contiguous_targets = [&](SpanRef<const DemTarget> targets) {
bool has_observables = false;
Expand All @@ -102,6 +103,13 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
}
auto a = det_coords[0];
det_coords.push_back(a + d * 10);
if (has_observables) {
for (auto t : targets) {
if (t.is_relative_detector_id()) {
boundary_observable_detectors.insert(t.val());
}
}
}
}
if (det_coords.size() == 2) {
if (has_observables) {
Expand Down Expand Up @@ -129,10 +137,6 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
}
};

for (const auto &c : coords) {
out.elements.push_back({"DETECTOR", c});
}

dem.iter_flatten_error_instructions([&](const DemInstruction &op) {
if (op.type != DemInstructionType::DEM_ERROR) {
return;
Expand All @@ -148,5 +152,10 @@ Basic3dDiagram stim_draw_internal::dem_match_graph_to_basic_3d_diagram(const sti
handle_contiguous_targets({p + start, op.target_data.ptr_end});
});

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

return out;
}
158 changes: 94 additions & 64 deletions src/stim/diagram/json_obj.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,50 @@
using namespace stim;
using namespace stim_draw_internal;

JsonObj::JsonObj(bool boolean) : boolean(boolean), type(4) {
enum JsonType : uint8_t {
JsonTypeEmpty = 0,
JsonTypeMap = 1,
JsonTypeArray = 2,
JsonTypeBool = 3,
JsonTypeSingle = 4,
JsonTypeDouble = 5,
JsonTypeInt64 = 6,
JsonTypeUInt64 = 7,
JsonTypeString = 8,
};

JsonObj::JsonObj(float num) : val_float(num), type(JsonTypeSingle) {
}
JsonObj::JsonObj(int num) : num(num), type(0) {
JsonObj::JsonObj(double num) : val_double(num), type(JsonTypeDouble) {
}
JsonObj::JsonObj(size_t num) : num(num), type(0) {
JsonObj::JsonObj(uint64_t num) : val_uint64_t(num), type(JsonTypeUInt64) {
}
JsonObj::JsonObj(float num) : num(num), type(0) {
JsonObj::JsonObj(int num) : val_int64_t(num), type(JsonTypeInt64) {
}
JsonObj::JsonObj(double num) : double_num(num), type(11) {
JsonObj::JsonObj(int64_t num) : val_int64_t(num), type(JsonTypeInt64) {
}

JsonObj::JsonObj(std::string text) : text(text), type(1) {
JsonObj::JsonObj(std::string text) : text(text), type(JsonTypeString) {
}

JsonObj::JsonObj(const char *text) : text(text), type(1) {
JsonObj::JsonObj(const char *text) : text(text), type(JsonTypeString) {
}

JsonObj::JsonObj(std::map<std::string, JsonObj> map) : map(map), type(2) {
JsonObj::JsonObj(std::map<std::string, JsonObj> map) : map(map), type(JsonTypeMap) {
}

JsonObj::JsonObj(std::vector<JsonObj> arr) : arr(arr), type(3) {
JsonObj::JsonObj(std::vector<JsonObj> arr) : arr(arr), type(JsonTypeArray) {

};
JsonObj::JsonObj(bool boolean) : val_boolean(boolean), type(JsonTypeBool) {
}

void JsonObj::clear() {
auto old_type = type;
if (old_type == 1) {
text.clear();
} else if (old_type == 2) {
map.clear();
} else if (old_type == 3) {
arr.clear();
}
type = 0;
num = 0;
double_num = 0;
text.clear();
map.clear();
arr.clear();
type = JsonTypeEmpty;
val_uint64_t = 0;
}

void JsonObj::write_str(std::string_view s, std::ostream &out) {
Expand Down Expand Up @@ -70,55 +79,76 @@ void indented_new_line(std::ostream &out, int64_t indent) {
}

void JsonObj::write(std::ostream &out, int64_t indent) const {
if (type == 0) {
out << num;
} else if (type == 11) {
auto p = out.precision();
out.precision(std::numeric_limits<double>::digits10);
out << double_num;
out.precision(p);
} else if (type == 1) {
write_str(text, out);
} else if (type == 2) {
out << "{";
indented_new_line(out, indent + 2);
bool first = true;
for (const auto &e : map) {
if (first) {
first = false;
} else {
out << ',';
indented_new_line(out, indent + 2);
switch (type) {
case JsonTypeMap: {
out << "{";
indented_new_line(out, indent + 2);
bool first = true;
for (const auto &e : map) {
if (first) {
first = false;
} else {
out << ',';
indented_new_line(out, indent + 2);
}
write_str(e.first, out);
out << ':';
e.second.write(out, indent + 2);
}
write_str(e.first, out);
out << ':';
e.second.write(out, indent + 2);
}
if (!first) {
indented_new_line(out, indent);
if (!first) {
indented_new_line(out, indent);
}
out << "}";
break;
}
out << "}";
} else if (type == 3) {
out << "[";
indented_new_line(out, indent + 2);
bool first = true;
for (const auto &e : arr) {
if (first) {
first = false;
} else {
out << ',';
indented_new_line(out, indent + 2);
case JsonTypeArray: {
out << "[";
indented_new_line(out, indent + 2);
bool first = true;
for (const auto &e : arr) {
if (first) {
first = false;
} else {
out << ',';
indented_new_line(out, indent + 2);
}
e.write(out, indent + 2);
}
if (!first) {
indented_new_line(out, indent);
}
e.write(out, indent + 2);
out << "]";
break;
}
case JsonTypeString: {
write_str(text, out);
break;
}
case JsonTypeBool: {
out << (val_boolean ? "true" : "false");
break;
}
case JsonTypeSingle: {
out << val_float;
break;
}
case JsonTypeDouble: {
auto p = out.precision();
out.precision(std::numeric_limits<double>::digits10);
out << val_double;
out.precision(p);
break;
}
case JsonTypeInt64: {
out << val_int64_t;
break;
}
if (!first) {
indented_new_line(out, indent);
case JsonTypeUInt64: {
out << val_uint64_t;
break;
}
out << "]";
} else if (type == 4) {
out << (boolean ? "true" : "false");
} else {
throw std::invalid_argument("unknown type");
default:
throw std::invalid_argument("unknown type");
}
}

Expand Down
15 changes: 10 additions & 5 deletions src/stim/diagram/json_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,24 @@
namespace stim_draw_internal {

struct JsonObj {
float num = 0;
double double_num = 0;
union {
float val_float;
double val_double;
int64_t val_int64_t;
uint64_t val_uint64_t;
bool val_boolean;
};
std::string text;
std::map<std::string, JsonObj> map;
std::vector<JsonObj> arr;
bool boolean = false;
uint8_t type;

JsonObj(bool boolean);
JsonObj(int num);
JsonObj(size_t num);
JsonObj(float num);
JsonObj(double double_num);
JsonObj(int int_num);
JsonObj(int64_t int_num);
JsonObj(uint64_t uint_num);
JsonObj(std::string text);
JsonObj(const char *text);
JsonObj(std::map<std::string, JsonObj> map);
Expand Down
2 changes: 1 addition & 1 deletion testdata/circuit_all_ops_3d.gltf

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion testdata/classical_feedback.gltf

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion testdata/collapsing.gltf

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion testdata/detector_pseudo_targets.gltf

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion testdata/empty_match_graph.gltf
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":32,"max":[8,2,0],"min":[0,-1,0],"name":"buf_blue_scattered_lines","type":"VEC3"}],"asset":{"version":"2.0"},"bufferViews":[{"buffer":0,"byteLength":384,"byteOffset":0,"name":"buf_blue_scattered_lines","target":34962}],"buffers":[{"byteLength":384,"name":"buf_blue_scattered_lines","uri":"data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAACAPwAAAEAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAQAAAgD8AAAAAAABAQAAAgD8AAAAAAAAAQAAAAAAAAAAAAAAAQAAAgD8AAAAAAAAgQAAAAAAAAAAAAAAgQAAAgD8AAAAAAABAQAAAAAAAAAAAAABAQAAAgD8AAAAAAACAQAAAgD8AAAAAAACAQAAAgL8AAAAAAACAQAAAgD8AAAAAAACgQAAAgD8AAAAAAACgQAAAgD8AAAAAAACgQAAAAAAAAAAAAACAQAAAAAAAAAAAAACgQAAAAAAAAAAAAADAQAAAAAAAAAAAAADAQAAAAEAAAAAAAACwQAAAwD8AAAAAAADQQAAAwD8AAAAAAADgQAAAgL8AAAAAAAAAQQAAgD8AAAAAAADgQAAAgD8AAAAAAADwQAAAAAAAAAAA"}],"materials":[{"doubleSided":true,"name":"red","pbrMetallicRoughness":{"baseColorFactor":[1,0,0,1],"metallicFactor":1,"roughnessFactor":1}}],"meshes":[{"primitives":[{"attributes":{"POSITION":0},"material":0,"mode":1}]}],"nodes":[{"mesh":0,"translation":[0,0,0]}],"scene":0,"scenes":[{"nodes":[0]}]}
{"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5126,"count":32,"max":[8,2,0],"min":[0,-1,0],"name":"buf_blue_scattered_lines","type":"VEC3"}],"asset":{"version":"2.0"},"bufferViews":[{"buffer":0,"byteLength":384,"byteOffset":0,"name":"buf_blue_scattered_lines","target":34962}],"buffers":[{"byteLength":384,"name":"buf_blue_scattered_lines","uri":"data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAACAPwAAAEAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAQAAAgD8AAAAAAABAQAAAgD8AAAAAAAAAQAAAAAAAAAAAAAAAQAAAgD8AAAAAAAAgQAAAAAAAAAAAAAAgQAAAgD8AAAAAAABAQAAAAAAAAAAAAABAQAAAgD8AAAAAAACAQAAAgD8AAAAAAACAQAAAgL8AAAAAAACAQAAAgD8AAAAAAACgQAAAgD8AAAAAAACgQAAAgD8AAAAAAACgQAAAAAAAAAAAAACAQAAAAAAAAAAAAACgQAAAAAAAAAAAAADAQAAAAAAAAAAAAADAQAAAAEAAAAAAAACwQAAAwD8AAAAAAADQQAAAwD8AAAAAAADgQAAAgL8AAAAAAAAAQQAAgD8AAAAAAADgQAAAgD8AAAAAAADwQAAAAAAAAAAA"}],"materials":[{"doubleSided":true,"pbrMetallicRoughness":{"baseColorFactor":[1,0,0,1],"metallicFactor":1,"roughnessFactor":1}}],"meshes":[{"primitives":[{"attributes":{"POSITION":0},"material":0,"mode":1}]}],"nodes":[{"mesh":0,"translation":[0,0,0]}],"scene":0,"scenes":[{"nodes":[0]}]}
2 changes: 1 addition & 1 deletion testdata/lattice_surgery_cnot.gltf

Large diffs are not rendered by default.

Loading

0 comments on commit 8106795

Please sign in to comment.