flippy
a c++20 package for dynamically triangulated membrane simulations.
Loading...
Searching...
No Matches
stlSerializer.hpp
1#ifndef FLIPPY_HPP_STLSERIALIZER_HPP
2#define FLIPPY_HPP_STLSERIALIZER_HPP
3
4#include <fstream>
5#include <vector>
6#include "vec3.hpp"
7
8
9namespace fp::implementation {
11 float normal[3]{};
12 float v1[3]{};
13 float v2[3]{};
14 float v3[3]{};
15
16 uint16_t attr_byte_count{0};
17 };
18
19 struct rawSTLSolid {
20 char header[80]{};
21 uint32_t num_triangles{};
22 std::vector<rawSTLTriangle> stl_triangles;
23 };
24
25 [[maybe_unused]] static void printSTLTriangle(rawSTLTriangle const &triangle, std::optional<std::string> const &name = std::nullopt) {
26 if (name) {std::cout << name.value() << '\n';}
27 std::cout << triangle.normal[0] << ' ' << triangle.normal[1] << ' ' << triangle.normal[2] << '\n';
28 std::cout << triangle.v1[0] << ' ' << triangle.v1[1] << ' ' << triangle.v1[2] << '\n';
29 std::cout << triangle.v2[0] << ' ' << triangle.v2[1] << ' ' << triangle.v2[2] << '\n';
30 std::cout << triangle.v3[0] << ' ' << triangle.v3[1] << ' ' << triangle.v3[2] << '\n';
31 std::cout << "------------------------------------------------------------------\n";
32 }
33
34 static inline rawSTLTriangle loadSTLTriangle(std::ifstream &inp) {
35 rawSTLTriangle triangle;
36 inp.read(reinterpret_cast<char *>(&triangle), 50 /*sizeof(STLTriangle)*/);
37 return triangle;
38 }
39
40 static inline rawSTLSolid loadSTLSolid(std::ifstream &inp) {
41 rawSTLSolid solid;
42 inp.read(reinterpret_cast<char *>(&solid.header), sizeof(rawSTLSolid::header));
43 inp.read(reinterpret_cast<char *>(&solid.num_triangles), sizeof(rawSTLSolid::num_triangles));
44 std::vector<rawSTLTriangle> triangles;
45 triangles.reserve(solid.num_triangles);
46// std::cout << "loading STL solid with: " << solid.num_triangles << " triangles'\n";
47 for (uint32_t i = 0; i < solid.num_triangles; ++i) {
48 triangles.push_back(loadSTLTriangle(inp));
49 }
50 solid.stl_triangles = std::move(triangles);
51 return solid;
52 }
53
54 template<fp::floating_point_number Real, fp::indexing_number Index>
55 struct stlNode {
56 Index id;
57 vec3<Real> pos;
58
59 bool operator==(stlNode const &other) const {
60 return pos == other.pos;
61 }
62 };
63
64
65 template<fp::floating_point_number Real, fp::indexing_number Index>
67 vec3<Real> normal_{};
68
69 static vec3<Real> make_normal(stlNode<Real,Index> const &n1,
70 stlNode<Real,Index> const &n2,
71 stlNode<Real,Index> const &n3) {
72 return -1 * (n2.pos - n1.pos).cross(n3.pos - n1.pos).normalize();
73 }
74
75 public:
79
80 stlTriangle(stlNode<Real,Index> &n1_inp, stlNode<Real,Index> &n2_inp, stlNode<Real,Index> &n3_inp, vec3<float> const &normal_inp)
81 : normal_(normal_inp), n1_(n1_inp), n2_(n2_inp), n3_(n3_inp) {}
82
84 : stlTriangle(n1_inp, n2_inp, n3_inp, make_normal(n1_inp, n2_inp, n3_inp)) {}
85
86 explicit stlTriangle(rawSTLTriangle const &stl_triangle):
87 normal_({stl_triangle.normal[0], stl_triangle.normal[1], stl_triangle.normal[2]}),
88 n1_({.id=0, .pos={stl_triangle.v1[0], stl_triangle.v1[1], stl_triangle.v1[2]}}),
89 n2_({.id=0, .pos={stl_triangle.v2[0], stl_triangle.v2[1], stl_triangle.v2[2]}}),
90 n3_({.id=0, .pos={stl_triangle.v3[0], stl_triangle.v3[1], stl_triangle.v3[2]}})
91 {}
92
93 [[nodiscard]] vec3<float> const &normal() const {return normal_;}
94
95 [[nodiscard]] rawSTLTriangle to_stl_triangle() const {
96
97 rawSTLTriangle tr{.normal = {normal_.x, normal_.y, normal_.z}, .v1 = {n1_.pos.x, n1_.pos.y, n1_.pos.z}, .v2 = {n2_.pos.x, n2_.pos.y, n2_.pos.z}, .v3 = {n3_.pos.x, n3_.pos.y, n3_.pos.z}, .attr_byte_count=0};
98 return tr;
99 };
100
101 std::pair<Index, Index> other_node_ids(Index loc_node_id){
102 switch (loc_node_id) {
103 case 0:return {n2_.id, n3_.id};
104 case 1:return {n1_.id, n3_.id};
105 case 2:return {n1_.id, n2_.id};
106 default:std::cerr << loc_node_id << "is out of range for as stlTriangl index";
107 exit(12);
108 }
109 }
110
111 stlNode<Real,Index>& operator[](Index idx)
112 {
113 switch (idx) {
114 case 0:return n1_;
115 case 1:return n2_;
116 case 2:return n3_;
117 default:std::cerr << idx << "is out of range for as stlTriangl index";
118 exit(12);
119 }
120 }
121 };
122
123 template<fp::floating_point_number Real, fp::indexing_number Index> class stlSerializer {
124 static std::vector<stlTriangle<Real, Index>> solidTostlTriangls(rawSTLSolid const &solid) {
125 std::vector<stlTriangle<Real, Index>> triangles;
126 triangles.reserve(solid.num_triangles);
127 for (auto const &stl_triangle : solid.stl_triangles) {
128 triangles.emplace_back(stl_triangle);
129 }
130 return triangles;
131 }
132
133 public:
134
135
136 static std::vector<stlTriangle<Real, Index>> read_STLSolid_into_triangle_vec(std::filesystem::path const &input_file) {
137 std::ifstream inp(input_file, std::ios::in | std::ios::binary);
138 rawSTLSolid solid{loadSTLSolid(inp)};
139 inp.close();
140
141 std::vector<stlTriangle<Real, Index>> triangles{solidTostlTriangls(solid)};
142
143 return triangles;
144 }
145 };
146
147}
148
149#endif //FLIPPY_HPP_STLSERIALIZER_HPP
Definition stlSerializer.hpp:123
Definition stlSerializer.hpp:66
Internal implementation of a 3D vector.
Definition vec3.hpp:43
vec3< Real > const & normalize()
Normalize the vector in place. And return a reference to the new normalized vector.
Definition vec3.hpp:184
Definition custom_concepts.hpp:38
Definition stlSerializer.hpp:19
Definition stlSerializer.hpp:10
Definition stlSerializer.hpp:55
Header file containing the definition and implementation a 3 dimensional vector class,...