23#ifndef VCL_IO_MESH_PLY_DETAIL_VERTEX_H
24#define VCL_IO_MESH_PLY_DETAIL_VERTEX_H
28#include <vclib/io/read.h>
29#include <vclib/io/write.h>
31#include <vclib/mesh.h>
33namespace vcl::detail {
35template<MeshConcept MeshType, VertexConcept VertexType,
typename Stream>
36void readPlyVertexProperty(
41 std::endian end = std::endian::little)
43 bool hasBeenRead =
false;
44 if (p.name >= ply::x && p.name <= ply::z) {
45 using Scalar = VertexType::PositionType::ScalarType;
46 int a = p.name - ply::x;
47 v.position()[a] = io::readPrimitiveType<Scalar>(file, p.type, end);
50 if (p.name >= ply::nx && p.name <= ply::nz) {
51 if constexpr (HasPerVertexNormal<MeshType>) {
52 if (isPerVertexNormalAvailable(mesh)) {
53 using Scalar = VertexType::NormalType::ScalarType;
54 int a = p.name - ply::nx;
56 io::readPrimitiveType<Scalar>(file, p.type, end);
61 if (p.name >= ply::red && p.name <= ply::alpha) {
62 if constexpr (HasPerVertexColor<MeshType>) {
63 if (isPerVertexColorAvailable(mesh)) {
64 int a = p.name - ply::red;
66 io::readPrimitiveType<unsigned char>(file, p.type, end);
71 if (p.name == ply::quality) {
72 if constexpr (HasPerVertexQuality<MeshType>) {
73 using QualityType = VertexType::QualityType;
74 if (isPerVertexQualityAvailable(mesh)) {
76 io::readPrimitiveType<QualityType>(file, p.type, end);
81 if (p.name >= ply::texture_u && p.name <= ply::texture_v) {
82 if constexpr (HasPerVertexTexCoord<MeshType>) {
83 using Scalar = VertexType::TexCoordType::ScalarType;
84 if (isPerVertexTexCoordAvailable(mesh)) {
85 int a = p.name - ply::texture_u;
87 io::readPrimitiveType<Scalar>(file, p.type, end);
92 if (p.name == ply::texnumber) {
93 if constexpr (HasPerVertexTexCoord<MeshType>) {
94 if (isPerVertexTexCoordAvailable(mesh)) {
95 v.texCoord().index() =
96 io::readPrimitiveType<ushort>(file, p.type, end);
101 if (p.name == ply::unknown) {
102 if constexpr (HasPerVertexCustomComponents<MeshType>) {
103 if (mesh.hasPerVertexCustomComponent(p.unknownPropertyName)) {
104 io::readCustomComponent(
105 file, v, p.unknownPropertyName, p.type, end);
112 uint s = io::readPrimitiveType<int>(file, p.listSizeType);
113 for (uint i = 0; i < s; ++i)
114 io::readPrimitiveType<int>(file, p.type, end);
117 io::readPrimitiveType<int>(file, p.type, end);
122template<VertexConcept VertexType, MeshConcept MeshType>
123void readPlyVertexTxt(
127 const std::list<PlyProperty>& vertexProperties)
129 Tokenizer spaceTokenizer = readAndTokenizeNextNonEmptyLine(file);
130 Tokenizer::iterator token = spaceTokenizer.begin();
131 for (
const PlyProperty& p : vertexProperties) {
132 if (token == spaceTokenizer.end()) {
133 throw MalformedFileException(
"Unexpected end of line.");
135 readPlyVertexProperty(token, mesh, v, p);
139template<VertexConcept VertexType, MeshConcept MeshType>
140void readPlyVertexBin(
144 const std::list<PlyProperty>& vertexProperties,
147 for (
const PlyProperty& p : vertexProperties) {
148 readPlyVertexProperty(file, mesh, v, p, end);
152template<MeshConcept MeshType>
153void writePlyVertices(
155 const PlyHeader& header,
156 const MeshType& mesh)
158 using VertexType = MeshType::VertexType;
161 if (header.format() == ply::ASCII) {
162 format.isBinary =
false;
164 else if (header.format() == ply::BINARY_BIG_ENDIAN) {
165 format.endian = std::endian::big;
168 for (
const VertexType& v : mesh.
vertices()) {
169 for (
const PlyProperty& p : header.vertexProperties()) {
170 bool hasBeenWritten =
false;
171 if (p.name >= ply::x && p.name <= ply::z) {
173 file, v.position()[p.name - ply::x], p.type, format);
174 hasBeenWritten =
true;
176 if (p.name >= ply::nx && p.name <= ply::nz) {
177 if constexpr (HasPerVertexNormal<MeshType>) {
179 file, v.normal()[p.name - ply::nx], p.type, format);
180 hasBeenWritten =
true;
183 if (p.name >= ply::red && p.name <= ply::alpha) {
184 if constexpr (HasPerVertexColor<MeshType>) {
186 file, v.color()[p.name - ply::red], p.type, format);
187 hasBeenWritten =
true;
190 if (p.name == ply::quality) {
191 if constexpr (HasPerVertexQuality<MeshType>) {
192 io::writeProperty(file, v.quality(), p.type, format);
193 hasBeenWritten =
true;
196 if (p.name >= ply::texture_u && p.name <= ply::texture_v) {
197 if constexpr (HasPerVertexTexCoord<MeshType>) {
198 const uint a = p.name - ply::texture_u;
199 io::writeProperty(file, v.texCoord()[a], p.type, format);
200 hasBeenWritten =
true;
203 if (p.name == ply::texnumber) {
204 if constexpr (HasPerVertexTexCoord<MeshType>) {
206 file, v.texCoord().index(), p.type, format);
207 hasBeenWritten =
true;
210 if (p.name == ply::unknown) {
211 if constexpr (HasPerVertexCustomComponents<MeshType>) {
212 if (mesh.hasPerVertexCustomComponent(
213 p.unknownPropertyName)) {
214 io::writeCustomComponent(
215 file, v, p.unknownPropertyName, p.type, format);
216 hasBeenWritten =
true;
220 if (!hasBeenWritten) {
223 io::writeProperty(file, 0, p.type, format);
226 if (!format.isBinary)
231template<MeshConcept MeshType, LoggerConcept LogType>
234 const PlyHeader& header,
238 m.addVertices(header.numberVertices());
240 log.startProgress(
"Reading vertices", header.numberVertices());
242 for (uint vid = 0; vid < header.numberVertices(); ++vid) {
243 auto& v = m.vertex(vid);
244 if (header.format() == ply::ASCII) {
245 detail::readPlyVertexTxt(file, v, m, header.vertexProperties());
248 std::endian end = header.format() == ply::BINARY_BIG_ENDIAN ?
251 detail::readPlyVertexBin(
252 file, v, m, header.vertexProperties(), end);
constexpr detail::VerticesView vertices
A view that allows to iterate over the Vertex elements of an object.
Definition vertex.h:92