From 21fddfef793c28c567be318a27362bbf080ad95d Mon Sep 17 00:00:00 2001 From: Fabio Pellacini Date: Tue, 22 Dec 2020 07:40:19 +0100 Subject: [PATCH] Mesh loading of STL and triangles only --- apps/ymeshproc/ymeshproc.cpp | 8 +- apps/ymeshtest/ymeshtest.cpp | 2 +- libs/yocto/yocto_mesh.cpp | 185 ++++++++++++++++++++++++++--------- libs/yocto/yocto_mesh.h | 16 ++- 4 files changed, 156 insertions(+), 55 deletions(-) diff --git a/apps/ymeshproc/ymeshproc.cpp b/apps/ymeshproc/ymeshproc.cpp index 8a4c63c69..f54cfaa67 100644 --- a/apps/ymeshproc/ymeshproc.cpp +++ b/apps/ymeshproc/ymeshproc.cpp @@ -34,7 +34,7 @@ using namespace yocto; // Shape presets used ofr testing. bool make_mesh_preset(vector& triangles, vector& positions, - vector& normals, vector& texcoords, vector& colors, + vector& normals, vector& texcoords, vector& colors, const string& type, string& error) { auto set_quads = [&](quads_shape&& shape) { triangles = quads_to_triangles(shape.quads); @@ -157,7 +157,7 @@ int main(int argc, const char* argv[]) { auto positions = vector{}; auto normals = vector{}; auto texcoords = vector{}; - auto colors = vector{}; + auto colors = vector{}; auto triangles = vector{}; auto lines = vector{}; // for line output @@ -231,10 +231,10 @@ int main(int argc, const char* argv[]) { if (tags[i] == 1) triangles[i] = {-1, -1, -1}; } } else { - colors = vector(positions.size()); + colors = vector(positions.size()); for (int i = 0; i < colors.size(); ++i) { auto c = sinf(geodesic_scale * field[i]); - colors[i] = vec3f{c, c, c}; + colors[i] = vec4f{c, c, c, 1}; } // distance_to_color(shape.colors, field, geodesic_scale); } diff --git a/apps/ymeshtest/ymeshtest.cpp b/apps/ymeshtest/ymeshtest.cpp index f53e63f8c..d0b5946e6 100644 --- a/apps/ymeshtest/ymeshtest.cpp +++ b/apps/ymeshtest/ymeshtest.cpp @@ -600,7 +600,7 @@ int main(int argc, const char* argv[]) { auto positions = vector{}; auto normals = vector{}; auto texcoords = vector{}; - auto colors = vector{}; + auto colors = vector{}; auto triangles = vector{}; // stats, progress diff --git a/libs/yocto/yocto_mesh.cpp b/libs/yocto/yocto_mesh.cpp index 4323d708c..859036bae 100644 --- a/libs/yocto/yocto_mesh.cpp +++ b/libs/yocto/yocto_mesh.cpp @@ -2633,10 +2633,21 @@ mesh_point eval_path_point(const geodesic_path& path, // ----------------------------------------------------------------------------- namespace yocto { +// Convert quads to triangles +static vector quads_to_triangles(const vector& quads) { + auto triangles = vector{}; + triangles.reserve(quads.size() * 2); + for (auto& q : quads) { + triangles.push_back({q.x, q.y, q.w}); + if (q.z != q.w) triangles.push_back({q.z, q.w, q.y}); + } + return triangles; +} + // Load ply mesh bool load_mesh(const string& filename, vector& triangles, vector& positions, vector& normals, vector& texcoords, - vector& colors, string& error, bool flip_texcoord) { + vector& colors, string& error, bool flip_texcoord) { auto format_error = [filename, &error]() { error = filename + ": unknown format"; return false; @@ -2658,16 +2669,13 @@ bool load_mesh(const string& filename, vector& triangles, auto ply_guard = std::make_unique(); auto ply = ply_guard.get(); if (!load_ply(filename, ply, error)) return false; - // gets vertex get_positions(ply, positions); get_normals(ply, normals); get_texcoords(ply, texcoords, flip_texcoord); get_colors(ply, colors); - // get faces get_triangles(ply, triangles); - if (positions.empty()) return shape_error(); return true; } else if (ext == ".obj" || ext == ".OBJ") { @@ -2675,24 +2683,16 @@ bool load_mesh(const string& filename, vector& triangles, auto obj_guard = std::make_unique(); auto obj = obj_guard.get(); if (!load_obj(filename, obj, error, true)) return false; - // get shape if (obj->shapes.empty()) return shape_error(); if (obj->shapes.size() > 1) return shape_error(); auto shape = obj->shapes.front(); - if (shape->points.empty() && shape->lines.empty() && shape->faces.empty()) - return shape_error(); - + if (shape->faces.empty()) return shape_error(); // decide what to do and get properties auto materials = vector{}; auto ematerials = vector{}; - if (!shape->faces.empty()) { - get_triangles(shape, triangles, positions, normals, texcoords, materials, - ematerials, flip_texcoord); - } else { - return shape_error(); - } - + get_triangles(shape, triangles, positions, normals, texcoords, materials, + ematerials, flip_texcoord); if (positions.empty()) return shape_error(); return true; } else { @@ -2703,7 +2703,7 @@ bool load_mesh(const string& filename, vector& triangles, // Save ply mesh bool save_mesh(const string& filename, const vector& triangles, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, string& error, + const vector& texcoords, const vector& colors, string& error, bool ascii, bool flip_texcoord) { auto format_error = [filename, &error]() { error = filename + ": unknown format"; @@ -2730,15 +2730,126 @@ bool save_mesh(const string& filename, const vector& triangles, auto obj_guard = std::make_unique(); auto obj = obj_guard.get(); auto oshape = add_shape(obj); - if (!triangles.empty()) { - set_triangles( - oshape, triangles, positions, normals, texcoords, {}, flip_texcoord); - } else { + if (triangles.empty()) return shape_error(); + set_triangles( + oshape, triangles, positions, normals, texcoords, {}, flip_texcoord); + if (!save_obj(filename, obj, error)) return false; + return true; + } else if (ext == ".stl" || ext == ".STL") { + auto stl_guard = std::make_unique(); + auto stl = stl_guard.get(); + if (triangles.empty()) return shape_error(); + add_triangles(stl, triangles, positions, {}); + if (!save_stl(filename, stl, error)) return false; + return true; + } else { + return format_error(); + } +} + +// Load ply mesh +bool load_mesh(const string& filename, vector& triangles, + vector& positions, string& error) { + auto format_error = [filename, &error]() { + error = filename + ": unknown format"; + return false; + }; + auto shape_error = [filename, &error]() { + error = filename + ": empty shape"; + return false; + }; + + triangles = {}; + positions = {}; + + auto ext = path_extension(filename); + if (ext == ".ply" || ext == ".PLY") { + // open ply + auto ply_guard = std::make_unique(); + auto ply = ply_guard.get(); + if (!load_ply(filename, ply, error)) return false; + get_positions(ply, positions); + get_triangles(ply, triangles); + if (positions.empty()) return shape_error(); + return true; + } else if (ext == ".obj" || ext == ".OBJ") { + // load obj + auto obj_guard = std::make_unique(); + auto obj = obj_guard.get(); + if (!load_obj(filename, obj, error, true)) return false; + // get shape + if (obj->shapes.empty()) return shape_error(); + if (obj->shapes.size() > 1) return shape_error(); + auto shape = obj->shapes.front(); + if (shape->faces.empty()) return shape_error(); + // decide what to do and get properties + auto materials = vector{}; + auto ematerials = vector{}; + auto quadspos = vector{}; + auto quadsnorm = vector{}; + auto quadstexcoord = vector{}; + auto normals = vector{}; + auto texcoords = vector{}; + get_fvquads(shape, quadspos, quadsnorm, quadstexcoord, positions, normals, + texcoords, materials, ematerials); + triangles = quads_to_triangles(quadspos); + if (positions.empty()) return shape_error(); + return true; + } else if (ext == ".stl" || ext == ".STL") { + // open ply + auto stl_guard = std::make_unique(); + auto stl = stl_guard.get(); + if (!load_stl(filename, stl, error)) return false; + if (stl->shapes.empty()) return shape_error(); + if (stl->shapes.size() > 1) return shape_error(); + auto fnormals = vector{}; + if (!get_triangles(stl, 0, triangles, positions, fnormals)) return shape_error(); - } + if (positions.empty()) return shape_error(); + return true; + } else { + return format_error(); + } +} + +// Save ply mesh +bool save_mesh(const string& filename, const vector& triangles, + const vector& positions, string& error, bool ascii) { + auto format_error = [filename, &error]() { + error = filename + ": unknown format"; + return false; + }; + auto shape_error = [filename, &error]() { + error = filename + ": empty shape"; + return false; + }; + + auto ext = path_extension(filename); + if (ext == ".ply" || ext == ".PLY") { + // create ply + auto ply_guard = std::make_unique(); + auto ply = ply_guard.get(); + if (triangles.empty()) return shape_error(); + add_positions(ply, positions); + add_triangles(ply, triangles); + if (!save_ply(filename, ply, error)) return false; + return true; + } else if (ext == ".obj" || ext == ".OBJ") { + auto obj_guard = std::make_unique(); + auto obj = obj_guard.get(); + auto oshape = add_shape(obj); + if (triangles.empty()) return shape_error(); + set_triangles(oshape, triangles, positions, {}, {}, {}); auto err = ""s; if (!save_obj(filename, obj, error)) return false; return true; + } else if (ext == ".stl" || ext == ".STL") { + auto stl_guard = std::make_unique(); + auto stl = stl_guard.get(); + if (triangles.empty()) return shape_error(); + add_triangles(stl, triangles, positions, {}); + if (!save_stl(filename, stl, error)) return false; + return true; } else { return format_error(); } @@ -2747,7 +2858,7 @@ bool save_mesh(const string& filename, const vector& triangles, // Load ply mesh bool load_lines(const string& filename, vector& lines, vector& positions, vector& normals, vector& texcoords, - vector& colors, string& error, bool flip_texcoord) { + vector& colors, string& error, bool flip_texcoord) { auto format_error = [filename, &error]() { error = filename + ": unknown format"; return false; @@ -2769,16 +2880,13 @@ bool load_lines(const string& filename, vector& lines, auto ply_guard = std::make_unique(); auto ply = ply_guard.get(); if (!load_ply(filename, ply, error)) return false; - // gets vertex get_positions(ply, positions); get_normals(ply, normals); get_texcoords(ply, texcoords, flip_texcoord); get_colors(ply, colors); - // get faces get_lines(ply, lines); - if (positions.empty()) return shape_error(); return true; } else if (ext == ".obj" || ext == ".OBJ") { @@ -2786,24 +2894,16 @@ bool load_lines(const string& filename, vector& lines, auto obj_guard = std::make_unique(); auto obj = obj_guard.get(); if (!load_obj(filename, obj, error, true)) return false; - // get shape if (obj->shapes.empty()) return shape_error(); if (obj->shapes.size() > 1) return shape_error(); auto shape = obj->shapes.front(); - if (shape->points.empty() && shape->lines.empty() && shape->faces.empty()) - return shape_error(); - + if (shape->lines.empty()) return shape_error(); // decide what to do and get properties auto materials = vector{}; auto ematerials = vector{}; - if (!shape->faces.empty()) { - get_lines(shape, lines, positions, normals, texcoords, materials, - ematerials, flip_texcoord); - } else { - return shape_error(); - } - + get_lines(shape, lines, positions, normals, texcoords, materials, + ematerials, flip_texcoord); if (positions.empty()) return shape_error(); return true; } else { @@ -2814,7 +2914,7 @@ bool load_lines(const string& filename, vector& lines, // Save ply mesh bool save_lines(const string& filename, const vector& lines, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, string& error, + const vector& texcoords, const vector& colors, string& error, bool ascii, bool flip_texcoord) { auto format_error = [filename, &error]() { error = filename + ": unknown format"; @@ -2841,13 +2941,8 @@ bool save_lines(const string& filename, const vector& lines, auto obj_guard = std::make_unique(); auto obj = obj_guard.get(); auto oshape = add_shape(obj); - if (!lines.empty()) { - set_lines( - oshape, lines, positions, normals, texcoords, {}, flip_texcoord); - } else { - return shape_error(); - } - auto err = ""s; + if (lines.empty()) return shape_error(); + set_lines(oshape, lines, positions, normals, texcoords, {}, flip_texcoord); if (!save_obj(filename, obj, error)) return false; return true; } else { @@ -2864,7 +2959,7 @@ namespace yocto { vector mesh_stats(const vector& triangles, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, bool verbose) { + const vector& texcoords, const vector& colors, bool verbose) { auto format = [](auto num) { auto str = std::to_string(num); while (str.size() < 13) str = " " + str; diff --git a/libs/yocto/yocto_mesh.h b/libs/yocto/yocto_mesh.h index 0dd6f479b..d73433ad7 100644 --- a/libs/yocto/yocto_mesh.h +++ b/libs/yocto/yocto_mesh.h @@ -391,21 +391,27 @@ namespace yocto { // Load/save a shape as indexed meshes bool load_mesh(const string& filename, vector& triangles, vector& positions, vector& normals, vector& texcoords, - vector& colors, string& error, bool flip_texcoords = true); + vector& colors, string& error, bool flip_texcoords = true); bool save_mesh(const string& filename, const vector& triangles, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, string& error, + const vector& texcoords, const vector& colors, string& error, bool ascii = false, bool flip_texcoords = true); // Load/save a set of lines bool load_lines(const string& filename, vector& lines, vector& positions, vector& normals, vector& texcoords, - vector& colors, string& error, bool flip_texcoords = true); + vector& colors, string& error, bool flip_texcoords = true); bool save_lines(const string& filename, const vector& lines, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, string& error, + const vector& texcoords, const vector& colors, string& error, bool ascii = false, bool flip_texcoords = true); +// Load/save a shape as indexed meshes +bool load_mesh(const string& filename, vector& triangles, + vector& positions, string& error); +bool save_mesh(const string& filename, const vector& triangles, + const vector& positions, string& error, bool ascii = false); + } // namespace yocto // ----------------------------------------------------------------------------- @@ -416,7 +422,7 @@ namespace yocto { // Get mesh statistics for printing vector mesh_stats(const vector& triangles, const vector& positions, const vector& normals, - const vector& texcoords, const vector& colors, + const vector& texcoords, const vector& colors, bool verbose = false); } // namespace yocto