diff --git a/resources/shaders/gouraud.fs b/resources/shaders/gouraud.fs index 09003f407..dce033d7b 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/gouraud.fs @@ -1,6 +1,21 @@ #version 110 const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const vec3 GREEN = vec3(0.0, 0.7, 0.0); +const vec3 YELLOW = vec3(0.5, 0.7, 0.0); +const vec3 RED = vec3(0.7, 0.0, 0.0); +const float EPSILON = 0.0001; + +struct SlopeDetection +{ + bool active; + // x = yellow, y = red + vec2 z_range; + mat3 volume_world_normal_matrix; +}; + +uniform vec4 uniform_color; +uniform SlopeDetection slope; varying vec3 clipping_planes_dots; @@ -10,14 +25,20 @@ varying vec2 intensity; varying vec3 delta_box_min; varying vec3 delta_box_max; -uniform vec4 uniform_color; +varying float world_normal_z; +vec3 slope_color() +{ + float gradient_range = slope.z_range.x - slope.z_range.y; + return (world_normal_z > slope.z_range.x - EPSILON) ? GREEN : ((gradient_range == 0.0) ? RED : mix(RED, YELLOW, clamp((world_normal_z - slope.z_range.y) / gradient_range, 0.0, 1.0))); +} void main() { if (any(lessThan(clipping_planes_dots, ZERO))) discard; + vec3 color = slope.active ? slope_color() : uniform_color.rgb; // if the fragment is outside the print volume -> use darker color - vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb; + color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a); } diff --git a/resources/shaders/gouraud.vs b/resources/shaders/gouraud.vs index cc54c1c44..72d6c18b3 100644 --- a/resources/shaders/gouraud.vs +++ b/resources/shaders/gouraud.vs @@ -20,13 +20,22 @@ const vec3 ZERO = vec3(0.0, 0.0, 0.0); struct PrintBoxDetection { + bool active; vec3 min; vec3 max; - bool volume_detection; mat4 volume_world_matrix; }; +struct SlopeDetection +{ + bool active; + // x = yellow, y = red + vec2 z_range; + mat3 volume_world_normal_matrix; +}; + uniform PrintBoxDetection print_box; +uniform SlopeDetection slope; // Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. uniform vec2 z_range; @@ -41,6 +50,8 @@ varying vec3 delta_box_max; varying vec3 clipping_planes_dots; +varying float world_normal_z; + void main() { // First transform the normal into camera space and normalize the result. @@ -61,7 +72,7 @@ void main() intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; // compute deltas for out of print volume detection (world coordinates) - if (print_box.volume_detection) + if (print_box.active) { vec3 v = (print_box.volume_world_matrix * gl_Vertex).xyz; delta_box_min = v - print_box.min; @@ -73,6 +84,9 @@ void main() delta_box_max = ZERO; } + // z component of normal vector in world coordinate used for slope shading + world_normal_z = slope.active ? (normalize(slope.volume_world_normal_matrix * gl_Normal)).z : 0.0; + gl_Position = ftransform(); // Point in homogenous coordinates. vec4 world_pos = print_box.volume_world_matrix * gl_Vertex; diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index cd8bef794..57e4ed10d 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -535,8 +535,10 @@ int CLI::run(int argc, char **argv) gui->mainframe->load_config(m_extra_config); }); int result = wxEntry(argc, argv); +#if !ENABLE_NON_STATIC_CANVAS_MANAGER //FIXME this is a workaround for the PrusaSlicer 2.1 release. _3DScene::destroy(); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER return result; #else /* SLIC3R_GUI */ // No GUI support. Just print out a help. diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 6806f4f54..674410388 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -464,7 +464,7 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src, void ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append) { if (! this->set_deserialize_nothrow(opt_key_src, value_src, append)) - throw BadOptionTypeException("ConfigBase::set_deserialize() failed"); + throw BadOptionTypeException((boost::format("ConfigBase::set_deserialize() failed for parameter \"%1%\", value \"%2%\"") % opt_key_src % value_src).str()); } void ConfigBase::set_deserialize(std::initializer_list items) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index f02caf226..87e020898 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -56,10 +56,9 @@ public: class BadOptionTypeException : public std::runtime_error { public: - BadOptionTypeException() : - std::runtime_error("Bad option type exception") {} - BadOptionTypeException(const char* message) : - std::runtime_error(message) {} + BadOptionTypeException() : std::runtime_error("Bad option type exception") {} + BadOptionTypeException(const std::string &message) : std::runtime_error(message) {} + BadOptionTypeException(const char* message) : std::runtime_error(message) {} }; // Type of a configuration value. diff --git a/src/libslic3r/EdgeGrid.hpp b/src/libslic3r/EdgeGrid.hpp index 81517a5c4..6a9f482a1 100644 --- a/src/libslic3r/EdgeGrid.hpp +++ b/src/libslic3r/EdgeGrid.hpp @@ -218,10 +218,10 @@ public: bbox.min /= m_resolution; bbox.max /= m_resolution; // Trim with the cells. - bbox.min.x() = std::max(bbox.min.x(), 0); - bbox.min.y() = std::max(bbox.min.y(), 0); - bbox.max.x() = std::min(bbox.max.x(), (coord_t)m_cols - 1); - bbox.max.y() = std::min(bbox.max.y(), (coord_t)m_rows - 1); + bbox.min.x() = std::max(bbox.min.x(), 0); + bbox.min.y() = std::max(bbox.min.y(), 0); + bbox.max.x() = std::min(bbox.max.x(), (coord_t)m_cols - 1); + bbox.max.y() = std::min(bbox.max.y(), (coord_t)m_rows - 1); for (coord_t iy = bbox.min.y(); iy <= bbox.max.y(); ++ iy) for (coord_t ix = bbox.min.x(); ix <= bbox.max.x(); ++ ix) if (! visitor(iy, ix)) diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 9bdda3a4c..db398f06c 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -94,7 +94,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude // Reorder the extruders to minimize tool switches. this->reorder_extruders(first_extruder); - this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height); + this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, object.config().layer_height); this->collect_extruder_statistics(prime_multi_material); } @@ -107,6 +107,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool // Initialize the print layers for all objects and all layers. coordf_t object_bottom_z = 0.; + coordf_t max_layer_height = 0.; { std::vector zs; for (auto object : print.objects()) { @@ -122,6 +123,8 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool object_bottom_z = layer->print_z - layer->height; break; } + + max_layer_height = std::max(max_layer_height, object->config().layer_height.value); } this->initialize_layers(zs); } @@ -144,7 +147,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool // Reorder the extruders to minimize tool switches. this->reorder_extruders(first_extruder); - this->fill_wipe_tower_partitions(print.config(), object_bottom_z); + this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height); this->collect_extruder_statistics(prime_multi_material); } @@ -318,7 +321,7 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id) } } -void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z) +void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_object_layer_height) { if (m_layer_tools.empty()) return; @@ -351,6 +354,10 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ mlh = 0.75 * config.nozzle_diameter.values[i]; max_layer_height = std::min(max_layer_height, mlh); } + // The Prusa3D Fast (0.35mm layer height) print profile sets a higher layer height than what is normally allowed + // by the nozzle. This is a hack and it works by increasing extrusion width. + max_layer_height = std::max(max_layer_height, max_object_layer_height); + for (size_t i = 0; i + 1 < m_layer_tools.size(); ++ i) { const LayerTools < = m_layer_tools[i]; const LayerTools <_next = m_layer_tools[i + 1]; @@ -393,21 +400,47 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_ // and maybe other problems. We will therefore go through layer_tools and detect and fix this. // So, if there is a non-object layer starting with different extruder than the last one ended with (or containing more than one extruder), // we'll mark it with has_wipe tower. - for (unsigned int i=0; i+1 1)) - lt_next.has_wipe_tower = true; - // We should also check that the next wipe tower layer is no further than max_layer_height: - unsigned int j = i+1; - double last_wipe_tower_print_z = lt_next.print_z; - while (++j < m_layer_tools.size()-1 && !m_layer_tools[j].has_wipe_tower) - if (m_layer_tools[j+1].print_z - last_wipe_tower_print_z > max_layer_height) { - m_layer_tools[j].has_wipe_tower = true; - last_wipe_tower_print_z = m_layer_tools[j].print_z; + assert(! m_layer_tools.empty() && m_layer_tools.front().has_wipe_tower); + if (! m_layer_tools.empty() && m_layer_tools.front().has_wipe_tower) { + for (size_t i = 0; i + 1 < m_layer_tools.size();) { + const LayerTools < = m_layer_tools[i]; + assert(lt.has_wipe_tower); + assert(! lt.extruders.empty()); + // Find the next layer with wipe tower or mark a layer as such. + size_t j = i + 1; + for (; j < m_layer_tools.size() && ! m_layer_tools[j].has_wipe_tower; ++ j) { + LayerTools <_next = m_layer_tools[j]; + if (lt_next.extruders.empty()) { + //FIXME Vojtech: Lukasi, proc? + j = m_layer_tools.size(); + break; + } + if (lt_next.extruders.front() != lt.extruders.back() || lt_next.extruders.size() > 1) { + // Support only layer, soluble layers? Otherwise the layer should have been already marked as having wipe tower. + assert(lt_next.has_support && ! lt_next.has_object); + lt_next.has_wipe_tower = true; + break; + } } + if (j == m_layer_tools.size()) + // No wipe tower above layer i, therefore no need to add any wipe tower layer above i. + break; + // We should also check that the next wipe tower layer is no further than max_layer_height. + // This algorith may in theory create very thin wipe layer j if layer closely below j is marked as wipe tower. + // This may happen if printing with non-soluble break away supports. + // On the other side it should not hurt as there will be no wipe, just perimeter and sparse infill printed + // at that particular wipe tower layer without extruder change. + double last_wipe_tower_print_z = lt.print_z; + assert(m_layer_tools[j].has_wipe_tower); + for (size_t k = i + 1; k < j; ++k) { + assert(! m_layer_tools[k].has_wipe_tower); + if (m_layer_tools[k + 1].print_z - last_wipe_tower_print_z > max_layer_height + EPSILON) { + m_layer_tools[k].has_wipe_tower = true; + last_wipe_tower_print_z = m_layer_tools[k].print_z; + } + } + i = j; + } } // Calculate the wipe_tower_layer_height values. diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp index a82db2d04..5fe27516d 100644 --- a/src/libslic3r/GCode/ToolOrdering.hpp +++ b/src/libslic3r/GCode/ToolOrdering.hpp @@ -166,7 +166,7 @@ private: void initialize_layers(std::vector &zs); void collect_extruders(const PrintObject &object, const std::vector> &per_layer_extruder_switches); void reorder_extruders(unsigned int last_extruder_id); - void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z); + void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height); void collect_extruder_statistics(bool prime_multi_material); std::vector m_layer_tools; diff --git a/src/libslic3r/MeshBoolean.cpp b/src/libslic3r/MeshBoolean.cpp index 6c5418fd4..66167c720 100644 --- a/src/libslic3r/MeshBoolean.cpp +++ b/src/libslic3r/MeshBoolean.cpp @@ -29,7 +29,7 @@ TriangleMesh eigen_to_triangle_mesh(const EigenMesh &emesh) auto &VC = emesh.first; auto &FC = emesh.second; Pointf3s points(size_t(VC.rows())); - std::vector facets(size_t(FC.rows())); + std::vector facets(size_t(FC.rows())); for (Eigen::Index i = 0; i < VC.rows(); ++i) points[size_t(i)] = VC.row(i); @@ -154,7 +154,7 @@ inline Vec3d to_vec3d(const _EpecMesh::Point &v) template TriangleMesh cgal_to_triangle_mesh(const _Mesh &cgalmesh) { Pointf3s points; - std::vector facets; + std::vector facets; points.reserve(cgalmesh.num_vertices()); facets.reserve(cgalmesh.num_faces()); @@ -166,7 +166,7 @@ template TriangleMesh cgal_to_triangle_mesh(const _Mesh &cgalmesh) for (auto &face : cgalmesh.faces()) { auto vtc = cgalmesh.vertices_around_face(cgalmesh.halfedge(face)); int i = 0; - Vec3crd trface; + Vec3i trface; for (auto v : vtc) trface(i++) = static_cast(v); facets.emplace_back(trface); } diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index dced5c02a..e095f1c75 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -24,7 +24,9 @@ typedef Eigen::Matrix Vec2crd; typedef Eigen::Matrix Vec3crd; typedef Eigen::Matrix Vec2i; typedef Eigen::Matrix Vec3i; +typedef Eigen::Matrix Vec2i32; typedef Eigen::Matrix Vec2i64; +typedef Eigen::Matrix Vec3i32; typedef Eigen::Matrix Vec3i64; // Vector types with a double coordinate base type. @@ -53,12 +55,12 @@ typedef Eigen::Transform Transform3d inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); } +inline int32_t cross2(const Vec2i32 &v1, const Vec2i32 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } inline int64_t cross2(const Vec2i64 &v1, const Vec2i64 &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } -inline coord_t cross2(const Vec2crd &v1, const Vec2crd &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } inline float cross2(const Vec2f &v1, const Vec2f &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } inline double cross2(const Vec2d &v1, const Vec2d &v2) { return v1(0) * v2(1) - v1(1) * v2(0); } -inline Vec2crd to_2d(const Vec3crd &pt3) { return Vec2crd(pt3(0), pt3(1)); } +inline Vec2i32 to_2d(const Vec2i32 &pt3) { return Vec2i32(pt3(0), pt3(1)); } inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); } inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); } inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); } @@ -89,8 +91,8 @@ public: typedef coord_t coord_type; Point() : Vec2crd(0, 0) {} - Point(coord_t x, coord_t y) : Vec2crd(x, y) {} - Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {} // for Clipper + Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {} + Point(int64_t x, int64_t y) : Vec2crd(coord_t(x), coord_t(y)) {} Point(double x, double y) : Vec2crd(coord_t(lrint(x)), coord_t(lrint(y))) {} Point(const Point &rhs) { *this = rhs; } explicit Point(const Vec2d& rhs) : Vec2crd(coord_t(lrint(rhs.x())), coord_t(lrint(rhs.y()))) {} diff --git a/src/libslic3r/SLA/Common.cpp b/src/libslic3r/SLA/Common.cpp index d2aac18fd..9945ed7fa 100644 --- a/src/libslic3r/SLA/Common.cpp +++ b/src/libslic3r/SLA/Common.cpp @@ -228,7 +228,7 @@ void to_eigen_mesh(const TriangleMesh &tmesh, Eigen::MatrixXd &V, Eigen::MatrixX void to_triangle_mesh(const Eigen::MatrixXd &V, const Eigen::MatrixXi &F, TriangleMesh &out) { Pointf3s points(size_t(V.rows())); - std::vector facets(size_t(F.rows())); + std::vector facets(size_t(F.rows())); for (Eigen::Index i = 0; i < V.rows(); ++i) points[size_t(i)] = V.row(i); diff --git a/src/libslic3r/SLA/SupportTreeBuilder.cpp b/src/libslic3r/SLA/SupportTreeBuilder.cpp index d385e98a2..cf6e7e020 100644 --- a/src/libslic3r/SLA/SupportTreeBuilder.cpp +++ b/src/libslic3r/SLA/SupportTreeBuilder.cpp @@ -48,9 +48,8 @@ Contour3D sphere(double rho, Portion portion, double fa) { vertices.emplace_back(Vec3d(b(0), b(1), z)); if (sbegin == 0) - facets.emplace_back((i == 0) ? - Vec3crd(coord_t(ring.size()), 0, 1) : - Vec3crd(id - 1, 0, id)); + (i == 0) ? facets.emplace_back(coord_t(ring.size()), 0, 1) : + facets.emplace_back(id - 1, 0, id); ++id; } @@ -66,12 +65,11 @@ Contour3D sphere(double rho, Portion portion, double fa) { auto id_ringsize = coord_t(id - int(ring.size())); if (i == 0) { // wrap around - facets.emplace_back(Vec3crd(id - 1, id, - id + coord_t(ring.size() - 1))); - facets.emplace_back(Vec3crd(id - 1, id_ringsize, id)); + facets.emplace_back(id - 1, id, id + coord_t(ring.size() - 1) ); + facets.emplace_back(id - 1, id_ringsize, id); } else { - facets.emplace_back(Vec3crd(id_ringsize - 1, id_ringsize, id)); - facets.emplace_back(Vec3crd(id - 1, id_ringsize - 1, id)); + facets.emplace_back(id_ringsize - 1, id_ringsize, id); + facets.emplace_back(id - 1, id_ringsize - 1, id); } id++; } @@ -85,10 +83,10 @@ Contour3D sphere(double rho, Portion portion, double fa) { auto id_ringsize = coord_t(id - int(ring.size())); if (i == 0) { // third vertex is on the other side of the ring. - facets.emplace_back(Vec3crd(id - 1, id_ringsize, id)); + facets.emplace_back(id - 1, id_ringsize, id); } else { auto ci = coord_t(id_ringsize + coord_t(i)); - facets.emplace_back(Vec3crd(ci - 1, ci, id)); + facets.emplace_back(ci - 1, ci, id); } } } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 7b241037d..44c10fa54 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -44,6 +44,22 @@ // Enable fix for dragging mouse event handling for gizmobar #define ENABLE_GIZMO_TOOLBAR_DRAGGING_FIX (1 && ENABLE_2_2_0_FINAL) +//============ +// 2.3.0 techs +//============ +#define ENABLE_2_3_0 1 + +// Enable rendering of objects colored by facets' slope +#define ENABLE_SLOPE_RENDERING (1 && ENABLE_2_3_0) + +//=================== +// 2.3.0.alpha1 techs +//=================== +#define ENABLE_2_3_0_ALPHA1 1 + +// Moves GLCanvas3DManager from being a static member of _3DScene to be a normal member of GUI_App +#define ENABLE_NON_STATIC_CANVAS_MANAGER (1 && ENABLE_2_3_0_ALPHA1) + //================== // 2.3.0.alpha1 techs diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index ee5e96f3d..f2deb5cba 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -42,7 +42,7 @@ namespace Slic3r { -TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& facets) : repaired(false) +TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector &facets) : repaired(false) { stl_file &stl = this->stl; stl.stats.type = inmemory; @@ -600,7 +600,7 @@ TriangleMesh TriangleMesh::convex_hull_3d() const // Let's collect results: Pointf3s dst_vertices; - std::vector facets; + std::vector facets; auto facet_list = qhull.facetList().toStdVector(); for (const orgQhull::QhullFacet& facet : facet_list) { // iterate through facets @@ -1931,22 +1931,18 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) // Generate the vertex list for a cube solid of arbitrary size in X/Y/Z. TriangleMesh make_cube(double x, double y, double z) { - Vec3d pv[8] = { - Vec3d(x, y, 0), Vec3d(x, 0, 0), Vec3d(0, 0, 0), - Vec3d(0, y, 0), Vec3d(x, y, z), Vec3d(0, y, z), - Vec3d(0, 0, z), Vec3d(x, 0, z) - }; - Vec3crd fv[12] = { - Vec3crd(0, 1, 2), Vec3crd(0, 2, 3), Vec3crd(4, 5, 6), - Vec3crd(4, 6, 7), Vec3crd(0, 4, 7), Vec3crd(0, 7, 1), - Vec3crd(1, 7, 6), Vec3crd(1, 6, 2), Vec3crd(2, 6, 5), - Vec3crd(2, 5, 3), Vec3crd(4, 0, 3), Vec3crd(4, 3, 5) - }; - - std::vector facets(&fv[0], &fv[0]+12); - Pointf3s vertices(&pv[0], &pv[0]+8); - - TriangleMesh mesh(vertices ,facets); + TriangleMesh mesh( + { + {x, y, 0}, {x, 0, 0}, {0, 0, 0}, + {0, y, 0}, {x, y, z}, {0, y, z}, + {0, 0, z}, {x, 0, z} + }, + { + {0, 1, 2}, {0, 2, 3}, {4, 5, 6}, + {4, 6, 7}, {0, 4, 7}, {0, 7, 1}, + {1, 7, 6}, {1, 6, 2}, {2, 6, 5}, + {2, 5, 3}, {4, 0, 3}, {4, 3, 5} + }); mesh.repair(); return mesh; } @@ -1959,8 +1955,8 @@ TriangleMesh make_cylinder(double r, double h, double fa) size_t n_steps = (size_t)ceil(2. * PI / fa); double angle_step = 2. * PI / n_steps; - Pointf3s vertices; - std::vector facets; + Pointf3s vertices; + std::vector facets; vertices.reserve(2 * n_steps + 2); facets.reserve(4 * n_steps); @@ -1980,17 +1976,17 @@ TriangleMesh make_cylinder(double r, double h, double fa) vertices.emplace_back(Vec3d(p(0), p(1), 0.)); vertices.emplace_back(Vec3d(p(0), p(1), h)); int id = (int)vertices.size() - 1; - facets.emplace_back(Vec3crd( 0, id - 1, id - 3)); // top - facets.emplace_back(Vec3crd(id, 1, id - 2)); // bottom - facets.emplace_back(Vec3crd(id, id - 2, id - 3)); // upper-right of side - facets.emplace_back(Vec3crd(id, id - 3, id - 1)); // bottom-left of side + facets.emplace_back( 0, id - 1, id - 3); // top + facets.emplace_back(id, 1, id - 2); // bottom + facets.emplace_back(id, id - 2, id - 3); // upper-right of side + facets.emplace_back(id, id - 3, id - 1); // bottom-left of side } // Connect the last set of vertices with the first. int id = (int)vertices.size() - 1; - facets.emplace_back(Vec3crd( 0, 2, id - 1)); - facets.emplace_back(Vec3crd( 3, 1, id)); - facets.emplace_back(Vec3crd(id, 2, 3)); - facets.emplace_back(Vec3crd(id, id - 1, 2)); + facets.emplace_back( 0, 2, id - 1); + facets.emplace_back( 3, 1, id); + facets.emplace_back(id, 2, 3); + facets.emplace_back(id, id - 1, 2); TriangleMesh mesh(std::move(vertices), std::move(facets)); mesh.repair(); @@ -2025,7 +2021,7 @@ TriangleMesh make_sphere(double radius, double fa) } } - std::vector facets; + std::vector facets; facets.reserve(2 * (stackCount - 1) * sectorCount); for (int i = 0; i < stackCount; ++ i) { // Beginning of current stack. @@ -2040,11 +2036,11 @@ TriangleMesh make_sphere(double radius, double fa) int k2_next = k2; if (i != 0) { k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1); - facets.emplace_back(Vec3crd(k1, k2, k1_next)); + facets.emplace_back(k1, k2, k1_next); } if (i + 1 != stackCount) { k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1); - facets.emplace_back(Vec3crd(k1_next, k2, k2_next)); + facets.emplace_back(k1_next, k2, k2_next); } k1 = k1_next; k2 = k2_next; diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index bd872a975..723125aaa 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -22,7 +22,7 @@ class TriangleMesh { public: TriangleMesh() : repaired(false) {} - TriangleMesh(const Pointf3s &points, const std::vector &facets); + TriangleMesh(const Pointf3s &points, const std::vector &facets); explicit TriangleMesh(const indexed_triangle_set &M); void clear() { this->stl.clear(); this->its.clear(); this->repaired = false; } bool ReadSTLFile(const char* input_file) { return stl_open(&stl, input_file); } diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 41d9ac1ff..1cf946f8b 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -21,7 +21,13 @@ #include "Technologies.hpp" #include "Semver.hpp" +#if 1 +// Saves around 32% RAM after slicing step, 6.7% after G-code export (tested on PrusaSlicer 2.2.0 final). typedef int32_t coord_t; +#else +typedef int64_t coord_t; +#endif + typedef double coordf_t; //FIXME This epsilon value is used for many non-related purposes: @@ -33,6 +39,7 @@ typedef double coordf_t; // This scaling generates a following fixed point representation with for a 32bit integer: // 0..4294mm with 1nm resolution // int32_t fits an interval of (-2147.48mm, +2147.48mm) +// with int64_t we don't have to worry anymore about the size of the int. #define SCALING_FACTOR 0.000001 // RESOLUTION, SCALED_RESOLUTION: Used as an error threshold for a Douglas-Peucker polyline simplification algorithm. #define RESOLUTION 0.0125 diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index de56546ac..c13c1b937 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -394,6 +394,7 @@ void GLVolume::render() const glFrontFace(GL_CCW); } +#if !ENABLE_SLOPE_RENDERING void GLVolume::render(int color_id, int detection_id, int worldmatrix_id) const { if (color_id >= 0) @@ -409,6 +410,7 @@ void GLVolume::render(int color_id, int detection_id, int worldmatrix_id) const render(); } +#endif // !ENABLE_SLOPE_RENDERING bool GLVolume::is_sla_support() const { return this->composite_id.volume_id == -int(slaposSupportTree); } bool GLVolume::is_sla_pad() const { return this->composite_id.volume_id == -int(slaposPad); } @@ -535,16 +537,16 @@ int GLVolumeCollection::load_wipe_tower_preview( // We'll now create the box with jagged edge. y-coordinates of the pre-generated model are shifted so that the front // edge has y=0 and centerline of the back edge has y=depth: Pointf3s points; - std::vector facets; + std::vector facets; float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 }, { 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } }; int out_facets_idx[][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 5, 0 }, { 3, 5, 6 }, { 6, 2, 7 }, { 6, 0, 2 }, { 8, 9, 10 }, { 11, 12, 13 }, { 10, 11, 14 }, { 14, 11, 13 }, { 15, 8, 14 }, {8, 10, 14}, {3, 12, 4}, {3, 13, 12}, {6, 13, 3}, {6, 14, 13}, {7, 14, 6}, {7, 15, 14}, {2, 15, 7}, {2, 8, 15}, {1, 8, 2}, {1, 9, 8}, {0, 9, 1}, {0, 10, 9}, {5, 10, 0}, {5, 11, 10}, {4, 11, 5}, {4, 12, 11} }; for (int i = 0; i < 16; ++i) - points.push_back(Vec3d(out_points_idx[i][0] / (100.f / min_width), out_points_idx[i][1] + depth, out_points_idx[i][2])); + points.emplace_back(out_points_idx[i][0] / (100.f / min_width), out_points_idx[i][1] + depth, out_points_idx[i][2]); for (int i = 0; i < 28; ++i) - facets.push_back(Vec3crd(out_facets_idx[i][0], out_facets_idx[i][1], out_facets_idx[i][2])); + facets.emplace_back(out_facets_idx[i][0], out_facets_idx[i][1], out_facets_idx[i][2]); TriangleMesh tooth_mesh(points, facets); // We have the mesh ready. It has one tooth and width of min_width. We will now append several of these together until we are close to @@ -650,28 +652,64 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "z_range") : -1; GLint clipping_plane_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "clipping_plane") : -1; + GLint print_box_min_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.min") : -1; GLint print_box_max_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.max") : -1; - GLint print_box_detection_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1; + GLint print_box_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.active") : -1; GLint print_box_worldmatrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1; + +#if ENABLE_SLOPE_RENDERING + GLint slope_active_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.active") : -1; + GLint slope_normal_matrix_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.volume_world_normal_matrix") : -1; + GLint slope_z_range_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "slope.z_range") : -1; +#endif // ENABLE_SLOPE_RENDERING glcheck(); if (print_box_min_id != -1) - glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min)); + glsafe(::glUniform3fv(print_box_min_id, 1, (const GLfloat*)m_print_box_min)); if (print_box_max_id != -1) - glsafe(::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max)); + glsafe(::glUniform3fv(print_box_max_id, 1, (const GLfloat*)m_print_box_max)); if (z_range_id != -1) - glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range)); + glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)m_z_range)); if (clipping_plane_id != -1) - glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)clipping_plane)); + glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)m_clipping_plane)); + +#if ENABLE_SLOPE_RENDERING + if (slope_z_range_id != -1) + glsafe(::glUniform2fv(slope_z_range_id, 1, (const GLfloat*)m_slope.z_range.data())); +#endif // ENABLE_SLOPE_RENDERING GLVolumeWithIdAndZList to_render = volumes_to_render(this->volumes, type, view_matrix, filter_func); for (GLVolumeWithIdAndZ& volume : to_render) { volume.first->set_render_color(); +#if ENABLE_SLOPE_RENDERING + if (color_id >= 0) + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)volume.first->render_color)); + else + glsafe(::glColor4fv(volume.first->render_color)); + + if (print_box_active_id != -1) + glsafe(::glUniform1i(print_box_active_id, volume.first->shader_outside_printer_detection_enabled ? 1 : 0)); + + if (print_box_worldmatrix_id != -1) + glsafe(::glUniformMatrix4fv(print_box_worldmatrix_id, 1, GL_FALSE, (const GLfloat*)volume.first->world_matrix().cast().data())); + + if (slope_active_id != -1) + glsafe(::glUniform1i(slope_active_id, m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower ? 1 : 0)); + + if (slope_normal_matrix_id != -1) + { + Matrix3f normal_matrix = volume.first->world_matrix().matrix().block(0, 0, 3, 3).inverse().transpose().cast(); + glsafe(::glUniformMatrix3fv(slope_normal_matrix_id, 1, GL_FALSE, (const GLfloat*)normal_matrix.data())); + } + + volume.first->render(); +#else volume.first->render(color_id, print_box_detection_id, print_box_worldmatrix_id); +#endif // ENABLE_SLOPE_RENDERING } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); @@ -1816,7 +1854,9 @@ void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height thick_point_to_verts(point, width, height, volume); } +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GUI::GLCanvas3DManager _3DScene::s_canvas_mgr; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER GLModel::GLModel() : m_filename("") @@ -1885,7 +1925,16 @@ void GLModel::render() const GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1; glcheck(); +#if ENABLE_SLOPE_RENDERING + if (color_id >= 0) + glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)m_volume.render_color)); + else + glsafe(::glColor4fv(m_volume.render_color)); + + m_volume.render(); +#else m_volume.render(color_id, -1, -1); +#endif // ENABLE_SLOPE_RENDERING glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); @@ -1899,7 +1948,7 @@ void GLModel::render() const bool GLArrow::on_init() { Pointf3s vertices; - std::vector triangles; + std::vector triangles; // bottom face vertices.emplace_back(0.5, 0.0, -0.1); @@ -1965,7 +2014,7 @@ GLCurvedArrow::GLCurvedArrow(unsigned int resolution) bool GLCurvedArrow::on_init() { Pointf3s vertices; - std::vector triangles; + std::vector triangles; double ext_radius = 2.5; double int_radius = 1.5; @@ -2099,6 +2148,7 @@ bool GLBed::on_init_from_file(const std::string& filename) return true; } +#if !ENABLE_NON_STATIC_CANVAS_MANAGER std::string _3DScene::get_gl_info(bool format_as_html, bool extensions) { return Slic3r::GUI::GLCanvas3DManager::get_gl_info().to_string(format_as_html, extensions); @@ -2133,5 +2183,6 @@ GUI::GLCanvas3D* _3DScene::get_canvas(wxGLCanvas* canvas) { return s_canvas_mgr.get_canvas(canvas); } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER } // namespace Slic3r diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 1fc8308f7..70d6fb016 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -7,7 +7,9 @@ #include "libslic3r/TriangleMesh.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Model.hpp" +#if !ENABLE_NON_STATIC_CANVAS_MANAGER #include "slic3r/GUI/GLCanvas3DManager.hpp" +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER #include @@ -443,7 +445,9 @@ public: void set_range(double low, double high); void render() const; +#if !ENABLE_SLOPE_RENDERING void render(int color_id, int detection_id, int worldmatrix_id) const; +#endif // !ENABLE_SLOPE_RENDERING void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array.finalize_geometry(opengl_initialized); } void release_geometry() { this->indexed_vertex_array.release_geometry(); } @@ -479,20 +483,36 @@ public: private: // min and max vertex of the print box volume - float print_box_min[3]; - float print_box_max[3]; + float m_print_box_min[3]; + float m_print_box_max[3]; // z range for clipping in shaders - float z_range[2]; + float m_z_range[2]; // plane coeffs for clipping in shaders - float clipping_plane[4]; + float m_clipping_plane[4]; + +#if ENABLE_SLOPE_RENDERING + struct Slope + { + // toggle for slope rendering + bool active{ false }; + // [0] = yellow, [1] = red + std::array z_range; + }; + + Slope m_slope; +#endif // ENABLE_SLOPE_RENDERING public: GLVolumePtrs volumes; - GLVolumeCollection() {}; - ~GLVolumeCollection() { clear(); }; +#if ENABLE_SLOPE_RENDERING + GLVolumeCollection() { set_default_slope_z_range(); } +#else + GLVolumeCollection() = default; +#endif // ENABLE_SLOPE_RENDERING + ~GLVolumeCollection() { clear(); } std::vector load_object( const ModelObject *model_object, @@ -543,12 +563,21 @@ public: void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); } void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { - print_box_min[0] = min_x; print_box_min[1] = min_y; print_box_min[2] = min_z; - print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z; + m_print_box_min[0] = min_x; m_print_box_min[1] = min_y; m_print_box_min[2] = min_z; + m_print_box_max[0] = max_x; m_print_box_max[1] = max_y; m_print_box_max[2] = max_z; } - void set_z_range(float min_z, float max_z) { z_range[0] = min_z; z_range[1] = max_z; } - void set_clipping_plane(const double* coeffs) { clipping_plane[0] = coeffs[0]; clipping_plane[1] = coeffs[1]; clipping_plane[2] = coeffs[2]; clipping_plane[3] = coeffs[3]; } + void set_z_range(float min_z, float max_z) { m_z_range[0] = min_z; m_z_range[1] = max_z; } + void set_clipping_plane(const double* coeffs) { m_clipping_plane[0] = coeffs[0]; m_clipping_plane[1] = coeffs[1]; m_clipping_plane[2] = coeffs[2]; m_clipping_plane[3] = coeffs[3]; } + +#if ENABLE_SLOPE_RENDERING + bool is_slope_active() const { return m_slope.active; } + void set_slope_active(bool active) { m_slope.active = active; } + + const std::array& get_slope_z_range() const { return m_slope.z_range; } + void set_slope_z_range(const std::array& range) { m_slope.z_range = range; } + void set_default_slope_z_range() { m_slope.z_range = { -::cos(Geometry::deg2rad(90.0f - 45.0f)), -::cos(Geometry::deg2rad(90.0f - 70.0f)) }; } +#endif // ENABLE_SLOPE_RENDERING // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null @@ -639,10 +668,17 @@ protected: bool on_init_from_file(const std::string& filename) override; }; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +struct _3DScene +#else class _3DScene +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { +#if !ENABLE_NON_STATIC_CANVAS_MANAGER static GUI::GLCanvas3DManager s_canvas_mgr; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER +#if !ENABLE_NON_STATIC_CANVAS_MANAGER public: static std::string get_gl_info(bool format_as_html, bool extensions); @@ -654,6 +690,7 @@ public: static void destroy(); static GUI::GLCanvas3D* get_canvas(wxGLCanvas* canvas); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER static void thick_lines_to_verts(const Lines& lines, const std::vector& widths, const std::vector& heights, bool closed, double top_z, GLVolume& volume); static void thick_lines_to_verts(const Lines3& lines, const std::vector& widths, const std::vector& heights, bool closed, GLVolume& volume); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 53a661c7a..d8b102cee 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -20,6 +20,9 @@ #include "slic3r/GUI/PresetBundle.hpp" #include "slic3r/GUI/Tab.hpp" #include "slic3r/GUI/GUI_Preview.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "slic3r/GUI/GLCanvas3DManager.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include "slic3r/GUI/3DBed.hpp" #include "slic3r/GUI/Camera.hpp" @@ -359,7 +362,11 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) float half_w = 0.5f * (float)cnv_size.get_width(); float half_h = 0.5f * (float)cnv_size.get_height(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)canvas.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER return Rect((half_w - thickness_bar_width(canvas)) * inv_zoom, half_h * inv_zoom, half_w * inv_zoom, -half_h * inv_zoom); } @@ -774,6 +781,13 @@ bool GLCanvas3D::WarningTexture::generate(const std::string& msg_utf8, const GLC #else // select default font const float scale = canvas.get_canvas_size().get_scale_factor(); +#if ENABLE_RETINA_GL + // For non-visible or non-created window getBackingScaleFactor function return 0.0 value. + // And using of the zero scale causes a crash, when we trying to draw text to the (0,0) rectangle + // https://github.com/prusa3d/PrusaSlicer/issues/3916 + if (scale <= 0.0f) + return false; +#endif wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale); #endif @@ -851,7 +865,11 @@ void GLCanvas3D::WarningTexture::render(const GLCanvas3D& canvas) const if ((m_id > 0) && (m_original_width > 0) && (m_original_height > 0) && (m_width > 0) && (m_height > 0)) { const Size& cnv_size = canvas.get_canvas_size(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)canvas.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float left = (-0.5f * (float)m_original_width) * inv_zoom; float top = (-0.5f * (float)cnv_size.get_height() + (float)m_original_height + 2.0f) * inv_zoom; float right = left + (float)m_original_width * inv_zoom; @@ -1218,7 +1236,11 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const if ((m_id > 0) && (m_original_width > 0) && (m_original_height > 0) && (m_width > 0) && (m_height > 0)) { const Size& cnv_size = canvas.get_canvas_size(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)canvas.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float left = (-0.5f * (float)cnv_size.get_width()) * inv_zoom; float top = (0.5f * (float)cnv_size.get_height()) * inv_zoom; float right = left + (float)m_original_width * inv_zoom; @@ -1244,7 +1266,11 @@ void GLCanvas3D::Labels::render(const std::vector& sorted_ if (!m_enabled || !is_shown()) return; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); +#else const Camera& camera = m_canvas.get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const Model* model = m_canvas.get_model(); if (model == nullptr) return; @@ -1426,6 +1452,62 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas } #endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI +#if ENABLE_SLOPE_RENDERING +void GLCanvas3D::Slope::render() const +{ + if (is_shown()) + { + const std::array& z_range = m_volumes.get_slope_z_range(); + std::array angle_range = { Geometry::rad2deg(::acos(z_range[0])) - 90.0f, Geometry::rad2deg(::acos(z_range[1])) - 90.0f }; + bool modified = false; + + ImGuiWrapper& imgui = *wxGetApp().imgui(); + const Size& cnv_size = m_canvas.get_canvas_size(); + imgui.set_next_window_pos((float)cnv_size.get_width(), (float)cnv_size.get_height(), ImGuiCond_Always, 1.0f, 1.0f); + imgui.begin(_(L("Slope visualization")), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + + imgui.text(_(L("Facets' normal angle range (degrees)")) + ":"); + + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.75f, 0.75f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(1.0f, 1.0f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.85f, 0.85f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.25f, 0.25f, 0.0f, 1.0f)); + if (ImGui::SliderFloat("##yellow", &angle_range[0], 0.0f, 90.0f, "%.1f")) + { + modified = true; + if (angle_range[1] < angle_range[0]) + angle_range[1] = angle_range[0]; + } + ImGui::PopStyleColor(4); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.75f, 0.0f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(1.0f, 0.0f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.85f, 0.0f, 0.0f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(0.25f, 0.0f, 0.0f, 1.0f)); + if (ImGui::SliderFloat("##red", &angle_range[1], 0.0f, 90.0f, "%.1f")) + { + modified = true; + if (angle_range[0] > angle_range[1]) + angle_range[0] = angle_range[1]; + } + ImGui::PopStyleColor(4); + + ImGui::Separator(); + + if (imgui.button(_(L("Default")))) + m_volumes.set_default_slope_z_range(); + + // to let the dialog immediately showup without waiting for a mouse move + if (ImGui::GetWindowContentRegionWidth() + 2.0f * ImGui::GetStyle().WindowPadding.x != ImGui::CalcWindowExpectedSize(ImGui::GetCurrentWindow()).x) + m_canvas.request_extra_frame(); + + imgui.end(); + + if (modified) + m_volumes.set_slope_z_range({ -::cos(Geometry::deg2rad(90.0f - angle_range[0])), -::cos(Geometry::deg2rad(90.0f - angle_range[1])) }); + } + } +#endif // ENABLE_SLOPE_RENDERING + wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent); @@ -1457,16 +1539,22 @@ wxDEFINE_EVENT(EVT_GLCANVAS_RELOAD_FROM_DISK, SimpleEvent); const double GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) +#else GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER : m_canvas(canvas) , m_context(nullptr) #if ENABLE_RETINA_GL , m_retina_helper(nullptr) #endif , m_in_render(false) +#if !ENABLE_NON_STATIC_CANVAS_MANAGER , m_bed(bed) , m_camera(camera) , m_view_toolbar(view_toolbar) +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER , m_main_toolbar(GLToolbar::Normal, "Top") , m_undoredo_toolbar(GLToolbar::Normal, "Top") , m_gizmos(*this) @@ -1494,14 +1582,19 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar #endif // ENABLE_RENDER_PICKING_PASS , m_render_sla_auxiliaries(true) , m_labels(*this) +#if ENABLE_SLOPE_RENDERING + , m_slope(*this, m_volumes) +#endif // ENABLE_SLOPE_RENDERING { if (m_canvas != nullptr) { m_timer.SetOwner(m_canvas); #if ENABLE_RETINA_GL m_retina_helper.reset(new RetinaHelper(canvas)); +#if !ENABLE_NON_STATIC_CANVAS_MANAGER // set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size m_view_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size); -#endif +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER +#endif // ENABLE_RETINA_GL } m_selection.set_volumes(&m_volumes.volumes); @@ -1614,6 +1707,18 @@ void GLCanvas3D::reset_volumes() if (!m_initialized) return; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (m_volumes.empty()) + return; + + _set_current(); + + m_selection.clear(); + m_volumes.clear(); + m_dirty = true; + + _set_warning_texture(WarningTexture::ObjectOutside, false); +#else _set_current(); if (!m_volumes.empty()) @@ -1624,6 +1729,7 @@ void GLCanvas3D::reset_volumes() } _set_warning_texture(WarningTexture::ObjectOutside, false); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } int GLCanvas3D::check_volumes_outside_state() const @@ -1705,7 +1811,11 @@ void GLCanvas3D::set_model(Model* model) void GLCanvas3D::bed_shape_changed() { refresh_camera_scene_box(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().requires_zoom_to_bed = true; +#else m_camera.requires_zoom_to_bed = true; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_dirty = true; } @@ -1714,6 +1824,15 @@ void GLCanvas3D::set_color_by(const std::string& value) m_color_by = value; } +void GLCanvas3D::refresh_camera_scene_box() +{ +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box()); +#else + m_camera.set_scene_box(scene_bounding_box()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER +} + BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const { BoundingBoxf3 bb; @@ -1728,7 +1847,11 @@ BoundingBoxf3 GLCanvas3D::volumes_bounding_box() const BoundingBoxf3 GLCanvas3D::scene_bounding_box() const { BoundingBoxf3 bb = volumes_bounding_box(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bb.merge(wxGetApp().plater()->get_bed().get_bounding_box(true)); +#else bb.merge(m_bed.get_bounding_box(true)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER if (m_config != nullptr) { @@ -1781,6 +1904,11 @@ bool GLCanvas3D::is_reload_delayed() const void GLCanvas3D::enable_layers_editing(bool enable) { +#if ENABLE_SLOPE_RENDERING + if (enable && m_slope.is_shown()) + m_slope.show(false); +#endif // ENABLE_SLOPE_RENDERING + m_layers_editing.set_enabled(enable); const Selection::IndicesList& idxs = m_selection.get_volume_idxs(); for (unsigned int idx : idxs) @@ -1841,7 +1969,11 @@ void GLCanvas3D::allow_multisample(bool allow) void GLCanvas3D::zoom_to_bed() { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + _zoom_to_box(wxGetApp().plater()->get_bed().get_bounding_box(false)); +#else _zoom_to_box(m_bed.get_bounding_box(false)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } void GLCanvas3D::zoom_to_volumes() @@ -1859,7 +1991,11 @@ void GLCanvas3D::zoom_to_selection() void GLCanvas3D::select_view(const std::string& direction) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().select_view(direction); +#else m_camera.select_view(direction); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER if (m_canvas != nullptr) m_canvas->Refresh(); } @@ -1887,14 +2023,26 @@ void GLCanvas3D::render() return; // ensures this canvas is current and initialized +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (!_is_shown_on_screen() || !_set_current() || !wxGetApp().init_opengl()) + return; + + if (!is_initialized() && !init()) + return; +#else if (! _is_shown_on_screen() || !_set_current() || !_3DScene::init(m_canvas)) return; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #if ENABLE_RENDER_STATISTICS auto start_time = std::chrono::high_resolution_clock::now(); #endif // ENABLE_RENDER_STATISTICS +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (wxGetApp().plater()->get_bed().get_shape().empty()) +#else if (m_bed.get_shape().empty()) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { // this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE post_event(SimpleEvent(EVT_GLCANVAS_UPDATE_BED_SHAPE)); @@ -1906,6 +2054,20 @@ void GLCanvas3D::render() // to preview, this was called before canvas had its final size. It reported zero width // and the viewport was set incorrectly, leading to tripping glAsserts further down // the road (in apply_projection). That's why the minimum size is forced to 10. +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Camera& camera = wxGetApp().plater()->get_camera(); + camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); + + if (camera.requires_zoom_to_bed) + { + zoom_to_bed(); + _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height()); + camera.requires_zoom_to_bed = false; + } + + camera.apply_view_matrix(); + camera.apply_projection(_max_bounding_box(true, true)); +#else m_camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); if (m_camera.requires_zoom_to_bed) @@ -1917,6 +2079,7 @@ void GLCanvas3D::render() m_camera.apply_view_matrix(); m_camera.apply_projection(_max_bounding_box(true, true)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam)); @@ -1946,7 +2109,11 @@ void GLCanvas3D::render() _render_objects(); _render_sla_slices(); _render_selection(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + _render_bed(!camera.is_looking_downward(), true); +#else _render_bed(!m_camera.is_looking_downward(), true); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #if ENABLE_RENDER_SELECTION_CENTER _render_selection_center(); @@ -1955,7 +2122,7 @@ void GLCanvas3D::render() // we need to set the mouse's scene position here because the depth buffer // could be invalidated by the following gizmo render methods // this position is used later into on_mouse() to drag the objects - m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast()); + m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast()); _render_current_gizmo(); _render_selection_sidebar_hints(); @@ -2015,8 +2182,12 @@ void GLCanvas3D::render() tooltip = m_undoredo_toolbar.get_tooltip(); if (tooltip.empty()) - tooltip = m_view_toolbar.get_tooltip(); - } +#if ENABLE_NON_STATIC_CANVAS_MANAGER + tooltip = wxGetApp().plater()->get_view_toolbar().get_tooltip(); +#else + tooltip = m_view_toolbar.get_tooltip(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + } set_tooltip(tooltip); @@ -2060,8 +2231,13 @@ void GLCanvas3D::render_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, { switch (GLCanvas3DManager::get_framebuffers_type()) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + case GLCanvas3DManager::EFramebufferType::Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } + case GLCanvas3DManager::EFramebufferType::Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } +#else case GLCanvas3DManager::FB_Arb: { _render_thumbnail_framebuffer(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } case GLCanvas3DManager::FB_Ext: { _render_thumbnail_framebuffer_ext(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER default: { _render_thumbnail_legacy(thumbnail_data, w, h, printable_only, parts_only, show_bed, transparent_background); break; } } } @@ -2166,8 +2342,15 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (!m_initialized) + return; + + _set_current(); +#else if (m_initialized) _set_current(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER struct ModelVolumeState { ModelVolumeState(const GLVolume* volume) : @@ -2769,8 +2952,13 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) m_dirty |= m_main_toolbar.update_items_state(); m_dirty |= m_undoredo_toolbar.update_items_state(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); + bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); +#else m_dirty |= m_view_toolbar.update_items_state(); bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(m_camera); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_dirty |= mouse3d_controller_applied; if (!m_dirty) @@ -2911,12 +3099,27 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'a': { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; } case 'B': case 'b': { zoom_to_bed(); break; } +#if ENABLE_SLOPE_RENDERING + case 'D': + case 'd': { + if (!is_layers_editing_enabled()) + { + m_slope.show(!m_slope.is_shown()); + m_dirty = true; + } + break; + } +#endif // ENABLE_SLOPE_RENDERING case 'E': case 'e': { m_labels.show(!m_labels.is_shown()); m_dirty = true; break; } case 'I': case 'i': { _update_camera_zoom(1.0); break; } case 'K': +#if ENABLE_NON_STATIC_CANVAS_MANAGER + case 'k': { wxGetApp().plater()->get_camera().select_next_type(); m_dirty = true; break; } +#else case 'k': { m_camera.select_next_type(); m_dirty = true; break; } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER case 'O': case 'o': { _update_camera_zoom(-1.0); break; } #if ENABLE_RENDER_PICKING_PASS @@ -3043,7 +3246,11 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) Vec3d displacement; if (camera_space) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Eigen::Matrix inv_view_3x3 = wxGetApp().plater()->get_camera().get_view_matrix().inverse().matrix().block(0, 0, 3, 3); +#else Eigen::Matrix inv_view_3x3 = m_camera.get_view_matrix().inverse().matrix().block(0, 0, 3, 3); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER displacement = multiplier * (inv_view_3x3 * direction); displacement(2) = 0.0; } @@ -3369,7 +3576,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) return; } +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (wxGetApp().plater()->get_view_toolbar().on_mouse(evt, *this)) +#else if (m_view_toolbar.on_mouse(evt, *this)) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) mouse_up_cleanup(); @@ -3532,7 +3743,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag if (m_selection.contains_volume(get_first_hover_volume_idx())) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); + if (std::abs(camera.get_dir_forward()(2)) < EPSILON) +#else if (std::abs(m_camera.get_dir_forward()(2)) < EPSILON) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { // side view -> move selected volumes orthogonally to camera view direction Linef3 ray = mouse_ray(pos); @@ -3545,8 +3761,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // vector from the starting position to the found intersection Vec3d inters_vec = inters - m_mouse.drag.start_position_3D; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Vec3d camera_right = camera.get_dir_right(); + Vec3d camera_up = camera.get_dir_up(); +#else Vec3d camera_right = m_camera.get_dir_right(); Vec3d camera_up = m_camera.get_dir_up(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER // finds projection of the vector along the camera axes double projection_x = inters_vec.dot(camera_right); @@ -3596,15 +3817,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.); if (wxGetApp().app_config->get("use_free_camera") == "1") // Virtual track ball (similar to the 3DConnexion mouse). +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.)); +#else m_camera.rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER else { - // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation. - // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(), - // which checks an atomics (flushes CPU caches). - // See GH issue #3816. + // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation. + // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(), + // which checks an atomics (flushes CPU caches). + // See GH issue #3816. +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Camera& camera = wxGetApp().plater()->get_camera(); + camera.recover_from_free_camera(); + camera.rotate_on_sphere(rot.x(), rot.y(), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); +#else m_camera.recover_from_free_camera(); m_camera.rotate_on_sphere(rot.x(), rot.y(), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } m_dirty = true; @@ -3620,17 +3851,26 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) float z = 0.0f; const Vec3d& cur_pos = _mouse_to_3d(pos, &z); Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Camera& camera = wxGetApp().plater()->get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER if (wxGetApp().app_config->get("use_free_camera") != "1") - // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation. - // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(), - // which checks an atomics (flushes CPU caches). - // See GH issue #3816. + // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation. + // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(), + // which checks an atomics (flushes CPU caches). + // See GH issue #3816. +#if ENABLE_NON_STATIC_CANVAS_MANAGER + camera.recover_from_free_camera(); + + camera.set_target(camera.get_target() + orig - cur_pos); +#else m_camera.recover_from_free_camera(); m_camera.set_target(m_camera.get_target() + orig - cur_pos); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_dirty = true; } - + m_mouse.drag.start_position_2D = pos; } } @@ -4076,7 +4316,12 @@ void GLCanvas3D::update_ui_from_settings() if (new_scaling != orig_scaling) { BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << new_scaling; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Camera& camera = wxGetApp().plater()->get_camera(); + camera.set_zoom(camera.get_zoom() * new_scaling / orig_scaling); +#else m_camera.set_zoom(m_camera.get_zoom() * new_scaling / orig_scaling); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER _refresh_if_shown_on_screen(); } #endif @@ -4109,16 +4354,13 @@ Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos) return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1)); } - -void GLCanvas3D::refresh_camera_scene_box() -{ - m_camera.set_scene_box(scene_bounding_box()); -} - - double GLCanvas3D::get_size_proportional_to_max_bed_size(double factor) const { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + return factor * wxGetApp().plater()->get_bed().get_bounding_box(false).max_size(); +#else return factor * m_bed.get_bounding_box(false).max_size(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } void GLCanvas3D::set_cursor(ECursorType type) @@ -4181,7 +4423,11 @@ bool GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x) const ImGuiWrapper* imgui = wxGetApp().imgui(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const float x = pos_x * (float)wxGetApp().plater()->get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width(); +#else const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER imgui->set_next_window_pos(x, m_undoredo_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); std::string title = is_undo ? L("Undo History") : L("Redo History"); imgui->begin(_(title), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); @@ -4281,7 +4527,11 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, bool // extends the near and far z of the frustrum to avoid the bed being clipped // box in eye space +#if ENABLE_NON_STATIC_CANVAS_MANAGER + BoundingBoxf3 t_bed_box = wxGetApp().plater()->get_bed().get_bounding_box(true).transformed(camera.get_view_matrix()); +#else BoundingBoxf3 t_bed_box = m_bed.get_bounding_box(true).transformed(camera.get_view_matrix()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER near_z = -t_bed_box.max(2); far_z = -t_bed_box.min(2); } @@ -4558,7 +4808,11 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT // restore the default framebuffer size to avoid flickering on the 3D scene +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height()); +#else m_camera.apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } bool GLCanvas3D::_init_toolbars() @@ -4883,19 +5137,31 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_be bb.merge(BoundingBoxf3(sel_bb_center - extend_by, sel_bb_center + extend_by)); } +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bb.merge(wxGetApp().plater()->get_bed().get_bounding_box(include_bed_model)); +#else bb.merge(m_bed.get_bounding_box(include_bed_model)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER return bb; } void GLCanvas3D::_zoom_to_box(const BoundingBoxf3& box, double margin_factor) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().zoom_to_box(box, margin_factor); +#else m_camera.zoom_to_box(box, margin_factor); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_dirty = true; } void GLCanvas3D::_update_camera_zoom(double zoom) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_camera().update_zoom(zoom); +#else m_camera.update_zoom(zoom); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_dirty = true; } @@ -5086,7 +5352,11 @@ void GLCanvas3D::_render_bed(float theta, bool show_axes) const #if ENABLE_RETINA_GL scale_factor = m_retina_helper->get_scale_factor(); #endif // ENABLE_RETINA_GL +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGetApp().plater()->get_bed().render(const_cast(*this), theta, scale_factor, show_axes); +#else m_bed.render(const_cast(*this), theta, scale_factor, show_axes); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } void GLCanvas3D::_render_objects() const @@ -5105,7 +5375,11 @@ void GLCanvas3D::_render_objects() const if (m_config != nullptr) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const BoundingBoxf3& bed_bb = wxGetApp().plater()->get_bed().get_bounding_box(false); +#else const BoundingBoxf3& bed_bb = m_bed.get_bounding_box(false); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height")); m_volumes.check_outside_state(m_config, nullptr); } @@ -5121,19 +5395,37 @@ void GLCanvas3D::_render_objects() const m_shader.start_using(); if (m_picking_enabled && !m_gizmos.is_dragging() && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) { int object_id = m_layers_editing.last_object_id; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_volumes.render(GLVolumeCollection::Opaque, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { + // Which volume to paint without the layer height profile shader? + return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); + }); +#else m_volumes.render(GLVolumeCollection::Opaque, false, m_camera.get_view_matrix(), [object_id](const GLVolume& volume) { // Which volume to paint without the layer height profile shader? return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); }); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER // Let LayersEditing handle rendering of the active object using the layer height profile shader. m_layers_editing.render_volumes(*this, this->m_volumes); } else { // do not cull backfaces to show broken geometry, if any +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_volumes.render(GLVolumeCollection::Opaque, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) { + return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0); + }); +#else m_volumes.render(GLVolumeCollection::Opaque, m_picking_enabled, m_camera.get_view_matrix(), [this](const GLVolume& volume) { return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0); }); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } + +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_volumes.render(GLVolumeCollection::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix()); +#else m_volumes.render(GLVolumeCollection::Transparent, false, m_camera.get_view_matrix()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_shader.stop_using(); m_camera_clipping_plane = ClippingPlane::ClipsNothing(); @@ -5163,9 +5455,16 @@ void GLCanvas3D::_render_overlays() const glsafe(::glPushMatrix()); glsafe(::glLoadIdentity()); // ensure that the textures are renderered inside the frustrum +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); + glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.005))); + // ensure that the overlay fits the frustrum near z plane + double gui_scale = camera.get_gui_scale(); +#else glsafe(::glTranslated(0.0, 0.0, -(m_camera.get_near_z() + 0.005))); // ensure that the overlay fits the frustrum near z plane double gui_scale = m_camera.get_gui_scale(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER glsafe(::glScaled(gui_scale, gui_scale, 1.0)); _render_gizmos_overlay(); @@ -5202,6 +5501,10 @@ void GLCanvas3D::_render_overlays() const } m_labels.render(sorted_instances); +#if ENABLE_SLOPE_RENDERING + m_slope.render(); +#endif // ENABLE_SLOPE_RENDERING + glsafe(::glPopMatrix()); } @@ -5228,7 +5531,11 @@ void GLCanvas3D::_render_volumes_for_picking() const glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); +#else const Transform3d& view_matrix = m_camera.get_view_matrix(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER for (size_t type = 0; type < 2; ++ type) { GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::Opaque : GLVolumeCollection::Transparent, view_matrix); for (const GLVolumeWithIdAndZ& volume : to_render) @@ -5277,7 +5584,11 @@ void GLCanvas3D::_render_main_toolbar() const return; Size cnv_size = get_canvas_size(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)m_camera.get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; float left = -0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width()) * inv_zoom; @@ -5292,7 +5603,11 @@ void GLCanvas3D::_render_undoredo_toolbar() const return; Size cnv_size = get_canvas_size(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)m_camera.get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float top = 0.5f * (float)cnv_size.get_height() * inv_zoom; float left = (m_main_toolbar.get_width() - 0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width())) * inv_zoom; @@ -5302,25 +5617,50 @@ void GLCanvas3D::_render_undoredo_toolbar() const void GLCanvas3D::_render_view_toolbar() const { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + GLToolbar& view_toolbar = wxGetApp().plater()->get_view_toolbar(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + #if ENABLE_RETINA_GL // m_view_toolbar.set_scale(m_retina_helper->get_scale_factor()); const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + view_toolbar.set_scale(scale); //! #ys_FIXME_experiment +#else m_view_toolbar.set_scale(scale); //! #ys_FIXME_experiment +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #else // m_view_toolbar.set_scale(m_canvas->GetContentScaleFactor()); // m_view_toolbar.set_scale(wxGetApp().em_unit()*0.1f); const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale()); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + view_toolbar.set_icons_size(size); //! #ys_FIXME_experiment +#else m_view_toolbar.set_icons_size(size); //! #ys_FIXME_experiment +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #endif // ENABLE_RETINA_GL Size cnv_size = get_canvas_size(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)m_camera.get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER // places the toolbar on the bottom-left corner of the 3d scene +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float top = (-0.5f * (float)cnv_size.get_height() + view_toolbar.get_height()) * inv_zoom; +#else float top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar.get_height()) * inv_zoom; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float left = -0.5f * (float)cnv_size.get_width() * inv_zoom; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + view_toolbar.set_position(top, left); + view_toolbar.render(*this); +#else m_view_toolbar.set_position(top, left); m_view_toolbar.render(*this); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } #if ENABLE_SHOW_CAMERA_TARGET @@ -5599,10 +5939,16 @@ Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) if (m_canvas == nullptr) return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); + const std::array& viewport = camera.get_viewport(); + const Transform3d& modelview_matrix = camera.get_view_matrix(); + const Transform3d& projection_matrix = camera.get_projection_matrix(); +#else const std::array& viewport = m_camera.get_viewport(); const Transform3d& modelview_matrix = m_camera.get_view_matrix(); const Transform3d& projection_matrix = m_camera.get_projection_matrix(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER GLint y = viewport[3] - (GLint)mouse_pos(1); GLfloat mouse_z; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 5f38a9a42..8c29dab78 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -31,6 +31,9 @@ class wxMouseEvent; class wxTimerEvent; class wxPaintEvent; class wxGLCanvas; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +class wxGLContext; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER // Support for Retina OpenGL on Mac OS #define ENABLE_RETINA_GL __APPLE__ @@ -406,6 +409,24 @@ private: }; #endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI +#if ENABLE_SLOPE_RENDERING + class Slope + { + bool m_enabled{ false }; + GLCanvas3D& m_canvas; + GLVolumeCollection& m_volumes; + + public: + Slope(GLCanvas3D& canvas, GLVolumeCollection& volumes) : m_canvas(canvas), m_volumes(volumes) {} + + void enable(bool enable) { m_enabled = enable; } + bool is_enabled() const { return m_enabled; } + void show(bool show) { m_volumes.set_slope_active(m_enabled ? show : false); } + bool is_shown() const { return m_volumes.is_slope_active(); } + void render() const; + }; +#endif // ENABLE_SLOPE_RENDERING + public: enum ECursorType : unsigned char { @@ -423,9 +444,11 @@ private: LegendTexture m_legend_texture; WarningTexture m_warning_texture; wxTimer m_timer; +#if !ENABLE_NON_STATIC_CANVAS_MANAGER Bed3D& m_bed; Camera& m_camera; GLToolbar& m_view_toolbar; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER LayersEditing m_layers_editing; Shader m_shader; Mouse m_mouse; @@ -487,11 +510,22 @@ private: #if ENABLE_CANVAS_TOOLTIP_USING_IMGUI mutable Tooltip m_tooltip; #endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI +#if ENABLE_SLOPE_RENDERING + Slope m_slope; +#endif // ENABLE_SLOPE_RENDERING public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + explicit GLCanvas3D(wxGLCanvas* canvas); +#else GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER ~GLCanvas3D(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bool is_initialized() const { return m_initialized; } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + void set_context(wxGLContext* context) { m_context = context; } wxGLCanvas* get_wxglcanvas() { return m_canvas; } @@ -538,9 +572,14 @@ public: void set_color_by(const std::string& value); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + void refresh_camera_scene_box(); +#else + void refresh_camera_scene_box() { m_camera.set_scene_box(scene_bounding_box()); } const Camera& get_camera() const { return m_camera; } - const Shader& get_shader() const { return m_shader; } Camera& get_camera() { return m_camera; } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + const Shader& get_shader() const { return m_shader; } BoundingBoxf3 volumes_bounding_box() const; BoundingBoxf3 scene_bounding_box() const; @@ -564,6 +603,9 @@ public: void enable_undoredo_toolbar(bool enable); void enable_dynamic_background(bool enable); void enable_labels(bool enable) { m_labels.enable(enable); } +#if ENABLE_SLOPE_RENDERING + void enable_slope(bool enable) { m_slope.enable(enable); } +#endif // ENABLE_SLOPE_RENDERING void allow_multisample(bool allow); void zoom_to_bed(); @@ -636,7 +678,9 @@ public: void update_ui_from_settings(); +#if !ENABLE_NON_STATIC_CANVAS_MANAGER float get_view_toolbar_height() const { return m_view_toolbar.get_height(); } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER int get_move_volume_id() const { return m_mouse.drag.move_volume_idx; } int get_first_hover_volume_idx() const { return m_hover_volume_idxs.empty() ? -1 : m_hover_volume_idxs.front(); } @@ -668,7 +712,6 @@ public: Linef3 mouse_ray(const Point& mouse_pos); void set_mouse_as_dragging() { m_mouse.dragging = true; } - void refresh_camera_scene_box(); bool is_mouse_dragging() const { return m_mouse.dragging; } double get_size_proportional_to_max_bed_size(double factor) const; @@ -690,6 +733,11 @@ public: bool are_labels_shown() const { return m_labels.is_shown(); } void show_labels(bool show) { m_labels.show(show); } +#if ENABLE_SLOPE_RENDERING + bool is_slope_shown() const { return m_slope.is_shown(); } + void show_slope(bool show) { m_slope.show(show); } +#endif // ENABLE_SLOPE_RENDERING + private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 02585c5f7..d4522bb07 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -1,3 +1,4 @@ +#include "libslic3r/libslic3r.h" #include "GLCanvas3DManager.hpp" #include "../../slic3r/GUI/GUI.hpp" #include "../../slic3r/GUI/AppConfig.hpp" @@ -7,7 +8,9 @@ #include #include - +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include #include #include @@ -17,8 +20,10 @@ #include #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 -// Part of temporary hack to remove crash when closing on OSX 10.9.5 +#ifdef __APPLE__ +// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets #include +#endif // __APPLE__ #endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ @@ -28,6 +33,7 @@ namespace Slic3r { namespace GUI { +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3DManager::GLInfo::GLInfo() : m_detected(false) , m_version("") @@ -38,6 +44,7 @@ GLCanvas3DManager::GLInfo::GLInfo() , m_max_anisotropy(0.0f) { } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER const std::string& GLCanvas3DManager::GLInfo::get_version() const { @@ -196,27 +203,57 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten return out.str(); } -GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown; -bool GLCanvas3DManager::s_compressed_textures_supported = false; -GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None; GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info; +bool GLCanvas3DManager::s_compressed_textures_supported = false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::EMultisampleState::Unknown; +GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::EFramebufferType::Unknown; +#else +GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown; +GLCanvas3DManager::EFramebufferType GLCanvas3DManager::s_framebuffers_type = GLCanvas3DManager::FB_None; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ +// Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets GLCanvas3DManager::OSInfo GLCanvas3DManager::s_os_info; #endif // __APPLE__ #endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3DManager::GLCanvas3DManager() : m_context(nullptr) , m_gl_initialized(false) { } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3DManager::~GLCanvas3DManager() { - this->destroy(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 +#ifdef __APPLE__ + // This is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 with newer wxWidgets + // The crash is triggered inside wxGLContext destructor + if (s_os_info.major != 10 || s_os_info.minor != 9 || s_os_info.micro != 5) + { +#endif //__APPLE__ +#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 + + if (m_context != nullptr) + delete m_context; + +#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 +#ifdef __APPLE__ + } +#endif //__APPLE__ +#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 +#else + this->destroy(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } +#if !ENABLE_NON_STATIC_CANVAS_MANAGER bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar) { if (canvas == nullptr) @@ -239,7 +276,7 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLTo #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ - // Part of temporary hack to remove crash when closing on OSX 10.9.5 + // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion(); s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion(); s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion(); @@ -277,28 +314,50 @@ void GLCanvas3DManager::remove_all() m_canvases.clear(); } -unsigned int GLCanvas3DManager::count() const +size_t GLCanvas3DManager::count() const { - return (unsigned int)m_canvases.size(); + return m_canvases.size(); } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_NON_STATIC_CANVAS_MANAGER +bool GLCanvas3DManager::init_gl() +#else void GLCanvas3DManager::init_gl() +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (!m_gl_initialized) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (glewInit() != GLEW_OK) + { + BOOST_LOG_TRIVIAL(error) << "Unable to init glew library"; + return false; + } +#else glewInit(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_gl_initialized = true; if (GLEW_EXT_texture_compression_s3tc) s_compressed_textures_supported = true; else s_compressed_textures_supported = false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (GLEW_ARB_framebuffer_object) + s_framebuffers_type = EFramebufferType::Arb; + else if (GLEW_EXT_framebuffer_object) + s_framebuffers_type = EFramebufferType::Ext; + else + s_framebuffers_type = EFramebufferType::Unknown; +#else if (GLEW_ARB_framebuffer_object) s_framebuffers_type = FB_Arb; else if (GLEW_EXT_framebuffer_object) s_framebuffers_type = FB_Ext; else s_framebuffers_type = FB_None; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER if (! s_gl_info.is_version_greater_or_equal_to(2, 0)) { // Complain about the OpenGL version. @@ -314,8 +373,31 @@ void GLCanvas3DManager::init_gl() wxMessageBox(message, wxString("PrusaSlicer - ") + _(L("Unsupported OpenGL version")), wxOK | wxICON_ERROR); } } + +#if ENABLE_NON_STATIC_CANVAS_MANAGER + return true; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +wxGLContext* GLCanvas3DManager::init_glcontext(wxGLCanvas& canvas) +{ + if (m_context == nullptr) + { + m_context = new wxGLContext(&canvas); + +#if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 +#ifdef __APPLE__ + // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets + s_os_info.major = wxPlatformInfo::Get().GetOSMajorVersion(); + s_os_info.minor = wxPlatformInfo::Get().GetOSMinorVersion(); + s_os_info.micro = wxPlatformInfo::Get().GetOSMicroVersion(); +#endif //__APPLE__ +#endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 + } + return m_context; +} +#else bool GLCanvas3DManager::init(wxGLCanvas* canvas) { CanvasesMap::const_iterator it = do_get_canvas(canvas); @@ -331,7 +413,7 @@ void GLCanvas3DManager::destroy() { #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ - // this is a temporary ugly hack to solve the crash happening when closing the application on OSX 10.9.5 + // this is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 // the crash is inside wxGLContext destructor if (s_os_info.major == 10 && s_os_info.minor == 9 && s_os_info.micro == 5) return; @@ -342,14 +424,21 @@ void GLCanvas3DManager::destroy() m_context = nullptr; } } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas) { CanvasesMap::const_iterator it = do_get_canvas(canvas); return (it != m_canvases.end()) ? it->second : nullptr; } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_NON_STATIC_CANVAS_MANAGER +wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow& parent) +#else wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { int attribList[] = { WX_GL_RGBA, @@ -367,7 +456,11 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) 0 }; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (s_multisample == EMultisampleState::Unknown) +#else if (s_multisample == MS_Unknown) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { detect_multisample(attribList); // // debug output @@ -377,9 +470,14 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) if (! can_multisample()) attribList[12] = 0; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + return new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); +#else return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER } +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::do_get_canvas(wxGLCanvas* canvas) { return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); @@ -397,12 +495,17 @@ bool GLCanvas3DManager::init(GLCanvas3D& canvas) return canvas.init(); } +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER void GLCanvas3DManager::detect_multisample(int* attribList) { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; bool enable_multisample = wxVersion >= 30003; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? EMultisampleState::Enabled : EMultisampleState::Disabled; +#else s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER // Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows // s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); } diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index c7301f2b4..428ccd96a 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -23,22 +23,43 @@ class PrintObject; namespace GUI { class GLCanvas3D; +#if !ENABLE_NON_STATIC_CANVAS_MANAGER class Bed3D; class GLToolbar; struct Camera; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER class GLCanvas3DManager { public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + enum class EFramebufferType : unsigned char + { + Unknown, + Arb, + Ext + }; +#else enum EFramebufferType : unsigned char { FB_None, FB_Arb, FB_Ext }; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER class GLInfo { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + mutable bool m_detected{ false }; + mutable int m_max_tex_size{ 0 }; + mutable float m_max_anisotropy{ 0.0f }; + + mutable std::string m_version; + mutable std::string m_glsl_version; + mutable std::string m_vendor; + mutable std::string m_renderer; +#else mutable bool m_detected; mutable std::string m_version; @@ -48,9 +69,14 @@ public: mutable int m_max_tex_size; mutable float m_max_anisotropy; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + GLInfo() = default; +#else GLInfo(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const std::string& get_version() const; const std::string& get_glsl_version() const; @@ -70,6 +96,7 @@ public: #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ + // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets struct OSInfo { int major{ 0 }; @@ -80,6 +107,14 @@ public: #endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 private: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + enum class EMultisampleState : unsigned char + { + Unknown, + Enabled, + Disabled + }; +#else enum EMultisampleState : unsigned char { MS_Unknown, @@ -88,51 +123,85 @@ private: }; typedef std::map CanvasesMap; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER - CanvasesMap m_canvases; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bool m_gl_initialized{ false }; + wxGLContext* m_context{ nullptr }; +#else wxGLContext* m_context; + bool m_gl_initialized; + CanvasesMap m_canvases; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER static GLInfo s_gl_info; #if ENABLE_HACK_CLOSING_ON_OSX_10_9_5 #ifdef __APPLE__ + // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets static OSInfo s_os_info; #endif //__APPLE__ #endif // ENABLE_HACK_CLOSING_ON_OSX_10_9_5 - bool m_gl_initialized; - static EMultisampleState s_multisample; static bool s_compressed_textures_supported; + static EMultisampleState s_multisample; static EFramebufferType s_framebuffers_type; public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + GLCanvas3DManager() = default; +#else GLCanvas3DManager(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER ~GLCanvas3DManager(); +#if !ENABLE_NON_STATIC_CANVAS_MANAGER bool add(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar); bool remove(wxGLCanvas* canvas); void remove_all(); - unsigned int count() const; + size_t count() const; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bool init_gl(); +#else void init_gl(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_NON_STATIC_CANVAS_MANAGER + wxGLContext* init_glcontext(wxGLCanvas& canvas); +#else bool init(wxGLCanvas* canvas); void destroy(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER +#if !ENABLE_NON_STATIC_CANVAS_MANAGER GLCanvas3D* get_canvas(wxGLCanvas* canvas); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER - static bool can_multisample() { return s_multisample == MS_Enabled; } static bool are_compressed_textures_supported() { return s_compressed_textures_supported; } +#if ENABLE_NON_STATIC_CANVAS_MANAGER + static bool can_multisample() { return s_multisample == EMultisampleState::Enabled; } + static bool are_framebuffers_supported() { return (s_framebuffers_type != EFramebufferType::Unknown); } +#else + static bool can_multisample() { return s_multisample == MS_Enabled; } static bool are_framebuffers_supported() { return (s_framebuffers_type != FB_None); } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; } +#if ENABLE_NON_STATIC_CANVAS_MANAGER + static wxGLCanvas* create_wxglcanvas(wxWindow& parent); +#else static wxGLCanvas* create_wxglcanvas(wxWindow *parent); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER static const GLInfo& get_gl_info() { return s_gl_info; } private: +#if !ENABLE_NON_STATIC_CANVAS_MANAGER CanvasesMap::iterator do_get_canvas(wxGLCanvas* canvas); CanvasesMap::const_iterator do_get_canvas(wxGLCanvas* canvas) const; bool init(GLCanvas3D& canvas); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER static void detect_multisample(int* attribList); }; diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index a8b69d75a..eacf7a153 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -2,6 +2,9 @@ #include "Camera.hpp" #include "3DScene.hpp" #include "GLCanvas3D.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "GUI_App.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include @@ -35,13 +38,17 @@ namespace GUI { m_state = Off; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); +#else const Camera& camera = canvas.get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const std::array& viewport = camera.get_viewport(); const Transform3d& modelview_matrix = camera.get_view_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix(); // bounding box created from the rectangle corners - will take care of order of the corners - BoundingBox rectangle(Points{ Point(m_start_corner.cast()), Point(m_end_corner.cast()) }); + BoundingBox rectangle(Points{ Point(m_start_corner.cast()), Point(m_end_corner.cast()) }); // Iterate over all points and determine whether they're in the rectangle. for (unsigned int i = 0; iget_camera(); +#else const Camera& camera = canvas.get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float inv_zoom = (float)camera.get_inv_zoom(); Size cnv_size = canvas.get_canvas_size(); diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index f178ddc73..545b066bb 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -2,6 +2,9 @@ #include "GLTexture.hpp" #include "3DScene.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "GLCanvas3DManager.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index be3d5495e..4219fe482 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -3,8 +3,14 @@ #include "GLToolbar.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/Camera.hpp" +#else #include "../../slic3r/GUI/GLCanvas3D.hpp" #include "../../slic3r/GUI/Camera.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include #include @@ -15,7 +21,6 @@ namespace Slic3r { namespace GUI { - wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); @@ -718,7 +723,11 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC { // NB: mouse_pos is already scaled appropriately +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = m_layout.scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); @@ -859,7 +868,11 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan { // NB: mouse_pos is already scaled appropriately +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = m_layout.scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); @@ -1008,7 +1021,11 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3 { // NB: mouse_pos is already scaled appropriately +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = m_layout.scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); @@ -1081,7 +1098,11 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& { // NB: mouse_pos is already scaled appropriately +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = m_layout.scale * inv_zoom; Size cnv_size = parent.get_canvas_size(); @@ -1233,7 +1254,11 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const int tex_width = m_icons_texture.get_width(); int tex_height = m_icons_texture.get_height(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = inv_zoom * m_layout.scale; float scaled_icons_size = m_layout.icons_size * factor; @@ -1281,7 +1306,11 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const int tex_width = m_icons_texture.get_width(); int tex_height = m_icons_texture.get_height(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float inv_zoom = (float)parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float factor = inv_zoom * m_layout.scale; float scaled_icons_size = m_layout.icons_size * factor; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index f44efa130..f5a4a3d92 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -50,8 +50,8 @@ #include "RemovableDriveManager.hpp" #ifdef __WXMSW__ -#include #include +#include #endif // __WXMSW__ #if ENABLE_THUMBNAIL_GENERATOR_DEBUG @@ -158,6 +158,41 @@ static void register_win32_device_notification_event() } return true; }); + + wxWindow::MSWRegisterMessageHandler(MainFrame::WM_USER_MEDIACHANGED, [](wxWindow *win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) { + // Some messages are sent to top level windows by default, some messages are sent to only registered windows, and we explictely register on MainFrame only. + auto main_frame = dynamic_cast(win); + auto plater = (main_frame == nullptr) ? nullptr : main_frame->plater(); + if (plater == nullptr) + // Maybe some other top level window like a dialog or maybe a pop-up menu? + return true; + wchar_t sPath[MAX_PATH]; + if (lParam == SHCNE_MEDIAINSERTED || lParam == SHCNE_MEDIAREMOVED) { + struct _ITEMIDLIST* pidl = *reinterpret_cast(wParam); + if (! SHGetPathFromIDList(pidl, sPath)) { + BOOST_LOG_TRIVIAL(error) << "MediaInserted: SHGetPathFromIDList failed"; + return false; + } + } + switch (lParam) { + case SHCNE_MEDIAINSERTED: + { + //printf("SHCNE_MEDIAINSERTED %S\n", sPath); + plater->GetEventHandler()->AddPendingEvent(VolumeAttachedEvent(EVT_VOLUME_ATTACHED)); + break; + } + case SHCNE_MEDIAREMOVED: + { + //printf("SHCNE_MEDIAREMOVED %S\n", sPath); + plater->GetEventHandler()->AddPendingEvent(VolumeDetachedEvent(EVT_VOLUME_DETACHED)); + break; + } + default: +// printf("Unknown\n"); + break; + } + return true; + }); } #endif // WIN32 @@ -216,6 +251,23 @@ GUI_App::~GUI_App() delete preset_updater; } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +std::string GUI_App::get_gl_info(bool format_as_html, bool extensions) +{ + return GLCanvas3DManager::get_gl_info().to_string(format_as_html, extensions); +} + +wxGLContext* GUI_App::init_glcontext(wxGLCanvas& canvas) +{ + return m_canvas_mgr.init_glcontext(canvas); +} + +bool GUI_App::init_opengl() +{ + return m_canvas_mgr.init_gl(); +} +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + bool GUI_App::OnInit() { try { @@ -667,15 +719,16 @@ bool GUI_App::select_language() // Try to load a new language. if (index != -1 && (init_selection == -1 || init_selection != index)) { const wxLanguageInfo *new_language_info = language_infos[index]; - if (new_language_info == m_language_info_best || new_language_info == m_language_info_system) { - // The newly selected profile matches user's default profile exactly. That's great. - } else if (m_language_info_best != nullptr && new_language_info->CanonicalName.BeforeFirst('_') == m_language_info_best->CanonicalName.BeforeFirst('_')) - new_language_info = m_language_info_best; - else if (m_language_info_system != nullptr && new_language_info->CanonicalName.BeforeFirst('_') == m_language_info_system->CanonicalName.BeforeFirst('_')) - new_language_info = m_language_info_system; if (this->load_language(new_language_info->CanonicalName, false)) { // Save language at application config. - app_config->set("translation_language", m_wxLocale->GetCanonicalName().ToUTF8().data()); + // Which language to save as the selected dictionary language? + // 1) Hopefully the language set to wxTranslations by this->load_language(), but that API is weird and we don't want to rely on its + // stability in the future: + // wxTranslations::Get()->GetBestTranslation(SLIC3R_APP_KEY, wxLANGUAGE_ENGLISH); + // 2) Current locale language may not match the dictionary name, see GH issue #3901 + // m_wxLocale->GetCanonicalName() + // 3) new_language_info->CanonicalName is a safe bet. It points to a valid dictionary name. + app_config->set("translation_language", new_language_info->CanonicalName.ToUTF8().data()); app_config->save(); return true; } @@ -704,7 +757,6 @@ bool GUI_App::load_language(wxString language, bool initial) BOOST_LOG_TRIVIAL(trace) << boost::format("System language detected (user locales and such): %1%") % m_language_info_system->CanonicalName.ToUTF8().data(); } } -#if defined(__WXMSW__) || defined(__WXOSX__) { // Allocating a temporary locale will switch the default wxTranslations to its internal wxTranslations instance. wxLocale temp_locale; @@ -721,7 +773,6 @@ bool GUI_App::load_language(wxString language, bool initial) BOOST_LOG_TRIVIAL(trace) << boost::format("Best translation language detected (may be different from user locales): %1%") % m_language_info_best->CanonicalName.ToUTF8().data(); } } -#endif } const wxLanguageInfo *language_info = language.empty() ? nullptr : wxLocale::FindLanguageInfo(language); @@ -737,6 +788,7 @@ bool GUI_App::load_language(wxString language, bool initial) } if (language_info == nullptr) { + // PrusaSlicer does not support the Right to Left languages yet. if (m_language_info_system != nullptr && m_language_info_system->LayoutDirection != wxLayout_RightToLeft) language_info = m_language_info_system; if (m_language_info_best != nullptr && m_language_info_best->LayoutDirection != wxLayout_RightToLeft) @@ -755,6 +807,16 @@ bool GUI_App::load_language(wxString language, bool initial) BOOST_LOG_TRIVIAL(trace) << "Using Czech dictionaries for Slovak language"; } + // Select language for locales. This language may be different from the language of the dictionary. + if (language_info == m_language_info_best || language_info == m_language_info_system) { + // The current language matches user's default profile exactly. That's great. + } else if (m_language_info_best != nullptr && language_info->CanonicalName.BeforeFirst('_') == m_language_info_best->CanonicalName.BeforeFirst('_')) { + // Use whatever the operating system recommends, if it the language code of the dictionary matches the recommended language. + // This allows a Swiss guy to use a German dictionary without forcing him to German locales. + language_info = m_language_info_best; + } else if (m_language_info_system != nullptr && language_info->CanonicalName.BeforeFirst('_') == m_language_info_system->CanonicalName.BeforeFirst('_')) + language_info = m_language_info_system; + if (! wxLocale::IsAvailable(language_info->Language)) { // Loading the language dictionary failed. wxString message = "Switching PrusaSlicer to language " + language_info->CanonicalName + " failed."; @@ -781,7 +843,7 @@ bool GUI_App::load_language(wxString language, bool initial) wxTranslations::Get()->SetLanguage(language_dict); m_wxLocale->AddCatalog(SLIC3R_APP_KEY); m_imgui->set_language(into_u8(language_info->CanonicalName)); - //FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only. + //FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only. wxSetlocale(LC_NUMERIC, "C"); Preset::update_suffix_modified(); return true; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index d02a60ba9..bf75eaaa6 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -7,6 +7,9 @@ #include "MainFrame.hpp" #include "ImGuiWrapper.hpp" #include "ConfigWizard.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "GLCanvas3DManager.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include #include @@ -96,7 +99,11 @@ class GUI_App : public wxApp // Best translation language, provided by Windows or OSX, owned by wxWidgets. const wxLanguageInfo *m_language_info_best = nullptr; - std::unique_ptr m_removable_drive_manager; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + GLCanvas3DManager m_canvas_mgr; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + + std::unique_ptr m_removable_drive_manager; std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; @@ -109,6 +116,12 @@ public: GUI_App(); ~GUI_App() override; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + static std::string get_gl_info(bool format_as_html, bool extensions); + wxGLContext* init_glcontext(wxGLCanvas& canvas); + bool init_opengl(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + static unsigned get_colour_approx_luma(const wxColour &colour); static bool dark_mode(); void init_label_colours(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c1c93327c..979509562 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -27,31 +27,63 @@ namespace Slic3r { namespace GUI { +#if ENABLE_NON_STATIC_CANVAS_MANAGER +View3D::View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) + : m_canvas_widget(nullptr) + , m_canvas(nullptr) +{ + init(parent, model, config, process); +} +#else View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) : m_canvas_widget(nullptr) , m_canvas(nullptr) { init(parent, bed, camera, view_toolbar, model, config, process); } +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER View3D::~View3D() { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (m_canvas != nullptr) + delete m_canvas; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + if (m_canvas_widget != nullptr) { +#if !ENABLE_NON_STATIC_CANVAS_MANAGER _3DScene::remove_canvas(m_canvas_widget); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER delete m_canvas_widget; +#if !ENABLE_NON_STATIC_CANVAS_MANAGER m_canvas = nullptr; +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER } } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +bool View3D::init(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) +#else bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */)) return false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(*this); + if (m_canvas_widget == nullptr) + return false; + + m_canvas = new GLCanvas3D(m_canvas_widget); + m_canvas->set_context(wxGetApp().init_glcontext(*m_canvas_widget)); + m_canvas->bind_event_handlers(); +#else m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this); _3DScene::add_canvas(m_canvas_widget, bed, camera, view_toolbar); m_canvas = _3DScene::get_canvas(this->m_canvas_widget); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_canvas->allow_multisample(GLCanvas3DManager::can_multisample()); // XXX: If have OpenGL @@ -66,6 +98,9 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_ m_canvas->enable_main_toolbar(true); m_canvas->enable_undoredo_toolbar(true); m_canvas->enable_labels(true); +#if ENABLE_SLOPE_RENDERING + m_canvas->enable_slope(true); +#endif // ENABLE_SLOPE_RENDERING wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); @@ -163,15 +198,27 @@ void View3D::render() m_canvas->set_as_dirty(); } +#if ENABLE_NON_STATIC_CANVAS_MANAGER #if ENABLE_GCODE_VIEWER Preview::Preview( - wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, + wxWindow* parent, Model* model, DynamicPrintConfig* config, + BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function schedule_background_process_func) +#else +Preview::Preview( + wxWindow* parent, Model* model, DynamicPrintConfig* config, + BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function schedule_background_process_func) +#endif // ENABLE_GCODE_VIEWER +#else +#if ENABLE_GCODE_VIEWER +Preview::Preview( + wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function schedule_background_process_func) #else Preview::Preview( wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function schedule_background_process_func) #endif // ENABLE_GCODE_VIEWER +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER : m_canvas_widget(nullptr) , m_canvas(nullptr) , m_double_slider_sizer(nullptr) @@ -199,21 +246,39 @@ Preview::Preview( , m_volumes_cleanup_required(false) #endif // __linux__ { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (init(parent, model)) +#else if (init(parent, bed, camera, view_toolbar, model)) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { show_hide_ui_elements("none"); load_print(); } } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +bool Preview::init(wxWindow* parent, Model* model) +#else bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */)) return false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(*this); + if (m_canvas_widget == nullptr) + return false; + + m_canvas = new GLCanvas3D(m_canvas_widget); + m_canvas->set_context(wxGetApp().init_glcontext(*m_canvas_widget)); + m_canvas->bind_event_handlers(); +#else m_canvas_widget = GLCanvas3DManager::create_wxglcanvas(this); _3DScene::add_canvas(m_canvas_widget, bed, camera, view_toolbar); m_canvas = _3DScene::get_canvas(this->m_canvas_widget); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_canvas->allow_multisample(GLCanvas3DManager::can_multisample()); m_canvas->set_config(m_config); m_canvas->set_model(model); @@ -322,9 +387,16 @@ Preview::~Preview() { unbind_event_handlers(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + if (m_canvas != nullptr) + delete m_canvas; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + if (m_canvas_widget != nullptr) { - _3DScene::remove_canvas(m_canvas_widget); +#if !ENABLE_NON_STATIC_CANVAS_MANAGER + _3DScene::remove_canvas(m_canvas_widget); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER delete m_canvas_widget; m_canvas = nullptr; } diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index f0e7abfec..654ce4dbf 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -37,6 +37,9 @@ class GLCanvas3D; class GLToolbar; class Bed3D; struct Camera; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +class Plater; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER class View3D : public wxPanel { @@ -44,7 +47,11 @@ class View3D : public wxPanel GLCanvas3D* m_canvas; public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + View3D(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); +#else View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER virtual ~View3D(); wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } @@ -72,7 +79,11 @@ public: void render(); private: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bool init(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); +#else bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER }; class Preview : public wxPanel @@ -115,6 +126,15 @@ class Preview : public wxPanel DoubleSlider::Control* m_slider {nullptr}; public: +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#if ENABLE_GCODE_VIEWER + Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, + BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function schedule_background_process = []() {}); +#else + Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, + BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function schedule_background_process = []() {}); +#endif // ENABLE_GCODE_VIEWER +#else #if ENABLE_GCODE_VIEWER Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, GCodeProcessor::Result* gcode_result, std::function schedule_background_process = []() {}); @@ -122,6 +142,7 @@ public: Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function schedule_background_process = []() {}); #endif // ENABLE_GCODE_VIEWER +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER virtual ~Preview(); wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } @@ -148,7 +169,11 @@ public: bool is_loaded() const { return m_loaded; } private: +#if ENABLE_NON_STATIC_CANVAS_MANAGER + bool init(wxWindow* parent, Model* model); +#else bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER void bind_event_handlers(); void unbind_event_handlers(); @@ -181,7 +206,6 @@ private: void load_print_as_sla(); void on_sliders_scroll_changed(wxCommandEvent& event); - }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 0a3a6f898..51e6d7458 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -10,6 +10,9 @@ #include "slic3r/GUI/GUI_ObjectList.hpp" #include "slic3r/GUI/MeshUtils.hpp" #include "slic3r/GUI/Plater.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "slic3r/GUI/Camera.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include "slic3r/GUI/PresetBundle.hpp" #include "libslic3r/SLAPrint.hpp" #include "libslic3r/TriangleMesh.hpp" @@ -311,7 +314,11 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairm_mesh_raycaster) return false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); +#else const Camera& camera = m_parent.get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const Selection& selection = m_parent.get_selection(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); Geometry::Transformation trafo = volume->get_instance_transformation(); @@ -426,7 +433,11 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos points_inside.push_back(points[idx].cast()); // Only select/deselect points that are actually visible +#if ENABLE_NON_STATIC_CANVAS_MANAGER + for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, wxGetApp().plater()->get_camera(), points_inside, m_c->m_clipping_plane.get())) +#else for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (rectangle_status == GLSelectionRectangle::Deselect) unselect_point(points_idxs[idx]); @@ -1026,8 +1037,13 @@ void GLGizmoHollow::update_clipping_plane(bool keep_normal) const { if (! m_c->m_model_object) return; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? + m_c->m_clipping_plane->get_normal() : -wxGetApp().plater()->get_camera().get_dir_forward()); +#else Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); float dist = normal.dot(center); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index ab0b9b5d6..064302c02 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -14,6 +14,9 @@ #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI_ObjectSettings.hpp" #include "slic3r/GUI/GUI_ObjectList.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "slic3r/GUI/Camera.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include "slic3r/GUI/MeshUtils.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/PresetBundle.hpp" @@ -379,7 +382,11 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairm_mesh_raycaster) return false; +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Camera& camera = wxGetApp().plater()->get_camera(); +#else const Camera& camera = m_parent.get_camera(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const Selection& selection = m_parent.get_selection(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); Geometry::Transformation trafo = volume->get_instance_transformation(); @@ -489,7 +496,11 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous points_inside.push_back(points[idx].cast()); // Only select/deselect points that are actually visible +#if ENABLE_NON_STATIC_CANVAS_MANAGER + for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, wxGetApp().plater()->get_camera(), points_inside, m_c->m_clipping_plane.get())) +#else for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER { if (rectangle_status == GLSelectionRectangle::Deselect) unselect_point(points_idxs[idx]); @@ -1282,8 +1293,14 @@ void GLGizmoSlaSupports::update_clipping_plane(bool keep_normal) const { if (! m_c->m_model_object) return; + +#if ENABLE_NON_STATIC_CANVAS_MANAGER Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? - m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); + m_c->m_clipping_plane->get_normal() : -wxGetApp().plater()->get_camera().get_dir_forward()); +#else + Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? + m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); float dist = normal.dot(center); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 18d603507..379bd48d1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -2,6 +2,9 @@ #include "GLGizmosManager.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/3DScene.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#include "slic3r/GUI/Camera.hpp" +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/PresetBundle.hpp" @@ -1029,8 +1032,13 @@ void GLGizmosManager::do_render_overlay() const float cnv_w = (float)m_parent.get_canvas_size().get_width(); float cnv_h = (float)m_parent.get_canvas_size().get_height(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float zoom = (float)wxGetApp().plater()->get_camera().get_zoom(); + float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); +#else float zoom = (float)m_parent.get_camera().get_zoom(); float inv_zoom = (float)m_parent.get_camera().get_inv_zoom(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER float height = get_scaled_total_height(); float width = get_scaled_total_width(); @@ -1081,7 +1089,11 @@ void GLGizmosManager::do_render_overlay() const GLTexture::render_sub_texture(icons_texture_id, zoomed_top_x, zoomed_top_x + zoomed_icons_size, zoomed_top_y - zoomed_icons_size, zoomed_top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); if (idx == m_current) { +#if ENABLE_NON_STATIC_CANVAS_MANAGER + float toolbar_top = cnv_h - wxGetApp().plater()->get_view_toolbar().get_height(); +#else float toolbar_top = cnv_h - m_parent.get_view_toolbar_height(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER gizmo->render_input_window(width, 0.5f * cnv_h - zoomed_top_y * zoom, toolbar_top); } zoomed_top_y -= zoomed_stride_y; diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 842cec5e2..d05ecbcd8 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -145,6 +145,9 @@ void KBShortcutsDialog::fill_shortcuts() // View { "0-6", L("Camera view") }, { "E", L("Show/Hide object/instance labels") }, +#if ENABLE_SLOPE_RENDERING + { "D", L("Turn On/Off facets' slope rendering") }, +#endif // ENABLE_SLOPE_RENDERING // Configuration { ctrl + "P", L("Preferences") }, // Help diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1e22359ab..69d20fd9f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -33,6 +33,7 @@ #ifdef _WIN32 #include +#include #endif // _WIN32 namespace Slic3r { @@ -127,6 +128,30 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S // DEV_BROADCAST_HANDLE NotificationFilter = { 0 }; // NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); // NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; + + // Using Win32 Shell API to register for media insert / removal events. + LPITEMIDLIST ppidl; + if (SHGetSpecialFolderLocation(this->GetHWND(), CSIDL_DESKTOP, &ppidl) == NOERROR) { + SHChangeNotifyEntry shCNE; + shCNE.pidl = ppidl; + shCNE.fRecursive = TRUE; + // Returns a positive integer registration identifier (ID). + // Returns zero if out of memory or in response to invalid parameters. + m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(this->GetHWND(), // Hwnd to receive notification + SHCNE_DISKEVENTS, // Event types of interest (sources) + SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED, + //SHCNE_UPDATEITEM, // Events of interest - use SHCNE_ALLEVENTS for all events + WM_USER_MEDIACHANGED, // Notification message to be sent upon the event + 1, // Number of entries in the pfsne array + &shCNE); // Array of SHChangeNotifyEntry structures that + // contain the notifications. This array should + // always be set to one when calling SHChnageNotifyRegister + // or SHChangeNotifyDeregister will not work properly. + assert(m_ulSHChangeNotifyRegister != 0); // Shell notification failed + } else { + // Failed to get desktop location + assert(false); + } #endif // _WIN32 // propagate event @@ -161,13 +186,26 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S void MainFrame::shutdown() { #ifdef _WIN32 - ::UnregisterDeviceNotification(HDEVNOTIFY(m_hDeviceNotify)); - m_hDeviceNotify = nullptr; + if (m_hDeviceNotify) { + ::UnregisterDeviceNotification(HDEVNOTIFY(m_hDeviceNotify)); + m_hDeviceNotify = nullptr; + } + if (m_ulSHChangeNotifyRegister) { + SHChangeNotifyDeregister(m_ulSHChangeNotifyRegister); + m_ulSHChangeNotifyRegister = 0; + } #endif // _WIN32 if (m_plater) m_plater->stop_jobs(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + // Unbinding of wxWidgets event handling in canvases needs to be done here because on MAC, + // when closing the application using Command+Q, a mouse event is triggered after this lambda is completed, + // causing a crash + if (m_plater) m_plater->unbind_canvas_event_handlers(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + // Weird things happen as the Paint messages are floating around the windows being destructed. // Avoid the Paint messages by hiding the main window. // Also the application closes much faster without these unnecessary screen refreshes. @@ -188,7 +226,9 @@ void MainFrame::shutdown() wxGetApp().app_config->save(); // if (m_plater) // m_plater->print = undef; +#if !ENABLE_NON_STATIC_CANVAS_MANAGER _3DScene::remove_all_canvases(); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER // Slic3r::GUI::deregister_on_request_update_callback(); // set to null tabs and a plater @@ -214,7 +254,8 @@ void MainFrame::update_title() if (idx_plus != build_id.npos) { // Parse what is behind the '+'. If there is a number, then it is a build number after the label, and full build ID is shown. int commit_after_label; - if (! boost::starts_with(build_id.data() + idx_plus + 1, "UNKNOWN") && sscanf(build_id.data() + idx_plus + 1, "%d-", &commit_after_label) == 0) { + if (! boost::starts_with(build_id.data() + idx_plus + 1, "UNKNOWN") && + (build_id.at(idx_plus + 1) == '-' || sscanf(build_id.data() + idx_plus + 1, "%d-", &commit_after_label) == 0)) { // It is a release build. build_id.erase(build_id.begin() + idx_plus, build_id.end()); #if defined(_WIN32) && ! defined(_WIN64) @@ -754,9 +795,20 @@ void MainFrame::init_menubar() append_menu_item(viewMenu, wxID_ANY, _(L("Right")) + sep + "&6", _(L("Right View")), [this](wxCommandEvent&) { select_view("right"); }, "", nullptr, [this](){return can_change_view(); }, this); viewMenu->AppendSeparator(); +#if ENABLE_SLOPE_RENDERING + wxMenu* options_menu = new wxMenu(); + append_menu_check_item(options_menu, wxID_ANY, _(L("Show &labels")) + sep + "E", _(L("Show object/instance labels in 3D scene")), + [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, + [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); + append_menu_check_item(options_menu, wxID_ANY, _(L("Show &slope")) + sep + "D", _(L("Objects coloring using faces' slope")), + [this](wxCommandEvent&) { m_plater->show_view3D_slope(!m_plater->is_view3D_slope_shown()); }, this, + [this]() { return m_plater->is_view3D_shown() && !m_plater->is_view3D_layers_editing_enabled(); }, [this]() { return m_plater->is_view3D_slope_shown(); }, this); + append_submenu(viewMenu, options_menu, wxID_ANY, _(L("&Options")), ""); +#else append_menu_check_item(viewMenu, wxID_ANY, _(L("Show &labels")) + sep + "E", _(L("Show object/instance labels in 3D scene")), [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); +#endif // ENABLE_SLOPE_RENDERING } // Help menu diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 8c8b98090..6038e6d2f 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -144,6 +144,8 @@ public: #ifdef _WIN32 void* m_hDeviceNotify { nullptr }; + uint32_t m_ulSHChangeNotifyRegister { 0 }; + static constexpr int WM_USER_MEDIACHANGED { 0x7FFF }; // WM_USER from 0x0400 to 0x7FFF, picking the last one to not interfere with wxWidgets allocation #endif // _WIN32 }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f4ef41b30..0cdb4b7c0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -79,6 +79,11 @@ #include "../Utils/FixModelByWin10.hpp" #include "../Utils/UndoRedo.hpp" #include "RemovableDriveManager.hpp" +#if ENABLE_NON_STATIC_CANVAS_MANAGER +#ifdef __APPLE__ +#include "Gizmos/GLGizmosManager.hpp" +#endif // __APPLE__ +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER #include // Needs to be last because reasons :-/ #include "WipeTowerDialog.hpp" @@ -1821,8 +1826,18 @@ struct Plater::priv bool are_view3D_labels_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->are_labels_shown(); } void show_view3D_labels(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_labels(show); } +#if ENABLE_SLOPE_RENDERING + bool is_view3D_slope_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_slope_shown(); } + void show_view3D_slope(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_slope(show); } + + bool is_view3D_layers_editing_enabled() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_layers_editing_enabled(); } +#endif // ENABLE_SLOPE_RENDERING + void set_current_canvas_as_dirty(); GLCanvas3D* get_current_canvas3D(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + void unbind_canvas_event_handlers(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER bool init_view_toolbar(); @@ -2054,12 +2069,26 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) sla_print.set_status_callback(statuscb); this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + view3D = new View3D(q, &model, config, &background_process); +#if ENABLE_GCODE_VIEWER + preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, &gcode_result, [this]() { schedule_background_process(); }); +#else + preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, [this]() { schedule_background_process(); }); +#endif // ENABLE_GCODE_VIEWER + +#ifdef __APPLE__ + // set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size + view_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size); +#endif // __APPLE__ +#else view3D = new View3D(q, bed, camera, view_toolbar, &model, config, &background_process); #if ENABLE_GCODE_VIEWER preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, &gcode_result, [this]() { schedule_background_process(); }); #else - preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); }); + preview = new Preview(q, bed, camera, view_toolbar, &model, config, &background_process, &gcode_preview_data, [this]() { schedule_background_process(); }); #endif // ENABLE_GCODE_VIEWER +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER panels.push_back(view3D); panels.push_back(preview); @@ -2159,7 +2188,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // Drop target: q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership +#if !ENABLE_NON_STATIC_CANVAS_MANAGER update_ui_from_settings(); +#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER q->Layout(); set_current_panel(view3D); @@ -4058,6 +4089,17 @@ GLCanvas3D* Plater::priv::get_current_canvas3D() return (current_panel == view3D) ? view3D->get_canvas3d() : ((current_panel == preview) ? preview->get_canvas3d() : nullptr); } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +void Plater::priv::unbind_canvas_event_handlers() +{ + if (view3D != nullptr) + view3D->get_canvas3d()->unbind_event_handlers(); + + if (preview != nullptr) + preview->get_canvas3d()->unbind_event_handlers(); +} +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + bool Plater::priv::init_view_toolbar() { if (view_toolbar.get_items_count() > 0) @@ -4528,7 +4570,8 @@ void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& lab // Plater / Public Plater::Plater(wxWindow *parent, MainFrame *main_frame) - : wxPanel(parent), p(new priv(this, main_frame)) + : wxPanel(parent) + , p(new priv(this, main_frame)) { // Initialization performed in the private c-tor } @@ -4652,6 +4695,13 @@ bool Plater::is_view3D_shown() const { return p->is_view3D_shown(); } bool Plater::are_view3D_labels_shown() const { return p->are_view3D_labels_shown(); } void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); } +#if ENABLE_SLOPE_RENDERING +bool Plater::is_view3D_slope_shown() const { return p->is_view3D_slope_shown(); } +void Plater::show_view3D_slope(bool show) { p->show_view3D_slope(show); } + +bool Plater::is_view3D_layers_editing_enabled() const { return p->is_view3D_layers_editing_enabled(); } +#endif // ENABLE_SLOPE_RENDERING + void Plater::select_all() { p->select_all(); } void Plater::deselect_all() { p->deselect_all(); } @@ -5459,6 +5509,13 @@ void Plater::set_current_canvas_as_dirty() p->set_current_canvas_as_dirty(); } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +void Plater::unbind_canvas_event_handlers() +{ + p->unbind_canvas_event_handlers(); +} +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + PrinterTechnology Plater::printer_technology() const { return p->printer_technology; @@ -5592,6 +5649,28 @@ Camera& Plater::get_camera() return p->camera; } +#if ENABLE_NON_STATIC_CANVAS_MANAGER +const Bed3D& Plater::get_bed() const +{ + return p->bed; +} + +Bed3D& Plater::get_bed() +{ + return p->bed; +} + +const GLToolbar& Plater::get_view_toolbar() const +{ + return p->view_toolbar; +} + +GLToolbar& Plater::get_view_toolbar() +{ + return p->view_toolbar; +} +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + const Mouse3DController& Plater::get_mouse3d_controller() const { return p->mouse3d_controller; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 601c04476..a1ce52389 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -42,6 +42,10 @@ class ObjectList; class GLCanvas3D; class Mouse3DController; struct Camera; +#if ENABLE_NON_STATIC_CANVAS_MANAGER +class Bed3D; +class GLToolbar; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER using t_optgroups = std::vector >; @@ -171,6 +175,13 @@ public: bool are_view3D_labels_shown() const; void show_view3D_labels(bool show); +#if ENABLE_SLOPE_RENDERING + bool is_view3D_slope_shown() const; + void show_view3D_slope(bool show); + + bool is_view3D_layers_editing_enabled() const; +#endif // ENABLE_SLOPE_RENDERING + // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. void update_ui_from_settings(); @@ -249,6 +260,9 @@ public: BoundingBoxf bed_shape_bb() const; void set_current_canvas_as_dirty(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + void unbind_canvas_event_handlers(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER PrinterTechnology printer_technology() const; void set_printer_technology(PrinterTechnology printer_technology); @@ -278,12 +292,21 @@ public: const Camera& get_camera() const; Camera& get_camera(); + +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const Bed3D& get_bed() const; + Bed3D& get_bed(); + + const GLToolbar& get_view_toolbar() const; + GLToolbar& get_view_toolbar(); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + const Mouse3DController& get_mouse3d_controller() const; Mouse3DController& get_mouse3d_controller(); void set_bed_shape() const; - // ROII wrapper for suppressing the Undo / Redo snapshot to be taken. + // ROII wrapper for suppressing the Undo / Redo snapshot to be taken. class SuppressSnapshots { public: diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index cdb1c1d45..d67ac4a22 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -33,17 +33,19 @@ wxDEFINE_EVENT(EVT_REMOVABLE_DRIVES_CHANGED, RemovableDrivesChangedEvent); #if _WIN32 std::vector RemovableDriveManager::search_for_removable_drives() const { - //get logical drives flags by letter in alphabetical order + // Get logical drives flags by letter in alphabetical order. DWORD drives_mask = ::GetLogicalDrives(); // Allocate the buffers before the loop. std::wstring volume_name; std::wstring file_system_name; - // Iterate the Windows drives from 'A' to 'Z' + // Iterate the Windows drives from 'C' to 'Z' std::vector current_drives; - for (size_t i = 0; i < 26; ++ i) - if (drives_mask & (1 << i)) { - std::string path { char('A' + i), ':' }; + // Skip A and B drives. + drives_mask >>= 2; + for (char drive = 'C'; drive <= 'Z'; ++ drive, drives_mask >>= 1) + if (drives_mask & 1) { + std::string path { drive, ':' }; UINT drive_type = ::GetDriveTypeA(path.c_str()); // DRIVE_REMOVABLE on W are sd cards and usb thumbnails (not usb harddrives) if (drive_type == DRIVE_REMOVABLE) { @@ -450,14 +452,8 @@ void RemovableDriveManager::thread_proc() { std::unique_lock lck(m_thread_stop_mutex); #ifdef _WIN32 - // Windows do not send an update on insert / eject of an SD card into an external SD card reader. - // Windows also do not send an update on software eject of a FLASH drive. - // We can likely use the Windows WMI API, but it will be quite time consuming to implement. - // https://www.codeproject.com/Articles/10539/Making-WMI-Queries-In-C - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-start-page - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/com-api-for-wmi - // https://docs.microsoft.com/en-us/windows/win32/wmisdk/example--receiving-event-notifications-through-wmi- - m_thread_stop_condition.wait_for(lck, std::chrono::seconds(2), [this]{ return m_stop || m_wakeup; }); + // Reacting to updates by WM_DEVICECHANGE and WM_USER_MEDIACHANGED + m_thread_stop_condition.wait(lck, [this]{ return m_stop || m_wakeup; }); #else m_thread_stop_condition.wait_for(lck, std::chrono::seconds(2), [this]{ return m_stop; }); #endif diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 146111f49..b07463857 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -440,6 +440,12 @@ void Selection::clear() update_type(); this->set_bounding_boxes_dirty(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + // this happens while the application is closing + if (wxGetApp().obj_manipul() == nullptr) + return; +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER + // resets the cache in the sidebar wxGetApp().obj_manipul()->reset_cache(); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index a1bae8742..f26fe7033 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -145,7 +145,11 @@ SysInfoDialog::SysInfoDialog() "" "" "", bgr_clr_str, text_clr_str, text_clr_str, +#if ENABLE_NON_STATIC_CANVAS_MANAGER + get_mem_info(true) + "
" + wxGetApp().get_gl_info(true, true)); +#else get_mem_info(true) + "
" + _3DScene::get_gl_info(true, true)); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER m_opengl_info_html->SetPage(text); main_sizer->Add(m_opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15); } @@ -198,7 +202,11 @@ void SysInfoDialog::on_dpi_changed(const wxRect &suggested_rect) void SysInfoDialog::onCopyToClipboard(wxEvent &) { wxTheClipboard->Open(); +#if ENABLE_NON_STATIC_CANVAS_MANAGER + const auto text = get_main_info(false) + "\n" + wxGetApp().get_gl_info(false, true); +#else const auto text = get_main_info(false)+"\n"+_3DScene::get_gl_info(false, true); +#endif // ENABLE_NON_STATIC_CANVAS_MANAGER wxTheClipboard->SetData(new wxTextDataObject(text)); wxTheClipboard->Close(); } diff --git a/tests/fff_print/test_data.cpp b/tests/fff_print/test_data.cpp index 06f2a6068..4ee43e2b1 100644 --- a/tests/fff_print/test_data.cpp +++ b/tests/fff_print/test_data.cpp @@ -52,88 +52,88 @@ TriangleMesh mesh(TestMesh m) break; case TestMesh::cube_with_hole: mesh = TriangleMesh( - { Vec3d(0,0,0), Vec3d(0,0,10), Vec3d(0,20,0), Vec3d(0,20,10), Vec3d(20,0,0), Vec3d(20,0,10), Vec3d(5,5,0), Vec3d(15,5,0), Vec3d(5,15,0), Vec3d(20,20,0), Vec3d(15,15,0), Vec3d(20,20,10), Vec3d(5,5,10), Vec3d(5,15,10), Vec3d(15,5,10), Vec3d(15,15,10) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(1,0,4), Vec3crd(5,1,4), Vec3crd(6,7,4), Vec3crd(8,2,9), Vec3crd(0,2,8), Vec3crd(10,8,9), Vec3crd(0,8,6), Vec3crd(0,6,4), Vec3crd(4,7,9), Vec3crd(7,10,9), Vec3crd(2,3,9), Vec3crd(9,3,11), Vec3crd(12,1,5), Vec3crd(13,3,12), Vec3crd(14,12,5), Vec3crd(3,1,12), Vec3crd(11,3,13), Vec3crd(11,15,5), Vec3crd(11,13,15), Vec3crd(15,14,5), Vec3crd(5,4,9), Vec3crd(11,5,9), Vec3crd(8,13,12), Vec3crd(6,8,12), Vec3crd(10,15,13), Vec3crd(8,10,13), Vec3crd(15,10,14), Vec3crd(14,10,7), Vec3crd(14,7,12), Vec3crd(12,7,6) }); + { {0,0,0}, {0,0,10}, {0,20,0}, {0,20,10}, {20,0,0}, {20,0,10}, {5,5,0}, {15,5,0}, {5,15,0}, {20,20,0}, {15,15,0}, {20,20,10}, {5,5,10}, {5,15,10}, {15,5,10}, {15,15,10} }, + { {0,1,2}, {2,1,3}, {1,0,4}, {5,1,4}, {6,7,4}, {8,2,9}, {0,2,8}, {10,8,9}, {0,8,6}, {0,6,4}, {4,7,9}, {7,10,9}, {2,3,9}, {9,3,11}, {12,1,5}, {13,3,12}, {14,12,5}, {3,1,12}, {11,3,13}, {11,15,5}, {11,13,15}, {15,14,5}, {5,4,9}, {11,5,9}, {8,13,12}, {6,8,12}, {10,15,13}, {8,10,13}, {15,10,14}, {14,10,7}, {14,7,12}, {12,7,6} }); break; case TestMesh::cube_with_concave_hole: mesh = TriangleMesh( - { Vec3d(-10,-10,-5), Vec3d(-10,-10,5), Vec3d(-10,10,-5), Vec3d(-10,10,5), Vec3d(10,-10,-5), Vec3d(10,-10,5), Vec3d(-5,-5,-5), Vec3d(5,-5,-5), Vec3d(5,5,-5), Vec3d(5,10,-5), Vec3d(-5,5,-5), Vec3d(3.06161699911402e-16,5,-5), Vec3d(5,0,-5), Vec3d(0,0,-5), Vec3d(10,5,-5), Vec3d(5,10,5), Vec3d(-5,-5,5), Vec3d(5,0,5), Vec3d(5,-5,5), Vec3d(-5,5,5), Vec3d(10,5,5), Vec3d(5,5,5), Vec3d(3.06161699911402e-16,5,5), Vec3d(0,0,5) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(1,0,4), Vec3crd(5,1,4), Vec3crd(6,7,4), Vec3crd(8,2,9), Vec3crd(10,2,11), Vec3crd(11,12,13), Vec3crd(0,2,10), Vec3crd(0,10,6), Vec3crd(0,6,4), Vec3crd(11,2,8), Vec3crd(4,7,12), Vec3crd(4,12,8), Vec3crd(12,11,8), Vec3crd(14,4,8), Vec3crd(2,3,9), Vec3crd(9,3,15), Vec3crd(16,1,5), Vec3crd(17,18,5), Vec3crd(19,3,16), Vec3crd(20,21,5), Vec3crd(18,16,5), Vec3crd(3,1,16), Vec3crd(22,3,19), Vec3crd(21,3,22), Vec3crd(21,17,5), Vec3crd(21,22,17), Vec3crd(21,15,3), Vec3crd(23,17,22), Vec3crd(5,4,14), Vec3crd(20,5,14), Vec3crd(20,14,21), Vec3crd(21,14,8), Vec3crd(9,15,21), Vec3crd(8,9,21), Vec3crd(10,19,16), Vec3crd(6,10,16), Vec3crd(11,22,19), Vec3crd(10,11,19), Vec3crd(13,23,11), Vec3crd(11,23,22), Vec3crd(23,13,12), Vec3crd(17,23,12), Vec3crd(17,12,18), Vec3crd(18,12,7), Vec3crd(18,7,16), Vec3crd(16,7,6) }); + { {-10,-10,-5}, {-10,-10,5}, {-10,10,-5}, {-10,10,5}, {10,-10,-5}, {10,-10,5}, {-5,-5,-5}, {5,-5,-5}, {5,5,-5}, {5,10,-5}, {-5,5,-5}, Vec3d(3.06161699911402e-16,5,-5), {5,0,-5}, {0,0,-5}, {10,5,-5}, {5,10,5}, {-5,-5,5}, {5,0,5}, {5,-5,5}, {-5,5,5}, {10,5,5}, {5,5,5}, Vec3d(3.06161699911402e-16,5,5), {0,0,5} }, + { {0,1,2}, {2,1,3}, {1,0,4}, {5,1,4}, {6,7,4}, {8,2,9}, {10,2,11}, {11,12,13}, {0,2,10}, {0,10,6}, {0,6,4}, {11,2,8}, {4,7,12}, {4,12,8}, {12,11,8}, {14,4,8}, {2,3,9}, {9,3,15}, {16,1,5}, {17,18,5}, {19,3,16}, {20,21,5}, {18,16,5}, {3,1,16}, {22,3,19}, {21,3,22}, {21,17,5}, {21,22,17}, {21,15,3}, {23,17,22}, {5,4,14}, {20,5,14}, {20,14,21}, {21,14,8}, {9,15,21}, {8,9,21}, {10,19,16}, {6,10,16}, {11,22,19}, {10,11,19}, {13,23,11}, {11,23,22}, {23,13,12}, {17,23,12}, {17,12,18}, {18,12,7}, {18,7,16}, {16,7,6} }); break; case TestMesh::V: mesh = TriangleMesh( - { Vec3d(-14,0,20), Vec3d(-14,15,20), Vec3d(0,0,0), Vec3d(0,15,0), Vec3d(-4,0,20), Vec3d(-4,15,20), Vec3d(5,0,7.14286), Vec3d(10,0,0), Vec3d(24,0,20), Vec3d(14,0,20), Vec3d(10,15,0), Vec3d(5,15,7.14286), Vec3d(14,15,20), Vec3d(24,15,20) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(1,0,4), Vec3crd(5,1,4), Vec3crd(4,0,2), Vec3crd(6,4,2), Vec3crd(7,6,2), Vec3crd(8,9,7), Vec3crd(9,6,7), Vec3crd(2,3,7), Vec3crd(7,3,10), Vec3crd(1,5,3), Vec3crd(3,5,11), Vec3crd(11,12,13), Vec3crd(11,13,3), Vec3crd(3,13,10), Vec3crd(5,4,6), Vec3crd(11,5,6), Vec3crd(6,9,11), Vec3crd(11,9,12), Vec3crd(12,9,8), Vec3crd(13,12,8), Vec3crd(8,7,10), Vec3crd(13,8,10) }); + { {-14,0,20}, {-14,15,20}, {0,0,0}, {0,15,0}, {-4,0,20}, {-4,15,20}, {5,0,7.14286}, {10,0,0}, {24,0,20}, {14,0,20}, {10,15,0}, {5,15,7.14286}, {14,15,20}, {24,15,20} }, + { {0,1,2}, {2,1,3}, {1,0,4}, {5,1,4}, {4,0,2}, {6,4,2}, {7,6,2}, {8,9,7}, {9,6,7}, {2,3,7}, {7,3,10}, {1,5,3}, {3,5,11}, {11,12,13}, {11,13,3}, {3,13,10}, {5,4,6}, {11,5,6}, {6,9,11}, {11,9,12}, {12,9,8}, {13,12,8}, {8,7,10}, {13,8,10} }); break; case TestMesh::L: mesh = TriangleMesh( - { Vec3d(0,10,0), Vec3d(0,10,10), Vec3d(0,20,0), Vec3d(0,20,10), Vec3d(10,10,0), Vec3d(10,10,10), Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(10,0,0), Vec3d(20,20,10), Vec3d(10,0,10), Vec3d(20,0,10) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(4,5,1), Vec3crd(0,4,1), Vec3crd(0,2,4), Vec3crd(4,2,6), Vec3crd(4,6,7), Vec3crd(4,7,8), Vec3crd(2,3,6), Vec3crd(6,3,9), Vec3crd(3,1,5), Vec3crd(9,3,5), Vec3crd(10,11,5), Vec3crd(11,9,5), Vec3crd(5,4,10), Vec3crd(10,4,8), Vec3crd(10,8,7), Vec3crd(11,10,7), Vec3crd(11,7,6), Vec3crd(9,11,6) }); + { {0,10,0}, {0,10,10}, {0,20,0}, {0,20,10}, {10,10,0}, {10,10,10}, {20,20,0}, {20,0,0}, {10,0,0}, {20,20,10}, {10,0,10}, {20,0,10} }, + { {0,1,2}, {2,1,3}, {4,5,1}, {0,4,1}, {0,2,4}, {4,2,6}, {4,6,7}, {4,7,8}, {2,3,6}, {6,3,9}, {3,1,5}, {9,3,5}, {10,11,5}, {11,9,5}, {5,4,10}, {10,4,8}, {10,8,7}, {11,10,7}, {11,7,6}, {9,11,6} }); break; case TestMesh::overhang: mesh = TriangleMesh( - { Vec3d(1364.68505859375,614.398010253906,20.002498626709), Vec3d(1389.68505859375,614.398010253906,20.002498626709), Vec3d(1377.18505859375,589.398986816406,20.002498626709), Vec3d(1389.68505859375,589.398986816406,20.002498626709), Vec3d(1389.68505859375,564.398986816406,20.0014991760254), Vec3d(1364.68505859375,589.398986816406,20.002498626709), Vec3d(1364.68505859375,564.398986816406,20.0014991760254), Vec3d(1360.93505859375,589.398986816406,17.0014991760254), Vec3d(1360.93505859375,585.64697265625,17.0014991760254), Vec3d(1357.18505859375,564.398986816406,17.0014991760254), Vec3d(1364.68505859375,589.398986816406,17.0014991760254), Vec3d(1364.68505859375,571.899963378906,17.0014991760254), Vec3d(1364.68505859375,564.398986816406,17.0014991760254), Vec3d(1348.43603515625,564.398986816406,17.0014991760254), Vec3d(1352.80908203125,589.398986816406,17.0014991760254), Vec3d(1357.18408203125,589.398986816406,17.0014991760254), Vec3d(1357.18310546875,614.398010253906,17.0014991760254), Vec3d(1364.68505859375,606.89599609375,17.0014991760254), Vec3d(1364.68505859375,614.398010253906,17.0014991760254), Vec3d(1352.18603515625,564.398986816406,20.0014991760254), Vec3d(1363.65405273438,589.398986816406,23.3004989624023), Vec3d(1359.46704101562,589.398986816406,23.3004989624023), Vec3d(1358.37109375,564.398986816406,23.3004989624023), Vec3d(1385.56103515625,564.398986816406,23.3004989624023), Vec3d(1373.06311035156,589.398986816406,23.3004989624023), Vec3d(1368.80810546875,564.398986816406,23.3004989624023), Vec3d(1387.623046875,589.398986816406,23.3004989624023), Vec3d(1387.623046875,585.276000976562,23.3004989624023), Vec3d(1389.68505859375,589.398986816406,23.3004989624023), Vec3d(1389.68505859375,572.64599609375,23.3004989624023), Vec3d(1389.68505859375,564.398986816406,23.3004989624023), Vec3d(1367.77709960938,589.398986816406,23.3004989624023), Vec3d(1366.7470703125,564.398986816406,23.3004989624023), Vec3d(1354.31201171875,589.398986816406,23.3004989624023), Vec3d(1352.18603515625,564.398986816406,23.3004989624023), Vec3d(1389.68505859375,614.398010253906,23.3004989624023), Vec3d(1377.31701660156,614.398010253906,23.3004989624023), Vec3d(1381.43908691406,589.398986816406,23.3004989624023), Vec3d(1368.80700683594,614.398010253906,23.3004989624023), Vec3d(1368.80810546875,589.398986816406,23.3004989624023), Vec3d(1356.43908691406,614.398010253906,23.3004989624023), Vec3d(1357.40502929688,589.398986816406,23.3004989624023), Vec3d(1360.56201171875,614.398010253906,23.3004989624023), Vec3d(1348.705078125,614.398010253906,23.3004989624023), Vec3d(1350.44506835938,589.398986816406,23.3004989624023), Vec3d(1389.68505859375,606.153015136719,23.3004989624023), Vec3d(1347.35205078125,589.398986816406,23.3004989624023), Vec3d(1346.56005859375,589.398986816406,23.3004989624023), Vec3d(1346.56005859375,594.159912109375,17.0014991760254), Vec3d(1346.56005859375,589.398986816406,17.0014991760254), Vec3d(1346.56005859375,605.250427246094,23.3004989624023), Vec3d(1346.56005859375,614.398010253906,23.3004989624023), Vec3d(1346.56005859375,614.398010253906,20.8258285522461), Vec3d(1346.56005859375,614.398010253906,17.0014991760254), Vec3d(1346.56005859375,564.398986816406,19.10133934021), Vec3d(1346.56005859375,567.548583984375,23.3004989624023), Vec3d(1346.56005859375,564.398986816406,17.0020332336426), Vec3d(1346.56005859375,564.398986816406,23.0018501281738), Vec3d(1346.56005859375,564.398986816406,23.3004989624023), Vec3d(1346.56005859375,575.118957519531,17.0014991760254), Vec3d(1346.56005859375,574.754028320312,23.3004989624023) }, - { Vec3crd(0,1,2), Vec3crd(2,3,4), Vec3crd(2,5,0), Vec3crd(4,6,2), Vec3crd(2,6,5), Vec3crd(2,1,3), Vec3crd(7,8,9), Vec3crd(10,9,8), Vec3crd(11,9,10), Vec3crd(12,9,11), Vec3crd(9,13,14), Vec3crd(7,15,16), Vec3crd(10,17,0), Vec3crd(10,0,5), Vec3crd(12,11,6), Vec3crd(18,16,0), Vec3crd(6,19,13), Vec3crd(6,13,9), Vec3crd(9,12,6), Vec3crd(17,18,0), Vec3crd(11,10,5), Vec3crd(11,5,6), Vec3crd(14,16,15), Vec3crd(17,7,18), Vec3crd(16,18,7), Vec3crd(14,15,9), Vec3crd(7,9,15), Vec3crd(7,17,8), Vec3crd(10,8,17), Vec3crd(20,21,22), Vec3crd(23,24,25), Vec3crd(26,23,27), Vec3crd(28,27,23), Vec3crd(29,28,23), Vec3crd(30,29,23), Vec3crd(25,31,32), Vec3crd(22,33,34), Vec3crd(35,36,37), Vec3crd(24,38,39), Vec3crd(21,40,41), Vec3crd(38,42,20), Vec3crd(33,43,44), Vec3crd(6,4,23), Vec3crd(6,23,25), Vec3crd(36,35,1), Vec3crd(1,0,38), Vec3crd(1,38,36), Vec3crd(29,30,4), Vec3crd(25,32,6), Vec3crd(40,42,0), Vec3crd(35,45,1), Vec3crd(4,3,28), Vec3crd(4,28,29), Vec3crd(3,1,45), Vec3crd(3,45,28), Vec3crd(22,34,19), Vec3crd(19,6,32), Vec3crd(19,32,22), Vec3crd(42,38,0), Vec3crd(30,23,4), Vec3crd(0,16,43), Vec3crd(0,43,40), Vec3crd(24,37,36), Vec3crd(38,24,36), Vec3crd(24,23,37), Vec3crd(37,23,26), Vec3crd(22,32,20), Vec3crd(20,32,31), Vec3crd(33,41,40), Vec3crd(43,33,40), Vec3crd(45,35,26), Vec3crd(37,26,35), Vec3crd(33,44,34), Vec3crd(44,43,46), Vec3crd(20,42,21), Vec3crd(40,21,42), Vec3crd(31,39,38), Vec3crd(20,31,38), Vec3crd(33,22,41), Vec3crd(21,41,22), Vec3crd(31,25,39), Vec3crd(24,39,25), Vec3crd(26,27,45), Vec3crd(28,45,27), Vec3crd(47,48,49), Vec3crd(47,50,48), Vec3crd(51,48,50), Vec3crd(52,48,51), Vec3crd(53,48,52), Vec3crd(54,55,56), Vec3crd(57,55,54), Vec3crd(58,55,57), Vec3crd(49,59,47), Vec3crd(60,56,55), Vec3crd(59,56,60), Vec3crd(60,47,59), Vec3crd(48,53,16), Vec3crd(56,13,19), Vec3crd(54,56,19), Vec3crd(56,59,13), Vec3crd(59,49,14), Vec3crd(59,14,13), Vec3crd(49,48,16), Vec3crd(49,16,14), Vec3crd(44,46,60), Vec3crd(44,60,55), Vec3crd(51,50,43), Vec3crd(19,34,58), Vec3crd(19,58,57), Vec3crd(53,52,16), Vec3crd(43,16,52), Vec3crd(43,52,51), Vec3crd(57,54,19), Vec3crd(47,60,46), Vec3crd(55,58,34), Vec3crd(55,34,44), Vec3crd(50,47,46), Vec3crd(50,46,43) }); + { {1364.68505859375,614.398010253906,20.002498626709}, {1389.68505859375,614.398010253906,20.002498626709}, {1377.18505859375,589.398986816406,20.002498626709}, {1389.68505859375,589.398986816406,20.002498626709}, {1389.68505859375,564.398986816406,20.0014991760254}, {1364.68505859375,589.398986816406,20.002498626709}, {1364.68505859375,564.398986816406,20.0014991760254}, {1360.93505859375,589.398986816406,17.0014991760254}, {1360.93505859375,585.64697265625,17.0014991760254}, {1357.18505859375,564.398986816406,17.0014991760254}, {1364.68505859375,589.398986816406,17.0014991760254}, {1364.68505859375,571.899963378906,17.0014991760254}, {1364.68505859375,564.398986816406,17.0014991760254}, {1348.43603515625,564.398986816406,17.0014991760254}, {1352.80908203125,589.398986816406,17.0014991760254}, {1357.18408203125,589.398986816406,17.0014991760254}, {1357.18310546875,614.398010253906,17.0014991760254}, {1364.68505859375,606.89599609375,17.0014991760254}, {1364.68505859375,614.398010253906,17.0014991760254}, {1352.18603515625,564.398986816406,20.0014991760254}, {1363.65405273438,589.398986816406,23.3004989624023}, {1359.46704101562,589.398986816406,23.3004989624023}, {1358.37109375,564.398986816406,23.3004989624023}, {1385.56103515625,564.398986816406,23.3004989624023}, {1373.06311035156,589.398986816406,23.3004989624023}, {1368.80810546875,564.398986816406,23.3004989624023}, {1387.623046875,589.398986816406,23.3004989624023}, {1387.623046875,585.276000976562,23.3004989624023}, {1389.68505859375,589.398986816406,23.3004989624023}, {1389.68505859375,572.64599609375,23.3004989624023}, {1389.68505859375,564.398986816406,23.3004989624023}, {1367.77709960938,589.398986816406,23.3004989624023}, {1366.7470703125,564.398986816406,23.3004989624023}, {1354.31201171875,589.398986816406,23.3004989624023}, {1352.18603515625,564.398986816406,23.3004989624023}, {1389.68505859375,614.398010253906,23.3004989624023}, {1377.31701660156,614.398010253906,23.3004989624023}, {1381.43908691406,589.398986816406,23.3004989624023}, {1368.80700683594,614.398010253906,23.3004989624023}, {1368.80810546875,589.398986816406,23.3004989624023}, {1356.43908691406,614.398010253906,23.3004989624023}, {1357.40502929688,589.398986816406,23.3004989624023}, {1360.56201171875,614.398010253906,23.3004989624023}, {1348.705078125,614.398010253906,23.3004989624023}, {1350.44506835938,589.398986816406,23.3004989624023}, {1389.68505859375,606.153015136719,23.3004989624023}, {1347.35205078125,589.398986816406,23.3004989624023}, {1346.56005859375,589.398986816406,23.3004989624023}, {1346.56005859375,594.159912109375,17.0014991760254}, {1346.56005859375,589.398986816406,17.0014991760254}, {1346.56005859375,605.250427246094,23.3004989624023}, {1346.56005859375,614.398010253906,23.3004989624023}, {1346.56005859375,614.398010253906,20.8258285522461}, {1346.56005859375,614.398010253906,17.0014991760254}, {1346.56005859375,564.398986816406,19.10133934021}, {1346.56005859375,567.548583984375,23.3004989624023}, {1346.56005859375,564.398986816406,17.0020332336426}, {1346.56005859375,564.398986816406,23.0018501281738}, {1346.56005859375,564.398986816406,23.3004989624023}, {1346.56005859375,575.118957519531,17.0014991760254}, {1346.56005859375,574.754028320312,23.3004989624023} }, + { {0,1,2}, {2,3,4}, {2,5,0}, {4,6,2}, {2,6,5}, {2,1,3}, {7,8,9}, {10,9,8}, {11,9,10}, {12,9,11}, {9,13,14}, {7,15,16}, {10,17,0}, {10,0,5}, {12,11,6}, {18,16,0}, {6,19,13}, {6,13,9}, {9,12,6}, {17,18,0}, {11,10,5}, {11,5,6}, {14,16,15}, {17,7,18}, {16,18,7}, {14,15,9}, {7,9,15}, {7,17,8}, {10,8,17}, {20,21,22}, {23,24,25}, {26,23,27}, {28,27,23}, {29,28,23}, {30,29,23}, {25,31,32}, {22,33,34}, {35,36,37}, {24,38,39}, {21,40,41}, {38,42,20}, {33,43,44}, {6,4,23}, {6,23,25}, {36,35,1}, {1,0,38}, {1,38,36}, {29,30,4}, {25,32,6}, {40,42,0}, {35,45,1}, {4,3,28}, {4,28,29}, {3,1,45}, {3,45,28}, {22,34,19}, {19,6,32}, {19,32,22}, {42,38,0}, {30,23,4}, {0,16,43}, {0,43,40}, {24,37,36}, {38,24,36}, {24,23,37}, {37,23,26}, {22,32,20}, {20,32,31}, {33,41,40}, {43,33,40}, {45,35,26}, {37,26,35}, {33,44,34}, {44,43,46}, {20,42,21}, {40,21,42}, {31,39,38}, {20,31,38}, {33,22,41}, {21,41,22}, {31,25,39}, {24,39,25}, {26,27,45}, {28,45,27}, {47,48,49}, {47,50,48}, {51,48,50}, {52,48,51}, {53,48,52}, {54,55,56}, {57,55,54}, {58,55,57}, {49,59,47}, {60,56,55}, {59,56,60}, {60,47,59}, {48,53,16}, {56,13,19}, {54,56,19}, {56,59,13}, {59,49,14}, {59,14,13}, {49,48,16}, {49,16,14}, {44,46,60}, {44,60,55}, {51,50,43}, {19,34,58}, {19,58,57}, {53,52,16}, {43,16,52}, {43,52,51}, {57,54,19}, {47,60,46}, {55,58,34}, {55,34,44}, {50,47,46}, {50,46,43} }); break; case TestMesh::_40x10: mesh = TriangleMesh( - { Vec3d(12.8680295944214,29.5799007415771,12), Vec3d(11.7364797592163,29.8480796813965,12), Vec3d(11.1571502685547,29.5300102233887,12), Vec3d(10.5814504623413,29.9830799102783,12), Vec3d(10,29.6000003814697,12), Vec3d(9.41855144500732,29.9830799102783,12), Vec3d(8.84284687042236,29.5300102233887,12), Vec3d(8.26351833343506,29.8480796813965,12), Vec3d(7.70256900787354,29.3210391998291,12), Vec3d(7.13196802139282,29.5799007415771,12), Vec3d(6.59579277038574,28.9761600494385,12), Vec3d(6.03920221328735,29.1821594238281,12), Vec3d(5.53865718841553,28.5003795623779,12), Vec3d(5,28.6602592468262,12), Vec3d(4.54657793045044,27.9006500244141,12), Vec3d(4.02841377258301,28.0212306976318,12), Vec3d(3.63402199745178,27.1856994628906,12), Vec3d(3.13758301734924,27.2737407684326,12), Vec3d(2.81429696083069,26.3659801483154,12), Vec3d(2.33955597877502,26.4278793334961,12), Vec3d(2.0993549823761,25.4534206390381,12), Vec3d(1.64512205123901,25.4950904846191,12), Vec3d(1.49962198734283,24.4613399505615,12), Vec3d(1.0636739730835,24.4879894256592,12), Vec3d(1.02384400367737,23.4042091369629,12), Vec3d(0.603073298931122,23.4202003479004,12), Vec3d(0.678958415985107,22.2974300384521,12), Vec3d(0.269550800323486,22.3061599731445,12), Vec3d(0.469994693994522,21.1571502685547,12), Vec3d(0.067615881562233,21.1609306335449,12), Vec3d(0.399999290704727,20,12), Vec3d(0,20,12), Vec3d(0.399999290704727,5,12), Vec3d(0,5,12), Vec3d(0.456633001565933,4.2804012298584,12), Vec3d(0.0615576282143593,4.21782684326172,12), Vec3d(0.625140011310577,3.5785219669342,12), Vec3d(0.244717106223106,3.45491504669189,12), Vec3d(0.901369392871857,2.91164398193359,12), Vec3d(0.544967114925385,2.73004698753357,12), Vec3d(1.27852201461792,2.29618692398071,12), Vec3d(0.954914808273315,2.06107401847839,12), Vec3d(1.74730801582336,1.74730801582336,12), Vec3d(1.46446597576141,1.46446597576141,12), Vec3d(2.29618692398071,1.27852201461792,12), Vec3d(2.06107401847839,0.954914808273315,12), Vec3d(2.91164398193359,0.901369392871857,12), Vec3d(2.73004698753357,0.544967114925385,12), Vec3d(3.5785219669342,0.625140011310577,12), Vec3d(3.45491504669189,0.244717106223106,12), Vec3d(4.2804012298584,0.456633001565933,12), Vec3d(4.21782684326172,0.0615576282143593,12), Vec3d(5,0.399999290704727,12), Vec3d(5,0,12), Vec3d(19.6000003814697,0.399999290704727,12), Vec3d(20,0,12), Vec3d(19.6000003814697,20,12), Vec3d(20,20,12), Vec3d(19.5300102233887,21.1571502685547,12), Vec3d(19.9323806762695,21.1609306335449,12), Vec3d(19.3210391998291,22.2974300384521,12), Vec3d(19.7304496765137,22.3061599731445,12), Vec3d(18.9761600494385,23.4042091369629,12), Vec3d(19.3969306945801,23.4202003479004,12), Vec3d(18.5003795623779,24.4613399505615,12), Vec3d(18.9363307952881,24.4879894256592,12), Vec3d(17.9006500244141,25.4534206390381,12), Vec3d(18.3548793792725,25.4950904846191,12), Vec3d(17.1856994628906,26.3659801483154,12), Vec3d(17.6604404449463,26.4278793334961,12), Vec3d(16.3659801483154,27.1856994628906,12), Vec3d(16.862419128418,27.2737407684326,12), Vec3d(15.4534196853638,27.9006500244141,12), Vec3d(15.9715900421143,28.0212306976318,12), Vec3d(14.4613399505615,28.5003795623779,12), Vec3d(15,28.6602592468262,12), Vec3d(13.4042100906372,28.9761600494385,12), Vec3d(13.9608001708984,29.1821594238281,12), Vec3d(12.2974300384521,29.3210391998291,12), Vec3d(7.13196802139282,29.5799007415771,0), Vec3d(8.26351833343506,29.8480796813965,0), Vec3d(8.84284687042236,29.5300102233887,0), Vec3d(9.41855144500732,29.9830799102783,0), Vec3d(10,29.6000003814697,0), Vec3d(10.5814504623413,29.9830799102783,0), Vec3d(11.1571502685547,29.5300102233887,0), Vec3d(11.7364797592163,29.8480796813965,0), Vec3d(12.2974300384521,29.3210391998291,0), Vec3d(12.8680295944214,29.5799007415771,0), Vec3d(13.4042100906372,28.9761600494385,0), Vec3d(13.9608001708984,29.1821594238281,0), Vec3d(14.4613399505615,28.5003795623779,0), Vec3d(15,28.6602592468262,0), Vec3d(15.4534196853638,27.9006500244141,0), Vec3d(15.9715900421143,28.0212306976318,0), Vec3d(16.3659801483154,27.1856994628906,0), Vec3d(16.862419128418,27.2737407684326,0), Vec3d(17.1856994628906,26.3659801483154,0), Vec3d(17.6604404449463,26.4278793334961,0), Vec3d(17.9006500244141,25.4534206390381,0), Vec3d(18.3548793792725,25.4950904846191,0), Vec3d(18.5003795623779,24.4613399505615,0), Vec3d(18.9363307952881,24.4879894256592,0), Vec3d(18.9761600494385,23.4042091369629,0), Vec3d(19.3969306945801,23.4202003479004,0), Vec3d(19.3210391998291,22.2974300384521,0), Vec3d(19.7304496765137,22.3061599731445,0), Vec3d(19.5300102233887,21.1571502685547,0), Vec3d(19.9323806762695,21.1609306335449,0), Vec3d(19.6000003814697,20,0), Vec3d(20,20,0), Vec3d(19.6000003814697,0.399999290704727,0), Vec3d(20,0,0), Vec3d(5,0.399999290704727,0), Vec3d(5,0,0), Vec3d(4.2804012298584,0.456633001565933,0), Vec3d(4.21782684326172,0.0615576282143593,0), Vec3d(3.5785219669342,0.625140011310577,0), Vec3d(3.45491504669189,0.244717106223106,0), Vec3d(2.91164398193359,0.901369392871857,0), Vec3d(2.73004698753357,0.544967114925385,0), Vec3d(2.29618692398071,1.27852201461792,0), Vec3d(2.06107401847839,0.954914808273315,0), Vec3d(1.74730801582336,1.74730801582336,0), Vec3d(1.46446597576141,1.46446597576141,0), Vec3d(1.27852201461792,2.29618692398071,0), Vec3d(0.954914808273315,2.06107401847839,0), Vec3d(0.901369392871857,2.91164398193359,0), Vec3d(0.544967114925385,2.73004698753357,0), Vec3d(0.625140011310577,3.5785219669342,0), Vec3d(0.244717106223106,3.45491504669189,0), Vec3d(0.456633001565933,4.2804012298584,0), Vec3d(0.0615576282143593,4.21782684326172,0), Vec3d(0.399999290704727,5,0), Vec3d(0,5,0), Vec3d(0.399999290704727,20,0), Vec3d(0,20,0), Vec3d(0.469994693994522,21.1571502685547,0), Vec3d(0.067615881562233,21.1609306335449,0), Vec3d(0.678958415985107,22.2974300384521,0), Vec3d(0.269550800323486,22.3061599731445,0), Vec3d(1.02384400367737,23.4042091369629,0), Vec3d(0.603073298931122,23.4202003479004,0), Vec3d(1.49962198734283,24.4613399505615,0), Vec3d(1.0636739730835,24.4879894256592,0), Vec3d(2.0993549823761,25.4534206390381,0), Vec3d(1.64512205123901,25.4950904846191,0), Vec3d(2.81429696083069,26.3659801483154,0), Vec3d(2.33955597877502,26.4278793334961,0), Vec3d(3.63402199745178,27.1856994628906,0), Vec3d(3.13758301734924,27.2737407684326,0), Vec3d(4.54657793045044,27.9006500244141,0), Vec3d(4.02841377258301,28.0212306976318,0), Vec3d(5.53865718841553,28.5003795623779,0), Vec3d(5,28.6602592468262,0), Vec3d(6.59579277038574,28.9761600494385,0), Vec3d(6.03920221328735,29.1821594238281,0), Vec3d(7.70256900787354,29.3210391998291,0) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(2,3,4), Vec3crd(4,3,5), Vec3crd(4,5,6), Vec3crd(6,5,7), Vec3crd(6,7,8), Vec3crd(8,7,9), Vec3crd(8,9,10), Vec3crd(10,9,11), Vec3crd(10,11,12), Vec3crd(12,11,13), Vec3crd(12,13,14), Vec3crd(14,13,15), Vec3crd(14,15,16), Vec3crd(16,15,17), Vec3crd(16,17,18), Vec3crd(18,17,19), Vec3crd(18,19,20), Vec3crd(20,19,21), Vec3crd(20,21,22), Vec3crd(22,21,23), Vec3crd(22,23,24), Vec3crd(24,23,25), Vec3crd(24,25,26), Vec3crd(26,25,27), Vec3crd(26,27,28), Vec3crd(28,27,29), Vec3crd(28,29,30), Vec3crd(30,29,31), Vec3crd(30,31,32), Vec3crd(32,31,33), Vec3crd(32,33,34), Vec3crd(34,33,35), Vec3crd(34,35,36), Vec3crd(36,35,37), Vec3crd(36,37,38), Vec3crd(38,37,39), Vec3crd(38,39,40), Vec3crd(40,39,41), Vec3crd(40,41,42), Vec3crd(42,41,43), Vec3crd(42,43,44), Vec3crd(44,43,45), Vec3crd(44,45,46), Vec3crd(46,45,47), Vec3crd(46,47,48), Vec3crd(48,47,49), Vec3crd(48,49,50), Vec3crd(50,49,51), Vec3crd(50,51,52), Vec3crd(52,51,53), Vec3crd(52,53,54), Vec3crd(54,53,55), Vec3crd(54,55,56), Vec3crd(56,55,57), Vec3crd(56,57,58), Vec3crd(58,57,59), Vec3crd(58,59,60), Vec3crd(60,59,61), Vec3crd(60,61,62), Vec3crd(62,61,63), Vec3crd(62,63,64), Vec3crd(64,63,65), Vec3crd(64,65,66), Vec3crd(66,65,67), Vec3crd(66,67,68), Vec3crd(68,67,69), Vec3crd(68,69,70), Vec3crd(70,69,71), Vec3crd(70,71,72), Vec3crd(72,71,73), Vec3crd(72,73,74), Vec3crd(74,73,75), Vec3crd(74,75,76), Vec3crd(76,75,77), Vec3crd(76,77,78), Vec3crd(78,77,0), Vec3crd(78,0,2), Vec3crd(79,80,81), Vec3crd(81,80,82), Vec3crd(81,82,83), Vec3crd(83,82,84), Vec3crd(83,84,85), Vec3crd(85,84,86), Vec3crd(85,86,87), Vec3crd(87,86,88), Vec3crd(87,88,89), Vec3crd(89,88,90), Vec3crd(89,90,91), Vec3crd(91,90,92), Vec3crd(91,92,93), Vec3crd(93,92,94), Vec3crd(93,94,95), Vec3crd(95,94,96), Vec3crd(95,96,97), Vec3crd(97,96,98), Vec3crd(97,98,99), Vec3crd(99,98,100), Vec3crd(99,100,101), Vec3crd(101,100,102), Vec3crd(101,102,103), Vec3crd(103,102,104), Vec3crd(103,104,105), Vec3crd(105,104,106), Vec3crd(105,106,107), Vec3crd(107,106,108), Vec3crd(107,108,109), Vec3crd(109,108,110), Vec3crd(109,110,111), Vec3crd(111,110,112), Vec3crd(111,112,113), Vec3crd(113,112,114), Vec3crd(113,114,115), Vec3crd(115,114,116), Vec3crd(115,116,117), Vec3crd(117,116,118), Vec3crd(117,118,119), Vec3crd(119,118,120), Vec3crd(119,120,121), Vec3crd(121,120,122), Vec3crd(121,122,123), Vec3crd(123,122,124), Vec3crd(123,124,125), Vec3crd(125,124,126), Vec3crd(125,126,127), Vec3crd(127,126,128), Vec3crd(127,128,129), Vec3crd(129,128,130), Vec3crd(129,130,131), Vec3crd(131,130,132), Vec3crd(131,132,133), Vec3crd(133,132,134), Vec3crd(133,134,135), Vec3crd(135,134,136), Vec3crd(135,136,137), Vec3crd(137,136,138), Vec3crd(137,138,139), Vec3crd(139,138,140), Vec3crd(139,140,141), Vec3crd(141,140,142), Vec3crd(141,142,143), Vec3crd(143,142,144), Vec3crd(143,144,145), Vec3crd(145,144,146), Vec3crd(145,146,147), Vec3crd(147,146,148), Vec3crd(147,148,149), Vec3crd(149,148,150), Vec3crd(149,150,151), Vec3crd(151,150,152), Vec3crd(151,152,153), Vec3crd(153,152,154), Vec3crd(153,154,155), Vec3crd(155,154,156), Vec3crd(155,156,157), Vec3crd(157,156,79), Vec3crd(157,79,81), Vec3crd(57,110,108), Vec3crd(57,108,59), Vec3crd(59,108,106), Vec3crd(59,106,61), Vec3crd(61,106,104), Vec3crd(61,104,63), Vec3crd(63,104,102), Vec3crd(63,102,65), Vec3crd(65,102,100), Vec3crd(65,100,67), Vec3crd(67,100,98), Vec3crd(67,98,69), Vec3crd(69,98,96), Vec3crd(69,96,71), Vec3crd(71,96,94), Vec3crd(71,94,73), Vec3crd(73,94,92), Vec3crd(73,92,75), Vec3crd(75,92,90), Vec3crd(75,90,77), Vec3crd(77,90,88), Vec3crd(77,88,0), Vec3crd(0,88,86), Vec3crd(0,86,1), Vec3crd(1,86,84), Vec3crd(1,84,3), Vec3crd(3,84,82), Vec3crd(3,82,5), Vec3crd(5,82,80), Vec3crd(5,80,7), Vec3crd(7,80,79), Vec3crd(7,79,9), Vec3crd(9,79,156), Vec3crd(9,156,11), Vec3crd(11,156,154), Vec3crd(11,154,13), Vec3crd(13,154,152), Vec3crd(13,152,15), Vec3crd(15,152,150), Vec3crd(15,150,17), Vec3crd(17,150,148), Vec3crd(17,148,19), Vec3crd(19,148,146), Vec3crd(19,146,21), Vec3crd(21,146,144), Vec3crd(21,144,23), Vec3crd(23,144,142), Vec3crd(23,142,25), Vec3crd(25,142,140), Vec3crd(25,140,27), Vec3crd(27,140,138), Vec3crd(27,138,29), Vec3crd(29,138,136), Vec3crd(29,136,31), Vec3crd(33,31,134), Vec3crd(134,31,136), Vec3crd(33,134,132), Vec3crd(33,132,35), Vec3crd(35,132,130), Vec3crd(35,130,37), Vec3crd(37,130,128), Vec3crd(37,128,39), Vec3crd(39,128,126), Vec3crd(39,126,41), Vec3crd(41,126,124), Vec3crd(41,124,43), Vec3crd(43,124,122), Vec3crd(43,122,45), Vec3crd(45,122,120), Vec3crd(45,120,47), Vec3crd(47,120,118), Vec3crd(47,118,49), Vec3crd(49,118,116), Vec3crd(49,116,51), Vec3crd(51,116,114), Vec3crd(51,114,53), Vec3crd(55,53,112), Vec3crd(112,53,114), Vec3crd(57,55,110), Vec3crd(110,55,112), Vec3crd(30,135,137), Vec3crd(30,137,28), Vec3crd(28,137,139), Vec3crd(28,139,26), Vec3crd(26,139,141), Vec3crd(26,141,24), Vec3crd(24,141,143), Vec3crd(24,143,22), Vec3crd(22,143,145), Vec3crd(22,145,20), Vec3crd(20,145,147), Vec3crd(20,147,18), Vec3crd(18,147,149), Vec3crd(18,149,16), Vec3crd(16,149,151), Vec3crd(16,151,14), Vec3crd(14,151,153), Vec3crd(14,153,12), Vec3crd(12,153,155), Vec3crd(12,155,10), Vec3crd(10,155,157), Vec3crd(10,157,8), Vec3crd(8,157,81), Vec3crd(8,81,6), Vec3crd(6,81,83), Vec3crd(6,83,4), Vec3crd(4,83,85), Vec3crd(4,85,2), Vec3crd(2,85,87), Vec3crd(2,87,78), Vec3crd(78,87,89), Vec3crd(78,89,76), Vec3crd(76,89,91), Vec3crd(76,91,74), Vec3crd(74,91,93), Vec3crd(74,93,72), Vec3crd(72,93,95), Vec3crd(72,95,70), Vec3crd(70,95,97), Vec3crd(70,97,68), Vec3crd(68,97,99), Vec3crd(68,99,66), Vec3crd(66,99,101), Vec3crd(66,101,64), Vec3crd(64,101,103), Vec3crd(64,103,62), Vec3crd(62,103,105), Vec3crd(62,105,60), Vec3crd(60,105,107), Vec3crd(60,107,58), Vec3crd(58,107,109), Vec3crd(58,109,56), Vec3crd(30,32,135), Vec3crd(135,32,133), Vec3crd(52,113,115), Vec3crd(52,115,50), Vec3crd(50,115,117), Vec3crd(50,117,48), Vec3crd(48,117,119), Vec3crd(48,119,46), Vec3crd(46,119,121), Vec3crd(46,121,44), Vec3crd(44,121,123), Vec3crd(44,123,42), Vec3crd(42,123,125), Vec3crd(42,125,40), Vec3crd(40,125,127), Vec3crd(40,127,38), Vec3crd(38,127,129), Vec3crd(38,129,36), Vec3crd(36,129,131), Vec3crd(36,131,34), Vec3crd(34,131,133), Vec3crd(34,133,32), Vec3crd(52,54,113), Vec3crd(113,54,111), Vec3crd(54,56,111), Vec3crd(111,56,109) }); + { {12.8680295944214,29.5799007415771,12}, {11.7364797592163,29.8480796813965,12}, {11.1571502685547,29.5300102233887,12}, {10.5814504623413,29.9830799102783,12}, {10,29.6000003814697,12}, {9.41855144500732,29.9830799102783,12}, {8.84284687042236,29.5300102233887,12}, {8.26351833343506,29.8480796813965,12}, {7.70256900787354,29.3210391998291,12}, {7.13196802139282,29.5799007415771,12}, {6.59579277038574,28.9761600494385,12}, {6.03920221328735,29.1821594238281,12}, {5.53865718841553,28.5003795623779,12}, {5,28.6602592468262,12}, {4.54657793045044,27.9006500244141,12}, {4.02841377258301,28.0212306976318,12}, {3.63402199745178,27.1856994628906,12}, {3.13758301734924,27.2737407684326,12}, {2.81429696083069,26.3659801483154,12}, {2.33955597877502,26.4278793334961,12}, {2.0993549823761,25.4534206390381,12}, {1.64512205123901,25.4950904846191,12}, {1.49962198734283,24.4613399505615,12}, {1.0636739730835,24.4879894256592,12}, {1.02384400367737,23.4042091369629,12}, {0.603073298931122,23.4202003479004,12}, {0.678958415985107,22.2974300384521,12}, {0.269550800323486,22.3061599731445,12}, {0.469994693994522,21.1571502685547,12}, {0.067615881562233,21.1609306335449,12}, {0.399999290704727,20,12}, {0,20,12}, {0.399999290704727,5,12}, {0,5,12}, {0.456633001565933,4.2804012298584,12}, {0.0615576282143593,4.21782684326172,12}, {0.625140011310577,3.5785219669342,12}, {0.244717106223106,3.45491504669189,12}, {0.901369392871857,2.91164398193359,12}, {0.544967114925385,2.73004698753357,12}, {1.27852201461792,2.29618692398071,12}, {0.954914808273315,2.06107401847839,12}, {1.74730801582336,1.74730801582336,12}, {1.46446597576141,1.46446597576141,12}, {2.29618692398071,1.27852201461792,12}, {2.06107401847839,0.954914808273315,12}, {2.91164398193359,0.901369392871857,12}, {2.73004698753357,0.544967114925385,12}, {3.5785219669342,0.625140011310577,12}, {3.45491504669189,0.244717106223106,12}, {4.2804012298584,0.456633001565933,12}, {4.21782684326172,0.0615576282143593,12}, {5,0.399999290704727,12}, {5,0,12}, {19.6000003814697,0.399999290704727,12}, {20,0,12}, {19.6000003814697,20,12}, {20,20,12}, {19.5300102233887,21.1571502685547,12}, {19.9323806762695,21.1609306335449,12}, {19.3210391998291,22.2974300384521,12}, {19.7304496765137,22.3061599731445,12}, {18.9761600494385,23.4042091369629,12}, {19.3969306945801,23.4202003479004,12}, {18.5003795623779,24.4613399505615,12}, {18.9363307952881,24.4879894256592,12}, {17.9006500244141,25.4534206390381,12}, {18.3548793792725,25.4950904846191,12}, {17.1856994628906,26.3659801483154,12}, {17.6604404449463,26.4278793334961,12}, {16.3659801483154,27.1856994628906,12}, {16.862419128418,27.2737407684326,12}, {15.4534196853638,27.9006500244141,12}, {15.9715900421143,28.0212306976318,12}, {14.4613399505615,28.5003795623779,12}, {15,28.6602592468262,12}, {13.4042100906372,28.9761600494385,12}, {13.9608001708984,29.1821594238281,12}, {12.2974300384521,29.3210391998291,12}, {7.13196802139282,29.5799007415771,0}, {8.26351833343506,29.8480796813965,0}, {8.84284687042236,29.5300102233887,0}, {9.41855144500732,29.9830799102783,0}, {10,29.6000003814697,0}, {10.5814504623413,29.9830799102783,0}, {11.1571502685547,29.5300102233887,0}, {11.7364797592163,29.8480796813965,0}, {12.2974300384521,29.3210391998291,0}, {12.8680295944214,29.5799007415771,0}, {13.4042100906372,28.9761600494385,0}, {13.9608001708984,29.1821594238281,0}, {14.4613399505615,28.5003795623779,0}, {15,28.6602592468262,0}, {15.4534196853638,27.9006500244141,0}, {15.9715900421143,28.0212306976318,0}, {16.3659801483154,27.1856994628906,0}, {16.862419128418,27.2737407684326,0}, {17.1856994628906,26.3659801483154,0}, {17.6604404449463,26.4278793334961,0}, {17.9006500244141,25.4534206390381,0}, {18.3548793792725,25.4950904846191,0}, {18.5003795623779,24.4613399505615,0}, {18.9363307952881,24.4879894256592,0}, {18.9761600494385,23.4042091369629,0}, {19.3969306945801,23.4202003479004,0}, {19.3210391998291,22.2974300384521,0}, {19.7304496765137,22.3061599731445,0}, {19.5300102233887,21.1571502685547,0}, {19.9323806762695,21.1609306335449,0}, {19.6000003814697,20,0}, {20,20,0}, {19.6000003814697,0.399999290704727,0}, {20,0,0}, {5,0.399999290704727,0}, {5,0,0}, {4.2804012298584,0.456633001565933,0}, {4.21782684326172,0.0615576282143593,0}, {3.5785219669342,0.625140011310577,0}, {3.45491504669189,0.244717106223106,0}, {2.91164398193359,0.901369392871857,0}, {2.73004698753357,0.544967114925385,0}, {2.29618692398071,1.27852201461792,0}, {2.06107401847839,0.954914808273315,0}, {1.74730801582336,1.74730801582336,0}, {1.46446597576141,1.46446597576141,0}, {1.27852201461792,2.29618692398071,0}, {0.954914808273315,2.06107401847839,0}, {0.901369392871857,2.91164398193359,0}, {0.544967114925385,2.73004698753357,0}, {0.625140011310577,3.5785219669342,0}, {0.244717106223106,3.45491504669189,0}, {0.456633001565933,4.2804012298584,0}, {0.0615576282143593,4.21782684326172,0}, {0.399999290704727,5,0}, {0,5,0}, {0.399999290704727,20,0}, {0,20,0}, {0.469994693994522,21.1571502685547,0}, {0.067615881562233,21.1609306335449,0}, {0.678958415985107,22.2974300384521,0}, {0.269550800323486,22.3061599731445,0}, {1.02384400367737,23.4042091369629,0}, {0.603073298931122,23.4202003479004,0}, {1.49962198734283,24.4613399505615,0}, {1.0636739730835,24.4879894256592,0}, {2.0993549823761,25.4534206390381,0}, {1.64512205123901,25.4950904846191,0}, {2.81429696083069,26.3659801483154,0}, {2.33955597877502,26.4278793334961,0}, {3.63402199745178,27.1856994628906,0}, {3.13758301734924,27.2737407684326,0}, {4.54657793045044,27.9006500244141,0}, {4.02841377258301,28.0212306976318,0}, {5.53865718841553,28.5003795623779,0}, {5,28.6602592468262,0}, {6.59579277038574,28.9761600494385,0}, {6.03920221328735,29.1821594238281,0}, {7.70256900787354,29.3210391998291,0} }, + { {0,1,2}, {2,1,3}, {2,3,4}, {4,3,5}, {4,5,6}, {6,5,7}, {6,7,8}, {8,7,9}, {8,9,10}, {10,9,11}, {10,11,12}, {12,11,13}, {12,13,14}, {14,13,15}, {14,15,16}, {16,15,17}, {16,17,18}, {18,17,19}, {18,19,20}, {20,19,21}, {20,21,22}, {22,21,23}, {22,23,24}, {24,23,25}, {24,25,26}, {26,25,27}, {26,27,28}, {28,27,29}, {28,29,30}, {30,29,31}, {30,31,32}, {32,31,33}, {32,33,34}, {34,33,35}, {34,35,36}, {36,35,37}, {36,37,38}, {38,37,39}, {38,39,40}, {40,39,41}, {40,41,42}, {42,41,43}, {42,43,44}, {44,43,45}, {44,45,46}, {46,45,47}, {46,47,48}, {48,47,49}, {48,49,50}, {50,49,51}, {50,51,52}, {52,51,53}, {52,53,54}, {54,53,55}, {54,55,56}, {56,55,57}, {56,57,58}, {58,57,59}, {58,59,60}, {60,59,61}, {60,61,62}, {62,61,63}, {62,63,64}, {64,63,65}, {64,65,66}, {66,65,67}, {66,67,68}, {68,67,69}, {68,69,70}, {70,69,71}, {70,71,72}, {72,71,73}, {72,73,74}, {74,73,75}, {74,75,76}, {76,75,77}, {76,77,78}, {78,77,0}, {78,0,2}, {79,80,81}, {81,80,82}, {81,82,83}, {83,82,84}, {83,84,85}, {85,84,86}, {85,86,87}, {87,86,88}, {87,88,89}, {89,88,90}, {89,90,91}, {91,90,92}, {91,92,93}, {93,92,94}, {93,94,95}, {95,94,96}, {95,96,97}, {97,96,98}, {97,98,99}, {99,98,100}, {99,100,101}, {101,100,102}, {101,102,103}, {103,102,104}, {103,104,105}, {105,104,106}, {105,106,107}, {107,106,108}, {107,108,109}, {109,108,110}, {109,110,111}, {111,110,112}, {111,112,113}, {113,112,114}, {113,114,115}, {115,114,116}, {115,116,117}, {117,116,118}, {117,118,119}, {119,118,120}, {119,120,121}, {121,120,122}, {121,122,123}, {123,122,124}, {123,124,125}, {125,124,126}, {125,126,127}, {127,126,128}, {127,128,129}, {129,128,130}, {129,130,131}, {131,130,132}, {131,132,133}, {133,132,134}, {133,134,135}, {135,134,136}, {135,136,137}, {137,136,138}, {137,138,139}, {139,138,140}, {139,140,141}, {141,140,142}, {141,142,143}, {143,142,144}, {143,144,145}, {145,144,146}, {145,146,147}, {147,146,148}, {147,148,149}, {149,148,150}, {149,150,151}, {151,150,152}, {151,152,153}, {153,152,154}, {153,154,155}, {155,154,156}, {155,156,157}, {157,156,79}, {157,79,81}, {57,110,108}, {57,108,59}, {59,108,106}, {59,106,61}, {61,106,104}, {61,104,63}, {63,104,102}, {63,102,65}, {65,102,100}, {65,100,67}, {67,100,98}, {67,98,69}, {69,98,96}, {69,96,71}, {71,96,94}, {71,94,73}, {73,94,92}, {73,92,75}, {75,92,90}, {75,90,77}, {77,90,88}, {77,88,0}, {0,88,86}, {0,86,1}, {1,86,84}, {1,84,3}, {3,84,82}, {3,82,5}, {5,82,80}, {5,80,7}, {7,80,79}, {7,79,9}, {9,79,156}, {9,156,11}, {11,156,154}, {11,154,13}, {13,154,152}, {13,152,15}, {15,152,150}, {15,150,17}, {17,150,148}, {17,148,19}, {19,148,146}, {19,146,21}, {21,146,144}, {21,144,23}, {23,144,142}, {23,142,25}, {25,142,140}, {25,140,27}, {27,140,138}, {27,138,29}, {29,138,136}, {29,136,31}, {33,31,134}, {134,31,136}, {33,134,132}, {33,132,35}, {35,132,130}, {35,130,37}, {37,130,128}, {37,128,39}, {39,128,126}, {39,126,41}, {41,126,124}, {41,124,43}, {43,124,122}, {43,122,45}, {45,122,120}, {45,120,47}, {47,120,118}, {47,118,49}, {49,118,116}, {49,116,51}, {51,116,114}, {51,114,53}, {55,53,112}, {112,53,114}, {57,55,110}, {110,55,112}, {30,135,137}, {30,137,28}, {28,137,139}, {28,139,26}, {26,139,141}, {26,141,24}, {24,141,143}, {24,143,22}, {22,143,145}, {22,145,20}, {20,145,147}, {20,147,18}, {18,147,149}, {18,149,16}, {16,149,151}, {16,151,14}, {14,151,153}, {14,153,12}, {12,153,155}, {12,155,10}, {10,155,157}, {10,157,8}, {8,157,81}, {8,81,6}, {6,81,83}, {6,83,4}, {4,83,85}, {4,85,2}, {2,85,87}, {2,87,78}, {78,87,89}, {78,89,76}, {76,89,91}, {76,91,74}, {74,91,93}, {74,93,72}, {72,93,95}, {72,95,70}, {70,95,97}, {70,97,68}, {68,97,99}, {68,99,66}, {66,99,101}, {66,101,64}, {64,101,103}, {64,103,62}, {62,103,105}, {62,105,60}, {60,105,107}, {60,107,58}, {58,107,109}, {58,109,56}, {30,32,135}, {135,32,133}, {52,113,115}, {52,115,50}, {50,115,117}, {50,117,48}, {48,117,119}, {48,119,46}, {46,119,121}, {46,121,44}, {44,121,123}, {44,123,42}, {42,123,125}, {42,125,40}, {40,125,127}, {40,127,38}, {38,127,129}, {38,129,36}, {36,129,131}, {36,131,34}, {34,131,133}, {34,133,32}, {52,54,113}, {113,54,111}, {54,56,111}, {111,56,109} }); break; case TestMesh::sloping_hole: mesh = TriangleMesh( - { Vec3d(-20,-20,-5), Vec3d(-20,-20,5), Vec3d(-20,20,-5), Vec3d(-20,20,5), Vec3d(20,-20,-5), Vec3d(20,-20,5), Vec3d(4.46294021606445,7.43144989013672,-5), Vec3d(20,20,-5), Vec3d(-19.1420993804932,0,-5), Vec3d(-18.8330993652344,-2.07911992073059,-5), Vec3d(-17.9195003509521,-4.06736993789673,-5), Vec3d(-16.4412002563477,-5.87785005569458,-5), Vec3d(-14.4629001617432,-7.43144989013672,-5), Vec3d(-12.0711002349854,-8.66024971008301,-5), Vec3d(-9.37016010284424,-9.51056003570557,-5), Vec3d(-3.5217399597168,-9.94521999359131,-5), Vec3d(-6.4782600402832,-9.94521999359131,-5), Vec3d(-0.629840016365051,-9.51056003570557,-5), Vec3d(2.07106995582581,-8.66024971008301,-5), Vec3d(6.44122982025146,-5.87785005569458,-5), Vec3d(4.46294021606445,-7.43144989013672,-5), Vec3d(-12.0711002349854,8.66024971008301,-5), Vec3d(-9.37016010284424,9.51056003570557,-5), Vec3d(7.91947984695435,-4.06736993789673,-5), Vec3d(8.83310031890869,-2.07911992073059,-5), Vec3d(-6.4782600402832,9.94521999359131,-5), Vec3d(-0.629840016365051,9.51056003570557,-5), Vec3d(2.07106995582581,8.66024971008301,-5), Vec3d(9.14214038848877,0,-5), Vec3d(8.83310031890869,2.07911992073059,-5), Vec3d(-3.5217399597168,9.94521999359131,-5), Vec3d(7.91947984695435,4.06736993789673,-5), Vec3d(6.44122982025146,5.87785005569458,-5), Vec3d(-14.4629001617432,7.43144989013672,-5), Vec3d(-16.4412002563477,5.87785005569458,-5), Vec3d(-17.9195003509521,4.06736993789673,-5), Vec3d(-18.8330993652344,2.07911992073059,-5), Vec3d(20,20,5), Vec3d(3.5217399597168,-9.94521999359131,5), Vec3d(-8.83310031890869,-2.07911992073059,5), Vec3d(-9.14214038848877,0,5), Vec3d(-8.83310031890869,2.07911992073059,5), Vec3d(6.4782600402832,-9.94521999359131,5), Vec3d(-7.91947984695435,4.06736993789673,5), Vec3d(-6.44122982025146,5.87785005569458,5), Vec3d(-4.46294021606445,7.43144989013672,5), Vec3d(-2.07106995582581,8.66024971008301,5), Vec3d(0.629840016365051,9.51056003570557,5), Vec3d(12.0711002349854,-8.66024971008301,5), Vec3d(9.37016010284424,-9.51056003570557,5), Vec3d(3.5217399597168,9.94521999359131,5), Vec3d(6.4782600402832,9.94521999359131,5), Vec3d(9.37016010284424,9.51056003570557,5), Vec3d(12.0711002349854,8.66024971008301,5), Vec3d(14.4629001617432,7.43144989013672,5), Vec3d(16.4412002563477,-5.87785005569458,5), Vec3d(14.4629001617432,-7.43144989013672,5), Vec3d(16.4412002563477,5.87785005569458,5), Vec3d(17.9195003509521,4.06736993789673,5), Vec3d(18.8330993652344,-2.07911992073059,5), Vec3d(17.9195003509521,-4.06736993789673,5), Vec3d(18.8330993652344,2.07911992073059,5), Vec3d(19.1420993804932,0,5), Vec3d(0.629840016365051,-9.51056003570557,5), Vec3d(-2.07106995582581,-8.66024971008301,5), Vec3d(-4.46294021606445,-7.43144989013672,5), Vec3d(-6.44122982025146,-5.87785005569458,5), Vec3d(-7.91947984695435,-4.06736993789673,5) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(1,0,4), Vec3crd(5,1,4), Vec3crd(6,2,7), Vec3crd(0,2,8), Vec3crd(0,8,9), Vec3crd(0,9,10), Vec3crd(0,10,11), Vec3crd(0,11,12), Vec3crd(0,12,13), Vec3crd(0,13,4), Vec3crd(13,14,4), Vec3crd(15,4,16), Vec3crd(17,4,15), Vec3crd(18,4,17), Vec3crd(19,4,20), Vec3crd(18,20,4), Vec3crd(21,2,22), Vec3crd(4,19,23), Vec3crd(4,23,7), Vec3crd(23,24,7), Vec3crd(22,2,25), Vec3crd(26,2,27), Vec3crd(28,29,7), Vec3crd(25,2,30), Vec3crd(29,31,7), Vec3crd(30,2,26), Vec3crd(31,32,7), Vec3crd(27,2,6), Vec3crd(32,6,7), Vec3crd(28,7,24), Vec3crd(33,2,21), Vec3crd(34,2,33), Vec3crd(35,2,34), Vec3crd(36,2,35), Vec3crd(8,2,36), Vec3crd(16,4,14), Vec3crd(2,3,7), Vec3crd(7,3,37), Vec3crd(38,1,5), Vec3crd(3,1,39), Vec3crd(3,39,40), Vec3crd(3,40,41), Vec3crd(42,38,5), Vec3crd(3,41,43), Vec3crd(3,43,44), Vec3crd(37,3,45), Vec3crd(37,45,46), Vec3crd(37,46,47), Vec3crd(48,49,5), Vec3crd(37,47,50), Vec3crd(49,42,5), Vec3crd(37,50,51), Vec3crd(37,51,52), Vec3crd(37,52,53), Vec3crd(37,53,54), Vec3crd(55,56,5), Vec3crd(37,54,57), Vec3crd(37,57,58), Vec3crd(59,60,5), Vec3crd(37,58,61), Vec3crd(37,62,5), Vec3crd(37,61,62), Vec3crd(62,59,5), Vec3crd(60,55,5), Vec3crd(63,1,38), Vec3crd(64,1,63), Vec3crd(65,1,64), Vec3crd(66,1,65), Vec3crd(67,1,66), Vec3crd(39,1,67), Vec3crd(44,45,3), Vec3crd(56,48,5), Vec3crd(5,4,7), Vec3crd(37,5,7), Vec3crd(41,40,36), Vec3crd(36,40,8), Vec3crd(39,9,40), Vec3crd(40,9,8), Vec3crd(43,41,35), Vec3crd(35,41,36), Vec3crd(44,43,34), Vec3crd(34,43,35), Vec3crd(33,45,44), Vec3crd(34,33,44), Vec3crd(21,46,45), Vec3crd(33,21,45), Vec3crd(22,47,46), Vec3crd(21,22,46), Vec3crd(25,50,47), Vec3crd(22,25,47), Vec3crd(30,51,50), Vec3crd(25,30,50), Vec3crd(26,52,51), Vec3crd(30,26,51), Vec3crd(27,53,52), Vec3crd(26,27,52), Vec3crd(6,54,53), Vec3crd(27,6,53), Vec3crd(32,57,54), Vec3crd(6,32,54), Vec3crd(31,58,57), Vec3crd(32,31,57), Vec3crd(29,61,58), Vec3crd(31,29,58), Vec3crd(28,62,61), Vec3crd(29,28,61), Vec3crd(59,62,28), Vec3crd(24,59,28), Vec3crd(60,59,24), Vec3crd(23,60,24), Vec3crd(55,60,23), Vec3crd(19,55,23), Vec3crd(55,19,56), Vec3crd(56,19,20), Vec3crd(56,20,48), Vec3crd(48,20,18), Vec3crd(48,18,49), Vec3crd(49,18,17), Vec3crd(49,17,42), Vec3crd(42,17,15), Vec3crd(42,15,38), Vec3crd(38,15,16), Vec3crd(38,16,63), Vec3crd(63,16,14), Vec3crd(63,14,64), Vec3crd(64,14,13), Vec3crd(64,13,65), Vec3crd(65,13,12), Vec3crd(65,12,66), Vec3crd(66,12,11), Vec3crd(66,11,67), Vec3crd(67,11,10), Vec3crd(67,10,39), Vec3crd(39,10,9) }); + { {-20,-20,-5}, {-20,-20,5}, {-20,20,-5}, {-20,20,5}, {20,-20,-5}, {20,-20,5}, {4.46294021606445,7.43144989013672,-5}, {20,20,-5}, {-19.1420993804932,0,-5}, {-18.8330993652344,-2.07911992073059,-5}, {-17.9195003509521,-4.06736993789673,-5}, {-16.4412002563477,-5.87785005569458,-5}, {-14.4629001617432,-7.43144989013672,-5}, {-12.0711002349854,-8.66024971008301,-5}, {-9.37016010284424,-9.51056003570557,-5}, {-3.5217399597168,-9.94521999359131,-5}, {-6.4782600402832,-9.94521999359131,-5}, {-0.629840016365051,-9.51056003570557,-5}, {2.07106995582581,-8.66024971008301,-5}, {6.44122982025146,-5.87785005569458,-5}, {4.46294021606445,-7.43144989013672,-5}, {-12.0711002349854,8.66024971008301,-5}, {-9.37016010284424,9.51056003570557,-5}, {7.91947984695435,-4.06736993789673,-5}, {8.83310031890869,-2.07911992073059,-5}, {-6.4782600402832,9.94521999359131,-5}, {-0.629840016365051,9.51056003570557,-5}, {2.07106995582581,8.66024971008301,-5}, {9.14214038848877,0,-5}, {8.83310031890869,2.07911992073059,-5}, {-3.5217399597168,9.94521999359131,-5}, {7.91947984695435,4.06736993789673,-5}, {6.44122982025146,5.87785005569458,-5}, {-14.4629001617432,7.43144989013672,-5}, {-16.4412002563477,5.87785005569458,-5}, {-17.9195003509521,4.06736993789673,-5}, {-18.8330993652344,2.07911992073059,-5}, {20,20,5}, {3.5217399597168,-9.94521999359131,5}, {-8.83310031890869,-2.07911992073059,5}, {-9.14214038848877,0,5}, {-8.83310031890869,2.07911992073059,5}, {6.4782600402832,-9.94521999359131,5}, {-7.91947984695435,4.06736993789673,5}, {-6.44122982025146,5.87785005569458,5}, {-4.46294021606445,7.43144989013672,5}, {-2.07106995582581,8.66024971008301,5}, {0.629840016365051,9.51056003570557,5}, {12.0711002349854,-8.66024971008301,5}, {9.37016010284424,-9.51056003570557,5}, {3.5217399597168,9.94521999359131,5}, {6.4782600402832,9.94521999359131,5}, {9.37016010284424,9.51056003570557,5}, {12.0711002349854,8.66024971008301,5}, {14.4629001617432,7.43144989013672,5}, {16.4412002563477,-5.87785005569458,5}, {14.4629001617432,-7.43144989013672,5}, {16.4412002563477,5.87785005569458,5}, {17.9195003509521,4.06736993789673,5}, {18.8330993652344,-2.07911992073059,5}, {17.9195003509521,-4.06736993789673,5}, {18.8330993652344,2.07911992073059,5}, {19.1420993804932,0,5}, {0.629840016365051,-9.51056003570557,5}, {-2.07106995582581,-8.66024971008301,5}, {-4.46294021606445,-7.43144989013672,5}, {-6.44122982025146,-5.87785005569458,5}, {-7.91947984695435,-4.06736993789673,5} }, + { {0,1,2}, {2,1,3}, {1,0,4}, {5,1,4}, {6,2,7}, {0,2,8}, {0,8,9}, {0,9,10}, {0,10,11}, {0,11,12}, {0,12,13}, {0,13,4}, {13,14,4}, {15,4,16}, {17,4,15}, {18,4,17}, {19,4,20}, {18,20,4}, {21,2,22}, {4,19,23}, {4,23,7}, {23,24,7}, {22,2,25}, {26,2,27}, {28,29,7}, {25,2,30}, {29,31,7}, {30,2,26}, {31,32,7}, {27,2,6}, {32,6,7}, {28,7,24}, {33,2,21}, {34,2,33}, {35,2,34}, {36,2,35}, {8,2,36}, {16,4,14}, {2,3,7}, {7,3,37}, {38,1,5}, {3,1,39}, {3,39,40}, {3,40,41}, {42,38,5}, {3,41,43}, {3,43,44}, {37,3,45}, {37,45,46}, {37,46,47}, {48,49,5}, {37,47,50}, {49,42,5}, {37,50,51}, {37,51,52}, {37,52,53}, {37,53,54}, {55,56,5}, {37,54,57}, {37,57,58}, {59,60,5}, {37,58,61}, {37,62,5}, {37,61,62}, {62,59,5}, {60,55,5}, {63,1,38}, {64,1,63}, {65,1,64}, {66,1,65}, {67,1,66}, {39,1,67}, {44,45,3}, {56,48,5}, {5,4,7}, {37,5,7}, {41,40,36}, {36,40,8}, {39,9,40}, {40,9,8}, {43,41,35}, {35,41,36}, {44,43,34}, {34,43,35}, {33,45,44}, {34,33,44}, {21,46,45}, {33,21,45}, {22,47,46}, {21,22,46}, {25,50,47}, {22,25,47}, {30,51,50}, {25,30,50}, {26,52,51}, {30,26,51}, {27,53,52}, {26,27,52}, {6,54,53}, {27,6,53}, {32,57,54}, {6,32,54}, {31,58,57}, {32,31,57}, {29,61,58}, {31,29,58}, {28,62,61}, {29,28,61}, {59,62,28}, {24,59,28}, {60,59,24}, {23,60,24}, {55,60,23}, {19,55,23}, {55,19,56}, {56,19,20}, {56,20,48}, {48,20,18}, {48,18,49}, {49,18,17}, {49,17,42}, {42,17,15}, {42,15,38}, {38,15,16}, {38,16,63}, {63,16,14}, {63,14,64}, {64,14,13}, {64,13,65}, {65,13,12}, {65,12,66}, {66,12,11}, {66,11,67}, {67,11,10}, {67,10,39}, {39,10,9} }); break; case TestMesh::ipadstand: mesh = TriangleMesh( - { Vec3d(17.4344673156738,-2.69879599481136e-16,9.5), Vec3d(14.2814798355103,10,9.5), Vec3d(0,0,9.5), Vec3d(31.7159481048584,10,9.5), Vec3d(62.2344741821289,2.06667568800577e-16,20), Vec3d(31.7159481048584,10,20), Vec3d(17.4344673156738,-2.69879599481136e-16,20), Vec3d(62.2344741821289,10,20), Vec3d(98.2079696655273,10,0), Vec3d(98.2079696655273,8.56525380796383e-16,10), Vec3d(98.2079696655273,0,0), Vec3d(98.2079696655273,10,20), Vec3d(98.2079696655273,0,20), Vec3d(81.6609649658203,-4.39753856997999e-16,10), Vec3d(90.0549850463867,10,10), Vec3d(78.5079803466797,10,10), Vec3d(93.2079696655273,8.56525380796383e-16,10), Vec3d(14.2814798355103,10,20), Vec3d(0,0,20), Vec3d(87.4344711303711,2.81343962782118e-15,20), Vec3d(84.2814788818359,10,20), Vec3d(0,10,20), Vec3d(0,0,0), Vec3d(0,10,0), Vec3d(62.2344741821289,2.06667568800577e-16,30), Vec3d(66.9609756469727,10,30), Vec3d(62.2344741821289,10,30), Vec3d(70.1139602661133,8.5525763717214e-16,30), Vec3d(67.7053375244141,10,28.7107200622559), Vec3d(71.6787109375,1.24046736339707e-15,27.2897701263428) }, - { Vec3crd(0,1,2), Vec3crd(1,0,3), Vec3crd(4,5,6), Vec3crd(5,4,7), Vec3crd(8,9,10), Vec3crd(9,11,12), Vec3crd(11,9,8), Vec3crd(13,14,15), Vec3crd(14,13,16), Vec3crd(17,2,1), Vec3crd(2,17,18), Vec3crd(19,11,20), Vec3crd(11,19,12), Vec3crd(17,21,18), Vec3crd(21,2,18), Vec3crd(2,21,22), Vec3crd(22,21,23), Vec3crd(8,22,23), Vec3crd(22,8,10), Vec3crd(24,25,26), Vec3crd(25,24,27), Vec3crd(23,1,8), Vec3crd(1,23,21), Vec3crd(1,21,17), Vec3crd(5,15,3), Vec3crd(15,5,7), Vec3crd(15,7,28), Vec3crd(28,7,26), Vec3crd(28,26,25), Vec3crd(8,14,11), Vec3crd(14,8,3), Vec3crd(3,8,1), Vec3crd(14,3,15), Vec3crd(11,14,20), Vec3crd(26,4,24), Vec3crd(4,26,7), Vec3crd(12,16,9), Vec3crd(16,12,19), Vec3crd(29,4,13), Vec3crd(4,29,24), Vec3crd(24,29,27), Vec3crd(9,22,10), Vec3crd(22,9,0), Vec3crd(0,9,16), Vec3crd(0,16,13), Vec3crd(0,13,6), Vec3crd(6,13,4), Vec3crd(2,22,0), Vec3crd(19,14,16), Vec3crd(14,19,20), Vec3crd(15,29,13), Vec3crd(29,25,27), Vec3crd(25,29,15), Vec3crd(25,15,28), Vec3crd(6,3,0), Vec3crd(3,6,5) }); + { Vec3d(17.4344673156738,-2.69879599481136e-16,9.5), {14.2814798355103,10,9.5}, {0,0,9.5}, {31.7159481048584,10,9.5}, Vec3d(62.2344741821289,2.06667568800577e-16,20), {31.7159481048584,10,20}, Vec3d(17.4344673156738,-2.69879599481136e-16,20), {62.2344741821289,10,20}, {98.2079696655273,10,0}, Vec3d(98.2079696655273,8.56525380796383e-16,10), {98.2079696655273,0,0}, {98.2079696655273,10,20}, {98.2079696655273,0,20}, Vec3d(81.6609649658203,-4.39753856997999e-16,10), {90.0549850463867,10,10}, {78.5079803466797,10,10}, Vec3d(93.2079696655273,8.56525380796383e-16,10), {14.2814798355103,10,20}, {0,0,20}, Vec3d(87.4344711303711,2.81343962782118e-15,20), {84.2814788818359,10,20}, {0,10,20}, {0,0,0}, {0,10,0}, Vec3d(62.2344741821289,2.06667568800577e-16,30), {66.9609756469727,10,30}, {62.2344741821289,10,30}, Vec3d(70.1139602661133,8.5525763717214e-16,30), {67.7053375244141,10,28.7107200622559}, Vec3d(71.6787109375,1.24046736339707e-15,27.2897701263428) }, + { {0,1,2}, {1,0,3}, {4,5,6}, {5,4,7}, {8,9,10}, {9,11,12}, {11,9,8}, {13,14,15}, {14,13,16}, {17,2,1}, {2,17,18}, {19,11,20}, {11,19,12}, {17,21,18}, {21,2,18}, {2,21,22}, {22,21,23}, {8,22,23}, {22,8,10}, {24,25,26}, {25,24,27}, {23,1,8}, {1,23,21}, {1,21,17}, {5,15,3}, {15,5,7}, {15,7,28}, {28,7,26}, {28,26,25}, {8,14,11}, {14,8,3}, {3,8,1}, {14,3,15}, {11,14,20}, {26,4,24}, {4,26,7}, {12,16,9}, {16,12,19}, {29,4,13}, {4,29,24}, {24,29,27}, {9,22,10}, {22,9,0}, {0,9,16}, {0,16,13}, {0,13,6}, {6,13,4}, {2,22,0}, {19,14,16}, {14,19,20}, {15,29,13}, {29,25,27}, {25,29,15}, {25,15,28}, {6,3,0}, {3,6,5} }); break; case TestMesh::A: mesh = TriangleMesh( - { Vec3d(513.075988769531,51.6074333190918,36.0009002685547), Vec3d(516.648803710938,51.7324333190918,36.0009002685547), Vec3d(513.495178222656,51.7324333190918,36.0009002685547), Vec3d(489.391204833984,51.4824333190918,24.0011005401611), Vec3d(488.928588867188,51.7324333190918,24.0011005401611), Vec3d(492.06201171875,51.7324333190918,24.0011005401611), Vec3d(496.840393066406,51.2324333190918,24.0011005401611), Vec3d(495.195404052734,51.7324333190918,24.0011005401611), Vec3d(498.981994628906,51.7324333190918,24.0011005401611), Vec3d(506.966613769531,51.6074333190918,24.0011005401611), Vec3d(510.342010498047,51.7324333190918,24.0011005401611), Vec3d(507.163818359375,51.6074333190918,24.0011005401611), Vec3d(512.515380859375,54.7190322875977,36.0009002685547), Vec3d(514.161987304688,54.5058326721191,36.0009002685547), Vec3d(493.06201171875,54.7190322875977,36.0009002685547), Vec3d(495.195404052734,51.7324333190918,36.0009002685547), Vec3d(496.195404052734,54.7190322875977,36.0009002685547), Vec3d(497.195404052734,57.7058334350586,36.0009002685547), Vec3d(500.851989746094,60.2658309936523,36.0009002685547), Vec3d(498.915405273438,62.8258323669434,36.0009002685547), Vec3d(506.701995849609,62.8258323669434,36.0009002685547), Vec3d(503.648590087891,60.2658309936523,36.0009002685547), Vec3d(508.381805419922,57.7058334350586,36.0009002685547), Vec3d(496.418792724609,60.052433013916,36.0009002685547), Vec3d(506.515197753906,72.2124328613281,36.0009002685547), Vec3d(502.808807373047,74.5324325561523,36.0009002685547), Vec3d(503.781982421875,71.6058349609375,36.0009002685547), Vec3d(515.358764648438,55.4658317565918,36.0009002685547), Vec3d(499.375183105469,76.9058380126953,36.0009002685547), Vec3d(501.168792724609,78.0658340454102,36.0009002685547), Vec3d(504.568786621094,78.0658340454102,36.0009002685547), Vec3d(506.32861328125,81.599235534668,36.0009002685547), Vec3d(502.928588867188,81.599235534668,36.0009002685547), Vec3d(499.528594970703,81.599235534668,36.0009002685547), Vec3d(498.20361328125,77.8658294677734,36.0009002685547), Vec3d(495.195404052734,51.7324333190918,30.0011005401611), Vec3d(498.981994628906,51.7324333190918,27.0011005401611), Vec3d(506.555206298828,51.7324333190918,33.0009002685547), Vec3d(506.555206298828,51.7324333190918,36.0009002685547), Vec3d(510.342010498047,51.7324333190918,36.0009002685547), Vec3d(512.515380859375,54.7190322875977,24.0011005401611), Vec3d(509.361999511719,54.7190322875977,24.0011005401611), Vec3d(508.381805419922,57.7058334350586,24.0011005401611), Vec3d(506.701995849609,62.8258323669434,24.0011005401611), Vec3d(509.188812255859,60.052433013916,24.0011005401611), Vec3d(493.06201171875,54.7190322875977,24.0011005401611), Vec3d(503.648590087891,60.2658309936523,24.0011005401611), Vec3d(500.851989746094,60.2658309936523,24.0011005401611), Vec3d(498.915405273438,62.8258323669434,24.0011005401611), Vec3d(502.808807373047,62.8258323669434,24.0011005401611), Vec3d(491.425201416016,54.5058326721191,24.0011005401611), Vec3d(506.421813964844,76.9058380126953,24.0011005401611), Vec3d(502.808807373047,74.5324325561523,24.0011005401611), Vec3d(504.568786621094,78.0658340454102,24.0011005401611), Vec3d(506.32861328125,81.599235534668,24.0011005401611), Vec3d(507.618804931641,77.8658294677734,24.0011005401611), Vec3d(499.221801757812,72.2124328613281,24.0011005401611), Vec3d(501.835388183594,71.6058349609375,24.0011005401611), Vec3d(501.168792724609,78.0658340454102,24.0011005401611), Vec3d(499.528594970703,81.599235534668,24.0011005401611), Vec3d(502.048583984375,79.8324356079102,24.0011005401611), Vec3d(490.253601074219,55.4658317565918,24.0011005401611), Vec3d(488.928588867188,51.7324333190918,30.0011005401611), Vec3d(488.928588867188,51.7324333190918,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,31.5009002685547), Vec3d(498.20361328125,77.8658294677734,34.5009002685547), Vec3d(508.381805419922,57.7058334350586,30.0011005401611), Vec3d(505.585388183594,57.7058334350586,27.0011005401611), Vec3d(502.788818359375,57.7058334350586,36.0009002685547), Vec3d(499.992004394531,57.7058334350586,33.0009002685547), Vec3d(509.851989746094,53.2258338928223,33.0009002685547), Vec3d(509.361999511719,54.7190322875977,36.0009002685547), Vec3d(508.871795654297,56.2124328613281,27.0011005401611), Vec3d(496.695404052734,56.2124328613281,33.0009002685547), Vec3d(495.695404052734,53.2258338928223,27.0011005401611), Vec3d(506.32861328125,81.599235534668,30.0011005401611), Vec3d(507.618804931641,77.8658294677734,25.5011005401611), Vec3d(515.358764648438,55.4658317565918,34.5009002685547), Vec3d(501.228607177734,81.599235534668,33.0009002685547), Vec3d(504.628601074219,81.599235534668,27.0011005401611), Vec3d(503.781982421875,71.6058349609375,33.0009002685547), Vec3d(502.808807373047,74.5324325561523,30.0011005401611), Vec3d(498.915405273438,62.8258323669434,30.0011005401611), Vec3d(500.861999511719,62.8258323669434,27.0011005401611), Vec3d(502.808807373047,62.8258323669434,36.0009002685547), Vec3d(504.755187988281,62.8258323669434,33.0009002685547), Vec3d(501.835388183594,71.6058349609375,33.0009002685547), Vec3d(499.888793945312,65.7524337768555,33.0009002685547), Vec3d(499.888793945312,65.7524337768555,36.0009002685547), Vec3d(513.128601074219,51.4824333190918,36.0009002685547), Vec3d(513.075988769531,51.6074333190918,24.0011005401611), Vec3d(516.648803710938,51.7324333190918,24.0011005401611), Vec3d(513.128601074219,51.4824333190918,24.0011005401611), Vec3d(513.495178222656,51.7324333190918,24.0011005401611), Vec3d(506.966613769531,51.6074333190918,36.0009002685547), Vec3d(507.163818359375,51.6074333190918,36.0009002685547), Vec3d(490.337799072266,51.4824333190918,24.0011005401611), Vec3d(489.391204833984,51.4824333190918,36.0009002685547), Vec3d(492.06201171875,51.7324333190918,36.0009002685547), Vec3d(490.337799072266,51.4824333190918,36.0009002685547), Vec3d(513.233764648438,51.2324333190918,24.0011005401611), Vec3d(513.233764648438,51.2324333190918,36.0009002685547), Vec3d(504.773803710938,51.4824333190918,36.0009002685547), Vec3d(504.773803710938,51.4824333190918,24.0011005401611), Vec3d(489.266998291016,51.2324333190918,24.0011005401611), Vec3d(489.266998291016,51.2324333190918,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,25.5011005401611), Vec3d(499.528594970703,81.599235534668,30.0011005401611), Vec3d(498.20361328125,77.8658294677734,31.5009002685547), Vec3d(515.358764648438,55.4658317565918,28.5011005401611), Vec3d(515.358764648438,55.4658317565918,25.5011005401611), Vec3d(495.246795654297,61.0124320983887,36.0009002685547), Vec3d(490.253601074219,55.4658317565918,34.5009002685547), Vec3d(490.253601074219,55.4658317565918,36.0009002685547), Vec3d(494.228607177734,66.6658325195312,24.0011005401611), Vec3d(499.068786621094,67.5192337036133,24.0011005401611), Vec3d(498.20361328125,77.8658294677734,25.5011005401611), Vec3d(498.20361328125,77.8658294677734,24.0011005401611), Vec3d(506.608795166016,67.5192337036133,36.0009002685547), Vec3d(509.09521484375,64.7458343505859,36.0009002685547), Vec3d(507.618804931641,77.8658294677734,34.5009002685547), Vec3d(507.618804931641,77.8658294677734,36.0009002685547), Vec3d(510.385406494141,61.0124320983887,24.0011005401611), Vec3d(515.358764648438,55.4658317565918,24.0011005401611), Vec3d(489.32861328125,47.7324333190918,31.5009002685547), Vec3d(492.95361328125,47.7324333190918,33.5634994506836), Vec3d(489.32861328125,47.7324333190918,34.5009002685547), Vec3d(489.32861328125,47.7324333190918,28.5011005401611), Vec3d(489.32861328125,47.7324333190918,25.5011005401611), Vec3d(492.95361328125,47.7324333190918,26.4385013580322), Vec3d(492.95361328125,47.7324333190918,30.5635013580322), Vec3d(492.95361328125,47.7324333190918,32.0634994506836), Vec3d(492.95361328125,47.7324333190918,31.3135013580322), Vec3d(492.95361328125,47.7324333190918,35.4384994506836), Vec3d(489.32861328125,47.7324333190918,36.0009002685547), Vec3d(492.95361328125,47.7324333190918,34.3134994506836), Vec3d(492.95361328125,47.7324333190918,34.6884994506836), Vec3d(492.95361328125,47.7324333190918,27.9385013580322), Vec3d(492.95361328125,47.7324333190918,28.6885013580322), Vec3d(492.95361328125,47.7324333190918,29.0635013580322), Vec3d(489.32861328125,47.7324333190918,24.0011005401611), Vec3d(492.95361328125,47.7324333190918,24.5635013580322), Vec3d(492.95361328125,47.7324333190918,25.6885013580322), Vec3d(492.95361328125,47.7324333190918,25.3135013580322), Vec3d(492.95361328125,47.7324333190918,24.1885013580322), Vec3d(492.95361328125,47.7324333190918,24.0011005401611), Vec3d(513.443786621094,50.7324333190918,24.0011005401611), Vec3d(492.95361328125,47.7324333190918,35.8134994506836), Vec3d(492.95361328125,47.7324333190918,36.0009002685547), Vec3d(513.443786621094,50.7324333190918,36.0009002685547), Vec3d(506.350402832031,51.4824333190918,36.0009002685547), Vec3d(506.350402832031,51.4824333190918,24.0011005401611), Vec3d(492.743804931641,48.2324333190918,24.0011005401611), Vec3d(492.638793945312,48.4824333190918,24.0011005401611), Vec3d(492.743804931641,48.2324333190918,36.0009002685547), Vec3d(492.638793945312,48.4824333190918,36.0009002685547), Vec3d(490.089599609375,50.9824333190918,36.0009002685547), Vec3d(490.089599609375,50.9824333190918,24.0011005401611), Vec3d(510.342010498047,51.7324333190918,30.0011005401611), Vec3d(499.068786621094,67.5192337036133,36.0009002685547), Vec3d(494.228607177734,66.6658325195312,36.0009002685547), Vec3d(499.375183105469,76.9058380126953,24.0011005401611), Vec3d(506.421813964844,76.9058380126953,36.0009002685547), Vec3d(506.608795166016,67.5192337036133,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,24.0011005401611), Vec3d(509.09521484375,64.7458343505859,24.0011005401611), Vec3d(506.701995849609,62.8258323669434,30.0011005401611), Vec3d(505.728607177734,65.7524337768555,27.0011005401611), Vec3d(501.835388183594,71.6058349609375,27.0011005401611), Vec3d(499.888793945312,65.7524337768555,27.0011005401611), Vec3d(494.228607177734,66.6658325195312,30.0011005401611), Vec3d(495.553588867188,70.3992309570312,28.5011005401611), Vec3d(492.903594970703,62.9324340820312,28.5011005401611), Vec3d(495.553588867188,70.3992309570312,31.5009002685547), Vec3d(492.903594970703,62.9324340820312,31.5009002685547), Vec3d(511.488800048828,66.6658325195312,24.0011005401611), Vec3d(511.488800048828,66.6658325195312,30.0011005401611), Vec3d(512.778564453125,62.9324340820312,28.5011005401611), Vec3d(515.358764648438,55.4658317565918,31.5009002685547), Vec3d(507.618804931641,77.8658294677734,31.5009002685547), Vec3d(510.198791503906,70.3992309570312,28.5011005401611), Vec3d(511.488800048828,66.6658325195312,36.0009002685547), Vec3d(512.778564453125,62.9324340820312,31.5009002685547), Vec3d(510.198791503906,70.3992309570312,31.5009002685547), Vec3d(502.788818359375,57.7058334350586,24.0011005401611), Vec3d(497.195404052734,57.7058334350586,30.0011005401611), Vec3d(492.903594970703,62.9324340820312,34.5009002685547), Vec3d(492.903594970703,62.9324340820312,36.0009002685547), Vec3d(495.553588867188,70.3992309570312,24.0011005401611), Vec3d(496.725189208984,69.4392318725586,24.0011005401611), Vec3d(495.553588867188,70.3992309570312,25.5011005401611), Vec3d(495.246795654297,61.0124320983887,24.0011005401611), Vec3d(492.903594970703,62.9324340820312,25.5011005401611), Vec3d(492.903594970703,62.9324340820312,24.0011005401611), Vec3d(495.553588867188,70.3992309570312,36.0009002685547), Vec3d(496.725189208984,69.4392318725586,36.0009002685547), Vec3d(495.553588867188,70.3992309570312,34.5009002685547), Vec3d(510.198791503906,70.3992309570312,36.0009002685547), Vec3d(509.002014160156,69.4392318725586,36.0009002685547), Vec3d(510.198791503906,70.3992309570312,34.5009002685547), Vec3d(512.778564453125,62.9324340820312,25.5011005401611), Vec3d(512.778564453125,62.9324340820312,24.0011005401611), Vec3d(510.198791503906,70.3992309570312,24.0011005401611), Vec3d(509.002014160156,69.4392318725586,24.0011005401611), Vec3d(510.198791503906,70.3992309570312,25.5011005401611), Vec3d(510.385406494141,61.0124320983887,36.0009002685547), Vec3d(512.778564453125,62.9324340820312,34.5009002685547), Vec3d(512.778564453125,62.9324340820312,36.0009002685547), Vec3d(496.840393066406,51.2324333190918,36.0009002685547), Vec3d(498.981994628906,51.7324333190918,36.0009002685547), Vec3d(498.981994628906,51.7324333190918,33.0009002685547), Vec3d(506.555206298828,51.7324333190918,24.0011005401611), Vec3d(506.555206298828,51.7324333190918,27.0011005401611), Vec3d(503.82861328125,47.7324333190918,30.7509002685547), Vec3d(507.45361328125,47.7324333190918,32.8134994506836), Vec3d(503.82861328125,47.7324333190918,33.7509002685547), Vec3d(503.82861328125,47.7324333190918,29.2511005401611), Vec3d(503.82861328125,47.7324333190918,26.2511005401611), Vec3d(507.45361328125,47.7324333190918,27.1885013580322), Vec3d(493.921813964844,57.2792320251465,36.0009002685547), Vec3d(491.425201416016,54.5058326721191,36.0009002685547), Vec3d(497.195404052734,57.7058334350586,24.0011005401611), Vec3d(496.418792724609,60.052433013916,24.0011005401611), Vec3d(509.188812255859,60.052433013916,36.0009002685547), Vec3d(511.675415039062,57.2792320251465,24.0011005401611), Vec3d(514.161987304688,54.5058326721191,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,34.3134994506836), Vec3d(503.82861328125,47.7324333190918,35.2509002685547), Vec3d(507.45361328125,47.7324333190918,25.6885013580322), Vec3d(503.82861328125,47.7324333190918,24.7511005401611), Vec3d(500.20361328125,47.7324333190918,31.6885013580322), Vec3d(500.20361328125,47.7324333190918,28.3135013580322), Vec3d(500.20361328125,47.7324333190918,30.1885013580322), Vec3d(507.45361328125,47.7324333190918,29.8135013580322), Vec3d(507.45361328125,47.7324333190918,31.3135013580322), Vec3d(507.45361328125,47.7324333190918,30.5635013580322), Vec3d(503.82861328125,47.7324333190918,36.0009002685547), Vec3d(507.45361328125,47.7324333190918,35.4384994506836), Vec3d(507.45361328125,47.7324333190918,35.0634994506836), Vec3d(507.45361328125,47.7324333190918,28.6885013580322), Vec3d(507.45361328125,47.7324333190918,29.4385013580322), Vec3d(503.82861328125,47.7324333190918,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,24.5635013580322), Vec3d(507.45361328125,47.7324333190918,24.9385013580322), Vec3d(500.20361328125,47.7324333190918,34.6884994506836), Vec3d(500.20361328125,47.7324333190918,33.1884994506836), Vec3d(500.20361328125,47.7324333190918,33.9384994506836), Vec3d(500.20361328125,47.7324333190918,25.3135013580322), Vec3d(500.20361328125,47.7324333190918,26.8135013580322), Vec3d(500.20361328125,47.7324333190918,26.0635013580322), Vec3d(500.20361328125,47.7324333190918,30.9385013580322), Vec3d(500.20361328125,47.7324333190918,35.0634994506836), Vec3d(500.20361328125,47.7324333190918,35.4384994506836), Vec3d(500.20361328125,47.7324333190918,29.0635013580322), Vec3d(500.20361328125,47.7324333190918,29.4385013580322), Vec3d(500.20361328125,47.7324333190918,24.9385013580322), Vec3d(500.20361328125,47.7324333190918,24.5635013580322), Vec3d(507.45361328125,47.7324333190918,24.1885013580322), Vec3d(507.45361328125,47.7324333190918,24.0011005401611), Vec3d(513.86376953125,49.7324333190918,24.0011005401611), Vec3d(507.45361328125,47.7324333190918,35.8134994506836), Vec3d(507.45361328125,47.7324333190918,36.0009002685547), Vec3d(513.86376953125,49.7324333190918,36.0009002685547), Vec3d(500.20361328125,47.7324333190918,24.1885013580322), Vec3d(500.20361328125,47.7324333190918,24.0011005401611), Vec3d(502.988800048828,49.7324333190918,24.0011005401611), Vec3d(500.20361328125,47.7324333190918,35.8134994506836), Vec3d(500.20361328125,47.7324333190918,36.0009002685547), Vec3d(502.988800048828,49.7324333190918,36.0009002685547), Vec3d(504.755187988281,62.8258323669434,27.0011005401611), Vec3d(499.205383300781,51.2324333190918,36.0009002685547), Vec3d(498.786193847656,51.1074333190918,36.0009002685547), Vec3d(502.358795166016,51.2324333190918,36.0009002685547), Vec3d(499.205383300781,51.2324333190918,24.0011005401611), Vec3d(502.358795166016,51.2324333190918,24.0011005401611), Vec3d(498.786193847656,51.1074333190918,24.0011005401611), Vec3d(502.568786621094,50.7324333190918,24.0011005401611), Vec3d(505.931213378906,51.3574333190918,24.0011005401611), Vec3d(509.503601074219,51.4824333190918,24.0011005401611), Vec3d(502.568786621094,50.7324333190918,36.0009002685547), Vec3d(505.931213378906,51.3574333190918,36.0009002685547), Vec3d(509.503601074219,51.4824333190918,36.0009002685547), Vec3d(499.048583984375,50.4824333190918,36.0009002685547), Vec3d(492.428588867188,48.9824333190918,36.0009002685547), Vec3d(499.048583984375,50.4824333190918,24.0011005401611), Vec3d(492.428588867188,48.9824333190918,24.0011005401611), Vec3d(506.088806152344,50.9824333190918,24.0011005401611), Vec3d(506.036010742188,51.1074333190918,24.0011005401611), Vec3d(506.088806152344,50.9824333190918,36.0009002685547), Vec3d(506.036010742188,51.1074333190918,36.0009002685547), Vec3d(498.891204833984,50.8574333190918,36.0009002685547), Vec3d(498.943786621094,50.7324333190918,36.0009002685547), Vec3d(498.891204833984,50.8574333190918,24.0011005401611), Vec3d(498.943786621094,50.7324333190918,24.0011005401611), Vec3d(499.573608398438,49.2324333190918,24.0011005401611), Vec3d(499.783813476562,48.7324333190918,24.0011005401611), Vec3d(499.573608398438,49.2324333190918,36.0009002685547), Vec3d(499.783813476562,48.7324333190918,36.0009002685547), Vec3d(506.403594970703,50.2324333190918,24.0011005401611), Vec3d(506.298797607422,50.4824333190918,24.0011005401611), Vec3d(506.403594970703,50.2324333190918,36.0009002685547), Vec3d(506.298797607422,50.4824333190918,36.0009002685547), Vec3d(501.228607177734,81.599235534668,27.0011005401611), Vec3d(502.928588867188,81.599235534668,24.0011005401611), Vec3d(499.2587890625,49.9824333190918,36.0009002685547), Vec3d(499.363800048828,49.7324333190918,36.0009002685547), Vec3d(499.2587890625,49.9824333190918,24.0011005401611), Vec3d(499.363800048828,49.7324333190918,24.0011005401611), Vec3d(496.695404052734,56.2124328613281,27.0011005401611), Vec3d(496.195404052734,54.7190322875977,24.0011005401611), Vec3d(509.851989746094,53.2258338928223,27.0011005401611), Vec3d(493.464782714844,51.1074333190918,36.0009002685547), Vec3d(493.464782714844,51.1074333190918,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,24.0011005401611), Vec3d(500.215789794922,51.3574333190918,24.0011005401611), Vec3d(497.628601074219,51.2324333190918,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,36.0009002685547), Vec3d(500.215789794922,51.3574333190918,36.0009002685547), Vec3d(497.628601074219,51.2324333190918,36.0009002685547), Vec3d(507.033813476562,48.7324333190918,24.0011005401611), Vec3d(506.823791503906,49.2324333190918,24.0011005401611), Vec3d(507.033813476562,48.7324333190918,36.0009002685547), Vec3d(506.823791503906,49.2324333190918,36.0009002685547), Vec3d(494.4501953125,51.1074333190918,24.0011005401611), Vec3d(494.4501953125,51.1074333190918,36.0009002685547), Vec3d(500.807006835938,51.3574333190918,36.0009002685547), Vec3d(503.591186523438,51.4824333190918,36.0009002685547), Vec3d(503.591186523438,51.4824333190918,24.0011005401611), Vec3d(500.807006835938,51.3574333190918,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,36.0009002685547), Vec3d(505.728607177734,65.7524337768555,33.0009002685547), Vec3d(499.221801757812,72.2124328613281,36.0009002685547), Vec3d(501.835388183594,71.6058349609375,36.0009002685547), Vec3d(506.515197753906,72.2124328613281,24.0011005401611), Vec3d(503.781982421875,71.6058349609375,24.0011005401611), Vec3d(503.781982421875,71.6058349609375,27.0011005401611), Vec3d(499.888793945312,65.7524337768555,24.0011005401611), Vec3d(495.695404052734,53.2258338928223,33.0009002685547), Vec3d(516.648803710938,51.7324333190918,30.0011005401611), Vec3d(498.20361328125,77.8658294677734,28.5011005401611), Vec3d(505.585388183594,57.7058334350586,33.0009002685547), Vec3d(508.871795654297,56.2124328613281,33.0009002685547), Vec3d(499.992004394531,57.7058334350586,27.0011005401611), Vec3d(504.628601074219,81.599235534668,33.0009002685547), Vec3d(500.861999511719,62.8258323669434,33.0009002685547), Vec3d(496.878601074219,74.1324310302734,27.0011005401611), Vec3d(496.878601074219,74.1324310302734,33.0009002685547), Vec3d(491.57861328125,59.199031829834,27.0011005401611), Vec3d(490.253601074219,55.4658317565918,28.5011005401611), Vec3d(491.57861328125,59.199031829834,33.0009002685547), Vec3d(514.068786621094,59.199031829834,27.0011005401611), Vec3d(514.068786621094,59.199031829834,33.0009002685547), Vec3d(508.908813476562,74.1324310302734,27.0011005401611), Vec3d(507.618804931641,77.8658294677734,28.5011005401611), Vec3d(508.908813476562,74.1324310302734,33.0009002685547), Vec3d(491.271789550781,50.9824333190918,36.0009002685547), Vec3d(490.877807617188,50.9824333190918,36.0009002685547), Vec3d(491.271789550781,50.9824333190918,24.0011005401611), Vec3d(490.877807617188,50.9824333190918,24.0011005401611), Vec3d(495.213806152344,50.9824333190918,36.0009002685547), Vec3d(493.636993408203,50.9824333190918,36.0009002685547), Vec3d(495.213806152344,50.9824333190918,24.0011005401611), Vec3d(493.636993408203,50.9824333190918,24.0011005401611), Vec3d(503.985412597656,51.4824333190918,36.0009002685547), Vec3d(503.985412597656,51.4824333190918,24.0011005401611), Vec3d(511.675415039062,57.2792320251465,36.0009002685547), Vec3d(493.921813964844,57.2792320251465,24.0011005401611), Vec3d(502.768798828125,51.7324333190918,30.0011005401611), Vec3d(506.555206298828,51.7324333190918,30.0011005401611), Vec3d(498.981994628906,51.7324333190918,30.0011005401611), Vec3d(492.848815917969,50.9824333190918,24.0011005401611), Vec3d(492.848815917969,50.9824333190918,36.0009002685547), Vec3d(500.861999511719,68.6792297363281,36.0009002685547), Vec3d(500.861999511719,68.6792297363281,24.0011005401611), Vec3d(496.878601074219,74.1324310302734,24.0011005401611), Vec3d(496.878601074219,74.1324310302734,36.0009002685547), Vec3d(504.755187988281,68.6792297363281,24.0011005401611), Vec3d(504.755187988281,68.6792297363281,36.0009002685547), Vec3d(508.908813476562,74.1324310302734,36.0009002685547), Vec3d(508.908813476562,74.1324310302734,24.0011005401611), Vec3d(505.728607177734,65.7524337768555,30.0011005401611), Vec3d(504.755187988281,68.6792297363281,30.0011005401611), Vec3d(503.781982421875,71.6058349609375,30.0011005401611), Vec3d(500.861999511719,68.6792297363281,30.0011005401611), Vec3d(499.888793945312,65.7524337768555,30.0011005401611), Vec3d(501.835388183594,71.6058349609375,30.0011005401611), Vec3d(491.57861328125,59.199031829834,24.0011005401611), Vec3d(491.57861328125,59.199031829834,36.0009002685547), Vec3d(514.068786621094,59.199031829834,36.0009002685547), Vec3d(514.068786621094,59.199031829834,24.0011005401611), Vec3d(511.07861328125,47.7324333190918,34.8759002685547), Vec3d(511.07861328125,47.7324333190918,31.8759002685547), Vec3d(514.70361328125,47.7324333190918,33.9384994506836), Vec3d(511.07861328125,47.7324333190918,25.1261005401611), Vec3d(514.70361328125,47.7324333190918,26.0635013580322), Vec3d(511.07861328125,47.7324333190918,28.1261005401611), Vec3d(502.788818359375,57.7058334350586,30.0011005401611), Vec3d(502.048583984375,79.8324356079102,36.0009002685547), Vec3d(514.70361328125,47.7324333190918,30.9385013580322), Vec3d(511.07861328125,47.7324333190918,30.3759002685547), Vec3d(514.70361328125,47.7324333190918,29.0635013580322), Vec3d(511.07861328125,47.7324333190918,29.6261005401611), Vec3d(496.57861328125,47.7324333190918,31.1259002685547), Vec3d(496.57861328125,47.7324333190918,32.6259002685547), Vec3d(496.57861328125,47.7324333190918,34.1259002685547), Vec3d(496.57861328125,47.7324333190918,28.8761005401611), Vec3d(496.57861328125,47.7324333190918,27.3761005401611), Vec3d(496.57861328125,47.7324333190918,25.8761005401611), Vec3d(496.57861328125,47.7324333190918,29.6261005401611), Vec3d(514.70361328125,47.7324333190918,35.4384994506836), Vec3d(511.07861328125,47.7324333190918,35.6259002685547), Vec3d(514.70361328125,47.7324333190918,24.5635013580322), Vec3d(511.07861328125,47.7324333190918,24.3761005401611), Vec3d(496.57861328125,47.7324333190918,34.8759002685547), Vec3d(496.57861328125,47.7324333190918,25.1261005401611), Vec3d(496.57861328125,47.7324333190918,35.6259002685547), Vec3d(496.57861328125,47.7324333190918,24.3761005401611), Vec3d(511.07861328125,47.7324333190918,36.0009002685547), Vec3d(511.07861328125,47.7324333190918,24.0011005401611), Vec3d(514.70361328125,47.7324333190918,30.1885013580322), Vec3d(514.70361328125,47.7324333190918,35.8134994506836), Vec3d(514.70361328125,47.7324333190918,29.8135013580322), Vec3d(514.70361328125,47.7324333190918,24.1885013580322), Vec3d(496.57861328125,47.7324333190918,36.0009002685547), Vec3d(496.57861328125,47.7324333190918,24.0011005401611), Vec3d(510.238800048828,49.7324333190918,24.0011005401611), Vec3d(510.238800048828,49.7324333190918,36.0009002685547), Vec3d(514.70361328125,47.7324333190918,24.0011005401611), Vec3d(514.70361328125,47.7324333190918,36.0009002685547), Vec3d(496.158813476562,48.7324333190918,36.0009002685547), Vec3d(496.158813476562,48.7324333190918,24.0011005401611), Vec3d(502.808807373047,62.8258323669434,30.0011005401611), Vec3d(509.608795166016,51.2324333190918,24.0011005401611), Vec3d(509.608795166016,51.2324333190918,36.0009002685547), Vec3d(491.641204833984,50.8574333190918,24.0011005401611), Vec3d(495.423797607422,50.4824333190918,36.0009002685547), Vec3d(495.423797607422,50.4824333190918,24.0011005401611), Vec3d(491.641204833984,50.8574333190918,36.0009002685547), Vec3d(495.528594970703,50.2324333190918,24.0011005401611), Vec3d(492.0087890625,49.9824333190918,24.0011005401611), Vec3d(509.818786621094,50.7324333190918,24.0011005401611), Vec3d(495.948608398438,49.2324333190918,36.0009002685547), Vec3d(495.528594970703,50.2324333190918,36.0009002685547), Vec3d(495.948608398438,49.2324333190918,24.0011005401611), Vec3d(509.818786621094,50.7324333190918,36.0009002685547), Vec3d(492.0087890625,49.9824333190918,36.0009002685547), Vec3d(491.956207275391,50.1074333190918,24.0011005401611), Vec3d(491.956207275391,50.1074333190918,36.0009002685547), Vec3d(502.928588867188,81.599235534668,30.0011005401611), Vec3d(491.851013183594,50.3574333190918,36.0009002685547), Vec3d(491.851013183594,50.3574333190918,24.0011005401611), Vec3d(496.195404052734,54.7190322875977,30.0011005401611), Vec3d(509.361999511719,54.7190322875977,30.0011005401611), Vec3d(488.632598876953,51.7256317138672,30.0011005401611), Vec3d(488.632598876953,51.7256317138672,29.5091018676758), Vec3d(488.632598876953,51.7188339233398,24.0011005401611), Vec3d(488.632598876953,51.7256317138672,27.4929008483887), Vec3d(488.632598876953,51.7324333190918,30.0011005401611), Vec3d(488.632598876953,51.7324333190918,29.0175018310547), Vec3d(488.632598876953,51.7324333190918,24.9847011566162), Vec3d(488.632598876953,51.7324333190918,24.0011005401611), Vec3d(488.632598876953,51.7188339233398,30.0011005401611), Vec3d(488.632598876953,51.7176322937012,24.0011005401611), Vec3d(488.632598876953,51.7182312011719,30.0011005401611), Vec3d(488.632598876953,51.7176322937012,30.0011005401611), Vec3d(488.632598876953,51.715030670166,24.0011005401611), Vec3d(488.632598876953,51.7162322998047,30.0011005401611), Vec3d(488.632598876953,50.761833190918,24.0011005401611), Vec3d(488.632598876953,50.7578315734863,24.0011005401611), Vec3d(488.632598876953,50.7598342895508,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,24.0011005401611), Vec3d(488.632598876953,49.7838325500488,24.0011005401611), Vec3d(488.632598876953,50.2680320739746,30.0011005401611), Vec3d(488.632598876953,51.7046318054199,24.0011005401611), Vec3d(488.632598876953,51.709831237793,30.0011005401611), Vec3d(488.632598876953,50.9120330810547,24.0011005401611), Vec3d(488.632598876953,50.8882331848145,24.0011005401611), Vec3d(488.632598876953,50.9002304077148,30.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.0370998382568), Vec3d(488.632598876953,48.5612335205078,30.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.0011005401611), Vec3d(488.632598876953,47.7324333190918,24.1091003417969), Vec3d(488.632598876953,48.5612335205078,30.0189018249512), Vec3d(488.632598876953,47.7324333190918,25.3211002349854), Vec3d(488.632598876953,48.5612335205078,30.0551013946533), Vec3d(488.632598876953,47.7324333190918,25.4651012420654), Vec3d(488.632598876953,48.5612335205078,30.6609001159668), Vec3d(488.632598876953,47.7324333190918,25.5371017456055), Vec3d(488.632598876953,48.5612335205078,30.7329006195068), Vec3d(488.632598876953,47.7324333190918,25.6091003417969), Vec3d(488.632598876953,48.5612335205078,30.7689018249512), Vec3d(488.632598876953,47.7324333190918,25.8971004486084), Vec3d(488.632598876953,48.5612335205078,30.8051013946533), Vec3d(488.632598876953,47.7324333190918,28.321102142334), Vec3d(488.632598876953,48.5612335205078,30.9491004943848), Vec3d(488.632598876953,47.7324333190918,28.4651012420654), Vec3d(488.632598876953,48.5612335205078,32.1609001159668), Vec3d(488.632598876953,47.7324333190918,28.5371017456055), Vec3d(488.632598876953,48.5612335205078,32.2329025268555), Vec3d(488.632598876953,47.7324333190918,28.6811008453369), Vec3d(488.632598876953,48.5612335205078,32.2689018249512), Vec3d(488.632598876953,47.7324333190918,31.1049003601074), Vec3d(488.632598876953,48.5612335205078,32.3411026000977), Vec3d(488.632598876953,47.7324333190918,31.3929004669189), Vec3d(488.632598876953,49.3900299072266,36.0009002685547), Vec3d(488.632598876953,47.7324333190918,31.536901473999), Vec3d(488.632598876953,47.7324333190918,31.6809005737305), Vec3d(488.632598876953,47.7324333190918,34.1049003601074), Vec3d(488.632598876953,47.7324333190918,34.3929023742676), Vec3d(488.632598876953,47.7324333190918,34.464900970459), Vec3d(488.632598876953,47.7324333190918,34.5369033813477), Vec3d(488.632598876953,47.7324333190918,34.6809005737305), Vec3d(488.632598876953,47.7324333190918,35.8929023742676), Vec3d(488.632598876953,47.7324333190918,35.964900970459), Vec3d(488.632598876953,47.7324333190918,36.0009002685547), Vec3d(488.632598876953,50.8816299438477,24.0011005401611), Vec3d(488.632598876953,50.8850326538086,30.0011005401611), Vec3d(488.632598876953,49.7480316162109,24.0011005401611), Vec3d(488.632598876953,49.7426300048828,24.0011005401611), Vec3d(488.632598876953,49.745231628418,30.0011005401611), Vec3d(488.632598876953,49.7592315673828,24.0011005401611), Vec3d(488.632598876953,49.7536315917969,30.0011005401611), Vec3d(488.632598876953,49.3900299072266,24.0011005401611), Vec3d(488.632598876953,49.5664329528809,30.0011005401611), Vec3d(488.632598876953,50.8786315917969,24.0011005401611), Vec3d(488.632598876953,50.7764320373535,24.0011005401611), Vec3d(488.632598876953,50.8274307250977,30.0011005401611), Vec3d(488.632598876953,50.7550315856934,30.0011005401611), Vec3d(488.632598876953,50.7692337036133,30.0011005401611), Vec3d(488.632598876953,50.9284324645996,24.0011005401611), Vec3d(488.632598876953,50.9202308654785,30.0011005401611), Vec3d(488.632598876953,51.1788330078125,24.0011005401611), Vec3d(488.632598876953,51.139232635498,24.0011005401611), Vec3d(488.632598876953,51.1590309143066,30.0011005401611), Vec3d(488.632598876953,51.2324333190918,24.0011005401611), Vec3d(488.632598876953,51.2056312561035,30.0011005401611), Vec3d(488.632598876953,51.4340324401855,24.0011005401611), Vec3d(488.632598876953,51.3946304321289,24.0011005401611), Vec3d(488.632598876953,51.4142303466797,30.0011005401611), Vec3d(488.632598876953,51.4498329162598,24.0011005401611), Vec3d(488.632598876953,51.5772323608398,30.0011005401611), Vec3d(488.632598876953,51.4418334960938,30.0011005401611), Vec3d(488.632598876953,51.3136329650879,30.0011005401611), Vec3d(488.632598876953,49.7714309692383,30.0011005401611), Vec3d(488.632598876953,51.0338325500488,30.0011005401611), Vec3d(488.632598876953,50.8816299438477,30.0011005401611), Vec3d(488.632598876953,50.8800315856934,30.0011005401611), Vec3d(488.632598876953,51.7188339233398,36.0009002685547), Vec3d(488.632598876953,51.7176322937012,36.0009002685547), Vec3d(488.632598876953,49.3900299072266,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,30.0011005401611), Vec3d(488.632598876953,50.7522315979004,36.0009002685547), Vec3d(488.632598876953,49.7426300048828,30.0011005401611), Vec3d(488.632598876953,49.7426300048828,36.0009002685547), Vec3d(488.632598876953,49.7480316162109,30.0011005401611), Vec3d(488.632598876953,49.7480316162109,36.0009002685547), Vec3d(488.632598876953,51.715030670166,30.0011005401611), Vec3d(488.632598876953,51.715030670166,36.0009002685547), Vec3d(488.632598876953,50.7578315734863,30.0011005401611), Vec3d(488.632598876953,50.7578315734863,36.0009002685547), Vec3d(488.632598876953,50.761833190918,30.0011005401611), Vec3d(488.632598876953,50.761833190918,36.0009002685547), Vec3d(488.632598876953,50.8882331848145,30.0011005401611), Vec3d(488.632598876953,50.8882331848145,36.0009002685547), Vec3d(488.632598876953,49.7592315673828,30.0011005401611), Vec3d(488.632598876953,49.7592315673828,36.0009002685547), Vec3d(488.632598876953,51.1788330078125,30.0011005401611), Vec3d(488.632598876953,51.1788330078125,36.0009002685547), Vec3d(488.632598876953,50.9120330810547,30.0011005401611), Vec3d(488.632598876953,50.9120330810547,36.0009002685547), Vec3d(488.632598876953,51.4498329162598,30.0011005401611), Vec3d(488.632598876953,51.4498329162598,36.0009002685547), Vec3d(488.632598876953,51.7046318054199,30.0011005401611), Vec3d(488.632598876953,51.7046318054199,36.0009002685547), Vec3d(488.632598876953,51.2324333190918,30.0011005401611), Vec3d(488.632598876953,51.2324333190918,36.0009002685547), Vec3d(488.632598876953,51.3946304321289,30.0011005401611), Vec3d(488.632598876953,51.3946304321289,36.0009002685547), Vec3d(488.632598876953,51.4340324401855,30.0011005401611), Vec3d(488.632598876953,51.4340324401855,36.0009002685547), Vec3d(488.632598876953,49.7838325500488,30.0011005401611), Vec3d(488.632598876953,49.7838325500488,36.0009002685547), Vec3d(488.632598876953,50.7764320373535,30.0011005401611), Vec3d(488.632598876953,50.7764320373535,36.0009002685547), Vec3d(488.632598876953,51.139232635498,30.0011005401611), Vec3d(488.632598876953,51.139232635498,36.0009002685547), Vec3d(488.632598876953,50.9284324645996,30.0011005401611), Vec3d(488.632598876953,50.9284324645996,36.0009002685547), Vec3d(488.632598876953,50.8816299438477,36.0009002685547), Vec3d(488.632598876953,50.8786315917969,30.0011005401611), Vec3d(488.632598876953,50.8786315917969,36.0009002685547), Vec3d(488.632598876953,51.7324333190918,35.0173034667969), Vec3d(488.632598876953,51.7324333190918,36.0009002685547), Vec3d(488.632598876953,51.7324333190918,30.9847011566162), Vec3d(517.188415527344,51.7140884399414,24.0011005401611), Vec3d(517.188415527344,51.7140884399414,36.0009002685547), Vec3d(517.188415527344,50.4475173950195,24.0011005401611), Vec3d(517.188415527344,51.7324333190918,35.3734130859375), Vec3d(517.188415527344,51.7324333190918,36.0009002685547), Vec3d(517.188415527344,51.7324333190918,34.1185760498047), Vec3d(517.188415527344,51.7324333190918,31.88330078125), Vec3d(517.188415527344,51.7324333190918,30.0011005401611), Vec3d(517.188415527344,51.7324333190918,28.1187744140625), Vec3d(517.188415527344,51.7324333190918,25.8834266662598), Vec3d(517.188415527344,51.7324333190918,24.6285915374756), Vec3d(517.188415527344,51.7324333190918,24.0011005401611), Vec3d(517.188415527344,47.7324333190918,24.0600452423096), Vec3d(517.188415527344,47.7324333190918,24.0011005401611), Vec3d(517.188415527344,50.4475173950195,36.0009002685547), Vec3d(517.188415527344,47.7324333190918,24.1779975891113), Vec3d(517.188415527344,47.7324333190918,24.6498031616211), Vec3d(517.188415527344,47.7324333190918,28.7625770568848), Vec3d(517.188415527344,47.7324333190918,29.7061901092529), Vec3d(517.188415527344,47.7324333190918,29.9420928955078), Vec3d(517.188415527344,47.7324333190918,30.0600452423096), Vec3d(517.188415527344,47.7324333190918,30.2959480285645), Vec3d(517.188415527344,47.7324333190918,31.2395629882812), Vec3d(517.188415527344,47.7324333190918,35.3521995544434), Vec3d(517.188415527344,47.7324333190918,35.8240051269531), Vec3d(517.188415527344,47.7324333190918,35.9419555664062), Vec3d(517.188415527344,47.7324333190918,36.0009002685547) }, - { Vec3crd(0,1,2), Vec3crd(3,4,5), Vec3crd(6,7,8), Vec3crd(9,10,11), Vec3crd(12,2,1), Vec3crd(12,1,13), Vec3crd(14,15,16), Vec3crd(17,18,19), Vec3crd(20,21,22), Vec3crd(17,19,23), Vec3crd(24,25,26), Vec3crd(27,13,1), Vec3crd(28,25,29), Vec3crd(30,31,32), Vec3crd(28,33,34), Vec3crd(35,36,7), Vec3crd(37,38,39), Vec3crd(40,10,41), Vec3crd(42,43,44), Vec3crd(45,5,4), Vec3crd(46,47,48), Vec3crd(46,48,49), Vec3crd(45,4,50), Vec3crd(51,52,53), Vec3crd(51,54,55), Vec3crd(56,52,57), Vec3crd(58,59,60), Vec3crd(61,50,4), Vec3crd(62,63,64), Vec3crd(65,34,33), Vec3crd(66,67,42), Vec3crd(68,17,69), Vec3crd(70,71,22), Vec3crd(66,42,72), Vec3crd(73,16,15), Vec3crd(35,7,74), Vec3crd(75,76,54), Vec3crd(77,27,1), Vec3crd(78,32,31), Vec3crd(75,54,79), Vec3crd(80,26,25), Vec3crd(81,80,25), Vec3crd(82,83,48), Vec3crd(84,20,85), Vec3crd(81,25,86), Vec3crd(87,88,19), Vec3crd(0,89,1), Vec3crd(90,91,92), Vec3crd(90,10,93), Vec3crd(38,94,39), Vec3crd(94,95,39), Vec3crd(3,7,96), Vec3crd(97,15,98), Vec3crd(97,99,15), Vec3crd(92,91,100), Vec3crd(89,101,1), Vec3crd(102,39,95), Vec3crd(103,11,10), Vec3crd(104,96,7), Vec3crd(105,15,99), Vec3crd(106,61,4), Vec3crd(107,108,33), Vec3crd(76,55,54), Vec3crd(109,91,110), Vec3crd(111,23,19), Vec3crd(112,63,113), Vec3crd(114,115,48), Vec3crd(116,59,117), Vec3crd(118,20,119), Vec3crd(120,31,121), Vec3crd(122,44,43), Vec3crd(110,91,123), Vec3crd(124,125,126), Vec3crd(127,128,129), Vec3crd(127,130,124), Vec3crd(131,124,132), Vec3crd(126,133,134), Vec3crd(135,136,126), Vec3crd(137,138,127), Vec3crd(139,127,138), Vec3crd(128,140,141), Vec3crd(142,128,143), Vec3crd(144,140,145), Vec3crd(100,91,146), Vec3crd(147,148,134), Vec3crd(101,149,1), Vec3crd(102,150,39), Vec3crd(103,10,151), Vec3crd(145,140,152), Vec3crd(152,140,153), Vec3crd(148,154,134), Vec3crd(154,155,134), Vec3crd(156,15,105), Vec3crd(157,104,7), Vec3crd(36,8,7), Vec3crd(158,37,39), Vec3crd(159,19,88), Vec3crd(160,19,159), Vec3crd(161,59,58), Vec3crd(161,117,59), Vec3crd(162,31,30), Vec3crd(162,121,31), Vec3crd(163,43,164), Vec3crd(163,165,43), Vec3crd(166,167,43), Vec3crd(167,164,43), Vec3crd(168,57,52), Vec3crd(82,48,169), Vec3crd(114,170,171), Vec3crd(108,65,33), Vec3crd(64,63,112), Vec3crd(114,172,170), Vec3crd(160,173,170), Vec3crd(171,170,173), Vec3crd(172,174,170), Vec3crd(160,170,174), Vec3crd(175,176,177), Vec3crd(178,77,1), Vec3crd(179,31,120), Vec3crd(175,180,176), Vec3crd(181,182,176), Vec3crd(177,176,182), Vec3crd(180,183,176), Vec3crd(181,176,183), Vec3crd(184,42,67), Vec3crd(185,69,17), Vec3crd(160,111,19), Vec3crd(186,187,160), Vec3crd(188,189,114), Vec3crd(190,188,114), Vec3crd(114,48,191), Vec3crd(192,114,193), Vec3crd(194,160,195), Vec3crd(196,160,194), Vec3crd(197,198,181), Vec3crd(199,197,181), Vec3crd(122,43,165), Vec3crd(200,201,175), Vec3crd(202,175,203), Vec3crd(204,175,202), Vec3crd(205,119,20), Vec3crd(206,181,207), Vec3crd(208,209,15), Vec3crd(210,15,209), Vec3crd(211,10,9), Vec3crd(212,10,211), Vec3crd(213,214,215), Vec3crd(216,217,218), Vec3crd(219,14,17), Vec3crd(113,63,220), Vec3crd(221,222,48), Vec3crd(191,48,222), Vec3crd(22,223,20), Vec3crd(205,20,223), Vec3crd(224,40,42), Vec3crd(123,91,225), Vec3crd(214,226,215), Vec3crd(227,215,226), Vec3crd(218,217,228), Vec3crd(229,228,217), Vec3crd(215,230,213), Vec3crd(125,135,126), Vec3crd(217,216,231), Vec3crd(129,128,142), Vec3crd(216,213,232), Vec3crd(130,132,124), Vec3crd(213,216,233), Vec3crd(234,213,235), Vec3crd(236,227,237), Vec3crd(238,237,227), Vec3crd(239,240,216), Vec3crd(233,216,240), Vec3crd(241,242,229), Vec3crd(243,229,242), Vec3crd(215,227,244), Vec3crd(245,215,246), Vec3crd(217,247,229), Vec3crd(248,249,217), Vec3crd(232,213,250), Vec3crd(230,250,213), Vec3crd(133,147,134), Vec3crd(244,227,251), Vec3crd(236,252,227), Vec3crd(251,227,252), Vec3crd(231,216,253), Vec3crd(254,253,216), Vec3crd(141,140,144), Vec3crd(247,255,229), Vec3crd(241,229,256), Vec3crd(255,256,229), Vec3crd(257,241,258), Vec3crd(259,146,91), Vec3crd(260,261,236), Vec3crd(262,1,149), Vec3crd(263,264,241), Vec3crd(265,241,264), Vec3crd(266,236,267), Vec3crd(268,267,236), Vec3crd(49,48,83), Vec3crd(166,43,269), Vec3crd(270,271,272), Vec3crd(273,274,275), Vec3crd(276,274,277), Vec3crd(278,151,10), Vec3crd(279,280,272), Vec3crd(281,39,150), Vec3crd(272,282,279), Vec3crd(155,283,134), Vec3crd(274,276,284), Vec3crd(153,140,285), Vec3crd(286,276,287), Vec3crd(265,276,286), Vec3crd(288,289,279), Vec3crd(268,288,279), Vec3crd(290,291,272), Vec3crd(271,290,272), Vec3crd(292,274,293), Vec3crd(275,274,292), Vec3crd(294,265,295), Vec3crd(276,265,294), Vec3crd(296,297,268), Vec3crd(279,296,268), Vec3crd(241,265,298), Vec3crd(298,265,299), Vec3crd(236,300,268), Vec3crd(300,301,268), Vec3crd(107,33,78), Vec3crd(302,303,59), Vec3crd(304,305,279), Vec3crd(282,304,279), Vec3crd(306,276,307), Vec3crd(284,276,306), Vec3crd(185,17,73), Vec3crd(308,309,221), Vec3crd(158,39,70), Vec3crd(310,41,10), Vec3crd(15,311,208), Vec3crd(7,6,312), Vec3crd(313,314,6), Vec3crd(315,6,314), Vec3crd(316,208,317), Vec3crd(318,317,208), Vec3crd(258,241,319), Vec3crd(319,241,320), Vec3crd(261,321,236), Vec3crd(321,322,236), Vec3crd(6,315,323), Vec3crd(208,324,318), Vec3crd(270,325,318), Vec3crd(326,318,325), Vec3crd(327,328,315), Vec3crd(273,315,328), Vec3crd(118,329,20), Vec3crd(330,20,329), Vec3crd(331,332,25), Vec3crd(86,25,332), Vec3crd(333,334,52), Vec3crd(335,52,334), Vec3crd(115,336,48), Vec3crd(169,48,336), Vec3crd(62,106,4), Vec3crd(35,15,210), Vec3crd(35,337,15), Vec3crd(158,10,212), Vec3crd(158,310,10), Vec3crd(338,178,1), Vec3crd(339,59,116), Vec3crd(107,302,59), Vec3crd(66,22,340), Vec3crd(66,341,22), Vec3crd(185,221,342), Vec3crd(185,308,221), Vec3crd(75,31,179), Vec3crd(75,343,31), Vec3crd(166,20,330), Vec3crd(166,85,20), Vec3crd(81,52,335), Vec3crd(81,168,52), Vec3crd(82,19,344), Vec3crd(82,87,19), Vec3crd(108,339,345), Vec3crd(346,108,345), Vec3crd(64,347,348), Vec3crd(349,347,64), Vec3crd(178,109,350), Vec3crd(351,178,350), Vec3crd(179,352,353), Vec3crd(354,352,179), Vec3crd(355,208,356), Vec3crd(356,208,311), Vec3crd(357,358,6), Vec3crd(358,312,6), Vec3crd(68,22,21), Vec3crd(68,340,22), Vec3crd(221,48,47), Vec3crd(184,342,221), Vec3crd(359,270,360), Vec3crd(318,360,270), Vec3crd(361,362,273), Vec3crd(315,273,362), Vec3crd(272,102,270), Vec3crd(363,270,102), Vec3crd(274,273,103), Vec3crd(364,103,273), Vec3crd(21,19,18), Vec3crd(21,20,84), Vec3crd(184,46,42), Vec3crd(43,42,46), Vec3crd(12,22,71), Vec3crd(365,22,12), Vec3crd(14,98,15), Vec3crd(14,220,63), Vec3crd(40,93,10), Vec3crd(40,225,91), Vec3crd(45,221,309), Vec3crd(366,221,45), Vec3crd(313,367,212), Vec3crd(212,367,368), Vec3crd(36,369,367), Vec3crd(313,36,367), Vec3crd(316,37,367), Vec3crd(37,368,367), Vec3crd(210,367,369), Vec3crd(316,367,210), Vec3crd(362,370,315), Vec3crd(370,323,315), Vec3crd(360,318,371), Vec3crd(371,318,324), Vec3crd(372,331,159), Vec3crd(159,195,160), Vec3crd(373,115,56), Vec3crd(115,114,189), Vec3crd(52,56,161), Vec3crd(374,161,56), Vec3crd(25,28,331), Vec3crd(375,331,28), Vec3crd(376,333,163), Vec3crd(163,203,175), Vec3crd(377,118,24), Vec3crd(118,181,198), Vec3crd(25,24,162), Vec3crd(378,162,24), Vec3crd(52,51,333), Vec3crd(379,333,51), Vec3crd(167,380,381), Vec3crd(376,167,381), Vec3crd(377,381,330), Vec3crd(330,381,380), Vec3crd(335,381,382), Vec3crd(376,381,335), Vec3crd(373,383,169), Vec3crd(169,383,384), Vec3crd(168,385,383), Vec3crd(373,168,383), Vec3crd(372,87,383), Vec3crd(87,384,383), Vec3crd(377,80,381), Vec3crd(80,382,381), Vec3crd(86,383,385), Vec3crd(372,383,86), Vec3crd(106,348,347), Vec3crd(386,106,347), Vec3crd(375,65,346), Vec3crd(108,346,65), Vec3crd(64,112,349), Vec3crd(387,349,112), Vec3crd(171,190,114), Vec3crd(346,345,171), Vec3crd(374,190,345), Vec3crd(171,345,190), Vec3crd(349,172,347), Vec3crd(172,114,192), Vec3crd(386,347,192), Vec3crd(172,192,347), Vec3crd(173,160,196), Vec3crd(171,173,346), Vec3crd(375,346,196), Vec3crd(173,196,346), Vec3crd(172,349,174), Vec3crd(174,186,160), Vec3crd(387,186,349), Vec3crd(174,349,186), Vec3crd(64,348,62), Vec3crd(106,62,348), Vec3crd(108,107,339), Vec3crd(59,339,107), Vec3crd(374,345,116), Vec3crd(339,116,345), Vec3crd(76,353,352), Vec3crd(379,76,352), Vec3crd(388,77,351), Vec3crd(178,351,77), Vec3crd(179,120,354), Vec3crd(378,354,120), Vec3crd(177,200,175), Vec3crd(351,350,177), Vec3crd(389,200,350), Vec3crd(177,350,200), Vec3crd(354,180,352), Vec3crd(180,175,204), Vec3crd(379,352,204), Vec3crd(180,204,352), Vec3crd(182,181,206), Vec3crd(177,182,351), Vec3crd(388,351,206), Vec3crd(182,206,351), Vec3crd(180,354,183), Vec3crd(183,199,181), Vec3crd(378,199,354), Vec3crd(183,354,199), Vec3crd(91,109,338), Vec3crd(178,338,109), Vec3crd(76,75,353), Vec3crd(179,353,75), Vec3crd(389,350,110), Vec3crd(109,110,350), Vec3crd(390,391,392), Vec3crd(393,394,395), Vec3crd(224,122,389), Vec3crd(122,175,201), Vec3crd(365,388,205), Vec3crd(205,207,181), Vec3crd(66,340,396), Vec3crd(68,396,340), Vec3crd(184,396,342), Vec3crd(185,342,396), Vec3crd(66,396,67), Vec3crd(184,67,396), Vec3crd(68,69,396), Vec3crd(185,396,69), Vec3crd(219,111,387), Vec3crd(111,160,187), Vec3crd(366,386,191), Vec3crd(191,193,114), Vec3crd(150,272,280), Vec3crd(102,272,150), Vec3crd(151,277,274), Vec3crd(103,151,274), Vec3crd(161,374,117), Vec3crd(116,117,374), Vec3crd(366,61,386), Vec3crd(106,386,61), Vec3crd(111,187,387), Vec3crd(186,387,187), Vec3crd(56,188,374), Vec3crd(190,374,188), Vec3crd(191,386,193), Vec3crd(192,193,386), Vec3crd(331,375,194), Vec3crd(196,194,375), Vec3crd(28,34,375), Vec3crd(65,375,34), Vec3crd(219,387,113), Vec3crd(112,113,387), Vec3crd(224,389,123), Vec3crd(110,123,389), Vec3crd(51,55,379), Vec3crd(76,379,55), Vec3crd(24,197,378), Vec3crd(199,378,197), Vec3crd(122,201,389), Vec3crd(200,389,201), Vec3crd(333,379,202), Vec3crd(204,202,379), Vec3crd(205,388,207), Vec3crd(206,207,388), Vec3crd(365,27,388), Vec3crd(77,388,27), Vec3crd(162,378,121), Vec3crd(120,121,378), Vec3crd(162,30,25), Vec3crd(30,29,25), Vec3crd(51,53,54), Vec3crd(303,60,59), Vec3crd(28,29,33), Vec3crd(29,397,33), Vec3crd(161,58,52), Vec3crd(53,52,58), Vec3crd(21,84,19), Vec3crd(84,344,19), Vec3crd(46,49,43), Vec3crd(49,269,43), Vec3crd(208,316,209), Vec3crd(210,209,316), Vec3crd(327,313,211), Vec3crd(212,211,313), Vec3crd(36,35,369), Vec3crd(210,369,35), Vec3crd(37,158,368), Vec3crd(212,368,158), Vec3crd(6,8,313), Vec3crd(36,313,8), Vec3crd(326,38,316), Vec3crd(37,316,38), Vec3crd(392,391,398), Vec3crd(399,398,391), Vec3crd(394,400,395), Vec3crd(401,395,400), Vec3crd(390,214,391), Vec3crd(214,213,234), Vec3crd(393,395,218), Vec3crd(218,239,216), Vec3crd(402,230,403), Vec3crd(230,215,245), Vec3crd(125,124,131), Vec3crd(404,125,403), Vec3crd(405,406,231), Vec3crd(231,248,217), Vec3crd(129,137,127), Vec3crd(407,406,129), Vec3crd(130,127,139), Vec3crd(402,130,408), Vec3crd(194,195,331), Vec3crd(159,331,195), Vec3crd(115,189,56), Vec3crd(188,56,189), Vec3crd(14,219,220), Vec3crd(113,220,219), Vec3crd(45,50,366), Vec3crd(61,366,50), Vec3crd(221,366,222), Vec3crd(191,222,366), Vec3crd(17,23,219), Vec3crd(111,219,23), Vec3crd(118,198,24), Vec3crd(197,24,198), Vec3crd(202,203,333), Vec3crd(163,333,203), Vec3crd(40,224,225), Vec3crd(123,225,224), Vec3crd(12,13,365), Vec3crd(27,365,13), Vec3crd(22,365,223), Vec3crd(205,223,365), Vec3crd(42,44,224), Vec3crd(122,224,44), Vec3crd(399,391,234), Vec3crd(214,234,391), Vec3crd(401,239,395), Vec3crd(218,395,239), Vec3crd(214,390,226), Vec3crd(226,238,227), Vec3crd(218,228,393), Vec3crd(228,229,243), Vec3crd(401,399,233), Vec3crd(233,235,213), Vec3crd(392,409,390), Vec3crd(410,390,409), Vec3crd(394,393,411), Vec3crd(412,411,393), Vec3crd(402,403,131), Vec3crd(125,131,403), Vec3crd(405,137,406), Vec3crd(129,406,137), Vec3crd(405,408,139), Vec3crd(130,139,408), Vec3crd(230,245,403), Vec3crd(404,403,245), Vec3crd(231,406,248), Vec3crd(407,248,406), Vec3crd(232,254,216), Vec3crd(402,408,232), Vec3crd(413,404,244), Vec3crd(244,246,215), Vec3crd(414,247,407), Vec3crd(247,217,249), Vec3crd(133,126,136), Vec3crd(415,133,413), Vec3crd(141,143,128), Vec3crd(416,414,141), Vec3crd(410,238,390), Vec3crd(226,390,238), Vec3crd(412,393,243), Vec3crd(228,243,393), Vec3crd(233,399,235), Vec3crd(234,235,399), Vec3crd(237,260,236), Vec3crd(238,410,237), Vec3crd(417,260,410), Vec3crd(237,410,260), Vec3crd(239,401,240), Vec3crd(233,240,401), Vec3crd(242,241,257), Vec3crd(243,242,412), Vec3crd(418,412,257), Vec3crd(242,257,412), Vec3crd(401,419,399), Vec3crd(398,399,419), Vec3crd(417,410,420), Vec3crd(409,420,410), Vec3crd(400,421,401), Vec3crd(419,401,421), Vec3crd(418,422,412), Vec3crd(411,412,422), Vec3crd(413,135,404), Vec3crd(125,404,135), Vec3crd(414,407,142), Vec3crd(129,142,407), Vec3crd(130,402,132), Vec3crd(131,132,402), Vec3crd(133,136,413), Vec3crd(135,413,136), Vec3crd(423,147,415), Vec3crd(133,415,147), Vec3crd(137,405,138), Vec3crd(139,138,405), Vec3crd(141,414,143), Vec3crd(142,143,414), Vec3crd(424,416,144), Vec3crd(141,144,416), Vec3crd(405,254,408), Vec3crd(232,408,254), Vec3crd(244,404,246), Vec3crd(245,246,404), Vec3crd(247,249,407), Vec3crd(248,407,249), Vec3crd(232,250,402), Vec3crd(230,402,250), Vec3crd(415,413,251), Vec3crd(244,251,413), Vec3crd(252,236,266), Vec3crd(251,252,415), Vec3crd(423,415,266), Vec3crd(252,266,415), Vec3crd(231,253,405), Vec3crd(254,405,253), Vec3crd(416,255,414), Vec3crd(247,414,255), Vec3crd(256,263,241), Vec3crd(255,416,256), Vec3crd(424,263,416), Vec3crd(256,416,263), Vec3crd(257,258,418), Vec3crd(425,418,258), Vec3crd(260,417,261), Vec3crd(426,261,417), Vec3crd(422,418,427), Vec3crd(427,259,91), Vec3crd(420,428,417), Vec3crd(428,1,262), Vec3crd(147,423,148), Vec3crd(429,148,423), Vec3crd(263,424,264), Vec3crd(264,295,265), Vec3crd(266,267,423), Vec3crd(267,268,297), Vec3crd(144,145,424), Vec3crd(430,424,145), Vec3crd(49,431,269), Vec3crd(166,269,431), Vec3crd(82,431,83), Vec3crd(49,83,431), Vec3crd(84,85,431), Vec3crd(166,431,85), Vec3crd(82,344,431), Vec3crd(84,431,344), Vec3crd(432,278,90), Vec3crd(10,90,278), Vec3crd(433,0,281), Vec3crd(39,281,0), Vec3crd(362,361,434), Vec3crd(435,271,359), Vec3crd(270,359,271), Vec3crd(436,361,275), Vec3crd(273,275,361), Vec3crd(360,437,359), Vec3crd(277,287,276), Vec3crd(151,278,277), Vec3crd(280,279,289), Vec3crd(150,280,281), Vec3crd(436,438,439), Vec3crd(439,285,140), Vec3crd(90,92,432), Vec3crd(440,432,92), Vec3crd(282,272,291), Vec3crd(441,282,442), Vec3crd(284,293,274), Vec3crd(443,438,284), Vec3crd(278,432,286), Vec3crd(286,299,265), Vec3crd(281,288,433), Vec3crd(288,268,301), Vec3crd(0,433,89), Vec3crd(444,89,433), Vec3crd(435,445,442), Vec3crd(445,134,283), Vec3crd(439,446,436), Vec3crd(361,436,446), Vec3crd(442,290,435), Vec3crd(271,435,290), Vec3crd(438,436,292), Vec3crd(275,292,436), Vec3crd(445,435,447), Vec3crd(359,447,435), Vec3crd(286,287,278), Vec3crd(277,278,287), Vec3crd(288,281,289), Vec3crd(280,289,281), Vec3crd(145,152,430), Vec3crd(443,430,152), Vec3crd(148,429,154), Vec3crd(441,154,429), Vec3crd(424,430,294), Vec3crd(294,307,276), Vec3crd(423,296,429), Vec3crd(296,279,305), Vec3crd(425,440,100), Vec3crd(92,100,440), Vec3crd(290,442,291), Vec3crd(282,291,442), Vec3crd(292,293,438), Vec3crd(284,438,293), Vec3crd(298,320,241), Vec3crd(432,440,298), Vec3crd(300,236,322), Vec3crd(433,300,444), Vec3crd(426,101,444), Vec3crd(89,444,101), Vec3crd(107,448,302), Vec3crd(302,79,54), Vec3crd(78,31,343), Vec3crd(107,78,448), Vec3crd(75,79,448), Vec3crd(302,448,79), Vec3crd(78,343,448), Vec3crd(75,448,343), Vec3crd(427,418,259), Vec3crd(425,259,418), Vec3crd(428,262,417), Vec3crd(426,417,262), Vec3crd(437,449,359), Vec3crd(447,359,449), Vec3crd(434,361,450), Vec3crd(446,450,361), Vec3crd(32,33,397), Vec3crd(78,33,32), Vec3crd(53,303,54), Vec3crd(302,54,303), Vec3crd(152,153,443), Vec3crd(438,443,153), Vec3crd(429,304,441), Vec3crd(282,441,304), Vec3crd(430,443,306), Vec3crd(284,306,443), Vec3crd(154,441,155), Vec3crd(442,155,441), Vec3crd(298,299,432), Vec3crd(286,432,299), Vec3crd(300,433,301), Vec3crd(288,301,433), Vec3crd(185,451,308), Vec3crd(308,74,7), Vec3crd(73,15,337), Vec3crd(185,73,451), Vec3crd(35,74,451), Vec3crd(308,451,74), Vec3crd(73,337,451), Vec3crd(35,451,337), Vec3crd(158,452,310), Vec3crd(310,72,42), Vec3crd(70,22,341), Vec3crd(158,70,452), Vec3crd(66,72,452), Vec3crd(310,452,72), Vec3crd(70,341,452), Vec3crd(66,452,341), Vec3crd(313,327,314), Vec3crd(315,314,327), Vec3crd(316,317,326), Vec3crd(318,326,317), Vec3crd(15,156,311), Vec3crd(356,311,156), Vec3crd(7,312,157), Vec3crd(358,157,312), Vec3crd(211,9,327), Vec3crd(364,327,9), Vec3crd(38,326,94), Vec3crd(363,94,326), Vec3crd(294,295,424), Vec3crd(264,424,295), Vec3crd(296,423,297), Vec3crd(267,297,423), Vec3crd(262,149,426), Vec3crd(101,426,149), Vec3crd(258,319,425), Vec3crd(440,425,319), Vec3crd(261,426,321), Vec3crd(444,321,426), Vec3crd(259,425,146), Vec3crd(100,146,425), Vec3crd(306,307,430), Vec3crd(294,430,307), Vec3crd(304,429,305), Vec3crd(296,305,429), Vec3crd(319,320,440), Vec3crd(298,440,320), Vec3crd(321,444,322), Vec3crd(300,322,444), Vec3crd(445,283,442), Vec3crd(155,442,283), Vec3crd(439,438,285), Vec3crd(153,285,438), Vec3crd(17,68,18), Vec3crd(21,18,68), Vec3crd(46,184,47), Vec3crd(221,47,184), Vec3crd(102,95,363), Vec3crd(94,363,95), Vec3crd(9,11,364), Vec3crd(103,364,11), Vec3crd(6,323,357), Vec3crd(370,357,323), Vec3crd(371,324,355), Vec3crd(208,355,324), Vec3crd(270,363,325), Vec3crd(326,325,363), Vec3crd(327,364,328), Vec3crd(273,328,364), Vec3crd(0,2,39), Vec3crd(12,39,2), Vec3crd(90,93,91), Vec3crd(40,91,93), Vec3crd(14,16,17), Vec3crd(73,17,16), Vec3crd(45,309,7), Vec3crd(308,7,309), Vec3crd(12,71,39), Vec3crd(70,39,71), Vec3crd(40,41,42), Vec3crd(310,42,41), Vec3crd(97,98,63), Vec3crd(14,63,98), Vec3crd(3,5,7), Vec3crd(45,7,5), Vec3crd(118,377,329), Vec3crd(330,329,377), Vec3crd(331,372,332), Vec3crd(86,332,372), Vec3crd(333,376,334), Vec3crd(335,334,376), Vec3crd(115,373,336), Vec3crd(169,336,373), Vec3crd(167,166,380), Vec3crd(330,380,166), Vec3crd(80,81,382), Vec3crd(335,382,81), Vec3crd(86,385,81), Vec3crd(168,81,385), Vec3crd(169,384,82), Vec3crd(87,82,384), Vec3crd(159,88,372), Vec3crd(87,372,88), Vec3crd(163,164,376), Vec3crd(167,376,164), Vec3crd(24,26,377), Vec3crd(80,377,26), Vec3crd(56,57,373), Vec3crd(168,373,57), Vec3crd(32,397,30), Vec3crd(29,30,397), Vec3crd(58,60,53), Vec3crd(303,53,60), Vec3crd(205,181,119), Vec3crd(118,119,181), Vec3crd(163,175,165), Vec3crd(122,165,175), Vec3crd(453,454,455), Vec3crd(454,456,455), Vec3crd(457,455,456), Vec3crd(458,455,457), Vec3crd(459,455,458), Vec3crd(460,455,459), Vec3crd(461,462,463), Vec3crd(464,465,466), Vec3crd(467,468,469), Vec3crd(470,471,472), Vec3crd(465,473,474), Vec3crd(475,476,477), Vec3crd(478,479,480), Vec3crd(481,482,478), Vec3crd(483,484,481), Vec3crd(485,486,483), Vec3crd(487,488,485), Vec3crd(489,490,487), Vec3crd(491,492,489), Vec3crd(493,494,491), Vec3crd(495,496,493), Vec3crd(497,498,495), Vec3crd(499,500,497), Vec3crd(501,502,499), Vec3crd(503,504,501), Vec3crd(505,504,503), Vec3crd(506,504,505), Vec3crd(507,504,506), Vec3crd(508,504,507), Vec3crd(509,504,508), Vec3crd(510,504,509), Vec3crd(511,504,510), Vec3crd(512,504,511), Vec3crd(513,504,512), Vec3crd(514,504,513), Vec3crd(476,515,516), Vec3crd(517,518,519), Vec3crd(520,517,521), Vec3crd(518,522,523), Vec3crd(522,480,479), Vec3crd(524,525,526), Vec3crd(468,470,527), Vec3crd(525,467,528), Vec3crd(529,475,530), Vec3crd(531,532,533), Vec3crd(534,531,535), Vec3crd(536,537,538), Vec3crd(473,539,540), Vec3crd(539,536,541), Vec3crd(537,534,542), Vec3crd(471,520,543), Vec3crd(532,529,544), Vec3crd(545,524,546), Vec3crd(453,461,547), Vec3crd(463,464,548), Vec3crd(523,549,504), Vec3crd(527,550,551), Vec3crd(519,552,553), Vec3crd(521,554,555), Vec3crd(466,556,557), Vec3crd(469,558,559), Vec3crd(528,560,561), Vec3crd(477,562,563), Vec3crd(543,564,565), Vec3crd(535,566,567), Vec3crd(530,568,569), Vec3crd(540,570,571), Vec3crd(474,572,573), Vec3crd(542,574,575), Vec3crd(538,576,577), Vec3crd(541,578,579), Vec3crd(472,580,581), Vec3crd(526,582,583), Vec3crd(533,584,585), Vec3crd(544,586,587), Vec3crd(516,545,588), Vec3crd(588,589,590), Vec3crd(455,460,4), Vec3crd(591,592,63), Vec3crd(462,455,4), Vec3crd(592,547,63), Vec3crd(547,548,63), Vec3crd(465,462,4), Vec3crd(548,557,63), Vec3crd(127,124,501), Vec3crd(127,501,499), Vec3crd(505,503,124), Vec3crd(124,126,507), Vec3crd(124,507,506), Vec3crd(509,508,126), Vec3crd(126,134,512), Vec3crd(126,512,511), Vec3crd(510,509,126), Vec3crd(128,127,493), Vec3crd(128,493,491), Vec3crd(497,495,127), Vec3crd(489,487,128), Vec3crd(140,128,483), Vec3crd(140,483,481), Vec3crd(487,485,128), Vec3crd(478,480,140), Vec3crd(480,522,140), Vec3crd(514,513,134), Vec3crd(504,514,134), Vec3crd(551,581,437), Vec3crd(471,470,434), Vec3crd(445,447,555), Vec3crd(445,555,553), Vec3crd(134,445,553), Vec3crd(134,553,504), Vec3crd(446,439,518), Vec3crd(446,518,517), Vec3crd(439,140,522), Vec3crd(439,522,518), Vec3crd(515,476,358), Vec3crd(563,588,356), Vec3crd(557,573,63), Vec3crd(473,465,4), Vec3crd(437,360,559), Vec3crd(437,559,551), Vec3crd(360,371,561), Vec3crd(360,561,559), Vec3crd(362,434,470), Vec3crd(362,470,468), Vec3crd(370,362,468), Vec3crd(370,468,467), Vec3crd(499,497,127), Vec3crd(506,505,124), Vec3crd(495,493,127), Vec3crd(513,512,134), Vec3crd(481,478,140), Vec3crd(447,449,565), Vec3crd(447,565,555), Vec3crd(450,446,517), Vec3crd(450,517,520), Vec3crd(356,156,569), Vec3crd(356,569,563), Vec3crd(157,358,476), Vec3crd(157,476,475), Vec3crd(357,370,467), Vec3crd(357,467,525), Vec3crd(371,355,583), Vec3crd(371,583,561), Vec3crd(460,459,4), Vec3crd(63,62,593), Vec3crd(63,593,591), Vec3crd(62,4,459), Vec3crd(62,459,458), Vec3crd(532,531,104), Vec3crd(531,534,104), Vec3crd(567,585,105), Vec3crd(575,567,105), Vec3crd(4,3,539), Vec3crd(4,539,473), Vec3crd(536,539,3), Vec3crd(97,63,573), Vec3crd(97,573,571), Vec3crd(571,579,97), Vec3crd(99,97,579), Vec3crd(99,579,577), Vec3crd(105,99,577), Vec3crd(105,577,575), Vec3crd(96,104,534), Vec3crd(96,534,537), Vec3crd(3,96,537), Vec3crd(3,537,536), Vec3crd(503,501,124), Vec3crd(508,507,126), Vec3crd(491,489,128), Vec3crd(511,510,126), Vec3crd(485,483,128), Vec3crd(434,450,520), Vec3crd(434,520,471), Vec3crd(449,437,581), Vec3crd(449,581,565), Vec3crd(156,105,585), Vec3crd(156,585,587), Vec3crd(587,569,156), Vec3crd(104,157,529), Vec3crd(104,529,532), Vec3crd(475,529,157), Vec3crd(590,583,355), Vec3crd(355,356,588), Vec3crd(355,588,590), Vec3crd(358,357,524), Vec3crd(358,524,515), Vec3crd(525,524,357), Vec3crd(458,457,62), Vec3crd(457,593,62), Vec3crd(479,478,482), Vec3crd(479,504,549), Vec3crd(479,482,504), Vec3crd(482,481,484), Vec3crd(472,551,550), Vec3crd(581,551,472), Vec3crd(482,484,504), Vec3crd(484,483,486), Vec3crd(523,553,552), Vec3crd(504,553,523), Vec3crd(540,573,572), Vec3crd(571,573,540), Vec3crd(544,585,584), Vec3crd(587,585,544), Vec3crd(542,577,576), Vec3crd(575,577,542), Vec3crd(526,590,589), Vec3crd(583,590,526), Vec3crd(535,575,574), Vec3crd(567,575,535), Vec3crd(533,567,566), Vec3crd(585,567,533), Vec3crd(538,579,578), Vec3crd(577,579,538), Vec3crd(543,581,580), Vec3crd(565,581,543), Vec3crd(477,569,568), Vec3crd(563,569,477), Vec3crd(530,587,586), Vec3crd(569,587,530), Vec3crd(541,571,570), Vec3crd(579,571,541), Vec3crd(528,583,582), Vec3crd(561,583,528), Vec3crd(591,453,592), Vec3crd(547,592,453), Vec3crd(521,565,564), Vec3crd(555,565,521), Vec3crd(474,557,556), Vec3crd(573,557,474), Vec3crd(516,563,562), Vec3crd(588,563,516), Vec3crd(519,555,554), Vec3crd(553,555,519), Vec3crd(527,559,558), Vec3crd(551,559,527), Vec3crd(469,561,560), Vec3crd(559,561,469), Vec3crd(462,461,455), Vec3crd(453,455,461), Vec3crd(461,463,547), Vec3crd(548,547,463), Vec3crd(465,464,462), Vec3crd(463,462,464), Vec3crd(464,466,548), Vec3crd(557,548,466), Vec3crd(469,560,467), Vec3crd(528,467,560), Vec3crd(472,550,470), Vec3crd(527,470,550), Vec3crd(474,556,465), Vec3crd(466,465,556), Vec3crd(477,568,475), Vec3crd(530,475,568), Vec3crd(516,562,476), Vec3crd(477,476,562), Vec3crd(519,554,517), Vec3crd(521,517,554), Vec3crd(521,564,520), Vec3crd(543,520,564), Vec3crd(523,552,518), Vec3crd(519,518,552), Vec3crd(479,549,522), Vec3crd(523,522,549), Vec3crd(526,589,524), Vec3crd(589,546,524), Vec3crd(527,558,468), Vec3crd(469,468,558), Vec3crd(528,582,525), Vec3crd(526,525,582), Vec3crd(530,586,529), Vec3crd(544,529,586), Vec3crd(533,566,531), Vec3crd(535,531,566), Vec3crd(535,574,534), Vec3crd(542,534,574), Vec3crd(538,578,536), Vec3crd(541,536,578), Vec3crd(540,572,473), Vec3crd(474,473,572), Vec3crd(541,570,539), Vec3crd(540,539,570), Vec3crd(542,576,537), Vec3crd(538,537,576), Vec3crd(543,580,471), Vec3crd(472,471,580), Vec3crd(544,584,532), Vec3crd(533,532,584), Vec3crd(524,545,515), Vec3crd(516,515,545), Vec3crd(545,546,588), Vec3crd(589,588,546), Vec3crd(453,591,454), Vec3crd(593,454,591), Vec3crd(484,486,504), Vec3crd(486,485,488), Vec3crd(486,488,504), Vec3crd(488,487,490), Vec3crd(488,490,504), Vec3crd(490,489,492), Vec3crd(490,492,504), Vec3crd(492,491,494), Vec3crd(492,494,504), Vec3crd(494,493,496), Vec3crd(494,496,504), Vec3crd(496,495,498), Vec3crd(496,498,504), Vec3crd(498,497,500), Vec3crd(498,500,504), Vec3crd(500,499,502), Vec3crd(500,502,504), Vec3crd(501,504,502), Vec3crd(454,593,456), Vec3crd(457,456,593), Vec3crd(594,595,596), Vec3crd(597,598,594), Vec3crd(599,597,594), Vec3crd(600,599,594), Vec3crd(601,600,594), Vec3crd(602,601,594), Vec3crd(603,602,594), Vec3crd(604,603,594), Vec3crd(605,604,594), Vec3crd(606,607,608), Vec3crd(609,606,608), Vec3crd(610,609,608), Vec3crd(611,610,608), Vec3crd(612,611,608), Vec3crd(613,612,608), Vec3crd(614,613,608), Vec3crd(615,614,608), Vec3crd(616,615,608), Vec3crd(617,616,608), Vec3crd(618,617,608), Vec3crd(619,618,608), Vec3crd(620,619,608), Vec3crd(596,608,607), Vec3crd(595,594,598), Vec3crd(608,596,595), Vec3crd(605,594,91), Vec3crd(91,338,602), Vec3crd(91,602,603), Vec3crd(598,597,1), Vec3crd(594,596,91), Vec3crd(608,595,1), Vec3crd(595,598,1), Vec3crd(616,617,392), Vec3crd(610,611,394), Vec3crd(419,421,613), Vec3crd(419,613,614), Vec3crd(422,427,607), Vec3crd(422,607,606), Vec3crd(427,91,596), Vec3crd(427,596,607), Vec3crd(428,420,619), Vec3crd(428,619,620), Vec3crd(1,428,620), Vec3crd(1,620,608), Vec3crd(420,409,618), Vec3crd(420,618,619), Vec3crd(411,422,606), Vec3crd(411,606,609), Vec3crd(398,419,614), Vec3crd(398,614,615), Vec3crd(421,400,612), Vec3crd(421,612,613), Vec3crd(409,392,617), Vec3crd(409,617,618), Vec3crd(394,411,609), Vec3crd(394,609,610), Vec3crd(604,605,91), Vec3crd(338,1,599), Vec3crd(338,599,600), Vec3crd(392,398,615), Vec3crd(392,615,616), Vec3crd(400,394,611), Vec3crd(400,611,612), Vec3crd(603,604,91), Vec3crd(601,602,338), Vec3crd(597,599,1), Vec3crd(600,601,338) }); + { {513.075988769531,51.6074333190918,36.0009002685547}, {516.648803710938,51.7324333190918,36.0009002685547}, {513.495178222656,51.7324333190918,36.0009002685547}, {489.391204833984,51.4824333190918,24.0011005401611}, {488.928588867188,51.7324333190918,24.0011005401611}, {492.06201171875,51.7324333190918,24.0011005401611}, {496.840393066406,51.2324333190918,24.0011005401611}, {495.195404052734,51.7324333190918,24.0011005401611}, {498.981994628906,51.7324333190918,24.0011005401611}, {506.966613769531,51.6074333190918,24.0011005401611}, {510.342010498047,51.7324333190918,24.0011005401611}, {507.163818359375,51.6074333190918,24.0011005401611}, {512.515380859375,54.7190322875977,36.0009002685547}, {514.161987304688,54.5058326721191,36.0009002685547}, {493.06201171875,54.7190322875977,36.0009002685547}, {495.195404052734,51.7324333190918,36.0009002685547}, {496.195404052734,54.7190322875977,36.0009002685547}, {497.195404052734,57.7058334350586,36.0009002685547}, {500.851989746094,60.2658309936523,36.0009002685547}, {498.915405273438,62.8258323669434,36.0009002685547}, {506.701995849609,62.8258323669434,36.0009002685547}, {503.648590087891,60.2658309936523,36.0009002685547}, {508.381805419922,57.7058334350586,36.0009002685547}, {496.418792724609,60.052433013916,36.0009002685547}, {506.515197753906,72.2124328613281,36.0009002685547}, {502.808807373047,74.5324325561523,36.0009002685547}, {503.781982421875,71.6058349609375,36.0009002685547}, {515.358764648438,55.4658317565918,36.0009002685547}, {499.375183105469,76.9058380126953,36.0009002685547}, {501.168792724609,78.0658340454102,36.0009002685547}, {504.568786621094,78.0658340454102,36.0009002685547}, {506.32861328125,81.599235534668,36.0009002685547}, {502.928588867188,81.599235534668,36.0009002685547}, {499.528594970703,81.599235534668,36.0009002685547}, {498.20361328125,77.8658294677734,36.0009002685547}, {495.195404052734,51.7324333190918,30.0011005401611}, {498.981994628906,51.7324333190918,27.0011005401611}, {506.555206298828,51.7324333190918,33.0009002685547}, {506.555206298828,51.7324333190918,36.0009002685547}, {510.342010498047,51.7324333190918,36.0009002685547}, {512.515380859375,54.7190322875977,24.0011005401611}, {509.361999511719,54.7190322875977,24.0011005401611}, {508.381805419922,57.7058334350586,24.0011005401611}, {506.701995849609,62.8258323669434,24.0011005401611}, {509.188812255859,60.052433013916,24.0011005401611}, {493.06201171875,54.7190322875977,24.0011005401611}, {503.648590087891,60.2658309936523,24.0011005401611}, {500.851989746094,60.2658309936523,24.0011005401611}, {498.915405273438,62.8258323669434,24.0011005401611}, {502.808807373047,62.8258323669434,24.0011005401611}, {491.425201416016,54.5058326721191,24.0011005401611}, {506.421813964844,76.9058380126953,24.0011005401611}, {502.808807373047,74.5324325561523,24.0011005401611}, {504.568786621094,78.0658340454102,24.0011005401611}, {506.32861328125,81.599235534668,24.0011005401611}, {507.618804931641,77.8658294677734,24.0011005401611}, {499.221801757812,72.2124328613281,24.0011005401611}, {501.835388183594,71.6058349609375,24.0011005401611}, {501.168792724609,78.0658340454102,24.0011005401611}, {499.528594970703,81.599235534668,24.0011005401611}, {502.048583984375,79.8324356079102,24.0011005401611}, {490.253601074219,55.4658317565918,24.0011005401611}, {488.928588867188,51.7324333190918,30.0011005401611}, {488.928588867188,51.7324333190918,36.0009002685547}, {490.253601074219,55.4658317565918,31.5009002685547}, {498.20361328125,77.8658294677734,34.5009002685547}, {508.381805419922,57.7058334350586,30.0011005401611}, {505.585388183594,57.7058334350586,27.0011005401611}, {502.788818359375,57.7058334350586,36.0009002685547}, {499.992004394531,57.7058334350586,33.0009002685547}, {509.851989746094,53.2258338928223,33.0009002685547}, {509.361999511719,54.7190322875977,36.0009002685547}, {508.871795654297,56.2124328613281,27.0011005401611}, {496.695404052734,56.2124328613281,33.0009002685547}, {495.695404052734,53.2258338928223,27.0011005401611}, {506.32861328125,81.599235534668,30.0011005401611}, {507.618804931641,77.8658294677734,25.5011005401611}, {515.358764648438,55.4658317565918,34.5009002685547}, {501.228607177734,81.599235534668,33.0009002685547}, {504.628601074219,81.599235534668,27.0011005401611}, {503.781982421875,71.6058349609375,33.0009002685547}, {502.808807373047,74.5324325561523,30.0011005401611}, {498.915405273438,62.8258323669434,30.0011005401611}, {500.861999511719,62.8258323669434,27.0011005401611}, {502.808807373047,62.8258323669434,36.0009002685547}, {504.755187988281,62.8258323669434,33.0009002685547}, {501.835388183594,71.6058349609375,33.0009002685547}, {499.888793945312,65.7524337768555,33.0009002685547}, {499.888793945312,65.7524337768555,36.0009002685547}, {513.128601074219,51.4824333190918,36.0009002685547}, {513.075988769531,51.6074333190918,24.0011005401611}, {516.648803710938,51.7324333190918,24.0011005401611}, {513.128601074219,51.4824333190918,24.0011005401611}, {513.495178222656,51.7324333190918,24.0011005401611}, {506.966613769531,51.6074333190918,36.0009002685547}, {507.163818359375,51.6074333190918,36.0009002685547}, {490.337799072266,51.4824333190918,24.0011005401611}, {489.391204833984,51.4824333190918,36.0009002685547}, {492.06201171875,51.7324333190918,36.0009002685547}, {490.337799072266,51.4824333190918,36.0009002685547}, {513.233764648438,51.2324333190918,24.0011005401611}, {513.233764648438,51.2324333190918,36.0009002685547}, {504.773803710938,51.4824333190918,36.0009002685547}, {504.773803710938,51.4824333190918,24.0011005401611}, {489.266998291016,51.2324333190918,24.0011005401611}, {489.266998291016,51.2324333190918,36.0009002685547}, {490.253601074219,55.4658317565918,25.5011005401611}, {499.528594970703,81.599235534668,30.0011005401611}, {498.20361328125,77.8658294677734,31.5009002685547}, {515.358764648438,55.4658317565918,28.5011005401611}, {515.358764648438,55.4658317565918,25.5011005401611}, {495.246795654297,61.0124320983887,36.0009002685547}, {490.253601074219,55.4658317565918,34.5009002685547}, {490.253601074219,55.4658317565918,36.0009002685547}, {494.228607177734,66.6658325195312,24.0011005401611}, {499.068786621094,67.5192337036133,24.0011005401611}, {498.20361328125,77.8658294677734,25.5011005401611}, {498.20361328125,77.8658294677734,24.0011005401611}, {506.608795166016,67.5192337036133,36.0009002685547}, {509.09521484375,64.7458343505859,36.0009002685547}, {507.618804931641,77.8658294677734,34.5009002685547}, {507.618804931641,77.8658294677734,36.0009002685547}, {510.385406494141,61.0124320983887,24.0011005401611}, {515.358764648438,55.4658317565918,24.0011005401611}, {489.32861328125,47.7324333190918,31.5009002685547}, {492.95361328125,47.7324333190918,33.5634994506836}, {489.32861328125,47.7324333190918,34.5009002685547}, {489.32861328125,47.7324333190918,28.5011005401611}, {489.32861328125,47.7324333190918,25.5011005401611}, {492.95361328125,47.7324333190918,26.4385013580322}, {492.95361328125,47.7324333190918,30.5635013580322}, {492.95361328125,47.7324333190918,32.0634994506836}, {492.95361328125,47.7324333190918,31.3135013580322}, {492.95361328125,47.7324333190918,35.4384994506836}, {489.32861328125,47.7324333190918,36.0009002685547}, {492.95361328125,47.7324333190918,34.3134994506836}, {492.95361328125,47.7324333190918,34.6884994506836}, {492.95361328125,47.7324333190918,27.9385013580322}, {492.95361328125,47.7324333190918,28.6885013580322}, {492.95361328125,47.7324333190918,29.0635013580322}, {489.32861328125,47.7324333190918,24.0011005401611}, {492.95361328125,47.7324333190918,24.5635013580322}, {492.95361328125,47.7324333190918,25.6885013580322}, {492.95361328125,47.7324333190918,25.3135013580322}, {492.95361328125,47.7324333190918,24.1885013580322}, {492.95361328125,47.7324333190918,24.0011005401611}, {513.443786621094,50.7324333190918,24.0011005401611}, {492.95361328125,47.7324333190918,35.8134994506836}, {492.95361328125,47.7324333190918,36.0009002685547}, {513.443786621094,50.7324333190918,36.0009002685547}, {506.350402832031,51.4824333190918,36.0009002685547}, {506.350402832031,51.4824333190918,24.0011005401611}, {492.743804931641,48.2324333190918,24.0011005401611}, {492.638793945312,48.4824333190918,24.0011005401611}, {492.743804931641,48.2324333190918,36.0009002685547}, {492.638793945312,48.4824333190918,36.0009002685547}, {490.089599609375,50.9824333190918,36.0009002685547}, {490.089599609375,50.9824333190918,24.0011005401611}, {510.342010498047,51.7324333190918,30.0011005401611}, {499.068786621094,67.5192337036133,36.0009002685547}, {494.228607177734,66.6658325195312,36.0009002685547}, {499.375183105469,76.9058380126953,24.0011005401611}, {506.421813964844,76.9058380126953,36.0009002685547}, {506.608795166016,67.5192337036133,24.0011005401611}, {505.728607177734,65.7524337768555,24.0011005401611}, {509.09521484375,64.7458343505859,24.0011005401611}, {506.701995849609,62.8258323669434,30.0011005401611}, {505.728607177734,65.7524337768555,27.0011005401611}, {501.835388183594,71.6058349609375,27.0011005401611}, {499.888793945312,65.7524337768555,27.0011005401611}, {494.228607177734,66.6658325195312,30.0011005401611}, {495.553588867188,70.3992309570312,28.5011005401611}, {492.903594970703,62.9324340820312,28.5011005401611}, {495.553588867188,70.3992309570312,31.5009002685547}, {492.903594970703,62.9324340820312,31.5009002685547}, {511.488800048828,66.6658325195312,24.0011005401611}, {511.488800048828,66.6658325195312,30.0011005401611}, {512.778564453125,62.9324340820312,28.5011005401611}, {515.358764648438,55.4658317565918,31.5009002685547}, {507.618804931641,77.8658294677734,31.5009002685547}, {510.198791503906,70.3992309570312,28.5011005401611}, {511.488800048828,66.6658325195312,36.0009002685547}, {512.778564453125,62.9324340820312,31.5009002685547}, {510.198791503906,70.3992309570312,31.5009002685547}, {502.788818359375,57.7058334350586,24.0011005401611}, {497.195404052734,57.7058334350586,30.0011005401611}, {492.903594970703,62.9324340820312,34.5009002685547}, {492.903594970703,62.9324340820312,36.0009002685547}, {495.553588867188,70.3992309570312,24.0011005401611}, {496.725189208984,69.4392318725586,24.0011005401611}, {495.553588867188,70.3992309570312,25.5011005401611}, {495.246795654297,61.0124320983887,24.0011005401611}, {492.903594970703,62.9324340820312,25.5011005401611}, {492.903594970703,62.9324340820312,24.0011005401611}, {495.553588867188,70.3992309570312,36.0009002685547}, {496.725189208984,69.4392318725586,36.0009002685547}, {495.553588867188,70.3992309570312,34.5009002685547}, {510.198791503906,70.3992309570312,36.0009002685547}, {509.002014160156,69.4392318725586,36.0009002685547}, {510.198791503906,70.3992309570312,34.5009002685547}, {512.778564453125,62.9324340820312,25.5011005401611}, {512.778564453125,62.9324340820312,24.0011005401611}, {510.198791503906,70.3992309570312,24.0011005401611}, {509.002014160156,69.4392318725586,24.0011005401611}, {510.198791503906,70.3992309570312,25.5011005401611}, {510.385406494141,61.0124320983887,36.0009002685547}, {512.778564453125,62.9324340820312,34.5009002685547}, {512.778564453125,62.9324340820312,36.0009002685547}, {496.840393066406,51.2324333190918,36.0009002685547}, {498.981994628906,51.7324333190918,36.0009002685547}, {498.981994628906,51.7324333190918,33.0009002685547}, {506.555206298828,51.7324333190918,24.0011005401611}, {506.555206298828,51.7324333190918,27.0011005401611}, {503.82861328125,47.7324333190918,30.7509002685547}, {507.45361328125,47.7324333190918,32.8134994506836}, {503.82861328125,47.7324333190918,33.7509002685547}, {503.82861328125,47.7324333190918,29.2511005401611}, {503.82861328125,47.7324333190918,26.2511005401611}, {507.45361328125,47.7324333190918,27.1885013580322}, {493.921813964844,57.2792320251465,36.0009002685547}, {491.425201416016,54.5058326721191,36.0009002685547}, {497.195404052734,57.7058334350586,24.0011005401611}, {496.418792724609,60.052433013916,24.0011005401611}, {509.188812255859,60.052433013916,36.0009002685547}, {511.675415039062,57.2792320251465,24.0011005401611}, {514.161987304688,54.5058326721191,24.0011005401611}, {507.45361328125,47.7324333190918,34.3134994506836}, {503.82861328125,47.7324333190918,35.2509002685547}, {507.45361328125,47.7324333190918,25.6885013580322}, {503.82861328125,47.7324333190918,24.7511005401611}, {500.20361328125,47.7324333190918,31.6885013580322}, {500.20361328125,47.7324333190918,28.3135013580322}, {500.20361328125,47.7324333190918,30.1885013580322}, {507.45361328125,47.7324333190918,29.8135013580322}, {507.45361328125,47.7324333190918,31.3135013580322}, {507.45361328125,47.7324333190918,30.5635013580322}, {503.82861328125,47.7324333190918,36.0009002685547}, {507.45361328125,47.7324333190918,35.4384994506836}, {507.45361328125,47.7324333190918,35.0634994506836}, {507.45361328125,47.7324333190918,28.6885013580322}, {507.45361328125,47.7324333190918,29.4385013580322}, {503.82861328125,47.7324333190918,24.0011005401611}, {507.45361328125,47.7324333190918,24.5635013580322}, {507.45361328125,47.7324333190918,24.9385013580322}, {500.20361328125,47.7324333190918,34.6884994506836}, {500.20361328125,47.7324333190918,33.1884994506836}, {500.20361328125,47.7324333190918,33.9384994506836}, {500.20361328125,47.7324333190918,25.3135013580322}, {500.20361328125,47.7324333190918,26.8135013580322}, {500.20361328125,47.7324333190918,26.0635013580322}, {500.20361328125,47.7324333190918,30.9385013580322}, {500.20361328125,47.7324333190918,35.0634994506836}, {500.20361328125,47.7324333190918,35.4384994506836}, {500.20361328125,47.7324333190918,29.0635013580322}, {500.20361328125,47.7324333190918,29.4385013580322}, {500.20361328125,47.7324333190918,24.9385013580322}, {500.20361328125,47.7324333190918,24.5635013580322}, {507.45361328125,47.7324333190918,24.1885013580322}, {507.45361328125,47.7324333190918,24.0011005401611}, {513.86376953125,49.7324333190918,24.0011005401611}, {507.45361328125,47.7324333190918,35.8134994506836}, {507.45361328125,47.7324333190918,36.0009002685547}, {513.86376953125,49.7324333190918,36.0009002685547}, {500.20361328125,47.7324333190918,24.1885013580322}, {500.20361328125,47.7324333190918,24.0011005401611}, {502.988800048828,49.7324333190918,24.0011005401611}, {500.20361328125,47.7324333190918,35.8134994506836}, {500.20361328125,47.7324333190918,36.0009002685547}, {502.988800048828,49.7324333190918,36.0009002685547}, {504.755187988281,62.8258323669434,27.0011005401611}, {499.205383300781,51.2324333190918,36.0009002685547}, {498.786193847656,51.1074333190918,36.0009002685547}, {502.358795166016,51.2324333190918,36.0009002685547}, {499.205383300781,51.2324333190918,24.0011005401611}, {502.358795166016,51.2324333190918,24.0011005401611}, {498.786193847656,51.1074333190918,24.0011005401611}, {502.568786621094,50.7324333190918,24.0011005401611}, {505.931213378906,51.3574333190918,24.0011005401611}, {509.503601074219,51.4824333190918,24.0011005401611}, {502.568786621094,50.7324333190918,36.0009002685547}, {505.931213378906,51.3574333190918,36.0009002685547}, {509.503601074219,51.4824333190918,36.0009002685547}, {499.048583984375,50.4824333190918,36.0009002685547}, {492.428588867188,48.9824333190918,36.0009002685547}, {499.048583984375,50.4824333190918,24.0011005401611}, {492.428588867188,48.9824333190918,24.0011005401611}, {506.088806152344,50.9824333190918,24.0011005401611}, {506.036010742188,51.1074333190918,24.0011005401611}, {506.088806152344,50.9824333190918,36.0009002685547}, {506.036010742188,51.1074333190918,36.0009002685547}, {498.891204833984,50.8574333190918,36.0009002685547}, {498.943786621094,50.7324333190918,36.0009002685547}, {498.891204833984,50.8574333190918,24.0011005401611}, {498.943786621094,50.7324333190918,24.0011005401611}, {499.573608398438,49.2324333190918,24.0011005401611}, {499.783813476562,48.7324333190918,24.0011005401611}, {499.573608398438,49.2324333190918,36.0009002685547}, {499.783813476562,48.7324333190918,36.0009002685547}, {506.403594970703,50.2324333190918,24.0011005401611}, {506.298797607422,50.4824333190918,24.0011005401611}, {506.403594970703,50.2324333190918,36.0009002685547}, {506.298797607422,50.4824333190918,36.0009002685547}, {501.228607177734,81.599235534668,27.0011005401611}, {502.928588867188,81.599235534668,24.0011005401611}, {499.2587890625,49.9824333190918,36.0009002685547}, {499.363800048828,49.7324333190918,36.0009002685547}, {499.2587890625,49.9824333190918,24.0011005401611}, {499.363800048828,49.7324333190918,24.0011005401611}, {496.695404052734,56.2124328613281,27.0011005401611}, {496.195404052734,54.7190322875977,24.0011005401611}, {509.851989746094,53.2258338928223,27.0011005401611}, {493.464782714844,51.1074333190918,36.0009002685547}, {493.464782714844,51.1074333190918,24.0011005401611}, {502.768798828125,51.7324333190918,24.0011005401611}, {500.215789794922,51.3574333190918,24.0011005401611}, {497.628601074219,51.2324333190918,24.0011005401611}, {502.768798828125,51.7324333190918,36.0009002685547}, {500.215789794922,51.3574333190918,36.0009002685547}, {497.628601074219,51.2324333190918,36.0009002685547}, {507.033813476562,48.7324333190918,24.0011005401611}, {506.823791503906,49.2324333190918,24.0011005401611}, {507.033813476562,48.7324333190918,36.0009002685547}, {506.823791503906,49.2324333190918,36.0009002685547}, {494.4501953125,51.1074333190918,24.0011005401611}, {494.4501953125,51.1074333190918,36.0009002685547}, {500.807006835938,51.3574333190918,36.0009002685547}, {503.591186523438,51.4824333190918,36.0009002685547}, {503.591186523438,51.4824333190918,24.0011005401611}, {500.807006835938,51.3574333190918,24.0011005401611}, {505.728607177734,65.7524337768555,36.0009002685547}, {505.728607177734,65.7524337768555,33.0009002685547}, {499.221801757812,72.2124328613281,36.0009002685547}, {501.835388183594,71.6058349609375,36.0009002685547}, {506.515197753906,72.2124328613281,24.0011005401611}, {503.781982421875,71.6058349609375,24.0011005401611}, {503.781982421875,71.6058349609375,27.0011005401611}, {499.888793945312,65.7524337768555,24.0011005401611}, {495.695404052734,53.2258338928223,33.0009002685547}, {516.648803710938,51.7324333190918,30.0011005401611}, {498.20361328125,77.8658294677734,28.5011005401611}, {505.585388183594,57.7058334350586,33.0009002685547}, {508.871795654297,56.2124328613281,33.0009002685547}, {499.992004394531,57.7058334350586,27.0011005401611}, {504.628601074219,81.599235534668,33.0009002685547}, {500.861999511719,62.8258323669434,33.0009002685547}, {496.878601074219,74.1324310302734,27.0011005401611}, {496.878601074219,74.1324310302734,33.0009002685547}, {491.57861328125,59.199031829834,27.0011005401611}, {490.253601074219,55.4658317565918,28.5011005401611}, {491.57861328125,59.199031829834,33.0009002685547}, {514.068786621094,59.199031829834,27.0011005401611}, {514.068786621094,59.199031829834,33.0009002685547}, {508.908813476562,74.1324310302734,27.0011005401611}, {507.618804931641,77.8658294677734,28.5011005401611}, {508.908813476562,74.1324310302734,33.0009002685547}, {491.271789550781,50.9824333190918,36.0009002685547}, {490.877807617188,50.9824333190918,36.0009002685547}, {491.271789550781,50.9824333190918,24.0011005401611}, {490.877807617188,50.9824333190918,24.0011005401611}, {495.213806152344,50.9824333190918,36.0009002685547}, {493.636993408203,50.9824333190918,36.0009002685547}, {495.213806152344,50.9824333190918,24.0011005401611}, {493.636993408203,50.9824333190918,24.0011005401611}, {503.985412597656,51.4824333190918,36.0009002685547}, {503.985412597656,51.4824333190918,24.0011005401611}, {511.675415039062,57.2792320251465,36.0009002685547}, {493.921813964844,57.2792320251465,24.0011005401611}, {502.768798828125,51.7324333190918,30.0011005401611}, {506.555206298828,51.7324333190918,30.0011005401611}, {498.981994628906,51.7324333190918,30.0011005401611}, {492.848815917969,50.9824333190918,24.0011005401611}, {492.848815917969,50.9824333190918,36.0009002685547}, {500.861999511719,68.6792297363281,36.0009002685547}, {500.861999511719,68.6792297363281,24.0011005401611}, {496.878601074219,74.1324310302734,24.0011005401611}, {496.878601074219,74.1324310302734,36.0009002685547}, {504.755187988281,68.6792297363281,24.0011005401611}, {504.755187988281,68.6792297363281,36.0009002685547}, {508.908813476562,74.1324310302734,36.0009002685547}, {508.908813476562,74.1324310302734,24.0011005401611}, {505.728607177734,65.7524337768555,30.0011005401611}, {504.755187988281,68.6792297363281,30.0011005401611}, {503.781982421875,71.6058349609375,30.0011005401611}, {500.861999511719,68.6792297363281,30.0011005401611}, {499.888793945312,65.7524337768555,30.0011005401611}, {501.835388183594,71.6058349609375,30.0011005401611}, {491.57861328125,59.199031829834,24.0011005401611}, {491.57861328125,59.199031829834,36.0009002685547}, {514.068786621094,59.199031829834,36.0009002685547}, {514.068786621094,59.199031829834,24.0011005401611}, {511.07861328125,47.7324333190918,34.8759002685547}, {511.07861328125,47.7324333190918,31.8759002685547}, {514.70361328125,47.7324333190918,33.9384994506836}, {511.07861328125,47.7324333190918,25.1261005401611}, {514.70361328125,47.7324333190918,26.0635013580322}, {511.07861328125,47.7324333190918,28.1261005401611}, {502.788818359375,57.7058334350586,30.0011005401611}, {502.048583984375,79.8324356079102,36.0009002685547}, {514.70361328125,47.7324333190918,30.9385013580322}, {511.07861328125,47.7324333190918,30.3759002685547}, {514.70361328125,47.7324333190918,29.0635013580322}, {511.07861328125,47.7324333190918,29.6261005401611}, {496.57861328125,47.7324333190918,31.1259002685547}, {496.57861328125,47.7324333190918,32.6259002685547}, {496.57861328125,47.7324333190918,34.1259002685547}, {496.57861328125,47.7324333190918,28.8761005401611}, {496.57861328125,47.7324333190918,27.3761005401611}, {496.57861328125,47.7324333190918,25.8761005401611}, {496.57861328125,47.7324333190918,29.6261005401611}, {514.70361328125,47.7324333190918,35.4384994506836}, {511.07861328125,47.7324333190918,35.6259002685547}, {514.70361328125,47.7324333190918,24.5635013580322}, {511.07861328125,47.7324333190918,24.3761005401611}, {496.57861328125,47.7324333190918,34.8759002685547}, {496.57861328125,47.7324333190918,25.1261005401611}, {496.57861328125,47.7324333190918,35.6259002685547}, {496.57861328125,47.7324333190918,24.3761005401611}, {511.07861328125,47.7324333190918,36.0009002685547}, {511.07861328125,47.7324333190918,24.0011005401611}, {514.70361328125,47.7324333190918,30.1885013580322}, {514.70361328125,47.7324333190918,35.8134994506836}, {514.70361328125,47.7324333190918,29.8135013580322}, {514.70361328125,47.7324333190918,24.1885013580322}, {496.57861328125,47.7324333190918,36.0009002685547}, {496.57861328125,47.7324333190918,24.0011005401611}, {510.238800048828,49.7324333190918,24.0011005401611}, {510.238800048828,49.7324333190918,36.0009002685547}, {514.70361328125,47.7324333190918,24.0011005401611}, {514.70361328125,47.7324333190918,36.0009002685547}, {496.158813476562,48.7324333190918,36.0009002685547}, {496.158813476562,48.7324333190918,24.0011005401611}, {502.808807373047,62.8258323669434,30.0011005401611}, {509.608795166016,51.2324333190918,24.0011005401611}, {509.608795166016,51.2324333190918,36.0009002685547}, {491.641204833984,50.8574333190918,24.0011005401611}, {495.423797607422,50.4824333190918,36.0009002685547}, {495.423797607422,50.4824333190918,24.0011005401611}, {491.641204833984,50.8574333190918,36.0009002685547}, {495.528594970703,50.2324333190918,24.0011005401611}, {492.0087890625,49.9824333190918,24.0011005401611}, {509.818786621094,50.7324333190918,24.0011005401611}, {495.948608398438,49.2324333190918,36.0009002685547}, {495.528594970703,50.2324333190918,36.0009002685547}, {495.948608398438,49.2324333190918,24.0011005401611}, {509.818786621094,50.7324333190918,36.0009002685547}, {492.0087890625,49.9824333190918,36.0009002685547}, {491.956207275391,50.1074333190918,24.0011005401611}, {491.956207275391,50.1074333190918,36.0009002685547}, {502.928588867188,81.599235534668,30.0011005401611}, {491.851013183594,50.3574333190918,36.0009002685547}, {491.851013183594,50.3574333190918,24.0011005401611}, {496.195404052734,54.7190322875977,30.0011005401611}, {509.361999511719,54.7190322875977,30.0011005401611}, {488.632598876953,51.7256317138672,30.0011005401611}, {488.632598876953,51.7256317138672,29.5091018676758}, {488.632598876953,51.7188339233398,24.0011005401611}, {488.632598876953,51.7256317138672,27.4929008483887}, {488.632598876953,51.7324333190918,30.0011005401611}, {488.632598876953,51.7324333190918,29.0175018310547}, {488.632598876953,51.7324333190918,24.9847011566162}, {488.632598876953,51.7324333190918,24.0011005401611}, {488.632598876953,51.7188339233398,30.0011005401611}, {488.632598876953,51.7176322937012,24.0011005401611}, {488.632598876953,51.7182312011719,30.0011005401611}, {488.632598876953,51.7176322937012,30.0011005401611}, {488.632598876953,51.715030670166,24.0011005401611}, {488.632598876953,51.7162322998047,30.0011005401611}, {488.632598876953,50.761833190918,24.0011005401611}, {488.632598876953,50.7578315734863,24.0011005401611}, {488.632598876953,50.7598342895508,30.0011005401611}, {488.632598876953,50.7522315979004,24.0011005401611}, {488.632598876953,49.7838325500488,24.0011005401611}, {488.632598876953,50.2680320739746,30.0011005401611}, {488.632598876953,51.7046318054199,24.0011005401611}, {488.632598876953,51.709831237793,30.0011005401611}, {488.632598876953,50.9120330810547,24.0011005401611}, {488.632598876953,50.8882331848145,24.0011005401611}, {488.632598876953,50.9002304077148,30.0011005401611}, {488.632598876953,47.7324333190918,24.0370998382568}, {488.632598876953,48.5612335205078,30.0011005401611}, {488.632598876953,47.7324333190918,24.0011005401611}, {488.632598876953,47.7324333190918,24.1091003417969}, {488.632598876953,48.5612335205078,30.0189018249512}, {488.632598876953,47.7324333190918,25.3211002349854}, {488.632598876953,48.5612335205078,30.0551013946533}, {488.632598876953,47.7324333190918,25.4651012420654}, {488.632598876953,48.5612335205078,30.6609001159668}, {488.632598876953,47.7324333190918,25.5371017456055}, {488.632598876953,48.5612335205078,30.7329006195068}, {488.632598876953,47.7324333190918,25.6091003417969}, {488.632598876953,48.5612335205078,30.7689018249512}, {488.632598876953,47.7324333190918,25.8971004486084}, {488.632598876953,48.5612335205078,30.8051013946533}, {488.632598876953,47.7324333190918,28.321102142334}, {488.632598876953,48.5612335205078,30.9491004943848}, {488.632598876953,47.7324333190918,28.4651012420654}, {488.632598876953,48.5612335205078,32.1609001159668}, {488.632598876953,47.7324333190918,28.5371017456055}, {488.632598876953,48.5612335205078,32.2329025268555}, {488.632598876953,47.7324333190918,28.6811008453369}, {488.632598876953,48.5612335205078,32.2689018249512}, {488.632598876953,47.7324333190918,31.1049003601074}, {488.632598876953,48.5612335205078,32.3411026000977}, {488.632598876953,47.7324333190918,31.3929004669189}, {488.632598876953,49.3900299072266,36.0009002685547}, {488.632598876953,47.7324333190918,31.536901473999}, {488.632598876953,47.7324333190918,31.6809005737305}, {488.632598876953,47.7324333190918,34.1049003601074}, {488.632598876953,47.7324333190918,34.3929023742676}, {488.632598876953,47.7324333190918,34.464900970459}, {488.632598876953,47.7324333190918,34.5369033813477}, {488.632598876953,47.7324333190918,34.6809005737305}, {488.632598876953,47.7324333190918,35.8929023742676}, {488.632598876953,47.7324333190918,35.964900970459}, {488.632598876953,47.7324333190918,36.0009002685547}, {488.632598876953,50.8816299438477,24.0011005401611}, {488.632598876953,50.8850326538086,30.0011005401611}, {488.632598876953,49.7480316162109,24.0011005401611}, {488.632598876953,49.7426300048828,24.0011005401611}, {488.632598876953,49.745231628418,30.0011005401611}, {488.632598876953,49.7592315673828,24.0011005401611}, {488.632598876953,49.7536315917969,30.0011005401611}, {488.632598876953,49.3900299072266,24.0011005401611}, {488.632598876953,49.5664329528809,30.0011005401611}, {488.632598876953,50.8786315917969,24.0011005401611}, {488.632598876953,50.7764320373535,24.0011005401611}, {488.632598876953,50.8274307250977,30.0011005401611}, {488.632598876953,50.7550315856934,30.0011005401611}, {488.632598876953,50.7692337036133,30.0011005401611}, {488.632598876953,50.9284324645996,24.0011005401611}, {488.632598876953,50.9202308654785,30.0011005401611}, {488.632598876953,51.1788330078125,24.0011005401611}, {488.632598876953,51.139232635498,24.0011005401611}, {488.632598876953,51.1590309143066,30.0011005401611}, {488.632598876953,51.2324333190918,24.0011005401611}, {488.632598876953,51.2056312561035,30.0011005401611}, {488.632598876953,51.4340324401855,24.0011005401611}, {488.632598876953,51.3946304321289,24.0011005401611}, {488.632598876953,51.4142303466797,30.0011005401611}, {488.632598876953,51.4498329162598,24.0011005401611}, {488.632598876953,51.5772323608398,30.0011005401611}, {488.632598876953,51.4418334960938,30.0011005401611}, {488.632598876953,51.3136329650879,30.0011005401611}, {488.632598876953,49.7714309692383,30.0011005401611}, {488.632598876953,51.0338325500488,30.0011005401611}, {488.632598876953,50.8816299438477,30.0011005401611}, {488.632598876953,50.8800315856934,30.0011005401611}, {488.632598876953,51.7188339233398,36.0009002685547}, {488.632598876953,51.7176322937012,36.0009002685547}, {488.632598876953,49.3900299072266,30.0011005401611}, {488.632598876953,50.7522315979004,30.0011005401611}, {488.632598876953,50.7522315979004,36.0009002685547}, {488.632598876953,49.7426300048828,30.0011005401611}, {488.632598876953,49.7426300048828,36.0009002685547}, {488.632598876953,49.7480316162109,30.0011005401611}, {488.632598876953,49.7480316162109,36.0009002685547}, {488.632598876953,51.715030670166,30.0011005401611}, {488.632598876953,51.715030670166,36.0009002685547}, {488.632598876953,50.7578315734863,30.0011005401611}, {488.632598876953,50.7578315734863,36.0009002685547}, {488.632598876953,50.761833190918,30.0011005401611}, {488.632598876953,50.761833190918,36.0009002685547}, {488.632598876953,50.8882331848145,30.0011005401611}, {488.632598876953,50.8882331848145,36.0009002685547}, {488.632598876953,49.7592315673828,30.0011005401611}, {488.632598876953,49.7592315673828,36.0009002685547}, {488.632598876953,51.1788330078125,30.0011005401611}, {488.632598876953,51.1788330078125,36.0009002685547}, {488.632598876953,50.9120330810547,30.0011005401611}, {488.632598876953,50.9120330810547,36.0009002685547}, {488.632598876953,51.4498329162598,30.0011005401611}, {488.632598876953,51.4498329162598,36.0009002685547}, {488.632598876953,51.7046318054199,30.0011005401611}, {488.632598876953,51.7046318054199,36.0009002685547}, {488.632598876953,51.2324333190918,30.0011005401611}, {488.632598876953,51.2324333190918,36.0009002685547}, {488.632598876953,51.3946304321289,30.0011005401611}, {488.632598876953,51.3946304321289,36.0009002685547}, {488.632598876953,51.4340324401855,30.0011005401611}, {488.632598876953,51.4340324401855,36.0009002685547}, {488.632598876953,49.7838325500488,30.0011005401611}, {488.632598876953,49.7838325500488,36.0009002685547}, {488.632598876953,50.7764320373535,30.0011005401611}, {488.632598876953,50.7764320373535,36.0009002685547}, {488.632598876953,51.139232635498,30.0011005401611}, {488.632598876953,51.139232635498,36.0009002685547}, {488.632598876953,50.9284324645996,30.0011005401611}, {488.632598876953,50.9284324645996,36.0009002685547}, {488.632598876953,50.8816299438477,36.0009002685547}, {488.632598876953,50.8786315917969,30.0011005401611}, {488.632598876953,50.8786315917969,36.0009002685547}, {488.632598876953,51.7324333190918,35.0173034667969}, {488.632598876953,51.7324333190918,36.0009002685547}, {488.632598876953,51.7324333190918,30.9847011566162}, {517.188415527344,51.7140884399414,24.0011005401611}, {517.188415527344,51.7140884399414,36.0009002685547}, {517.188415527344,50.4475173950195,24.0011005401611}, {517.188415527344,51.7324333190918,35.3734130859375}, {517.188415527344,51.7324333190918,36.0009002685547}, {517.188415527344,51.7324333190918,34.1185760498047}, {517.188415527344,51.7324333190918,31.88330078125}, {517.188415527344,51.7324333190918,30.0011005401611}, {517.188415527344,51.7324333190918,28.1187744140625}, {517.188415527344,51.7324333190918,25.8834266662598}, {517.188415527344,51.7324333190918,24.6285915374756}, {517.188415527344,51.7324333190918,24.0011005401611}, {517.188415527344,47.7324333190918,24.0600452423096}, {517.188415527344,47.7324333190918,24.0011005401611}, {517.188415527344,50.4475173950195,36.0009002685547}, {517.188415527344,47.7324333190918,24.1779975891113}, {517.188415527344,47.7324333190918,24.6498031616211}, {517.188415527344,47.7324333190918,28.7625770568848}, {517.188415527344,47.7324333190918,29.7061901092529}, {517.188415527344,47.7324333190918,29.9420928955078}, {517.188415527344,47.7324333190918,30.0600452423096}, {517.188415527344,47.7324333190918,30.2959480285645}, {517.188415527344,47.7324333190918,31.2395629882812}, {517.188415527344,47.7324333190918,35.3521995544434}, {517.188415527344,47.7324333190918,35.8240051269531}, {517.188415527344,47.7324333190918,35.9419555664062}, {517.188415527344,47.7324333190918,36.0009002685547} }, + { {0,1,2}, {3,4,5}, {6,7,8}, {9,10,11}, {12,2,1}, {12,1,13}, {14,15,16}, {17,18,19}, {20,21,22}, {17,19,23}, {24,25,26}, {27,13,1}, {28,25,29}, {30,31,32}, {28,33,34}, {35,36,7}, {37,38,39}, {40,10,41}, {42,43,44}, {45,5,4}, {46,47,48}, {46,48,49}, {45,4,50}, {51,52,53}, {51,54,55}, {56,52,57}, {58,59,60}, {61,50,4}, {62,63,64}, {65,34,33}, {66,67,42}, {68,17,69}, {70,71,22}, {66,42,72}, {73,16,15}, {35,7,74}, {75,76,54}, {77,27,1}, {78,32,31}, {75,54,79}, {80,26,25}, {81,80,25}, {82,83,48}, {84,20,85}, {81,25,86}, {87,88,19}, {0,89,1}, {90,91,92}, {90,10,93}, {38,94,39}, {94,95,39}, {3,7,96}, {97,15,98}, {97,99,15}, {92,91,100}, {89,101,1}, {102,39,95}, {103,11,10}, {104,96,7}, {105,15,99}, {106,61,4}, {107,108,33}, {76,55,54}, {109,91,110}, {111,23,19}, {112,63,113}, {114,115,48}, {116,59,117}, {118,20,119}, {120,31,121}, {122,44,43}, {110,91,123}, {124,125,126}, {127,128,129}, {127,130,124}, {131,124,132}, {126,133,134}, {135,136,126}, {137,138,127}, {139,127,138}, {128,140,141}, {142,128,143}, {144,140,145}, {100,91,146}, {147,148,134}, {101,149,1}, {102,150,39}, {103,10,151}, {145,140,152}, {152,140,153}, {148,154,134}, {154,155,134}, {156,15,105}, {157,104,7}, {36,8,7}, {158,37,39}, {159,19,88}, {160,19,159}, {161,59,58}, {161,117,59}, {162,31,30}, {162,121,31}, {163,43,164}, {163,165,43}, {166,167,43}, {167,164,43}, {168,57,52}, {82,48,169}, {114,170,171}, {108,65,33}, {64,63,112}, {114,172,170}, {160,173,170}, {171,170,173}, {172,174,170}, {160,170,174}, {175,176,177}, {178,77,1}, {179,31,120}, {175,180,176}, {181,182,176}, {177,176,182}, {180,183,176}, {181,176,183}, {184,42,67}, {185,69,17}, {160,111,19}, {186,187,160}, {188,189,114}, {190,188,114}, {114,48,191}, {192,114,193}, {194,160,195}, {196,160,194}, {197,198,181}, {199,197,181}, {122,43,165}, {200,201,175}, {202,175,203}, {204,175,202}, {205,119,20}, {206,181,207}, {208,209,15}, {210,15,209}, {211,10,9}, {212,10,211}, {213,214,215}, {216,217,218}, {219,14,17}, {113,63,220}, {221,222,48}, {191,48,222}, {22,223,20}, {205,20,223}, {224,40,42}, {123,91,225}, {214,226,215}, {227,215,226}, {218,217,228}, {229,228,217}, {215,230,213}, {125,135,126}, {217,216,231}, {129,128,142}, {216,213,232}, {130,132,124}, {213,216,233}, {234,213,235}, {236,227,237}, {238,237,227}, {239,240,216}, {233,216,240}, {241,242,229}, {243,229,242}, {215,227,244}, {245,215,246}, {217,247,229}, {248,249,217}, {232,213,250}, {230,250,213}, {133,147,134}, {244,227,251}, {236,252,227}, {251,227,252}, {231,216,253}, {254,253,216}, {141,140,144}, {247,255,229}, {241,229,256}, {255,256,229}, {257,241,258}, {259,146,91}, {260,261,236}, {262,1,149}, {263,264,241}, {265,241,264}, {266,236,267}, {268,267,236}, {49,48,83}, {166,43,269}, {270,271,272}, {273,274,275}, {276,274,277}, {278,151,10}, {279,280,272}, {281,39,150}, {272,282,279}, {155,283,134}, {274,276,284}, {153,140,285}, {286,276,287}, {265,276,286}, {288,289,279}, {268,288,279}, {290,291,272}, {271,290,272}, {292,274,293}, {275,274,292}, {294,265,295}, {276,265,294}, {296,297,268}, {279,296,268}, {241,265,298}, {298,265,299}, {236,300,268}, {300,301,268}, {107,33,78}, {302,303,59}, {304,305,279}, {282,304,279}, {306,276,307}, {284,276,306}, {185,17,73}, {308,309,221}, {158,39,70}, {310,41,10}, {15,311,208}, {7,6,312}, {313,314,6}, {315,6,314}, {316,208,317}, {318,317,208}, {258,241,319}, {319,241,320}, {261,321,236}, {321,322,236}, {6,315,323}, {208,324,318}, {270,325,318}, {326,318,325}, {327,328,315}, {273,315,328}, {118,329,20}, {330,20,329}, {331,332,25}, {86,25,332}, {333,334,52}, {335,52,334}, {115,336,48}, {169,48,336}, {62,106,4}, {35,15,210}, {35,337,15}, {158,10,212}, {158,310,10}, {338,178,1}, {339,59,116}, {107,302,59}, {66,22,340}, {66,341,22}, {185,221,342}, {185,308,221}, {75,31,179}, {75,343,31}, {166,20,330}, {166,85,20}, {81,52,335}, {81,168,52}, {82,19,344}, {82,87,19}, {108,339,345}, {346,108,345}, {64,347,348}, {349,347,64}, {178,109,350}, {351,178,350}, {179,352,353}, {354,352,179}, {355,208,356}, {356,208,311}, {357,358,6}, {358,312,6}, {68,22,21}, {68,340,22}, {221,48,47}, {184,342,221}, {359,270,360}, {318,360,270}, {361,362,273}, {315,273,362}, {272,102,270}, {363,270,102}, {274,273,103}, {364,103,273}, {21,19,18}, {21,20,84}, {184,46,42}, {43,42,46}, {12,22,71}, {365,22,12}, {14,98,15}, {14,220,63}, {40,93,10}, {40,225,91}, {45,221,309}, {366,221,45}, {313,367,212}, {212,367,368}, {36,369,367}, {313,36,367}, {316,37,367}, {37,368,367}, {210,367,369}, {316,367,210}, {362,370,315}, {370,323,315}, {360,318,371}, {371,318,324}, {372,331,159}, {159,195,160}, {373,115,56}, {115,114,189}, {52,56,161}, {374,161,56}, {25,28,331}, {375,331,28}, {376,333,163}, {163,203,175}, {377,118,24}, {118,181,198}, {25,24,162}, {378,162,24}, {52,51,333}, {379,333,51}, {167,380,381}, {376,167,381}, {377,381,330}, {330,381,380}, {335,381,382}, {376,381,335}, {373,383,169}, {169,383,384}, {168,385,383}, {373,168,383}, {372,87,383}, {87,384,383}, {377,80,381}, {80,382,381}, {86,383,385}, {372,383,86}, {106,348,347}, {386,106,347}, {375,65,346}, {108,346,65}, {64,112,349}, {387,349,112}, {171,190,114}, {346,345,171}, {374,190,345}, {171,345,190}, {349,172,347}, {172,114,192}, {386,347,192}, {172,192,347}, {173,160,196}, {171,173,346}, {375,346,196}, {173,196,346}, {172,349,174}, {174,186,160}, {387,186,349}, {174,349,186}, {64,348,62}, {106,62,348}, {108,107,339}, {59,339,107}, {374,345,116}, {339,116,345}, {76,353,352}, {379,76,352}, {388,77,351}, {178,351,77}, {179,120,354}, {378,354,120}, {177,200,175}, {351,350,177}, {389,200,350}, {177,350,200}, {354,180,352}, {180,175,204}, {379,352,204}, {180,204,352}, {182,181,206}, {177,182,351}, {388,351,206}, {182,206,351}, {180,354,183}, {183,199,181}, {378,199,354}, {183,354,199}, {91,109,338}, {178,338,109}, {76,75,353}, {179,353,75}, {389,350,110}, {109,110,350}, {390,391,392}, {393,394,395}, {224,122,389}, {122,175,201}, {365,388,205}, {205,207,181}, {66,340,396}, {68,396,340}, {184,396,342}, {185,342,396}, {66,396,67}, {184,67,396}, {68,69,396}, {185,396,69}, {219,111,387}, {111,160,187}, {366,386,191}, {191,193,114}, {150,272,280}, {102,272,150}, {151,277,274}, {103,151,274}, {161,374,117}, {116,117,374}, {366,61,386}, {106,386,61}, {111,187,387}, {186,387,187}, {56,188,374}, {190,374,188}, {191,386,193}, {192,193,386}, {331,375,194}, {196,194,375}, {28,34,375}, {65,375,34}, {219,387,113}, {112,113,387}, {224,389,123}, {110,123,389}, {51,55,379}, {76,379,55}, {24,197,378}, {199,378,197}, {122,201,389}, {200,389,201}, {333,379,202}, {204,202,379}, {205,388,207}, {206,207,388}, {365,27,388}, {77,388,27}, {162,378,121}, {120,121,378}, {162,30,25}, {30,29,25}, {51,53,54}, {303,60,59}, {28,29,33}, {29,397,33}, {161,58,52}, {53,52,58}, {21,84,19}, {84,344,19}, {46,49,43}, {49,269,43}, {208,316,209}, {210,209,316}, {327,313,211}, {212,211,313}, {36,35,369}, {210,369,35}, {37,158,368}, {212,368,158}, {6,8,313}, {36,313,8}, {326,38,316}, {37,316,38}, {392,391,398}, {399,398,391}, {394,400,395}, {401,395,400}, {390,214,391}, {214,213,234}, {393,395,218}, {218,239,216}, {402,230,403}, {230,215,245}, {125,124,131}, {404,125,403}, {405,406,231}, {231,248,217}, {129,137,127}, {407,406,129}, {130,127,139}, {402,130,408}, {194,195,331}, {159,331,195}, {115,189,56}, {188,56,189}, {14,219,220}, {113,220,219}, {45,50,366}, {61,366,50}, {221,366,222}, {191,222,366}, {17,23,219}, {111,219,23}, {118,198,24}, {197,24,198}, {202,203,333}, {163,333,203}, {40,224,225}, {123,225,224}, {12,13,365}, {27,365,13}, {22,365,223}, {205,223,365}, {42,44,224}, {122,224,44}, {399,391,234}, {214,234,391}, {401,239,395}, {218,395,239}, {214,390,226}, {226,238,227}, {218,228,393}, {228,229,243}, {401,399,233}, {233,235,213}, {392,409,390}, {410,390,409}, {394,393,411}, {412,411,393}, {402,403,131}, {125,131,403}, {405,137,406}, {129,406,137}, {405,408,139}, {130,139,408}, {230,245,403}, {404,403,245}, {231,406,248}, {407,248,406}, {232,254,216}, {402,408,232}, {413,404,244}, {244,246,215}, {414,247,407}, {247,217,249}, {133,126,136}, {415,133,413}, {141,143,128}, {416,414,141}, {410,238,390}, {226,390,238}, {412,393,243}, {228,243,393}, {233,399,235}, {234,235,399}, {237,260,236}, {238,410,237}, {417,260,410}, {237,410,260}, {239,401,240}, {233,240,401}, {242,241,257}, {243,242,412}, {418,412,257}, {242,257,412}, {401,419,399}, {398,399,419}, {417,410,420}, {409,420,410}, {400,421,401}, {419,401,421}, {418,422,412}, {411,412,422}, {413,135,404}, {125,404,135}, {414,407,142}, {129,142,407}, {130,402,132}, {131,132,402}, {133,136,413}, {135,413,136}, {423,147,415}, {133,415,147}, {137,405,138}, {139,138,405}, {141,414,143}, {142,143,414}, {424,416,144}, {141,144,416}, {405,254,408}, {232,408,254}, {244,404,246}, {245,246,404}, {247,249,407}, {248,407,249}, {232,250,402}, {230,402,250}, {415,413,251}, {244,251,413}, {252,236,266}, {251,252,415}, {423,415,266}, {252,266,415}, {231,253,405}, {254,405,253}, {416,255,414}, {247,414,255}, {256,263,241}, {255,416,256}, {424,263,416}, {256,416,263}, {257,258,418}, {425,418,258}, {260,417,261}, {426,261,417}, {422,418,427}, {427,259,91}, {420,428,417}, {428,1,262}, {147,423,148}, {429,148,423}, {263,424,264}, {264,295,265}, {266,267,423}, {267,268,297}, {144,145,424}, {430,424,145}, {49,431,269}, {166,269,431}, {82,431,83}, {49,83,431}, {84,85,431}, {166,431,85}, {82,344,431}, {84,431,344}, {432,278,90}, {10,90,278}, {433,0,281}, {39,281,0}, {362,361,434}, {435,271,359}, {270,359,271}, {436,361,275}, {273,275,361}, {360,437,359}, {277,287,276}, {151,278,277}, {280,279,289}, {150,280,281}, {436,438,439}, {439,285,140}, {90,92,432}, {440,432,92}, {282,272,291}, {441,282,442}, {284,293,274}, {443,438,284}, {278,432,286}, {286,299,265}, {281,288,433}, {288,268,301}, {0,433,89}, {444,89,433}, {435,445,442}, {445,134,283}, {439,446,436}, {361,436,446}, {442,290,435}, {271,435,290}, {438,436,292}, {275,292,436}, {445,435,447}, {359,447,435}, {286,287,278}, {277,278,287}, {288,281,289}, {280,289,281}, {145,152,430}, {443,430,152}, {148,429,154}, {441,154,429}, {424,430,294}, {294,307,276}, {423,296,429}, {296,279,305}, {425,440,100}, {92,100,440}, {290,442,291}, {282,291,442}, {292,293,438}, {284,438,293}, {298,320,241}, {432,440,298}, {300,236,322}, {433,300,444}, {426,101,444}, {89,444,101}, {107,448,302}, {302,79,54}, {78,31,343}, {107,78,448}, {75,79,448}, {302,448,79}, {78,343,448}, {75,448,343}, {427,418,259}, {425,259,418}, {428,262,417}, {426,417,262}, {437,449,359}, {447,359,449}, {434,361,450}, {446,450,361}, {32,33,397}, {78,33,32}, {53,303,54}, {302,54,303}, {152,153,443}, {438,443,153}, {429,304,441}, {282,441,304}, {430,443,306}, {284,306,443}, {154,441,155}, {442,155,441}, {298,299,432}, {286,432,299}, {300,433,301}, {288,301,433}, {185,451,308}, {308,74,7}, {73,15,337}, {185,73,451}, {35,74,451}, {308,451,74}, {73,337,451}, {35,451,337}, {158,452,310}, {310,72,42}, {70,22,341}, {158,70,452}, {66,72,452}, {310,452,72}, {70,341,452}, {66,452,341}, {313,327,314}, {315,314,327}, {316,317,326}, {318,326,317}, {15,156,311}, {356,311,156}, {7,312,157}, {358,157,312}, {211,9,327}, {364,327,9}, {38,326,94}, {363,94,326}, {294,295,424}, {264,424,295}, {296,423,297}, {267,297,423}, {262,149,426}, {101,426,149}, {258,319,425}, {440,425,319}, {261,426,321}, {444,321,426}, {259,425,146}, {100,146,425}, {306,307,430}, {294,430,307}, {304,429,305}, {296,305,429}, {319,320,440}, {298,440,320}, {321,444,322}, {300,322,444}, {445,283,442}, {155,442,283}, {439,438,285}, {153,285,438}, {17,68,18}, {21,18,68}, {46,184,47}, {221,47,184}, {102,95,363}, {94,363,95}, {9,11,364}, {103,364,11}, {6,323,357}, {370,357,323}, {371,324,355}, {208,355,324}, {270,363,325}, {326,325,363}, {327,364,328}, {273,328,364}, {0,2,39}, {12,39,2}, {90,93,91}, {40,91,93}, {14,16,17}, {73,17,16}, {45,309,7}, {308,7,309}, {12,71,39}, {70,39,71}, {40,41,42}, {310,42,41}, {97,98,63}, {14,63,98}, {3,5,7}, {45,7,5}, {118,377,329}, {330,329,377}, {331,372,332}, {86,332,372}, {333,376,334}, {335,334,376}, {115,373,336}, {169,336,373}, {167,166,380}, {330,380,166}, {80,81,382}, {335,382,81}, {86,385,81}, {168,81,385}, {169,384,82}, {87,82,384}, {159,88,372}, {87,372,88}, {163,164,376}, {167,376,164}, {24,26,377}, {80,377,26}, {56,57,373}, {168,373,57}, {32,397,30}, {29,30,397}, {58,60,53}, {303,53,60}, {205,181,119}, {118,119,181}, {163,175,165}, {122,165,175}, {453,454,455}, {454,456,455}, {457,455,456}, {458,455,457}, {459,455,458}, {460,455,459}, {461,462,463}, {464,465,466}, {467,468,469}, {470,471,472}, {465,473,474}, {475,476,477}, {478,479,480}, {481,482,478}, {483,484,481}, {485,486,483}, {487,488,485}, {489,490,487}, {491,492,489}, {493,494,491}, {495,496,493}, {497,498,495}, {499,500,497}, {501,502,499}, {503,504,501}, {505,504,503}, {506,504,505}, {507,504,506}, {508,504,507}, {509,504,508}, {510,504,509}, {511,504,510}, {512,504,511}, {513,504,512}, {514,504,513}, {476,515,516}, {517,518,519}, {520,517,521}, {518,522,523}, {522,480,479}, {524,525,526}, {468,470,527}, {525,467,528}, {529,475,530}, {531,532,533}, {534,531,535}, {536,537,538}, {473,539,540}, {539,536,541}, {537,534,542}, {471,520,543}, {532,529,544}, {545,524,546}, {453,461,547}, {463,464,548}, {523,549,504}, {527,550,551}, {519,552,553}, {521,554,555}, {466,556,557}, {469,558,559}, {528,560,561}, {477,562,563}, {543,564,565}, {535,566,567}, {530,568,569}, {540,570,571}, {474,572,573}, {542,574,575}, {538,576,577}, {541,578,579}, {472,580,581}, {526,582,583}, {533,584,585}, {544,586,587}, {516,545,588}, {588,589,590}, {455,460,4}, {591,592,63}, {462,455,4}, {592,547,63}, {547,548,63}, {465,462,4}, {548,557,63}, {127,124,501}, {127,501,499}, {505,503,124}, {124,126,507}, {124,507,506}, {509,508,126}, {126,134,512}, {126,512,511}, {510,509,126}, {128,127,493}, {128,493,491}, {497,495,127}, {489,487,128}, {140,128,483}, {140,483,481}, {487,485,128}, {478,480,140}, {480,522,140}, {514,513,134}, {504,514,134}, {551,581,437}, {471,470,434}, {445,447,555}, {445,555,553}, {134,445,553}, {134,553,504}, {446,439,518}, {446,518,517}, {439,140,522}, {439,522,518}, {515,476,358}, {563,588,356}, {557,573,63}, {473,465,4}, {437,360,559}, {437,559,551}, {360,371,561}, {360,561,559}, {362,434,470}, {362,470,468}, {370,362,468}, {370,468,467}, {499,497,127}, {506,505,124}, {495,493,127}, {513,512,134}, {481,478,140}, {447,449,565}, {447,565,555}, {450,446,517}, {450,517,520}, {356,156,569}, {356,569,563}, {157,358,476}, {157,476,475}, {357,370,467}, {357,467,525}, {371,355,583}, {371,583,561}, {460,459,4}, {63,62,593}, {63,593,591}, {62,4,459}, {62,459,458}, {532,531,104}, {531,534,104}, {567,585,105}, {575,567,105}, {4,3,539}, {4,539,473}, {536,539,3}, {97,63,573}, {97,573,571}, {571,579,97}, {99,97,579}, {99,579,577}, {105,99,577}, {105,577,575}, {96,104,534}, {96,534,537}, {3,96,537}, {3,537,536}, {503,501,124}, {508,507,126}, {491,489,128}, {511,510,126}, {485,483,128}, {434,450,520}, {434,520,471}, {449,437,581}, {449,581,565}, {156,105,585}, {156,585,587}, {587,569,156}, {104,157,529}, {104,529,532}, {475,529,157}, {590,583,355}, {355,356,588}, {355,588,590}, {358,357,524}, {358,524,515}, {525,524,357}, {458,457,62}, {457,593,62}, {479,478,482}, {479,504,549}, {479,482,504}, {482,481,484}, {472,551,550}, {581,551,472}, {482,484,504}, {484,483,486}, {523,553,552}, {504,553,523}, {540,573,572}, {571,573,540}, {544,585,584}, {587,585,544}, {542,577,576}, {575,577,542}, {526,590,589}, {583,590,526}, {535,575,574}, {567,575,535}, {533,567,566}, {585,567,533}, {538,579,578}, {577,579,538}, {543,581,580}, {565,581,543}, {477,569,568}, {563,569,477}, {530,587,586}, {569,587,530}, {541,571,570}, {579,571,541}, {528,583,582}, {561,583,528}, {591,453,592}, {547,592,453}, {521,565,564}, {555,565,521}, {474,557,556}, {573,557,474}, {516,563,562}, {588,563,516}, {519,555,554}, {553,555,519}, {527,559,558}, {551,559,527}, {469,561,560}, {559,561,469}, {462,461,455}, {453,455,461}, {461,463,547}, {548,547,463}, {465,464,462}, {463,462,464}, {464,466,548}, {557,548,466}, {469,560,467}, {528,467,560}, {472,550,470}, {527,470,550}, {474,556,465}, {466,465,556}, {477,568,475}, {530,475,568}, {516,562,476}, {477,476,562}, {519,554,517}, {521,517,554}, {521,564,520}, {543,520,564}, {523,552,518}, {519,518,552}, {479,549,522}, {523,522,549}, {526,589,524}, {589,546,524}, {527,558,468}, {469,468,558}, {528,582,525}, {526,525,582}, {530,586,529}, {544,529,586}, {533,566,531}, {535,531,566}, {535,574,534}, {542,534,574}, {538,578,536}, {541,536,578}, {540,572,473}, {474,473,572}, {541,570,539}, {540,539,570}, {542,576,537}, {538,537,576}, {543,580,471}, {472,471,580}, {544,584,532}, {533,532,584}, {524,545,515}, {516,515,545}, {545,546,588}, {589,588,546}, {453,591,454}, {593,454,591}, {484,486,504}, {486,485,488}, {486,488,504}, {488,487,490}, {488,490,504}, {490,489,492}, {490,492,504}, {492,491,494}, {492,494,504}, {494,493,496}, {494,496,504}, {496,495,498}, {496,498,504}, {498,497,500}, {498,500,504}, {500,499,502}, {500,502,504}, {501,504,502}, {454,593,456}, {457,456,593}, {594,595,596}, {597,598,594}, {599,597,594}, {600,599,594}, {601,600,594}, {602,601,594}, {603,602,594}, {604,603,594}, {605,604,594}, {606,607,608}, {609,606,608}, {610,609,608}, {611,610,608}, {612,611,608}, {613,612,608}, {614,613,608}, {615,614,608}, {616,615,608}, {617,616,608}, {618,617,608}, {619,618,608}, {620,619,608}, {596,608,607}, {595,594,598}, {608,596,595}, {605,594,91}, {91,338,602}, {91,602,603}, {598,597,1}, {594,596,91}, {608,595,1}, {595,598,1}, {616,617,392}, {610,611,394}, {419,421,613}, {419,613,614}, {422,427,607}, {422,607,606}, {427,91,596}, {427,596,607}, {428,420,619}, {428,619,620}, {1,428,620}, {1,620,608}, {420,409,618}, {420,618,619}, {411,422,606}, {411,606,609}, {398,419,614}, {398,614,615}, {421,400,612}, {421,612,613}, {409,392,617}, {409,617,618}, {394,411,609}, {394,609,610}, {604,605,91}, {338,1,599}, {338,599,600}, {392,398,615}, {392,615,616}, {400,394,611}, {400,611,612}, {603,604,91}, {601,602,338}, {597,599,1}, {600,601,338} }); break; case TestMesh::gt2_teeth: mesh = TriangleMesh( - { Vec3d(15.8899993896484,19.444055557251,2.67489433288574), Vec3d(15.9129991531372,19.1590557098389,2.67489433288574), Vec3d(15.9039993286133,19.1500549316406,2.67489433288574), Vec3d(15.9489994049072,19.2490558624268,2.67489433288574), Vec3d(15.9579992294312,19.3570556640625,2.67489433288574), Vec3d(15.8819999694824,18.690055847168,2.67489433288574), Vec3d(15.8319997787476,17.7460556030273,2.67489433288574), Vec3d(15.8489999771118,18.819055557251,2.67489433288574), Vec3d(15.8589992523193,17.7190551757812,2.67489433288574), Vec3d(15.8769998550415,19.0490550994873,2.67489433288574), Vec3d(15.7529993057251,17.8080558776855,2.67489433288574), Vec3d(15.7869997024536,19.5010547637939,2.67489433288574), Vec3d(14.0329990386963,18.7170543670654,2.67489433288574), Vec3d(13.9599990844727,18.7460556030273,2.67489433288574), Vec3d(13.9869995117188,20.2840557098389,2.67489433288574), Vec3d(14.2029991149902,20.149055480957,2.67489433288574), Vec3d(14.1939992904663,19.9560546875,2.67489433288574), Vec3d(14.1939992904663,20.1670551300049,2.67489433288574), Vec3d(14.2119998931885,20.0590553283691,2.67489433288574), Vec3d(12.1899995803833,19.1840553283691,2.67489433288574), Vec3d(12.096999168396,19.1950550079346,2.67489433288574), Vec3d(12.1099996566772,20.6690559387207,2.67489433288574), Vec3d(11.382999420166,19.9750556945801,2.67489433288574), Vec3d(11.2599992752075,19.2490558624268,2.67489433288574), Vec3d(11.2369995117188,19.9320545196533,2.67489433288574), Vec3d(11.5349998474121,20.0640544891357,2.67489433288574), Vec3d(11.6259994506836,20.1550559997559,2.67489433288574), Vec3d(11.6829986572266,20.2390556335449,2.67489433288574), Vec3d(11.7369995117188,20.3570556640625,2.67489433288574), Vec3d(11.8449993133545,20.645055770874,2.67489433288574), Vec3d(11.7729988098145,20.4640560150146,2.67489433288574), Vec3d(11.7799987792969,20.5370559692383,9.41389465332031), Vec3d(11.7639999389648,20.4470558166504,2.67489433288574), Vec3d(11.9559993743896,20.6810550689697,2.67489433288574), Vec3d(12.3079996109009,20.6020545959473,2.67489433288574), Vec3d(12.1959991455078,19.1860542297363,2.67489433288574), Vec3d(12.2059993743896,20.6540546417236,2.67489433288574), Vec3d(12.3489990234375,20.3740558624268,2.67489433288574), Vec3d(12.3579998016357,20.2750549316406,2.67489433288574), Vec3d(12.3669996261597,20.266056060791,2.67489433288574), Vec3d(12.3849992752075,20.1670551300049,2.67489433288574), Vec3d(12.4269990921021,20.0680541992188,2.67489433288574), Vec3d(12.5029993057251,19.9540557861328,2.67489433288574), Vec3d(12.6169996261597,19.8550548553467,2.67489433288574), Vec3d(12.7449989318848,19.7800559997559,2.67489433288574), Vec3d(12.7629995346069,19.7800559997559,2.67489433288574), Vec3d(12.8799991607666,19.7350559234619,2.67489433288574), Vec3d(13.0369997024536,19.7250556945801,2.67489433288574), Vec3d(13.0149993896484,19.0340557098389,2.67489433288574), Vec3d(11.1699991226196,19.2580547332764,2.67489433288574), Vec3d(11.0959987640381,19.2580547332764,2.67489433288574), Vec3d(11.1209993362427,19.9230556488037,2.67489433288574), Vec3d(13.0599994659424,19.024055480957,2.67489433288574), Vec3d(14.9049997329712,18.3170547485352,2.67489433288574), Vec3d(14.8779993057251,18.3400554656982,2.67489433288574), Vec3d(14.8779993057251,19.149055480957,2.67489433288574), Vec3d(13.3039989471436,19.77805519104,2.67489433288574), Vec3d(13.1589994430542,18.9890556335449,2.67489433288574), Vec3d(13.1559991836548,19.7350559234619,2.67489433288574), Vec3d(13.4269990921021,19.8600559234619,2.67489433288574), Vec3d(13.5339994430542,19.9700546264648,2.67389440536499), Vec3d(13.6359996795654,20.1220550537109,2.67489433288574), Vec3d(13.6359996795654,20.1400547027588,2.67489433288574), Vec3d(13.6719989776611,20.2210559844971,2.67489433288574), Vec3d(13.6899995803833,20.2300548553467,2.67489433288574), Vec3d(13.7509994506836,20.3010559082031,2.67489433288574), Vec3d(13.8539991378784,20.3180541992188,2.67489433288574), Vec3d(14.8329992294312,18.3580551147461,2.67489433288574), Vec3d(14.1849994659424,19.8530559539795,2.67489433288574), Vec3d(14.0769996643066,18.7000541687012,2.67489433288574), Vec3d(14.1099996566772,20.2400550842285,2.67489433288574), Vec3d(14.2009992599487,19.6230545043945,2.67489433288574), Vec3d(14.2729997634888,19.4670543670654,2.67489433288574), Vec3d(14.3379993438721,19.3790550231934,2.67489433288574), Vec3d(14.4549999237061,19.2770557403564,2.67489433288574), Vec3d(14.5899991989136,19.2040557861328,2.67489433288574), Vec3d(14.6079998016357,19.2040557861328,2.67489433288574), Vec3d(14.7209997177124,19.1600551605225,2.67489433288574), Vec3d(15.1379995346069,19.210054397583,2.67489433288574), Vec3d(14.9949998855591,18.2680549621582,2.67489433288574), Vec3d(15.0029993057251,19.1580543518066,2.67489433288574), Vec3d(15.2369995117188,19.2760543823242,2.67489433288574), Vec3d(15.3779993057251,19.4060554504395,2.67489433288574), Vec3d(15.4539995193481,19.520055770874,2.67489433288574), Vec3d(15.471999168396,19.52805519104,2.67489433288574), Vec3d(15.5449991226196,19.5830554962158,2.67489433288574), Vec3d(15.6529998779297,19.573055267334,2.67489433288574), Vec3d(15.7059993743896,17.8360557556152,2.67489433288574), Vec3d(15.9449996948242,18.5560550689697,2.67489433288574), Vec3d(15.8589992523193,18.9380550384521,2.67489433288574), Vec3d(14.9589996337891,18.2950553894043,2.67489433288574), Vec3d(15.7779998779297,19.5100555419922,2.67489433288574), Vec3d(14.0049991607666,20.2750549316406,2.67489433288574), Vec3d(12.3489990234375,20.5000553131104,2.67489433288574), Vec3d(13.0689992904663,19.0150547027588,2.67489433288574), Vec3d(13.0999994277954,19.0100555419922,2.67489433288574), Vec3d(15.9489994049072,19.3670558929443,9.41489505767822), Vec3d(15.9489994049072,19.2490558624268,9.41489505767822), Vec3d(15.75,17.8080558776855,9.41489505767822), Vec3d(15.6639995574951,19.5710544586182,9.41489505767822), Vec3d(15.5709991455078,17.9260559082031,9.41489505767822), Vec3d(15.8769998550415,18.690055847168,9.41489505767822), Vec3d(15.8499994277954,18.8170547485352,9.41489505767822), Vec3d(15.9459991455078,18.5520553588867,9.41489505767822), Vec3d(15.914999961853,17.6890544891357,9.41489505767822), Vec3d(15.3999996185303,19.4290542602539,9.41489505767822), Vec3d(15.3099994659424,19.339054107666,9.41489505767822), Vec3d(15.3729991912842,18.0440559387207,9.41489505767822), Vec3d(15.4579992294312,19.5170555114746,9.41489505767822), Vec3d(15.5469999313354,19.5820541381836,9.41489505767822), Vec3d(13.2309989929199,19.7610549926758,9.41489505767822), Vec3d(13.168999671936,19.7360553741455,9.41489505767822), Vec3d(13.096999168396,19.0140552520752,9.41489505767822), Vec3d(13.1999988555908,18.9870548248291,9.41489505767822), Vec3d(15.1399993896484,19.2080554962158,9.41489505767822), Vec3d(15.0159997940063,19.1600551605225,9.41489505767822), Vec3d(14.9859991073608,18.2770557403564,9.41489505767822), Vec3d(15.1749992370605,18.1690559387207,9.41489505767822), Vec3d(15.9039993286133,19.1320552825928,9.41489505767822), Vec3d(15.8949995040894,19.4460544586182,9.41489505767822), Vec3d(15.8769998550415,19.0420551300049,9.41489505767822), Vec3d(12.2169990539551,20.6500549316406,9.41489505767822), Vec3d(11.9379997253418,20.6810550689697,9.41489505767822), Vec3d(11.8629989624023,19.2130546569824,9.41489505767822), Vec3d(12.096999168396,19.1950550079346,9.41489505767822), Vec3d(14.1669998168945,18.6640548706055,9.41489505767822), Vec3d(14.1039991378784,20.2460556030273,9.41489505767822), Vec3d(13.9849996566772,18.7360553741455,9.41489505767822), Vec3d(14.7349996566772,19.1590557098389,9.41489505767822), Vec3d(14.5849990844727,19.2050552368164,9.41489505767822), Vec3d(14.5719995498657,18.4850559234619,9.41489505767822), Vec3d(14.1939992904663,19.6760559082031,9.41489505767822), Vec3d(14.1849994659424,19.9330558776855,9.41489505767822), Vec3d(14.1759996414185,18.6640548706055,9.41489505767822), Vec3d(14.261999130249,19.4890556335449,9.41489505767822), Vec3d(14.3539991378784,19.3610553741455,9.41489505767822), Vec3d(14.3559989929199,18.5830554962158,9.41489505767822), Vec3d(11.6039991378784,20.1250553131104,9.41489505767822), Vec3d(11.5209999084473,20.0520553588867,9.41489505767822), Vec3d(11.4209995269775,19.2480545043945,9.41489505767822), Vec3d(11.6989994049072,20.2690544128418,9.41389465332031), Vec3d(11.7609996795654,20.4310550689697,9.41489505767822), Vec3d(11.8359994888306,19.2130546569824,9.41489505767822), Vec3d(14.1889991760254,20.1710548400879,9.41489505767822), Vec3d(13.9689998626709,20.2840557098389,9.41489505767822), Vec3d(13.8739995956421,20.315055847168,9.41489505767822), Vec3d(13.7799997329712,18.8080558776855,9.41489505767822), Vec3d(13.9869995117188,20.2750549316406,9.41489505767822), Vec3d(12.3129997253418,20.5980548858643,9.41489505767822), Vec3d(12.3399991989136,20.5090560913086,9.41489505767822), Vec3d(12.3489990234375,20.3830547332764,9.41489505767822), Vec3d(12.3599996566772,20.2680549621582,9.41489505767822), Vec3d(12.3849992752075,20.1850547790527,9.41489505767822), Vec3d(12.3849992752075,20.1670551300049,9.41489505767822), Vec3d(12.4249992370605,20.065055847168,9.41489505767822), Vec3d(12.4729995727539,19.1350555419922,9.41489505767822), Vec3d(14.4399995803833,19.2900543212891,9.41489505767822), Vec3d(14.3649997711182,18.5740547180176,9.41489505767822), Vec3d(13.5729999542236,20.0310554504395,9.41489505767822), Vec3d(13.4889993667603,19.9140548706055,9.41489505767822), Vec3d(13.5639991760254,18.8710556030273,9.41489505767822), Vec3d(13.6389999389648,20.1310558319092,9.41489505767822), Vec3d(13.6719989776611,20.2130546569824,9.41489505767822), Vec3d(13.75,20.3020553588867,9.41489505767822), Vec3d(12.7399997711182,19.7810554504395,9.41489505767822), Vec3d(12.6189994812012,19.8520545959473,9.41489505767822), Vec3d(12.5799999237061,19.1200542449951,9.41489505767822), Vec3d(12.8349990844727,19.069055557251,9.41489505767822), Vec3d(11.2669992446899,19.9350547790527,9.41489505767822), Vec3d(11.1029987335205,19.9230556488037,9.41489505767822), Vec3d(11.0209999084473,19.2600555419922,9.41489505767822), Vec3d(11.3819999694824,19.9710559844971,9.41489505767822), Vec3d(13.418999671936,19.8530559539795,9.41489505767822), Vec3d(13.4329996109009,18.9160556793213,9.41489505767822), Vec3d(11.8399991989136,20.6430549621582,9.41489505767822), Vec3d(13.3119993209839,19.7800559997559,9.41489505767822), Vec3d(15.2189998626709,19.2600555419922,9.41489505767822), Vec3d(15.1839990615845,18.1600551605225,9.41489505767822), Vec3d(15.3639993667603,18.0520553588867,9.41489505767822), Vec3d(13.0189990997314,19.7250556945801,9.41489505767822), Vec3d(12.8949995040894,19.7350559234619,9.41489505767822), Vec3d(15.9039993286133,19.1500549316406,9.41489505767822), Vec3d(15.7699995040894,19.5140552520752,9.41489505767822), Vec3d(15.8589992523193,18.9340553283691,9.41489505767822), Vec3d(14.1939992904663,19.9510555267334,9.41489505767822), Vec3d(14.2119998931885,20.0630550384521,9.41489505767822), Vec3d(14.8589992523193,19.149055480957,9.41489505767822), Vec3d(14.8159999847412,18.3670558929443,9.41489505767822), Vec3d(14.8959999084473,18.3220558166504,9.41489505767822), Vec3d(12.5189990997314,19.9360542297363,9.41489505767822), Vec3d(11.0209999084473,19.9290542602539,9.41489505767822), Vec3d(11.0209999084473,19.2530555725098,2.67489433288574), Vec3d(11.0209999084473,19.9300556182861,2.67489433288574), Vec3d(15.9799995422363,18.505931854248,5.58724021911621), Vec3d(15.9799995422363,18.5044555664062,9.41489505767822), Vec3d(15.9799995422363,18.5041732788086,2.67489433288574), Vec3d(15.9799995422363,18.1684837341309,2.67489433288574), Vec3d(15.9799995422363,18.1288299560547,9.41489505767822), Vec3d(15.9799995422363,17.9876575469971,2.67489433288574), Vec3d(15.9799995422363,17.6247596740723,3.91620373725891), Vec3d(15.9799995422363,17.6247596740723,2.67489433288574), Vec3d(15.9799995422363,17.6254329681396,4.32245063781738), Vec3d(15.9799995422363,17.8920269012451,9.41489505767822), Vec3d(15.9799995422363,17.8795108795166,2.67489433288574), Vec3d(15.9799995422363,17.629810333252,4.58585262298584), Vec3d(15.9799995422363,17.6336059570312,5.27938556671143), Vec3d(15.9799995422363,17.8311748504639,2.67489433288574), Vec3d(15.9799995422363,17.638355255127,9.41489505767822), Vec3d(15.9799995422363,17.6346111297607,5.98653984069824), Vec3d(15.9799995422363,17.8728256225586,2.67489433288574), Vec3d(15.9799995422363,18.2221603393555,2.67489433288574) }, - { Vec3crd(0,1,2), Vec3crd(0,3,1), Vec3crd(0,4,3), Vec3crd(5,6,7), Vec3crd(8,6,5), Vec3crd(2,9,0), Vec3crd(6,10,11), Vec3crd(12,13,14), Vec3crd(15,16,17), Vec3crd(18,16,15), Vec3crd(19,20,21), Vec3crd(22,23,24), Vec3crd(25,23,22), Vec3crd(26,23,25), Vec3crd(27,23,26), Vec3crd(28,23,27), Vec3crd(29,30,31), Vec3crd(29,32,30), Vec3crd(29,28,32), Vec3crd(33,28,29), Vec3crd(33,23,28), Vec3crd(21,23,33), Vec3crd(20,23,21), Vec3crd(34,35,36), Vec3crd(37,35,34), Vec3crd(38,35,37), Vec3crd(39,35,38), Vec3crd(40,35,39), Vec3crd(41,35,40), Vec3crd(42,35,41), Vec3crd(43,35,42), Vec3crd(44,35,43), Vec3crd(45,35,44), Vec3crd(46,35,45), Vec3crd(47,35,46), Vec3crd(48,35,47), Vec3crd(49,50,51), Vec3crd(52,48,47), Vec3crd(23,49,24), Vec3crd(53,54,55), Vec3crd(56,57,58), Vec3crd(59,57,56), Vec3crd(60,57,59), Vec3crd(61,57,60), Vec3crd(62,57,61), Vec3crd(63,57,62), Vec3crd(64,57,63), Vec3crd(65,57,64), Vec3crd(66,57,65), Vec3crd(13,57,66), Vec3crd(54,67,55), Vec3crd(68,69,70), Vec3crd(71,69,68), Vec3crd(72,69,71), Vec3crd(73,69,72), Vec3crd(74,69,73), Vec3crd(75,69,74), Vec3crd(76,69,75), Vec3crd(77,69,76), Vec3crd(67,69,77), Vec3crd(70,16,68), Vec3crd(70,17,16), Vec3crd(78,79,80), Vec3crd(81,79,78), Vec3crd(82,79,81), Vec3crd(83,79,82), Vec3crd(84,79,83), Vec3crd(85,79,84), Vec3crd(86,79,85), Vec3crd(87,79,86), Vec3crd(88,8,5), Vec3crd(11,7,6), Vec3crd(11,89,7), Vec3crd(11,9,89), Vec3crd(11,0,9), Vec3crd(55,90,53), Vec3crd(55,79,90), Vec3crd(55,80,79), Vec3crd(91,11,10), Vec3crd(92,69,12), Vec3crd(92,70,69), Vec3crd(34,93,37), Vec3crd(47,94,52), Vec3crd(47,95,94), Vec3crd(47,57,95), Vec3crd(47,58,57), Vec3crd(51,24,49), Vec3crd(21,35,19), Vec3crd(21,36,35), Vec3crd(14,92,12), Vec3crd(86,10,87), Vec3crd(86,91,10), Vec3crd(77,55,67), Vec3crd(66,14,13), Vec3crd(96,97,4), Vec3crd(98,99,100), Vec3crd(101,102,98), Vec3crd(103,101,98), Vec3crd(104,103,98), Vec3crd(105,106,107), Vec3crd(108,105,107), Vec3crd(109,108,107), Vec3crd(100,109,107), Vec3crd(110,111,112), Vec3crd(113,110,112), Vec3crd(114,115,116), Vec3crd(117,114,116), Vec3crd(118,119,120), Vec3crd(121,122,123), Vec3crd(124,121,123), Vec3crd(125,126,127), Vec3crd(128,129,130), Vec3crd(131,132,133), Vec3crd(71,131,133), Vec3crd(134,71,133), Vec3crd(135,134,133), Vec3crd(136,135,133), Vec3crd(137,138,139), Vec3crd(140,137,139), Vec3crd(141,140,139), Vec3crd(142,31,141), Vec3crd(142,141,139), Vec3crd(143,126,132), Vec3crd(144,145,146), Vec3crd(147,144,146), Vec3crd(127,147,146), Vec3crd(148,121,124), Vec3crd(149,148,124), Vec3crd(150,149,124), Vec3crd(151,150,124), Vec3crd(152,151,124), Vec3crd(153,152,124), Vec3crd(154,153,124), Vec3crd(155,154,124), Vec3crd(129,156,157), Vec3crd(130,129,157), Vec3crd(158,159,160), Vec3crd(161,158,160), Vec3crd(162,161,160), Vec3crd(163,162,160), Vec3crd(146,163,160), Vec3crd(164,165,166), Vec3crd(167,164,166), Vec3crd(168,169,170), Vec3crd(171,168,170), Vec3crd(139,171,170), Vec3crd(159,172,173), Vec3crd(123,174,142), Vec3crd(175,110,113), Vec3crd(173,175,113), Vec3crd(106,176,177), Vec3crd(178,106,177), Vec3crd(179,180,167), Vec3crd(112,179,167), Vec3crd(175,173,172), Vec3crd(119,118,181), Vec3crd(119,181,97), Vec3crd(119,97,96), Vec3crd(182,98,102), Vec3crd(182,102,183), Vec3crd(182,183,120), Vec3crd(182,120,119), Vec3crd(143,132,184), Vec3crd(184,185,143), Vec3crd(147,127,126), Vec3crd(174,123,122), Vec3crd(159,173,160), Vec3crd(126,125,133), Vec3crd(126,133,132), Vec3crd(186,187,188), Vec3crd(186,188,116), Vec3crd(186,116,115), Vec3crd(99,98,182), Vec3crd(109,100,99), Vec3crd(106,178,107), Vec3crd(114,117,177), Vec3crd(114,177,176), Vec3crd(128,130,187), Vec3crd(128,187,186), Vec3crd(135,136,157), Vec3crd(135,157,156), Vec3crd(163,146,145), Vec3crd(164,167,180), Vec3crd(179,112,111), Vec3crd(171,139,138), Vec3crd(189,155,166), Vec3crd(189,166,165), Vec3crd(149,150,93), Vec3crd(154,155,189), Vec3crd(31,142,174), Vec3crd(114,176,78), Vec3crd(81,78,176), Vec3crd(7,89,183), Vec3crd(89,9,120), Vec3crd(89,120,183), Vec3crd(78,80,114), Vec3crd(176,106,81), Vec3crd(88,5,103), Vec3crd(183,102,7), Vec3crd(118,120,9), Vec3crd(9,2,181), Vec3crd(9,181,118), Vec3crd(115,114,80), Vec3crd(82,81,106), Vec3crd(101,103,5), Vec3crd(102,101,5), Vec3crd(5,7,102), Vec3crd(97,181,2), Vec3crd(2,1,97), Vec3crd(1,3,97), Vec3crd(80,55,115), Vec3crd(172,159,59), Vec3crd(59,56,172), Vec3crd(3,4,97), Vec3crd(4,0,96), Vec3crd(105,108,82), Vec3crd(186,115,55), Vec3crd(82,106,105), Vec3crd(83,82,108), Vec3crd(60,59,159), Vec3crd(175,172,56), Vec3crd(119,96,0), Vec3crd(0,11,119), Vec3crd(108,109,84), Vec3crd(84,83,108), Vec3crd(55,77,186), Vec3crd(56,58,110), Vec3crd(56,110,175), Vec3crd(60,159,158), Vec3crd(11,91,182), Vec3crd(182,119,11), Vec3crd(91,86,182), Vec3crd(85,84,109), Vec3crd(86,85,99), Vec3crd(128,186,77), Vec3crd(58,111,110), Vec3crd(158,161,60), Vec3crd(26,25,137), Vec3crd(138,137,25), Vec3crd(99,182,86), Vec3crd(109,99,85), Vec3crd(77,76,128), Vec3crd(58,47,111), Vec3crd(61,60,161), Vec3crd(137,140,26), Vec3crd(27,26,140), Vec3crd(25,22,138), Vec3crd(129,128,76), Vec3crd(76,75,129), Vec3crd(75,74,129), Vec3crd(74,73,156), Vec3crd(73,72,135), Vec3crd(68,16,184), Vec3crd(68,184,132), Vec3crd(16,18,185), Vec3crd(161,162,62), Vec3crd(62,61,161), Vec3crd(179,111,47), Vec3crd(171,138,22), Vec3crd(156,129,74), Vec3crd(135,156,73), Vec3crd(134,135,72), Vec3crd(72,71,134), Vec3crd(68,132,131), Vec3crd(185,184,16), Vec3crd(18,15,185), Vec3crd(63,62,162), Vec3crd(28,27,140), Vec3crd(22,24,171), Vec3crd(71,68,131), Vec3crd(15,17,143), Vec3crd(15,143,185), Vec3crd(17,70,143), Vec3crd(70,92,126), Vec3crd(162,163,64), Vec3crd(64,63,162), Vec3crd(180,179,47), Vec3crd(47,46,180), Vec3crd(140,141,28), Vec3crd(168,171,24), Vec3crd(126,143,70), Vec3crd(92,14,147), Vec3crd(147,126,92), Vec3crd(14,66,144), Vec3crd(14,144,147), Vec3crd(65,64,163), Vec3crd(66,65,145), Vec3crd(46,45,180), Vec3crd(32,28,141), Vec3crd(24,51,168), Vec3crd(145,144,66), Vec3crd(163,145,65), Vec3crd(164,180,45), Vec3crd(45,44,164), Vec3crd(44,43,164), Vec3crd(43,42,165), Vec3crd(38,37,151), Vec3crd(150,151,37), Vec3crd(37,93,150), Vec3crd(141,31,30), Vec3crd(30,32,141), Vec3crd(169,168,51), Vec3crd(165,164,43), Vec3crd(189,165,42), Vec3crd(42,41,189), Vec3crd(40,39,152), Vec3crd(40,152,153), Vec3crd(151,152,39), Vec3crd(39,38,151), Vec3crd(93,34,149), Vec3crd(154,189,41), Vec3crd(153,154,41), Vec3crd(41,40,153), Vec3crd(148,149,34), Vec3crd(34,36,148), Vec3crd(36,21,121), Vec3crd(31,174,29), Vec3crd(121,148,36), Vec3crd(21,33,122), Vec3crd(21,122,121), Vec3crd(33,29,122), Vec3crd(174,122,29), Vec3crd(116,188,53), Vec3crd(104,98,10), Vec3crd(87,10,98), Vec3crd(98,100,87), Vec3crd(79,87,100), Vec3crd(79,100,107), Vec3crd(90,79,107), Vec3crd(90,107,178), Vec3crd(178,177,90), Vec3crd(53,90,177), Vec3crd(53,177,117), Vec3crd(117,116,53), Vec3crd(54,53,188), Vec3crd(54,188,187), Vec3crd(67,54,187), Vec3crd(67,187,130), Vec3crd(69,67,130), Vec3crd(69,130,157), Vec3crd(12,69,157), Vec3crd(12,157,136), Vec3crd(136,133,12), Vec3crd(12,133,125), Vec3crd(125,127,12), Vec3crd(13,12,127), Vec3crd(127,146,13), Vec3crd(57,13,146), Vec3crd(57,146,160), Vec3crd(95,57,160), Vec3crd(95,160,173), Vec3crd(173,113,95), Vec3crd(94,95,113), Vec3crd(113,112,94), Vec3crd(52,94,112), Vec3crd(48,52,112), Vec3crd(112,167,48), Vec3crd(35,48,167), Vec3crd(35,167,166), Vec3crd(19,35,166), Vec3crd(139,170,50), Vec3crd(50,49,139), Vec3crd(166,155,19), Vec3crd(20,19,155), Vec3crd(155,124,20), Vec3crd(23,20,124), Vec3crd(23,124,123), Vec3crd(49,23,123), Vec3crd(49,123,142), Vec3crd(142,139,49), Vec3crd(190,191,170), Vec3crd(192,191,190), Vec3crd(191,192,51), Vec3crd(191,51,50), Vec3crd(170,169,190), Vec3crd(169,51,192), Vec3crd(169,192,190), Vec3crd(170,191,50), Vec3crd(193,194,195), Vec3crd(196,197,198), Vec3crd(199,200,201), Vec3crd(198,202,203), Vec3crd(204,201,200), Vec3crd(205,204,200), Vec3crd(206,207,208), Vec3crd(206,208,205), Vec3crd(206,205,200), Vec3crd(207,206,209), Vec3crd(207,209,203), Vec3crd(207,203,202), Vec3crd(202,198,197), Vec3crd(197,196,210), Vec3crd(197,210,195), Vec3crd(197,195,194), Vec3crd(8,88,195), Vec3crd(8,195,210), Vec3crd(210,196,8), Vec3crd(196,198,8), Vec3crd(198,203,8), Vec3crd(203,209,8), Vec3crd(209,206,8), Vec3crd(206,200,8), Vec3crd(202,197,104), Vec3crd(207,202,104), Vec3crd(103,104,197), Vec3crd(103,197,194), Vec3crd(193,195,88), Vec3crd(88,103,194), Vec3crd(88,194,193), Vec3crd(200,199,8), Vec3crd(199,201,8), Vec3crd(204,205,6), Vec3crd(6,8,201), Vec3crd(6,201,204), Vec3crd(10,6,205), Vec3crd(10,205,208), Vec3crd(104,10,208), Vec3crd(104,208,207) }); + { {15.8899993896484,19.444055557251,2.67489433288574}, {15.9129991531372,19.1590557098389,2.67489433288574}, {15.9039993286133,19.1500549316406,2.67489433288574}, {15.9489994049072,19.2490558624268,2.67489433288574}, {15.9579992294312,19.3570556640625,2.67489433288574}, {15.8819999694824,18.690055847168,2.67489433288574}, {15.8319997787476,17.7460556030273,2.67489433288574}, {15.8489999771118,18.819055557251,2.67489433288574}, {15.8589992523193,17.7190551757812,2.67489433288574}, {15.8769998550415,19.0490550994873,2.67489433288574}, {15.7529993057251,17.8080558776855,2.67489433288574}, {15.7869997024536,19.5010547637939,2.67489433288574}, {14.0329990386963,18.7170543670654,2.67489433288574}, {13.9599990844727,18.7460556030273,2.67489433288574}, {13.9869995117188,20.2840557098389,2.67489433288574}, {14.2029991149902,20.149055480957,2.67489433288574}, {14.1939992904663,19.9560546875,2.67489433288574}, {14.1939992904663,20.1670551300049,2.67489433288574}, {14.2119998931885,20.0590553283691,2.67489433288574}, {12.1899995803833,19.1840553283691,2.67489433288574}, {12.096999168396,19.1950550079346,2.67489433288574}, {12.1099996566772,20.6690559387207,2.67489433288574}, {11.382999420166,19.9750556945801,2.67489433288574}, {11.2599992752075,19.2490558624268,2.67489433288574}, {11.2369995117188,19.9320545196533,2.67489433288574}, {11.5349998474121,20.0640544891357,2.67489433288574}, {11.6259994506836,20.1550559997559,2.67489433288574}, {11.6829986572266,20.2390556335449,2.67489433288574}, {11.7369995117188,20.3570556640625,2.67489433288574}, {11.8449993133545,20.645055770874,2.67489433288574}, {11.7729988098145,20.4640560150146,2.67489433288574}, {11.7799987792969,20.5370559692383,9.41389465332031}, {11.7639999389648,20.4470558166504,2.67489433288574}, {11.9559993743896,20.6810550689697,2.67489433288574}, {12.3079996109009,20.6020545959473,2.67489433288574}, {12.1959991455078,19.1860542297363,2.67489433288574}, {12.2059993743896,20.6540546417236,2.67489433288574}, {12.3489990234375,20.3740558624268,2.67489433288574}, {12.3579998016357,20.2750549316406,2.67489433288574}, {12.3669996261597,20.266056060791,2.67489433288574}, {12.3849992752075,20.1670551300049,2.67489433288574}, {12.4269990921021,20.0680541992188,2.67489433288574}, {12.5029993057251,19.9540557861328,2.67489433288574}, {12.6169996261597,19.8550548553467,2.67489433288574}, {12.7449989318848,19.7800559997559,2.67489433288574}, {12.7629995346069,19.7800559997559,2.67489433288574}, {12.8799991607666,19.7350559234619,2.67489433288574}, {13.0369997024536,19.7250556945801,2.67489433288574}, {13.0149993896484,19.0340557098389,2.67489433288574}, {11.1699991226196,19.2580547332764,2.67489433288574}, {11.0959987640381,19.2580547332764,2.67489433288574}, {11.1209993362427,19.9230556488037,2.67489433288574}, {13.0599994659424,19.024055480957,2.67489433288574}, {14.9049997329712,18.3170547485352,2.67489433288574}, {14.8779993057251,18.3400554656982,2.67489433288574}, {14.8779993057251,19.149055480957,2.67489433288574}, {13.3039989471436,19.77805519104,2.67489433288574}, {13.1589994430542,18.9890556335449,2.67489433288574}, {13.1559991836548,19.7350559234619,2.67489433288574}, {13.4269990921021,19.8600559234619,2.67489433288574}, {13.5339994430542,19.9700546264648,2.67389440536499}, {13.6359996795654,20.1220550537109,2.67489433288574}, {13.6359996795654,20.1400547027588,2.67489433288574}, {13.6719989776611,20.2210559844971,2.67489433288574}, {13.6899995803833,20.2300548553467,2.67489433288574}, {13.7509994506836,20.3010559082031,2.67489433288574}, {13.8539991378784,20.3180541992188,2.67489433288574}, {14.8329992294312,18.3580551147461,2.67489433288574}, {14.1849994659424,19.8530559539795,2.67489433288574}, {14.0769996643066,18.7000541687012,2.67489433288574}, {14.1099996566772,20.2400550842285,2.67489433288574}, {14.2009992599487,19.6230545043945,2.67489433288574}, {14.2729997634888,19.4670543670654,2.67489433288574}, {14.3379993438721,19.3790550231934,2.67489433288574}, {14.4549999237061,19.2770557403564,2.67489433288574}, {14.5899991989136,19.2040557861328,2.67489433288574}, {14.6079998016357,19.2040557861328,2.67489433288574}, {14.7209997177124,19.1600551605225,2.67489433288574}, {15.1379995346069,19.210054397583,2.67489433288574}, {14.9949998855591,18.2680549621582,2.67489433288574}, {15.0029993057251,19.1580543518066,2.67489433288574}, {15.2369995117188,19.2760543823242,2.67489433288574}, {15.3779993057251,19.4060554504395,2.67489433288574}, {15.4539995193481,19.520055770874,2.67489433288574}, {15.471999168396,19.52805519104,2.67489433288574}, {15.5449991226196,19.5830554962158,2.67489433288574}, {15.6529998779297,19.573055267334,2.67489433288574}, {15.7059993743896,17.8360557556152,2.67489433288574}, {15.9449996948242,18.5560550689697,2.67489433288574}, {15.8589992523193,18.9380550384521,2.67489433288574}, {14.9589996337891,18.2950553894043,2.67489433288574}, {15.7779998779297,19.5100555419922,2.67489433288574}, {14.0049991607666,20.2750549316406,2.67489433288574}, {12.3489990234375,20.5000553131104,2.67489433288574}, {13.0689992904663,19.0150547027588,2.67489433288574}, {13.0999994277954,19.0100555419922,2.67489433288574}, {15.9489994049072,19.3670558929443,9.41489505767822}, {15.9489994049072,19.2490558624268,9.41489505767822}, {15.75,17.8080558776855,9.41489505767822}, {15.6639995574951,19.5710544586182,9.41489505767822}, {15.5709991455078,17.9260559082031,9.41489505767822}, {15.8769998550415,18.690055847168,9.41489505767822}, {15.8499994277954,18.8170547485352,9.41489505767822}, {15.9459991455078,18.5520553588867,9.41489505767822}, {15.914999961853,17.6890544891357,9.41489505767822}, {15.3999996185303,19.4290542602539,9.41489505767822}, {15.3099994659424,19.339054107666,9.41489505767822}, {15.3729991912842,18.0440559387207,9.41489505767822}, {15.4579992294312,19.5170555114746,9.41489505767822}, {15.5469999313354,19.5820541381836,9.41489505767822}, {13.2309989929199,19.7610549926758,9.41489505767822}, {13.168999671936,19.7360553741455,9.41489505767822}, {13.096999168396,19.0140552520752,9.41489505767822}, {13.1999988555908,18.9870548248291,9.41489505767822}, {15.1399993896484,19.2080554962158,9.41489505767822}, {15.0159997940063,19.1600551605225,9.41489505767822}, {14.9859991073608,18.2770557403564,9.41489505767822}, {15.1749992370605,18.1690559387207,9.41489505767822}, {15.9039993286133,19.1320552825928,9.41489505767822}, {15.8949995040894,19.4460544586182,9.41489505767822}, {15.8769998550415,19.0420551300049,9.41489505767822}, {12.2169990539551,20.6500549316406,9.41489505767822}, {11.9379997253418,20.6810550689697,9.41489505767822}, {11.8629989624023,19.2130546569824,9.41489505767822}, {12.096999168396,19.1950550079346,9.41489505767822}, {14.1669998168945,18.6640548706055,9.41489505767822}, {14.1039991378784,20.2460556030273,9.41489505767822}, {13.9849996566772,18.7360553741455,9.41489505767822}, {14.7349996566772,19.1590557098389,9.41489505767822}, {14.5849990844727,19.2050552368164,9.41489505767822}, {14.5719995498657,18.4850559234619,9.41489505767822}, {14.1939992904663,19.6760559082031,9.41489505767822}, {14.1849994659424,19.9330558776855,9.41489505767822}, {14.1759996414185,18.6640548706055,9.41489505767822}, {14.261999130249,19.4890556335449,9.41489505767822}, {14.3539991378784,19.3610553741455,9.41489505767822}, {14.3559989929199,18.5830554962158,9.41489505767822}, {11.6039991378784,20.1250553131104,9.41489505767822}, {11.5209999084473,20.0520553588867,9.41489505767822}, {11.4209995269775,19.2480545043945,9.41489505767822}, {11.6989994049072,20.2690544128418,9.41389465332031}, {11.7609996795654,20.4310550689697,9.41489505767822}, {11.8359994888306,19.2130546569824,9.41489505767822}, {14.1889991760254,20.1710548400879,9.41489505767822}, {13.9689998626709,20.2840557098389,9.41489505767822}, {13.8739995956421,20.315055847168,9.41489505767822}, {13.7799997329712,18.8080558776855,9.41489505767822}, {13.9869995117188,20.2750549316406,9.41489505767822}, {12.3129997253418,20.5980548858643,9.41489505767822}, {12.3399991989136,20.5090560913086,9.41489505767822}, {12.3489990234375,20.3830547332764,9.41489505767822}, {12.3599996566772,20.2680549621582,9.41489505767822}, {12.3849992752075,20.1850547790527,9.41489505767822}, {12.3849992752075,20.1670551300049,9.41489505767822}, {12.4249992370605,20.065055847168,9.41489505767822}, {12.4729995727539,19.1350555419922,9.41489505767822}, {14.4399995803833,19.2900543212891,9.41489505767822}, {14.3649997711182,18.5740547180176,9.41489505767822}, {13.5729999542236,20.0310554504395,9.41489505767822}, {13.4889993667603,19.9140548706055,9.41489505767822}, {13.5639991760254,18.8710556030273,9.41489505767822}, {13.6389999389648,20.1310558319092,9.41489505767822}, {13.6719989776611,20.2130546569824,9.41489505767822}, {13.75,20.3020553588867,9.41489505767822}, {12.7399997711182,19.7810554504395,9.41489505767822}, {12.6189994812012,19.8520545959473,9.41489505767822}, {12.5799999237061,19.1200542449951,9.41489505767822}, {12.8349990844727,19.069055557251,9.41489505767822}, {11.2669992446899,19.9350547790527,9.41489505767822}, {11.1029987335205,19.9230556488037,9.41489505767822}, {11.0209999084473,19.2600555419922,9.41489505767822}, {11.3819999694824,19.9710559844971,9.41489505767822}, {13.418999671936,19.8530559539795,9.41489505767822}, {13.4329996109009,18.9160556793213,9.41489505767822}, {11.8399991989136,20.6430549621582,9.41489505767822}, {13.3119993209839,19.7800559997559,9.41489505767822}, {15.2189998626709,19.2600555419922,9.41489505767822}, {15.1839990615845,18.1600551605225,9.41489505767822}, {15.3639993667603,18.0520553588867,9.41489505767822}, {13.0189990997314,19.7250556945801,9.41489505767822}, {12.8949995040894,19.7350559234619,9.41489505767822}, {15.9039993286133,19.1500549316406,9.41489505767822}, {15.7699995040894,19.5140552520752,9.41489505767822}, {15.8589992523193,18.9340553283691,9.41489505767822}, {14.1939992904663,19.9510555267334,9.41489505767822}, {14.2119998931885,20.0630550384521,9.41489505767822}, {14.8589992523193,19.149055480957,9.41489505767822}, {14.8159999847412,18.3670558929443,9.41489505767822}, {14.8959999084473,18.3220558166504,9.41489505767822}, {12.5189990997314,19.9360542297363,9.41489505767822}, {11.0209999084473,19.9290542602539,9.41489505767822}, {11.0209999084473,19.2530555725098,2.67489433288574}, {11.0209999084473,19.9300556182861,2.67489433288574}, {15.9799995422363,18.505931854248,5.58724021911621}, {15.9799995422363,18.5044555664062,9.41489505767822}, {15.9799995422363,18.5041732788086,2.67489433288574}, {15.9799995422363,18.1684837341309,2.67489433288574}, {15.9799995422363,18.1288299560547,9.41489505767822}, {15.9799995422363,17.9876575469971,2.67489433288574}, {15.9799995422363,17.6247596740723,3.91620373725891}, {15.9799995422363,17.6247596740723,2.67489433288574}, {15.9799995422363,17.6254329681396,4.32245063781738}, {15.9799995422363,17.8920269012451,9.41489505767822}, {15.9799995422363,17.8795108795166,2.67489433288574}, {15.9799995422363,17.629810333252,4.58585262298584}, {15.9799995422363,17.6336059570312,5.27938556671143}, {15.9799995422363,17.8311748504639,2.67489433288574}, {15.9799995422363,17.638355255127,9.41489505767822}, {15.9799995422363,17.6346111297607,5.98653984069824}, {15.9799995422363,17.8728256225586,2.67489433288574}, {15.9799995422363,18.2221603393555,2.67489433288574} }, + { {0,1,2}, {0,3,1}, {0,4,3}, {5,6,7}, {8,6,5}, {2,9,0}, {6,10,11}, {12,13,14}, {15,16,17}, {18,16,15}, {19,20,21}, {22,23,24}, {25,23,22}, {26,23,25}, {27,23,26}, {28,23,27}, {29,30,31}, {29,32,30}, {29,28,32}, {33,28,29}, {33,23,28}, {21,23,33}, {20,23,21}, {34,35,36}, {37,35,34}, {38,35,37}, {39,35,38}, {40,35,39}, {41,35,40}, {42,35,41}, {43,35,42}, {44,35,43}, {45,35,44}, {46,35,45}, {47,35,46}, {48,35,47}, {49,50,51}, {52,48,47}, {23,49,24}, {53,54,55}, {56,57,58}, {59,57,56}, {60,57,59}, {61,57,60}, {62,57,61}, {63,57,62}, {64,57,63}, {65,57,64}, {66,57,65}, {13,57,66}, {54,67,55}, {68,69,70}, {71,69,68}, {72,69,71}, {73,69,72}, {74,69,73}, {75,69,74}, {76,69,75}, {77,69,76}, {67,69,77}, {70,16,68}, {70,17,16}, {78,79,80}, {81,79,78}, {82,79,81}, {83,79,82}, {84,79,83}, {85,79,84}, {86,79,85}, {87,79,86}, {88,8,5}, {11,7,6}, {11,89,7}, {11,9,89}, {11,0,9}, {55,90,53}, {55,79,90}, {55,80,79}, {91,11,10}, {92,69,12}, {92,70,69}, {34,93,37}, {47,94,52}, {47,95,94}, {47,57,95}, {47,58,57}, {51,24,49}, {21,35,19}, {21,36,35}, {14,92,12}, {86,10,87}, {86,91,10}, {77,55,67}, {66,14,13}, {96,97,4}, {98,99,100}, {101,102,98}, {103,101,98}, {104,103,98}, {105,106,107}, {108,105,107}, {109,108,107}, {100,109,107}, {110,111,112}, {113,110,112}, {114,115,116}, {117,114,116}, {118,119,120}, {121,122,123}, {124,121,123}, {125,126,127}, {128,129,130}, {131,132,133}, {71,131,133}, {134,71,133}, {135,134,133}, {136,135,133}, {137,138,139}, {140,137,139}, {141,140,139}, {142,31,141}, {142,141,139}, {143,126,132}, {144,145,146}, {147,144,146}, {127,147,146}, {148,121,124}, {149,148,124}, {150,149,124}, {151,150,124}, {152,151,124}, {153,152,124}, {154,153,124}, {155,154,124}, {129,156,157}, {130,129,157}, {158,159,160}, {161,158,160}, {162,161,160}, {163,162,160}, {146,163,160}, {164,165,166}, {167,164,166}, {168,169,170}, {171,168,170}, {139,171,170}, {159,172,173}, {123,174,142}, {175,110,113}, {173,175,113}, {106,176,177}, {178,106,177}, {179,180,167}, {112,179,167}, {175,173,172}, {119,118,181}, {119,181,97}, {119,97,96}, {182,98,102}, {182,102,183}, {182,183,120}, {182,120,119}, {143,132,184}, {184,185,143}, {147,127,126}, {174,123,122}, {159,173,160}, {126,125,133}, {126,133,132}, {186,187,188}, {186,188,116}, {186,116,115}, {99,98,182}, {109,100,99}, {106,178,107}, {114,117,177}, {114,177,176}, {128,130,187}, {128,187,186}, {135,136,157}, {135,157,156}, {163,146,145}, {164,167,180}, {179,112,111}, {171,139,138}, {189,155,166}, {189,166,165}, {149,150,93}, {154,155,189}, {31,142,174}, {114,176,78}, {81,78,176}, {7,89,183}, {89,9,120}, {89,120,183}, {78,80,114}, {176,106,81}, {88,5,103}, {183,102,7}, {118,120,9}, {9,2,181}, {9,181,118}, {115,114,80}, {82,81,106}, {101,103,5}, {102,101,5}, {5,7,102}, {97,181,2}, {2,1,97}, {1,3,97}, {80,55,115}, {172,159,59}, {59,56,172}, {3,4,97}, {4,0,96}, {105,108,82}, {186,115,55}, {82,106,105}, {83,82,108}, {60,59,159}, {175,172,56}, {119,96,0}, {0,11,119}, {108,109,84}, {84,83,108}, {55,77,186}, {56,58,110}, {56,110,175}, {60,159,158}, {11,91,182}, {182,119,11}, {91,86,182}, {85,84,109}, {86,85,99}, {128,186,77}, {58,111,110}, {158,161,60}, {26,25,137}, {138,137,25}, {99,182,86}, {109,99,85}, {77,76,128}, {58,47,111}, {61,60,161}, {137,140,26}, {27,26,140}, {25,22,138}, {129,128,76}, {76,75,129}, {75,74,129}, {74,73,156}, {73,72,135}, {68,16,184}, {68,184,132}, {16,18,185}, {161,162,62}, {62,61,161}, {179,111,47}, {171,138,22}, {156,129,74}, {135,156,73}, {134,135,72}, {72,71,134}, {68,132,131}, {185,184,16}, {18,15,185}, {63,62,162}, {28,27,140}, {22,24,171}, {71,68,131}, {15,17,143}, {15,143,185}, {17,70,143}, {70,92,126}, {162,163,64}, {64,63,162}, {180,179,47}, {47,46,180}, {140,141,28}, {168,171,24}, {126,143,70}, {92,14,147}, {147,126,92}, {14,66,144}, {14,144,147}, {65,64,163}, {66,65,145}, {46,45,180}, {32,28,141}, {24,51,168}, {145,144,66}, {163,145,65}, {164,180,45}, {45,44,164}, {44,43,164}, {43,42,165}, {38,37,151}, {150,151,37}, {37,93,150}, {141,31,30}, {30,32,141}, {169,168,51}, {165,164,43}, {189,165,42}, {42,41,189}, {40,39,152}, {40,152,153}, {151,152,39}, {39,38,151}, {93,34,149}, {154,189,41}, {153,154,41}, {41,40,153}, {148,149,34}, {34,36,148}, {36,21,121}, {31,174,29}, {121,148,36}, {21,33,122}, {21,122,121}, {33,29,122}, {174,122,29}, {116,188,53}, {104,98,10}, {87,10,98}, {98,100,87}, {79,87,100}, {79,100,107}, {90,79,107}, {90,107,178}, {178,177,90}, {53,90,177}, {53,177,117}, {117,116,53}, {54,53,188}, {54,188,187}, {67,54,187}, {67,187,130}, {69,67,130}, {69,130,157}, {12,69,157}, {12,157,136}, {136,133,12}, {12,133,125}, {125,127,12}, {13,12,127}, {127,146,13}, {57,13,146}, {57,146,160}, {95,57,160}, {95,160,173}, {173,113,95}, {94,95,113}, {113,112,94}, {52,94,112}, {48,52,112}, {112,167,48}, {35,48,167}, {35,167,166}, {19,35,166}, {139,170,50}, {50,49,139}, {166,155,19}, {20,19,155}, {155,124,20}, {23,20,124}, {23,124,123}, {49,23,123}, {49,123,142}, {142,139,49}, {190,191,170}, {192,191,190}, {191,192,51}, {191,51,50}, {170,169,190}, {169,51,192}, {169,192,190}, {170,191,50}, {193,194,195}, {196,197,198}, {199,200,201}, {198,202,203}, {204,201,200}, {205,204,200}, {206,207,208}, {206,208,205}, {206,205,200}, {207,206,209}, {207,209,203}, {207,203,202}, {202,198,197}, {197,196,210}, {197,210,195}, {197,195,194}, {8,88,195}, {8,195,210}, {210,196,8}, {196,198,8}, {198,203,8}, {203,209,8}, {209,206,8}, {206,200,8}, {202,197,104}, {207,202,104}, {103,104,197}, {103,197,194}, {193,195,88}, {88,103,194}, {88,194,193}, {200,199,8}, {199,201,8}, {204,205,6}, {6,8,201}, {6,201,204}, {10,6,205}, {10,205,208}, {104,10,208}, {104,208,207} }); break; case TestMesh::pyramid: mesh = TriangleMesh( - { Vec3d(10,10,40), Vec3d(0,0,0), Vec3d(20,0,0), Vec3d(20,20,0), Vec3d(0,20,0) }, - { Vec3crd(0,1,2), Vec3crd(0,3,4), Vec3crd(3,1,4), Vec3crd(1,3,2), Vec3crd(3,0,2), Vec3crd(4,1,0) }); + { {10,10,40}, {0,0,0}, {20,0,0}, {20,20,0}, {0,20,0} }, + { {0,1,2}, {0,3,4}, {3,1,4}, {1,3,2}, {3,0,2}, {4,1,0} }); break; case TestMesh::two_hollow_squares: mesh = TriangleMesh( - { Vec3d(66.7133483886719,104.286666870117,0), Vec3d(66.7133483886719,95.7133331298828,0), Vec3d(65.6666870117188,94.6666717529297,0), Vec3d(75.2866821289062,95.7133331298828,0), Vec3d(76.3333435058594,105.333335876465,0), Vec3d(76.3333435058594,94.6666717529297,0), Vec3d(65.6666870117188,105.33332824707,0), Vec3d(75.2866821289062,104.286666870117,0), Vec3d(71.1066818237305,104.58666229248,2.79999995231628), Vec3d(66.4133529663086,104.58666229248,2.79999995231628), Vec3d(75.5866851806641,104.58666229248,2.79999995231628), Vec3d(66.4133529663086,99.8933334350586,2.79999995231628), Vec3d(66.4133529663086,95.4133377075195,2.79999995231628), Vec3d(71.1066818237305,95.4133377075195,2.79999995231628), Vec3d(75.5866851806641,95.4133377075195,2.79999995231628), Vec3d(75.5866851806641,100.106666564941,2.79999995231628), Vec3d(74.5400161743164,103.540000915527,2.79999995231628), Vec3d(70.0320129394531,103.540000915527,2.79999995231628), Vec3d(67.4600067138672,103.540000915527,2.79999995231628), Vec3d(67.4600067138672,100.968002319336,2.79999995231628), Vec3d(67.4600067138672,96.4599990844727,2.79999995231628), Vec3d(74.5400161743164,99.0319976806641,2.79999995231628), Vec3d(74.5400161743164,96.4599990844727,2.79999995231628), Vec3d(70.0320129394531,96.4599990844727,2.79999995231628), Vec3d(123.666717529297,94.6666717529297,0), Vec3d(134.333312988281,94.6666717529297,0), Vec3d(124.413360595703,95.4133377075195,2.79999995231628), Vec3d(129.106674194336,95.4133377075195,2.79999995231628), Vec3d(133.586669921875,95.4133377075195,2.79999995231628), Vec3d(123.666717529297,105.33332824707,0), Vec3d(124.413360595703,104.58666229248,2.79999995231628), Vec3d(124.413360595703,99.8933334350586,2.79999995231628), Vec3d(134.333312988281,105.33332824707,0), Vec3d(129.106674194336,104.58666229248,2.79999995231628), Vec3d(133.586669921875,104.58666229248,2.79999995231628), Vec3d(133.586669921875,100.106666564941,2.79999995231628), Vec3d(124.713317871094,104.286666870117,0), Vec3d(124.713317871094,95.7133331298828,0), Vec3d(133.286712646484,95.7133331298828,0), Vec3d(133.286712646484,104.286666870117,0), Vec3d(132.540023803711,103.540000915527,2.79999995231628), Vec3d(128.032028198242,103.540008544922,2.79999995231628), Vec3d(125.460006713867,103.540000915527,2.79999995231628), Vec3d(125.460006713867,100.968002319336,2.79999995231628), Vec3d(125.460006713867,96.4599990844727,2.79999995231628), Vec3d(132.540023803711,99.0319976806641,2.79999995231628), Vec3d(132.540023803711,96.4599990844727,2.79999995231628), Vec3d(128.032028198242,96.4599990844727,2.79999995231628) }, - { Vec3crd(0,1,2), Vec3crd(3,4,5), Vec3crd(6,4,0), Vec3crd(6,0,2), Vec3crd(2,1,5), Vec3crd(7,4,3), Vec3crd(1,3,5), Vec3crd(0,4,7), Vec3crd(4,6,8), Vec3crd(6,9,8), Vec3crd(4,8,10), Vec3crd(6,2,9), Vec3crd(2,11,9), Vec3crd(2,12,11), Vec3crd(2,5,12), Vec3crd(5,13,12), Vec3crd(5,14,13), Vec3crd(4,10,15), Vec3crd(5,4,14), Vec3crd(4,15,14), Vec3crd(7,16,17), Vec3crd(0,7,18), Vec3crd(7,17,18), Vec3crd(1,19,20), Vec3crd(1,0,19), Vec3crd(0,18,19), Vec3crd(7,3,21), Vec3crd(3,22,21), Vec3crd(7,21,16), Vec3crd(3,23,22), Vec3crd(3,1,23), Vec3crd(1,20,23), Vec3crd(24,25,26), Vec3crd(25,27,26), Vec3crd(25,28,27), Vec3crd(29,24,30), Vec3crd(24,31,30), Vec3crd(24,26,31), Vec3crd(32,29,33), Vec3crd(29,30,33), Vec3crd(32,33,34), Vec3crd(32,34,35), Vec3crd(25,32,28), Vec3crd(32,35,28), Vec3crd(36,37,24), Vec3crd(38,32,25), Vec3crd(29,32,36), Vec3crd(29,36,24), Vec3crd(24,37,25), Vec3crd(39,32,38), Vec3crd(37,38,25), Vec3crd(36,32,39), Vec3crd(39,40,41), Vec3crd(36,39,42), Vec3crd(39,41,42), Vec3crd(37,43,44), Vec3crd(37,36,43), Vec3crd(36,42,43), Vec3crd(39,38,45), Vec3crd(38,46,45), Vec3crd(39,45,40), Vec3crd(38,47,46), Vec3crd(38,37,47), Vec3crd(37,44,47), Vec3crd(16,8,9), Vec3crd(16,10,8), Vec3crd(10,16,15), Vec3crd(15,16,21), Vec3crd(22,15,21), Vec3crd(15,22,14), Vec3crd(22,23,14), Vec3crd(23,20,14), Vec3crd(17,16,9), Vec3crd(18,17,9), Vec3crd(19,18,9), Vec3crd(19,9,11), Vec3crd(19,11,20), Vec3crd(13,14,20), Vec3crd(20,11,12), Vec3crd(13,20,12), Vec3crd(41,40,30), Vec3crd(42,41,30), Vec3crd(43,42,30), Vec3crd(43,30,31), Vec3crd(43,31,44), Vec3crd(27,28,44), Vec3crd(44,31,26), Vec3crd(27,44,26), Vec3crd(40,33,30), Vec3crd(40,34,33), Vec3crd(34,40,35), Vec3crd(35,40,45), Vec3crd(46,35,45), Vec3crd(35,46,28), Vec3crd(46,47,28), Vec3crd(47,44,28) }); + { {66.7133483886719,104.286666870117,0}, {66.7133483886719,95.7133331298828,0}, {65.6666870117188,94.6666717529297,0}, {75.2866821289062,95.7133331298828,0}, {76.3333435058594,105.333335876465,0}, {76.3333435058594,94.6666717529297,0}, {65.6666870117188,105.33332824707,0}, {75.2866821289062,104.286666870117,0}, {71.1066818237305,104.58666229248,2.79999995231628}, {66.4133529663086,104.58666229248,2.79999995231628}, {75.5866851806641,104.58666229248,2.79999995231628}, {66.4133529663086,99.8933334350586,2.79999995231628}, {66.4133529663086,95.4133377075195,2.79999995231628}, {71.1066818237305,95.4133377075195,2.79999995231628}, {75.5866851806641,95.4133377075195,2.79999995231628}, {75.5866851806641,100.106666564941,2.79999995231628}, {74.5400161743164,103.540000915527,2.79999995231628}, {70.0320129394531,103.540000915527,2.79999995231628}, {67.4600067138672,103.540000915527,2.79999995231628}, {67.4600067138672,100.968002319336,2.79999995231628}, {67.4600067138672,96.4599990844727,2.79999995231628}, {74.5400161743164,99.0319976806641,2.79999995231628}, {74.5400161743164,96.4599990844727,2.79999995231628}, {70.0320129394531,96.4599990844727,2.79999995231628}, {123.666717529297,94.6666717529297,0}, {134.333312988281,94.6666717529297,0}, {124.413360595703,95.4133377075195,2.79999995231628}, {129.106674194336,95.4133377075195,2.79999995231628}, {133.586669921875,95.4133377075195,2.79999995231628}, {123.666717529297,105.33332824707,0}, {124.413360595703,104.58666229248,2.79999995231628}, {124.413360595703,99.8933334350586,2.79999995231628}, {134.333312988281,105.33332824707,0}, {129.106674194336,104.58666229248,2.79999995231628}, {133.586669921875,104.58666229248,2.79999995231628}, {133.586669921875,100.106666564941,2.79999995231628}, {124.713317871094,104.286666870117,0}, {124.713317871094,95.7133331298828,0}, {133.286712646484,95.7133331298828,0}, {133.286712646484,104.286666870117,0}, {132.540023803711,103.540000915527,2.79999995231628}, {128.032028198242,103.540008544922,2.79999995231628}, {125.460006713867,103.540000915527,2.79999995231628}, {125.460006713867,100.968002319336,2.79999995231628}, {125.460006713867,96.4599990844727,2.79999995231628}, {132.540023803711,99.0319976806641,2.79999995231628}, {132.540023803711,96.4599990844727,2.79999995231628}, {128.032028198242,96.4599990844727,2.79999995231628} }, + { {0,1,2}, {3,4,5}, {6,4,0}, {6,0,2}, {2,1,5}, {7,4,3}, {1,3,5}, {0,4,7}, {4,6,8}, {6,9,8}, {4,8,10}, {6,2,9}, {2,11,9}, {2,12,11}, {2,5,12}, {5,13,12}, {5,14,13}, {4,10,15}, {5,4,14}, {4,15,14}, {7,16,17}, {0,7,18}, {7,17,18}, {1,19,20}, {1,0,19}, {0,18,19}, {7,3,21}, {3,22,21}, {7,21,16}, {3,23,22}, {3,1,23}, {1,20,23}, {24,25,26}, {25,27,26}, {25,28,27}, {29,24,30}, {24,31,30}, {24,26,31}, {32,29,33}, {29,30,33}, {32,33,34}, {32,34,35}, {25,32,28}, {32,35,28}, {36,37,24}, {38,32,25}, {29,32,36}, {29,36,24}, {24,37,25}, {39,32,38}, {37,38,25}, {36,32,39}, {39,40,41}, {36,39,42}, {39,41,42}, {37,43,44}, {37,36,43}, {36,42,43}, {39,38,45}, {38,46,45}, {39,45,40}, {38,47,46}, {38,37,47}, {37,44,47}, {16,8,9}, {16,10,8}, {10,16,15}, {15,16,21}, {22,15,21}, {15,22,14}, {22,23,14}, {23,20,14}, {17,16,9}, {18,17,9}, {19,18,9}, {19,9,11}, {19,11,20}, {13,14,20}, {20,11,12}, {13,20,12}, {41,40,30}, {42,41,30}, {43,42,30}, {43,30,31}, {43,31,44}, {27,28,44}, {44,31,26}, {27,44,26}, {40,33,30}, {40,34,33}, {34,40,35}, {35,40,45}, {46,35,45}, {35,46,28}, {46,47,28}, {47,44,28} }); break; case TestMesh::small_dorito: mesh = TriangleMesh( - { Vec3d(6.00058937072754,-22.9982089996338,0), Vec3d(22.0010242462158,-49.9998741149902,0), Vec3d(-9.99957847595215,-49.999870300293,0), Vec3d(6.00071382522583,-32.2371635437012,28.0019245147705), Vec3d(11.1670551300049,-37.9727020263672,18.9601669311523), Vec3d(6.00060224533081,-26.5392456054688,10.7321853637695) }, - { Vec3crd(0,1,2), Vec3crd(3,4,5), Vec3crd(2,1,4), Vec3crd(2,4,3), Vec3crd(2,3,5), Vec3crd(2,5,0), Vec3crd(5,4,1), Vec3crd(5,1,0) }); + { {6.00058937072754,-22.9982089996338,0}, {22.0010242462158,-49.9998741149902,0}, {-9.99957847595215,-49.999870300293,0}, {6.00071382522583,-32.2371635437012,28.0019245147705}, {11.1670551300049,-37.9727020263672,18.9601669311523}, {6.00060224533081,-26.5392456054688,10.7321853637695} }, + { {0,1,2}, {3,4,5}, {2,1,4}, {2,4,3}, {2,3,5}, {2,5,0}, {5,4,1}, {5,1,0} }); break; case TestMesh::bridge: mesh = TriangleMesh( - { Vec3d(75,84.5,8), Vec3d(125,84.5,8), Vec3d(75,94.5,8), Vec3d(120,84.5,5), Vec3d(125,94.5,8), Vec3d(75,84.5,0), Vec3d(80,84.5,5), Vec3d(125,84.5,0), Vec3d(125,94.5,0), Vec3d(80,94.5,5), Vec3d(75,94.5,0), Vec3d(120,94.5,5), Vec3d(120,84.5,0), Vec3d(80,94.5,0), Vec3d(80,84.5,0), Vec3d(120,94.5,0) }, - { Vec3crd(0,1,2), Vec3crd(1,0,3), Vec3crd(2,1,4), Vec3crd(2,5,0), Vec3crd(0,6,3), Vec3crd(1,3,7), Vec3crd(1,8,4), Vec3crd(4,9,2), Vec3crd(10,5,2), Vec3crd(5,6,0), Vec3crd(6,11,3), Vec3crd(3,12,7), Vec3crd(7,8,1), Vec3crd(4,8,11), Vec3crd(4,11,9), Vec3crd(9,10,2), Vec3crd(10,13,5), Vec3crd(14,6,5), Vec3crd(9,11,6), Vec3crd(11,12,3), Vec3crd(12,8,7), Vec3crd(11,8,15), Vec3crd(13,10,9), Vec3crd(5,13,14), Vec3crd(14,13,6), Vec3crd(6,13,9), Vec3crd(15,12,11), Vec3crd(15,8,12) }); + { {75,84.5,8}, {125,84.5,8}, {75,94.5,8}, {120,84.5,5}, {125,94.5,8}, {75,84.5,0}, {80,84.5,5}, {125,84.5,0}, {125,94.5,0}, {80,94.5,5}, {75,94.5,0}, {120,94.5,5}, {120,84.5,0}, {80,94.5,0}, {80,84.5,0}, {120,94.5,0} }, + { {0,1,2}, {1,0,3}, {2,1,4}, {2,5,0}, {0,6,3}, {1,3,7}, {1,8,4}, {4,9,2}, {10,5,2}, {5,6,0}, {6,11,3}, {3,12,7}, {7,8,1}, {4,8,11}, {4,11,9}, {9,10,2}, {10,13,5}, {14,6,5}, {9,11,6}, {11,12,3}, {12,8,7}, {11,8,15}, {13,10,9}, {5,13,14}, {14,13,6}, {6,13,9}, {15,12,11}, {15,8,12} }); break; case TestMesh::bridge_with_hole: mesh = TriangleMesh( - { Vec3d(75,69.5,8), Vec3d(80,76.9091644287109,8), Vec3d(75,94.5,8), Vec3d(125,69.5,8), Vec3d(120,76.9091644287109,8), Vec3d(120,87.0908355712891,8), Vec3d(80,87.0908355712891,8), Vec3d(125,94.5,8), Vec3d(80,87.0908355712891,5), Vec3d(120,87.0908355712891,5), Vec3d(125,94.5,0), Vec3d(120,69.5,0), Vec3d(120,94.5,0), Vec3d(125,69.5,0), Vec3d(120,94.5,5), Vec3d(80,94.5,5), Vec3d(80,94.5,0), Vec3d(75,94.5,0), Vec3d(80,69.5,5), Vec3d(80,69.5,0), Vec3d(80,76.9091644287109,5), Vec3d(120,69.5,5), Vec3d(75,69.5,0), Vec3d(120,76.9091644287109,5) }, - { Vec3crd(0,1,2), Vec3crd(1,0,3), Vec3crd(1,3,4), Vec3crd(4,3,5), Vec3crd(2,6,7), Vec3crd(6,2,1), Vec3crd(7,6,5), Vec3crd(7,5,3), Vec3crd(5,8,9), Vec3crd(8,5,6), Vec3crd(10,11,12), Vec3crd(11,10,13), Vec3crd(14,8,15), Vec3crd(8,14,9), Vec3crd(2,16,17), Vec3crd(16,2,15), Vec3crd(15,2,14), Vec3crd(14,10,12), Vec3crd(10,14,7), Vec3crd(7,14,2), Vec3crd(16,18,19), Vec3crd(18,16,20), Vec3crd(20,16,1), Vec3crd(1,16,8), Vec3crd(8,16,15), Vec3crd(6,1,8), Vec3crd(3,11,13), Vec3crd(11,3,21), Vec3crd(21,3,18), Vec3crd(18,22,19), Vec3crd(22,18,0), Vec3crd(0,18,3), Vec3crd(16,22,17), Vec3crd(22,16,19), Vec3crd(2,22,0), Vec3crd(22,2,17), Vec3crd(5,23,4), Vec3crd(23,11,21), Vec3crd(11,23,12), Vec3crd(12,23,9), Vec3crd(9,23,5), Vec3crd(12,9,14), Vec3crd(23,18,20), Vec3crd(18,23,21), Vec3crd(10,3,13), Vec3crd(3,10,7), Vec3crd(1,23,20), Vec3crd(23,1,4) }); + { {75,69.5,8}, {80,76.9091644287109,8}, {75,94.5,8}, {125,69.5,8}, {120,76.9091644287109,8}, {120,87.0908355712891,8}, {80,87.0908355712891,8}, {125,94.5,8}, {80,87.0908355712891,5}, {120,87.0908355712891,5}, {125,94.5,0}, {120,69.5,0}, {120,94.5,0}, {125,69.5,0}, {120,94.5,5}, {80,94.5,5}, {80,94.5,0}, {75,94.5,0}, {80,69.5,5}, {80,69.5,0}, {80,76.9091644287109,5}, {120,69.5,5}, {75,69.5,0}, {120,76.9091644287109,5} }, + { {0,1,2}, {1,0,3}, {1,3,4}, {4,3,5}, {2,6,7}, {6,2,1}, {7,6,5}, {7,5,3}, {5,8,9}, {8,5,6}, {10,11,12}, {11,10,13}, {14,8,15}, {8,14,9}, {2,16,17}, {16,2,15}, {15,2,14}, {14,10,12}, {10,14,7}, {7,14,2}, {16,18,19}, {18,16,20}, {20,16,1}, {1,16,8}, {8,16,15}, {6,1,8}, {3,11,13}, {11,3,21}, {21,3,18}, {18,22,19}, {22,18,0}, {0,18,3}, {16,22,17}, {22,16,19}, {2,22,0}, {22,2,17}, {5,23,4}, {23,11,21}, {11,23,12}, {12,23,9}, {9,23,5}, {12,9,14}, {23,18,20}, {18,23,21}, {10,3,13}, {3,10,7}, {1,23,20}, {23,1,4} }); break; case TestMesh::step: mesh = TriangleMesh( - { Vec3d(0,20,5), Vec3d(0,20,0), Vec3d(0,0,5), Vec3d(0,0,0), Vec3d(20,0,0), Vec3d(20,0,5), Vec3d(1,19,5), Vec3d(1,1,5), Vec3d(19,1,5), Vec3d(20,20,5), Vec3d(19,19,5), Vec3d(20,20,0), Vec3d(19,19,10), Vec3d(1,19,10), Vec3d(1,1,10), Vec3d(19,1,10) }, - { Vec3crd(0,1,2), Vec3crd(1,3,2), Vec3crd(3,4,5), Vec3crd(2,3,5), Vec3crd(6,0,2), Vec3crd(6,2,7), Vec3crd(5,8,7), Vec3crd(5,7,2), Vec3crd(9,10,8), Vec3crd(9,8,5), Vec3crd(9,0,6), Vec3crd(9,6,10), Vec3crd(9,11,1), Vec3crd(9,1,0), Vec3crd(3,1,11), Vec3crd(4,3,11), Vec3crd(5,11,9), Vec3crd(5,4,11), Vec3crd(12,10,6), Vec3crd(12,6,13), Vec3crd(6,7,14), Vec3crd(13,6,14), Vec3crd(7,8,15), Vec3crd(14,7,15), Vec3crd(15,8,10), Vec3crd(15,10,12), Vec3crd(12,13,14), Vec3crd(12,14,15) }); + { {0,20,5}, {0,20,0}, {0,0,5}, {0,0,0}, {20,0,0}, {20,0,5}, {1,19,5}, {1,1,5}, {19,1,5}, {20,20,5}, {19,19,5}, {20,20,0}, {19,19,10}, {1,19,10}, {1,1,10}, {19,1,10} }, + { {0,1,2}, {1,3,2}, {3,4,5}, {2,3,5}, {6,0,2}, {6,2,7}, {5,8,7}, {5,7,2}, {9,10,8}, {9,8,5}, {9,0,6}, {9,6,10}, {9,11,1}, {9,1,0}, {3,1,11}, {4,3,11}, {5,11,9}, {5,4,11}, {12,10,6}, {12,6,13}, {6,7,14}, {13,6,14}, {7,8,15}, {14,7,15}, {15,8,10}, {15,10,12}, {12,13,14}, {12,14,15} }); break; case TestMesh::slopy_cube: mesh = TriangleMesh( - { Vec3d(-10,-10,0), Vec3d(-10,-10,20), Vec3d(-10,10,0), Vec3d(-10,10,20), Vec3d(0,-10,10), Vec3d(10,-10,0), Vec3d(2.92893,-10,10), Vec3d(10,-10,2.92893), Vec3d(0,-10,20), Vec3d(10,10,0), Vec3d(0,10,10), Vec3d(0,10,20), Vec3d(2.92893,10,10), Vec3d(10,10,2.92893) }, - { Vec3crd(0,1,2), Vec3crd(2,1,3), Vec3crd(4,0,5), Vec3crd(4,1,0), Vec3crd(6,4,7), Vec3crd(7,4,5), Vec3crd(4,8,1), Vec3crd(0,2,5), Vec3crd(5,2,9), Vec3crd(2,10,9), Vec3crd(10,3,11), Vec3crd(2,3,10), Vec3crd(9,10,12), Vec3crd(13,9,12), Vec3crd(3,1,8), Vec3crd(11,3,8), Vec3crd(10,11,8), Vec3crd(4,10,8), Vec3crd(6,12,10), Vec3crd(4,6,10), Vec3crd(7,13,12), Vec3crd(6,7,12), Vec3crd(7,5,9), Vec3crd(13,7,9) }); + { {-10,-10,0}, {-10,-10,20}, {-10,10,0}, {-10,10,20}, {0,-10,10}, {10,-10,0}, {2.92893,-10,10}, {10,-10,2.92893}, {0,-10,20}, {10,10,0}, {0,10,10}, {0,10,20}, {2.92893,10,10}, {10,10,2.92893} }, + { {0,1,2}, {2,1,3}, {4,0,5}, {4,1,0}, {6,4,7}, {7,4,5}, {4,8,1}, {0,2,5}, {5,2,9}, {2,10,9}, {10,3,11}, {2,3,10}, {9,10,12}, {13,9,12}, {3,1,8}, {11,3,8}, {10,11,8}, {4,10,8}, {6,12,10}, {4,6,10}, {7,13,12}, {6,7,12}, {7,5,9}, {13,7,9} }); break; default: throw std::invalid_argument("Slic3r::Test::mesh(): called with invalid mesh ID"); diff --git a/tests/fff_print/test_trianglemesh.cpp b/tests/fff_print/test_trianglemesh.cpp index 6b467a511..233b0e515 100644 --- a/tests/fff_print/test_trianglemesh.cpp +++ b/tests/fff_print/test_trianglemesh.cpp @@ -18,8 +18,8 @@ using namespace std; SCENARIO( "TriangleMesh: Basic mesh statistics") { GIVEN( "A 20mm cube, built from constexpr std::array" ) { - std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -68,8 +68,8 @@ SCENARIO( "TriangleMesh: Basic mesh statistics") { } GIVEN( "A 20mm cube with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -121,8 +121,8 @@ SCENARIO( "TriangleMesh: Basic mesh statistics") { SCENARIO( "TriangleMesh: Transformation functions affect mesh as expected.") { GIVEN( "A 20mm cube with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -184,8 +184,8 @@ SCENARIO( "TriangleMesh: Transformation functions affect mesh as expected.") { SCENARIO( "TriangleMesh: slice behavior.") { GIVEN( "A 20mm cube with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -205,8 +205,8 @@ SCENARIO( "TriangleMesh: slice behavior.") { } } GIVEN( "A STL with an irregular shape.") { - const std::vector vertices {Vec3d(0,0,0),Vec3d(0,0,20),Vec3d(0,5,0),Vec3d(0,5,20),Vec3d(50,0,0),Vec3d(50,0,20),Vec3d(15,5,0),Vec3d(35,5,0),Vec3d(15,20,0),Vec3d(50,5,0),Vec3d(35,20,0),Vec3d(15,5,10),Vec3d(50,5,20),Vec3d(35,5,10),Vec3d(35,20,10),Vec3d(15,20,10)}; - const std::vector facets {Vec3crd(0,1,2),Vec3crd(2,1,3),Vec3crd(1,0,4),Vec3crd(5,1,4),Vec3crd(0,2,4),Vec3crd(4,2,6),Vec3crd(7,6,8),Vec3crd(4,6,7),Vec3crd(9,4,7),Vec3crd(7,8,10),Vec3crd(2,3,6),Vec3crd(11,3,12),Vec3crd(7,12,9),Vec3crd(13,12,7),Vec3crd(6,3,11),Vec3crd(11,12,13),Vec3crd(3,1,5),Vec3crd(12,3,5),Vec3crd(5,4,9),Vec3crd(12,5,9),Vec3crd(13,7,10),Vec3crd(14,13,10),Vec3crd(8,15,10),Vec3crd(10,15,14),Vec3crd(6,11,8),Vec3crd(8,11,15),Vec3crd(15,11,13),Vec3crd(14,15,13)}; + const std::vector vertices {{0,0,0},{0,0,20},{0,5,0},{0,5,20},{50,0,0},{50,0,20},{15,5,0},{35,5,0},{15,20,0},{50,5,0},{35,20,0},{15,5,10},{50,5,20},{35,5,10},{35,20,10},{15,20,10}}; + const std::vector facets {{0,1,2},{2,1,3},{1,0,4},{5,1,4},{0,2,4},{4,2,6},{7,6,8},{4,6,7},{9,4,7},{7,8,10},{2,3,6},{11,3,12},{7,12,9},{13,12,7},{6,3,11},{11,12,13},{3,1,5},{12,3,5},{5,4,9},{12,5,9},{13,7,10},{14,13,10},{8,15,10},{10,15,14},{6,11,8},{8,11,15},{15,11,13},{14,15,13}}; TriangleMesh cube(vertices, facets); cube.repair(); @@ -294,8 +294,8 @@ SCENARIO( "make_xxx functions produce meshes.") { SCENARIO( "TriangleMesh: split functionality.") { GIVEN( "A 20mm cube with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -308,8 +308,8 @@ SCENARIO( "TriangleMesh: split functionality.") { } } GIVEN( "Two 20mm cubes, each with one corner on the origin, merged into a single TriangleMesh") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -329,8 +329,8 @@ SCENARIO( "TriangleMesh: split functionality.") { SCENARIO( "TriangleMesh: Mesh merge functions") { GIVEN( "Two 20mm cubes, each with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); @@ -349,8 +349,8 @@ SCENARIO( "TriangleMesh: Mesh merge functions") { SCENARIO( "TriangleMeshSlicer: Cut behavior.") { GIVEN( "A 20mm cube with one corner on the origin") { - const std::vector vertices { Vec3d(20,20,0), Vec3d(20,0,0), Vec3d(0,0,0), Vec3d(0,20,0), Vec3d(20,20,20), Vec3d(0,20,20), Vec3d(0,0,20), Vec3d(20,0,20) }; - const std::vector facets { Vec3crd(0,1,2), Vec3crd(0,2,3), Vec3crd(4,5,6), Vec3crd(4,6,7), Vec3crd(0,4,7), Vec3crd(0,7,1), Vec3crd(1,7,6), Vec3crd(1,6,2), Vec3crd(2,6,5), Vec3crd(2,5,3), Vec3crd(4,0,3), Vec3crd(4,3,5) }; + const std::vector vertices { {20,20,0}, {20,0,0}, {0,0,0}, {0,20,0}, {20,20,20}, {0,20,20}, {0,0,20}, {20,0,20} }; + const std::vector facets { {0,1,2}, {0,2,3}, {4,5,6}, {4,6,7}, {0,4,7}, {0,7,1}, {1,7,6}, {1,6,2}, {2,6,5}, {2,5,3}, {4,0,3}, {4,3,5} }; TriangleMesh cube(vertices, facets); cube.repair(); diff --git a/tests/libslic3r/test_clipper_offset.cpp b/tests/libslic3r/test_clipper_offset.cpp index f40856a63..8209d99bf 100644 --- a/tests/libslic3r/test_clipper_offset.cpp +++ b/tests/libslic3r/test_clipper_offset.cpp @@ -15,7 +15,7 @@ SCENARIO("Constant offset", "[ClipperUtils]") { coord_t s = 1000000; GIVEN("20mm box") { ExPolygon box20mm; - box20mm.contour.points = { { 0, 0 }, { 20 * s, 0 }, { 20 * s, 20 * s}, { 0, 20 * s} }; + box20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 20 * s, 20 * s}, Vec2crd{ 0, 20 * s} }; std::vector deltas_plus(box20mm.contour.points.size(), 1. * s); std::vector deltas_minus(box20mm.contour.points.size(), - 1. * s); Polygons output; @@ -87,8 +87,8 @@ SCENARIO("Constant offset", "[ClipperUtils]") { GIVEN("20mm box with 10mm hole") { ExPolygon box20mm; - box20mm.contour.points = { { 0, 0 }, { 20 * s, 0 }, { 20 * s, 20 * s}, { 0, 20 * s} }; - box20mm.holes.emplace_back(Slic3r::Polygon({ { 5 * s, 5 * s }, { 5 * s, 15 * s}, { 15 * s, 15 * s}, { 15 * s, 5 * s } })); + box20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 20 * s, 20 * s}, Vec2crd{ 0, 20 * s} }; + box20mm.holes.emplace_back(Slic3r::Polygon({ Vec2crd{ 5 * s, 5 * s }, Vec2crd{ 5 * s, 15 * s}, Vec2crd{ 15 * s, 15 * s}, Vec2crd{ 15 * s, 5 * s } })); std::vector deltas_plus(box20mm.contour.points.size(), 1. * s); std::vector deltas_minus(box20mm.contour.points.size(), -1. * s); ExPolygons output; @@ -164,7 +164,7 @@ SCENARIO("Constant offset", "[ClipperUtils]") { GIVEN("20mm right angle triangle") { ExPolygon triangle20mm; - triangle20mm.contour.points = { { 0, 0 }, { 20 * s, 0 }, { 0, 20 * s} }; + triangle20mm.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 20 * s, 0 }, Vec2crd{ 0, 20 * s } }; Polygons output; double offset = 1.; // Angle of the sharp corner bisector. diff --git a/tests/libslic3r/test_clipper_utils.cpp b/tests/libslic3r/test_clipper_utils.cpp index 69e9d0efb..a660b29cb 100644 --- a/tests/libslic3r/test_clipper_utils.cpp +++ b/tests/libslic3r/test_clipper_utils.cpp @@ -246,7 +246,7 @@ TEST_CASE("Traversing Clipper PolyTree", "[ClipperUtils]") { // Create a polygon representing unit box Polygon unitbox; const auto UNIT = coord_t(1. / SCALING_FACTOR); - unitbox.points = {{0, 0}, {UNIT, 0}, {UNIT, UNIT}, {0, UNIT}}; + unitbox.points = { Vec2crd{0, 0}, Vec2crd{UNIT, 0}, Vec2crd{UNIT, UNIT}, Vec2crd{0, UNIT}}; Polygon box_frame = unitbox; box_frame.scale(20, 10); diff --git a/tests/libslic3r/test_elephant_foot_compensation.cpp b/tests/libslic3r/test_elephant_foot_compensation.cpp index 616c0c6ad..a571e8d03 100644 --- a/tests/libslic3r/test_elephant_foot_compensation.cpp +++ b/tests/libslic3r/test_elephant_foot_compensation.cpp @@ -519,7 +519,7 @@ SCENARIO("Elephant foot compensation", "[ElephantFoot]") { // Rectangle ExPolygon expoly; coord_t scaled_w = coord_t(scale_(10)); - expoly.contour.points = { { 0, 0 }, { 0, scaled_w, }, { scaled_w, scaled_w }, { scaled_w, 0 } }; + expoly.contour.points = { Vec2crd{ 0, 0 }, Vec2crd{ 0, scaled_w, }, Vec2crd{ scaled_w, scaled_w }, Vec2crd{ scaled_w, 0 } }; // Narrow part ExPolygon expoly2; coord_t scaled_h = coord_t(scale_(0.8));