From 60ac88168053e916dbe0b8e0be3cda0096fc3a15 Mon Sep 17 00:00:00 2001 From: Ton van den Heuvel Date: Mon, 2 Jan 2023 18:57:48 +0100 Subject: [PATCH] Add tinyply 2.3 benchmarks Note; parsing of ASCII PLY files is not benchmarked as ASCII support in tinyply 2.3 seems to be broken (https://github.com/ddiakopoulos/tinyply/issues/59). --- .gitmodules | 3 +++ CMakeLists.txt | 1 + src/parsers.cpp | 33 ++++++++++++++++++++++++++++++++- src/parsers.h | 1 + src/plybench.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/tests.cpp | 27 ++++++++++++++++++++++++++- src/writers.cpp | 19 +++++++++++++++++++ src/writers.h | 1 + submodules/tinyply | 1 + 9 files changed, 121 insertions(+), 2 deletions(-) create mode 160000 submodules/tinyply diff --git a/.gitmodules b/.gitmodules index 209bb81..a09ad0e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "submodules/vcglib"] path = submodules/vcglib url = https://github.com/cnr-isti-vclab/vcglib +[submodule "submodules/tinyply"] + path = submodules/tinyply + url = https://github.com/ddiakopoulos/tinyply diff --git a/CMakeLists.txt b/CMakeLists.txt index 22f1c09..8d62def 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ add_library(msh_ply OBJECT # and unit test applications. add_library(PLYbench OBJECT submodules/miniply/miniply.cpp + submodules/tinyply/source/tinyply.cpp submodules/vcglib/wrap/ply/plylib.cpp src/parsers.cpp src/util.cpp diff --git a/src/parsers.cpp b/src/parsers.cpp index 2577aab..95ea0d1 100644 --- a/src/parsers.cpp +++ b/src/parsers.cpp @@ -7,12 +7,14 @@ #include #include #include +#include +#include +#include #include #include #include #include -#include #include std::optional parseHapply(const std::string &filename) @@ -326,3 +328,32 @@ std::optional parseRPly(const std::string &filename) return mesh; } + +std::optional parseTinyply(const std::string &filename) +{ + using namespace tinyply; + + std::ifstream ifs(filename); + + std::vector buffer = read_file_binary(filename); + memory_stream is{(char *)buffer.data(), buffer.size()}; + + PlyFile file; + file.parse_header(is); + + const std::shared_ptr vertices = + file.request_properties_from_element("vertex", {"x", "y", "z"}); + const std::shared_ptr triangles = + file.request_properties_from_element("face", {"vertex_indices"}, 3); + + file.read(is); + + TriangleMesh mesh; + mesh.vertices.resize(vertices->count); + mesh.triangles.resize(triangles->count); + + std::memcpy(mesh.vertices.data(), vertices->buffer.get(), vertices->buffer.size_bytes()); + std::memcpy(mesh.triangles.data(), triangles->buffer.get(), triangles->buffer.size_bytes()); + + return mesh; +} diff --git a/src/parsers.h b/src/parsers.h index 3cbeab6..1faa258 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -12,3 +12,4 @@ std::optional parseNanoPly(const std::string &filename); std::optional parsePlyLib(const std::string &filename); std::optional parsePlywoot(const std::string &filename); std::optional parseRPly(const std::string &filename); +std::optional parseTinyply(const std::string &filename); diff --git a/src/plybench.cpp b/src/plybench.cpp index baee3a6..7597d97 100644 --- a/src/plybench.cpp +++ b/src/plybench.cpp @@ -164,6 +164,33 @@ static void BM_WriteRPly(benchmark::State &state, Format format) state.SetBytesProcessed(state.iterations() * meshSizeInBytes(mesh)); } +static void BM_ParseTinyply(benchmark::State &state, const std::string &filename) +{ + benchmark::ClobberMemory(); + + std::optional maybeMesh; + for (auto _ : state) + { + if (!(maybeMesh = parseTinyply(filename))) + state.SkipWithError((std::string{"could not parse '"} + filename + "' with tinyply").data()); + } + + if (maybeMesh) state.SetBytesProcessed(state.iterations() * meshSizeInBytes(*maybeMesh)); +} + +static void BM_WriteTinyply(benchmark::State &state, Format format) +{ + benchmark::ClobberMemory(); + + const TriangleMesh mesh{createMesh()}; + for (auto _ : state) { writeTinyply(mesh, format); } + + state.SetBytesProcessed(state.iterations() * meshSizeInBytes(mesh)); +} + +// Note; tinyply 2.3 seems to be broken for ASCII +// (https://github.com/ddiakopoulos/tinyply/issues/59) + #define BENCHMARK_PARSE(name, filename) \ BENCHMARK_CAPTURE(BM_ParseHapply, (name), (filename))->Unit(benchmark::kMillisecond); \ BENCHMARK_CAPTURE(BM_ParseMiniply, (name), (filename))->Unit(benchmark::kMillisecond); \ @@ -174,9 +201,16 @@ static void BM_WriteRPly(benchmark::State &state, Format format) BENCHMARK_CAPTURE(BM_ParseRPly, (name), (filename))->Unit(benchmark::kMillisecond); BENCHMARK_PARSE("Asian Dragon (binary b/e)", "models/xyzrgb_dragon.ply") +BENCHMARK_CAPTURE(BM_ParseTinyply, "Asian Dragon (binary b/e)", "models/xyzrgb_dragon.ply") + ->Unit(benchmark::kMillisecond); + BENCHMARK_PARSE("Lucy (binary b/e)", "models/lucy.ply"); +BENCHMARK_CAPTURE(BM_ParseTinyply, "Lucy (binary b/e)", "models/lucy.ply") + ->Unit(benchmark::kMillisecond); BENCHMARK_PARSE("DOOM Combat Scene (binary l/e)", "models/Doom combat scene.ply"); +BENCHMARK_CAPTURE(BM_ParseTinyply, "DOOM Combat Scene (binary l/e)", "models/Doom combat scene.ply") + ->Unit(benchmark::kMillisecond); BENCHMARK_PARSE("Dragon (ASCII)", "models/dragon_vrip.ply"); BENCHMARK_PARSE("Happy Buddha (ASCII)", "models/happy_vrip.ply"); @@ -197,5 +231,8 @@ BENCHMARK_CAPTURE(BM_WritePlywoot, "Binary", Format::BinaryLittleEndian) BENCHMARK_CAPTURE(BM_WriteRPly, "ASCII", Format::Ascii)->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(BM_WriteRPly, "Binary", Format::BinaryLittleEndian) ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_WriteTinyply, "ASCII", Format::Ascii)->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_WriteTinyply, "Binary", Format::BinaryLittleEndian) + ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); diff --git a/src/tests.cpp b/src/tests.cpp index 3e02f59..0eb8b88 100644 --- a/src/tests.cpp +++ b/src/tests.cpp @@ -1,8 +1,8 @@ #include "mesh.h" #include "mesh_ios.h" #include "parsers.h" -#include "writers.h" #include "util.h" +#include "writers.h" #include #include @@ -128,6 +128,20 @@ TEST_CASE("Verify parsers against PLYwoot") } } +// Note; tinyply 2.3 is broken for ASCII PLY files (see: +// https://github.com/ddiakopoulos/tinyply/issues/59). +TEST_CASE("Verify tinyply against PLYwoot") +{ + auto filename = GENERATE("lucy.ply", "xyzrgb_dragon.ply", "Doom combat scene.ply"); + + const auto plywootMesh = parsePlywoot(std::string("models/") + filename); + + auto mesh = parseTinyply(std::string("models/") + filename); + + INFO(std::string{filename} + ": " + meshComparisonInfo(mesh, plywootMesh, "tinyply", "PLYwoot")); + CHECK(mesh == plywootMesh); +} + TEST_CASE("Test functionality of various writer libraries") { auto format = GENERATE(Format::Ascii, Format::BinaryLittleEndian); @@ -188,6 +202,17 @@ TEST_CASE("Test functionality of various writer libraries") REQUIRE(maybeMesh.has_value()); CHECK(mesh == *maybeMesh); } + + SECTION(std::string{"tinyply ("} + formatToString(format) + ')') + { + TemporaryFile tf = writeTinyply(mesh, format); + REQUIRE(bool(tf)); + tf.stream().flush(); + + const std::optional maybeMesh = parsePlywoot(tf.filename()); + REQUIRE(maybeMesh.has_value()); + CHECK(mesh == *maybeMesh); + } } int main(int argc, char *argv[]) { return Catch::Session().run(argc, argv); } diff --git a/src/writers.cpp b/src/writers.cpp index c310d57..786a5fc 100644 --- a/src/writers.cpp +++ b/src/writers.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -217,3 +218,21 @@ TemporaryFile writeRPly(const TriangleMesh &mesh, Format format) return tf; } + +TemporaryFile writeTinyply(const TriangleMesh &mesh, Format format) +{ + TemporaryFile tf; + + tinyply::PlyFile outFile; + outFile.add_properties_to_element( + "vertex", {"x", "y", "z"}, tinyply::Type::FLOAT32, mesh.vertices.size(), + reinterpret_cast(const_cast(mesh.vertices.data())), + tinyply::Type::INVALID, 0); + outFile.add_properties_to_element( + "face", {"vertex_indices"}, tinyply::Type::UINT32, mesh.triangles.size(), + reinterpret_cast(const_cast(mesh.triangles.data())), + tinyply::Type::UINT8, 3); + outFile.write(tf.stream(), format != Format::Ascii); + + return tf; +} diff --git a/src/writers.h b/src/writers.h index 34b999b..c8b976d 100644 --- a/src/writers.h +++ b/src/writers.h @@ -32,3 +32,4 @@ TemporaryFile writeMshPly(const TriangleMesh &mesh, Format format); TemporaryFile writeNanoPly(const TriangleMesh &mesh, Format format); TemporaryFile writePlywoot(const TriangleMesh &mesh, Format format); TemporaryFile writeRPly(const TriangleMesh &mesh, Format format); +TemporaryFile writeTinyply(const TriangleMesh &mesh, Format format); diff --git a/submodules/tinyply b/submodules/tinyply new file mode 160000 index 0000000..40aa4a0 --- /dev/null +++ b/submodules/tinyply @@ -0,0 +1 @@ +Subproject commit 40aa4a0ae9e9c203e11893f78b8bcaf8a50e65f0