From c77f0fa2f052627a245490a32930be272c136f62 Mon Sep 17 00:00:00 2001 From: Eisenwave Date: Wed, 3 Mar 2021 19:42:17 +0100 Subject: [PATCH] fix only one tinyobj shape being voxelized --- src/io.cpp | 131 +++++++++++++++++++++++++++++++++++------------------ src/io.hpp | 26 ++++++----- 2 files changed, 101 insertions(+), 56 deletions(-) diff --git a/src/io.cpp b/src/io.cpp index 6750d7f..f6197d8 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -58,7 +58,7 @@ void dumpDebugStl(const std::string &path) // TRIANGLE STREAMS ==================================================================================================== -ITriangleStream::~ITriangleStream() = default; +ITriangleStream::~ITriangleStream() noexcept = default; namespace { @@ -71,46 +71,82 @@ struct CallbackTriangleStream final : public ITriangleStream { { } - bool next(VisualTriangle &out) final; + bool next(VisualTriangle &out) noexcept final; }; -bool CallbackTriangleStream::next(VisualTriangle &out) +bool CallbackTriangleStream::next(VisualTriangle &out) noexcept { return callback(callbackData, &out); } struct ObjTriangleStream final : public ITriangleStream { - tinyobj::attrib_t attrib; - std::vector shapes; - std::vector materials; - std::map textures; - const Texture *defaultTexture = nullptr; +public: + using attrib_type = tinyobj::attrib_t; + using shapes_type = std::vector; + using materials_type = std::vector; + using textures_type = std::map; + +private: + attrib_type attrib; + shapes_type shapes; + materials_type materials; + textures_type textures; + const Texture *defaultTexture; usize shapesIndex = 0; usize faceIndex = 0; + usize faceCountOfCurrentShape; + usize indexOffset = 0; +public: + ObjTriangleStream(attrib_type attrib, + shapes_type shapes, + materials_type materials, + textures_type textures, + const Texture *defaultTexture) + : attrib{std::move(attrib)} + , shapes{std::move(shapes)} + , materials{std::move(materials)} + , textures{std::move(textures)} + , defaultTexture{defaultTexture} + , faceCountOfCurrentShape{faceCountOfShapeOrZero(0)} + { + } + + bool next(VisualTriangle &out) noexcept final; + +private: bool hasNext() const { - return shapesIndex < shapes.size() && faceIndex < shapes[shapesIndex].mesh.num_face_vertices.size(); + return shapesIndex < shapes.size() && faceIndex < faceCountOfCurrentShape; } - bool next(VisualTriangle &out) final; + /// Returns the face count of the shape at the given index or zero if the index is out of bounds. + usize faceCountOfShapeOrZero(usize index) const + { + return index >= shapes.size() ? 0 : shapes[index].mesh.num_face_vertices.size(); + } }; struct StlTriangleStream final : public ITriangleStream { +private: std::vector vertices; usize index = 0; +public: + StlTriangleStream(std::vector vertices) noexcept : vertices{std::move(vertices)} {} + + bool next(VisualTriangle &out) noexcept final; + +private: bool hasNext() const { return index < vertices.size(); } - - bool next(VisualTriangle &out) final; }; -bool ObjTriangleStream::next(VisualTriangle &triangle) +bool ObjTriangleStream::next(VisualTriangle &triangle) noexcept { if (not hasNext()) { return false; @@ -172,12 +208,15 @@ bool ObjTriangleStream::next(VisualTriangle &triangle) } indexOffset += vertexCount; - ++faceIndex; - + if (++faceIndex >= faceCountOfCurrentShape) { + faceIndex = 0; + indexOffset = 0; + faceCountOfCurrentShape = faceCountOfShapeOrZero(++shapesIndex); + } return true; } -bool StlTriangleStream::next(VisualTriangle &triangle) +bool StlTriangleStream::next(VisualTriangle &triangle) noexcept { if (not hasNext()) { return false; @@ -195,23 +234,26 @@ bool StlTriangleStream::next(VisualTriangle &triangle) } // namespace -std::unique_ptr ITriangleStream::fromCallback(obj2voxel_triangle_callback callback, void *callbackData) +std::unique_ptr ITriangleStream::fromCallback(obj2voxel_triangle_callback callback, + void *callbackData) noexcept { return std::unique_ptr{new CallbackTriangleStream{callback, callbackData}}; } // FILE LOADING ======================================================================================================== -std::unique_ptr ITriangleStream::fromObjFile(const std::string &inFile, const Texture *defaultTexture) +std::unique_ptr ITriangleStream::fromObjFile(const std::string &inFile, + const Texture *defaultTexture) noexcept { std::string warn; std::string err; - ObjTriangleStream stream; - stream.defaultTexture = defaultTexture; + ObjTriangleStream::attrib_type attrib; + ObjTriangleStream::shapes_type shapes; + ObjTriangleStream::materials_type materials; + ObjTriangleStream::textures_type textures; - bool tinyobjSuccess = - tinyobj::LoadObj(&stream.attrib, &stream.shapes, &stream.materials, &warn, &err, inFile.c_str()); + bool tinyobjSuccess = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, inFile.c_str()); trim(warn); trim(err); @@ -228,22 +270,23 @@ std::unique_ptr ITriangleStream::fromObjFile(const std::string return nullptr; } - for (tinyobj::material_t &material : stream.materials) { + for (tinyobj::material_t &material : materials) { std::string name = material.diffuse_texname; if (name.empty()) { continue; } std::optional tex = loadTexture(name, material.name); if (tex.has_value()) { - stream.textures.emplace(std::move(name), std::move(*tex)); + textures.emplace(std::move(name), std::move(*tex)); } } - VXIO_LOG(INFO, "Loaded " + stringifyLargeInt(stream.textures.size()) + " material textures"); + VXIO_LOG(INFO, "Loaded " + stringifyLargeInt(textures.size()) + " material textures"); - return std::make_unique(std::move(stream)); + return std::unique_ptr(new ObjTriangleStream{ + std::move(attrib), std::move(shapes), std::move(materials), std::move(textures), defaultTexture}); } -std::unique_ptr ITriangleStream::fromStlFile(const std::string &inFile) +std::unique_ptr ITriangleStream::fromStlFile(const std::string &inFile) noexcept { std::optional stream = FileInputStream::open(inFile); if (not stream.has_value()) { @@ -268,7 +311,7 @@ std::unique_ptr ITriangleStream::fromStlFile(const std::string return nullptr; } - StlTriangleStream result; + std::vector vertices; for (u32 i = 0; i < triangleCount; ++i) { f32 triangleData[12]; @@ -279,10 +322,10 @@ std::unique_ptr ITriangleStream::fromStlFile(const std::string return nullptr; } - result.vertices.insert(result.vertices.end(), triangleData + 3, triangleData + 12); + vertices.insert(vertices.end(), triangleData + 3, triangleData + 12); } - return std::make_unique(std::move(result)); + return std::unique_ptr(new StlTriangleStream{std::move(vertices)}); } std::optional loadTexture(const std::string &name, const std::string &material) @@ -311,7 +354,7 @@ std::optional loadTexture(const std::string &name, const std::string &m // OUTPUT ============================================================================================================== -IVoxelSink::~IVoxelSink() = default; +IVoxelSink::~IVoxelSink() noexcept = default; namespace { @@ -339,19 +382,19 @@ struct CallbackVoxelSink final : public IVoxelSink { { } - bool canWrite() const final + bool canWrite() const noexcept final { return good; } - usize voxelsWritten() const final + usize voxelsWritten() const noexcept final { return voxelCount; } - void write(Voxel32 voxels[], usize size) final; + void write(Voxel32 voxels[], usize size) noexcept final; - void finalize() final + void finalize() noexcept final { VXIO_LOG(DEBUG, "Flushing callback sink (no-op)"); } @@ -392,19 +435,19 @@ struct VoxelioVoxelSink final : public IVoxelSink { } } - bool canWrite() const final + bool canWrite() const noexcept final { return isGood(err); } - usize voxelsWritten() const final + usize voxelsWritten() const noexcept final { return voxelCount; } - void write(Voxel32 voxels[], usize size) final; + void write(Voxel32 voxels[], usize size) noexcept final; - void finalize() final; + void finalize() noexcept final; }; VoxelioVoxelSink::VoxelioVoxelSink(std::unique_ptr out, FileType outFormat, usize resolution) @@ -419,7 +462,7 @@ VoxelioVoxelSink::VoxelioVoxelSink(std::unique_ptr out, FileType o buffer.reserve(BUFFER_SIZE); } -void VoxelioVoxelSink::write(Voxel32 voxels[], usize size) +void VoxelioVoxelSink::write(Voxel32 voxels[], usize size) noexcept { VXIO_ASSERTM(not finalized, "Writing to finalized voxel sink"); VXIO_ASSERTM(canWrite(), "Writing to a failed voxel sink"); @@ -443,7 +486,7 @@ void VoxelioVoxelSink::write(Voxel32 voxels[], usize size) } } -void VoxelioVoxelSink::finalize() +void VoxelioVoxelSink::finalize() noexcept { if (finalized) { return; @@ -475,7 +518,7 @@ void VoxelioVoxelSink::finalize() err = writer->finalize(); } -void CallbackVoxelSink::write(Voxel32 voxels[], usize size) +void CallbackVoxelSink::write(Voxel32 voxels[], usize size) noexcept { VXIO_ASSERTM(canWrite(), "Writing to a failed voxel sink"); @@ -493,14 +536,14 @@ void CallbackVoxelSink::write(Voxel32 voxels[], usize size) } // namespace -std::unique_ptr IVoxelSink::fromCallback(obj2voxel_voxel_callback callback, void *callbackData) +std::unique_ptr IVoxelSink::fromCallback(obj2voxel_voxel_callback callback, void *callbackData) noexcept { return std::unique_ptr{new CallbackVoxelSink{callback, callbackData}}; } std::unique_ptr IVoxelSink::fromVoxelio(std::unique_ptr out, FileType outFormat, - usize resolution) + usize resolution) noexcept { return std::unique_ptr{new VoxelioVoxelSink{std::move(out), outFormat, resolution}}; } diff --git a/src/io.hpp b/src/io.hpp index 20b8b51..50a76d5 100644 --- a/src/io.hpp +++ b/src/io.hpp @@ -25,7 +25,8 @@ void dumpDebugStl(const std::string &path); * internal format. */ struct ITriangleStream { - static std::unique_ptr fromCallback(obj2voxel_triangle_callback callback, void *callbackData); + static std::unique_ptr fromCallback(obj2voxel_triangle_callback callback, + void *callbackData) noexcept; /** * @brief Loads an OBJ file from disk. @@ -33,7 +34,8 @@ struct ITriangleStream { * @param textureFile the default texture file, to be used for vertices with no material but UV coordinates * @return the OBJ triangle stream or nullptr if the file couldn't be opened */ - static std::unique_ptr fromObjFile(const std::string &inFile, const Texture *defaultTexture); + static std::unique_ptr fromObjFile(const std::string &inFile, + const Texture *defaultTexture) noexcept; /** * @brief Loads an STL file from disk. @@ -43,37 +45,37 @@ struct ITriangleStream { * @param inFile the input file path * @return the STL triangle stream or nullptr if the file couldn't be opened */ - static std::unique_ptr fromStlFile(const std::string &inFile); + static std::unique_ptr fromStlFile(const std::string &inFile) noexcept; /// virtual destructor - virtual ~ITriangleStream(); + virtual ~ITriangleStream() noexcept; /// Assigns the next triangle. /// Returns true if another triangle could be obtained from the stream, else false. /// If false gets returned, this signals the end of the stream and no more triangles should be read. - virtual bool next(VisualTriangle &out) = 0; + virtual bool next(VisualTriangle &out) noexcept = 0; }; struct IVoxelSink { - static std::unique_ptr fromCallback(obj2voxel_voxel_callback callback, void *callbackData); + static std::unique_ptr fromCallback(obj2voxel_voxel_callback callback, void *callbackData) noexcept; static std::unique_ptr fromVoxelio(std::unique_ptr out, FileType outFormat, - usize resolution); + usize resolution) noexcept; /// Virtual destructor, flushes the sink. - virtual ~IVoxelSink(); + virtual ~IVoxelSink() noexcept; /// Returns true if the writer has not encountered any errors yet and the sink can take more voxels. - virtual bool canWrite() const = 0; + virtual bool canWrite() const noexcept = 0; /// Returns the total number of voxels written to the sink. - virtual usize voxelsWritten() const = 0; + virtual usize voxelsWritten() const noexcept = 0; /// Writes a buffer of voxels to the sink. - virtual void write(Voxel32 voxels[], usize size) = 0; + virtual void write(Voxel32 voxels[], usize size) noexcept = 0; /// Flushes the sink. - virtual void finalize() = 0; + virtual void finalize() noexcept = 0; }; /// Loads a texture with the given file name.