23#ifndef VCL_IO_MESH_STL_SAVE_H
24#define VCL_IO_MESH_STL_SAVE_H
26#include <vclib/io/mesh/settings.h>
27#include <vclib/io/write.h>
29#include <vclib/algorithms/core.h>
30#include <vclib/space/complex.h>
36inline void writeStlHeader(std::ostream& fp,
const SaveSettings& settings)
38 std::string header =
"solid STL generated by VCLib";
39 if (settings.binary) {
40 if (settings.magicsMode) {
42 for (uint i = 0; i < 3; i++)
43 p.push_back((
char) 0x7f);
44 header =
"COLOR=" + p +
" MATERIAL=" + p +
" " + p +
" " + p;
46 while (header.size() < 80)
47 header.push_back(
' ');
55template<Po
int3Concept Po
intType, Po
int3Concept NormalType>
63 const SaveSettings& settings)
65 if (settings.binary) {
66 for (uint i = 0; i < 3; ++i)
67 io::writeFloat(fp, n[i]);
69 for (uint i = 0; i < 3; ++i)
70 io::writeFloat(fp, p0[i]);
72 for (uint i = 0; i < 3; ++i)
73 io::writeFloat(fp, p1[i]);
75 for (uint i = 0; i < 3; ++i)
76 io::writeFloat(fp, p2[i]);
78 io::writeUShort(fp, attributes);
81 fp <<
" facet normal " << n.x() <<
" " << n.y() <<
" " << n.z()
83 fp <<
" outer loop" << std::endl;
85 fp <<
" vertex " << p0.x() <<
" " << p0.y() <<
" " << p0.z()
87 fp <<
" vertex " << p1.x() <<
" " << p1.y() <<
" " << p1.z()
89 fp <<
" vertex " << p2.x() <<
" " << p2.y() <<
" " << p2.z()
92 fp <<
" endloop" << std::endl;
93 fp <<
" endfacet" << std::endl;
99template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
103 const SaveSettings& settings = SaveSettings(),
106 MeshInfo meshInfo(m);
112 if (!settings.info.isEmpty())
113 meshInfo = settings.info.intersect(meshInfo);
115 log.log(0,
"Saving STL file");
117 detail::writeStlHeader(fp, settings);
119 if constexpr (HasFaces<MeshType>) {
120 using FaceType = MeshType::FaceType;
122 if (settings.binary) {
123 io::writeInt(fp, m.faceNumber());
126 log.startProgress(
"Saving STL file", m.faceNumber());
128 for (
const FaceType& f : m.
faces()) {
133 unsigned short attributes = 0;
135 if constexpr (HasPerFaceColor<MeshType>) {
136 if (meshInfo.hasPerFaceColor()) {
137 if (settings.magicsMode)
138 attributes = 32768 | f.color().bgr5();
140 attributes = 32768 | f.color().rgb5();
144 if (f.vertexNumber() == 3) {
145 detail::writeSTLTriangle(
147 f.vertex(0)->position(),
148 f.vertex(1)->position(),
149 f.vertex(2)->position(),
155 std::vector<uint> tris =
earCut(f);
156 for (uint i = 0; i < tris.size(); i += 3) {
157 detail::writeSTLTriangle(
159 f.vertex(tris[i])->position(),
160 f.vertex(tris[i + 1])->position(),
161 f.vertex(tris[i + 2])->position(),
168 log.progress(m.index(f));
174 if (!settings.binary) {
175 fp <<
"endsolid VCLib" << std::endl;
179template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
182 const std::string& filename,
183 const SaveSettings& settings = SaveSettings(),
186 std::ofstream fp = openOutputFileStream(filename,
"stl");
188 saveStl(m, fp, settings, log);
NullLogger nullLogger
The nullLogger object is an object of type NullLogger that is used as default argument in the functio...
Definition null_logger.h:123
FaceType::VertexType::PositionType faceNormal(const FaceType &f)
Computes the normal of a face, without modifying the face. Works both for triangle and polygonal face...
Definition geometry.h:46
std::vector< uint > earCut(Iterator begin, Iterator end)
Triangulates a simple polygon with no holes using the ear-cutting algorithm.
Definition ear_cut.h:90
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:84