Visual Computing Library
Loading...
Searching...
No Matches
save.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_LOAD_SAVE_OFF_SAVE_H
24#define VCL_LOAD_SAVE_OFF_SAVE_H
25
26#include <vclib/exceptions/io.h>
27#include <vclib/io/write.h>
28#include <vclib/load_save/settings.h>
29#include <vclib/misc/logger.h>
30#include <vclib/space/complex/mesh_info.h>
31
32namespace vcl {
33
34template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
35void saveOff(
36 const MeshType& m,
37 std::ostream& fp,
38 LogType& log = nullLogger,
39 const SaveSettings& settings = SaveSettings())
40{
41 MeshInfo meshInfo(m);
42
43 // make sure that the given info contains only components that are actually
44 // available in the mesh. meshInfo will contain the intersection between the
45 // components that the user wants to save and the components that are
46 // available in the mesh.
47 if (!settings.info.isEmpty())
48 meshInfo = settings.info.intersect(meshInfo);
49
50 if (meshInfo.hasVertexNormals())
51 fp << "N";
52 if (meshInfo.hasVertexColors())
53 fp << "C";
54 if (meshInfo.hasVertexTexCoords())
55 fp << "ST";
56 fp << "OFF" << std::endl;
57
58 uint vn = 0;
59 uint fn = 0;
60 uint en = 0;
61 if constexpr (HasVertices<MeshType>) {
62 vn = m.vertexNumber();
63 }
64 if constexpr (HasFaces<MeshType>) {
65 fn = m.faceNumber();
66 }
67
68 io::writeInt(fp, vn, false);
69 io::writeInt(fp, fn, false);
70 io::writeInt(fp, en, false);
71 fp << std::endl; // remove last char (a space) and add a newline
72
73 // vertices
74 if constexpr (HasVertices<MeshType>) {
75 using VertexType = MeshType::VertexType;
76 for (const VertexType& v : m.vertices()) {
77 io::writeDouble(fp, v.coord().x(), false);
78 io::writeDouble(fp, v.coord().y(), false);
79 io::writeDouble(fp, v.coord().z(), false);
80
81 if constexpr (HasPerVertexColor<MeshType>) {
82 if (meshInfo.hasVertexColors()) {
83 io::writeInt(fp, v.color().red(), false);
84 io::writeInt(fp, v.color().green(), false);
85 io::writeInt(fp, v.color().blue(), false);
86 io::writeInt(fp, v.color().alpha(), false);
87 }
88 }
89 if constexpr (HasPerVertexNormal<MeshType>) {
90 if (meshInfo.hasVertexNormals()) {
91 io::writeDouble(fp, v.normal().x(), false);
92 io::writeDouble(fp, v.normal().y(), false);
93 io::writeDouble(fp, v.normal().z(), false);
94 }
95 }
96 if constexpr (HasPerVertexTexCoord<MeshType>) {
97 if (meshInfo.hasVertexTexCoords()) {
98 io::writeDouble(fp, v.texCoord().u(), false);
99 io::writeDouble(fp, v.texCoord().v(), false);
100 }
101 }
102
103 fp << std::endl;
104 }
105 }
106
107 // faces
108 if constexpr (HasFaces<MeshType>) {
109 using VertexType = MeshType::VertexType;
110 using FaceType = MeshType::FaceType;
111
112 // indices of vertices that do not consider deleted vertices
113 std::vector<uint> vIndices = m.vertexCompactIndices();
114
115 for (const FaceType& f : m.faces()) {
116 io::writeInt(fp, f.vertexNumber(), false);
117 for (const VertexType* v : f.vertices()) {
118 io::writeInt(fp, vIndices[m.index(v)], false);
119 }
120 if constexpr (HasPerFaceColor<MeshType>) {
121 if (meshInfo.hasFaceColors()) {
122 io::writeInt(fp, f.color().red(), false);
123 io::writeInt(fp, f.color().green(), false);
124 io::writeInt(fp, f.color().blue(), false);
125 io::writeInt(fp, f.color().alpha(), false);
126 }
127 }
128
129 fp << std::endl;
130 }
131 }
132}
133
134template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
135void saveOff(
136 const MeshType& m,
137 std::ostream& fp,
138 const SaveSettings& settings,
139 LogType& log = nullLogger)
140{
141 saveOff(m, fp, log, settings);
142}
143
144template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
145void saveOff(
146 const MeshType& m,
147 const std::string& filename,
148 LogType& log = nullLogger,
149 const SaveSettings& settings = SaveSettings())
150{
151 std::ofstream fp = openOutputFileStream(filename, "off");
152 saveOff(m, fp, log, settings);
153 fp.close();
154}
155
156template<MeshConcept MeshType, LoggerConcept LogType = NullLogger>
157void saveOff(
158 const MeshType& m,
159 const std::string& filename,
160 const SaveSettings& settings,
161 LogType& log = nullLogger)
162{
163 saveOff(m, filename, log, settings);
164}
165
166} // namespace vcl
167
168#endif // VCL_LOAD_SAVE_OFF_SAVE_H
NullLogger nullLogger
The nullLogger object is an object of type NullLogger that is used as default argument in the functio...
Definition null_logger.h:125
constexpr detail::FacesView faces
A view that allows to iterate overt the Face elements of an object.
Definition face.h:52
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:60