diff --git a/openVulkanoCpp/IO/Archive/ZipWriter.cpp b/openVulkanoCpp/IO/Archive/ZipWriter.cpp index 77994c4..a5c12a8 100644 --- a/openVulkanoCpp/IO/Archive/ZipWriter.cpp +++ b/openVulkanoCpp/IO/Archive/ZipWriter.cpp @@ -106,54 +106,64 @@ namespace static_assert(sizeof(EndOfCentralDirectoryHeader) == 22, "Well packed struct"); static_assert(sizeof(NtfsExtraField) == 36, "Well packed struct"); - uint32_t Cat(std::vector& dest, size_t size, uint8_t* thing) + uint32_t Cat(std::vector& dest, size_t size, const uint8_t* thing) { uint32_t startOffset = dest.size(); - dest.insert(dest.end(), (uint8_t*)thing, (uint8_t*)(thing + size)); + dest.insert(dest.end(), thing, thing + size); return startOffset; } template - uint32_t Cat(std::vector& dest, T* thing) + uint32_t Cat(std::vector& dest, const T* thing) { - return Cat(dest, sizeof(T), reinterpret_cast(thing)); + return Cat(dest, sizeof(T), reinterpret_cast(thing)); } uint32_t Cat(std::vector& dest, const std::vector& thing) { - return Cat(dest, thing.size(), const_cast(thing.data())); + return Cat(dest, thing.size(), thing.data()); } - std::pair ConvertToDosTimeDate(time_t time) + std::pair ConvertToDosTimeDate(const time_t time) { - std::tm* tm = std::gmtime(&time); - if (tm) - { - uint16_t dosTime = 0; - dosTime |= (tm->tm_sec / 2) & 0x1F; // Seconds divided by 2 (Bits 00-04) - dosTime |= (tm->tm_min & 0x3F) << 5; // Minutes (Bits 05-10) - dosTime |= (tm->tm_hour & 0x1F) << 11; // Hours (Bits 11-15) + std::tm tm; +#if _MSC_VER >= 1400 + if (gmtime_s(&tm, &time) != 0) [[unlikely]] + throw std::runtime_error("gmtime_s() failed"); +#else + if (gmtime_r(&time, &tm) == nullptr) [[unlikely]] + throw std::runtime_error("gmtime_r() failed"); +#endif + uint16_t dosTime = 0; + dosTime |= (tm.tm_sec / 2) & 0x1F; // Seconds divided by 2 (Bits 00-04) + dosTime |= (tm.tm_min & 0x3F) << 5; // Minutes (Bits 05-10) + dosTime |= (tm.tm_hour & 0x1F) << 11; // Hours (Bits 11-15) - uint16_t dosDate = 0; - dosDate |= (tm->tm_mday & 0x1F); // Day (Bits 00-04) - dosDate |= ((tm->tm_mon + 1) & 0x0F) << 5; // Month (Bits 05-08) - dosDate |= ((tm->tm_year - 80) & 0x7F) << 9; // Year from 1980 (Bits 09-15) - return { dosTime, dosDate }; - } + uint16_t dosDate = 0; + dosDate |= (tm.tm_mday & 0x1F); // Day (Bits 00-04) + dosDate |= ((tm.tm_mon + 1) & 0x0F) << 5; // Month (Bits 05-08) + dosDate |= ((tm.tm_year - 80) & 0x7F) << 9; // Year from 1980 (Bits 09-15) + return { dosTime, dosDate }; + } - return {}; + template + void ZFill(FILE *handle, size_t num) + { + uint8_t zeros[MAX_PADDING_SIZE] = {}; + fwrite(&zeros, num, 1, handle); } } namespace OpenVulkano { - ZipWriter::ZipWriter(const std::filesystem::path& filePath) + ZipWriter::ZipWriter(const std::filesystem::path& filePath, bool alignHeadersby64) { m_file = fopen(filePath.string().c_str(), "wb"); if (!m_file) { throw std::runtime_error("Unable to open file for writing: " + filePath.string()); } + m_pad = alignHeadersby64; } void ZipWriter::AddFile(const FileDescription& description, const void* buffer) @@ -169,6 +179,13 @@ namespace OpenVulkano time_t accessTime = modTime; // FileDescription doesn't have this field auto [dosTime, dosDate] = ConvertToDosTimeDate(modTime); + if (m_pad) + { + size_t headerSize = sizeof(LocalFileHeader) + fileNameLength; + size_t padding = 64 - ((ftell(m_file) + headerSize) & 63); + ZFill<64>(m_file, padding); + } + LocalFileHeader lfh; lfh.fileLastModTime = dosTime; lfh.fileLastModDate = dosDate; @@ -209,7 +226,7 @@ namespace OpenVulkano ZipWriter::~ZipWriter() { - if (m_file) + if (IsOpen()) { int centralDirsOffset = 0; if (m_numFiles) diff --git a/openVulkanoCpp/IO/Archive/ZipWriter.hpp b/openVulkanoCpp/IO/Archive/ZipWriter.hpp index 0ae044c..24be87a 100644 --- a/openVulkanoCpp/IO/Archive/ZipWriter.hpp +++ b/openVulkanoCpp/IO/Archive/ZipWriter.hpp @@ -17,12 +17,15 @@ namespace OpenVulkano { std::vector m_centralDirs; int m_numFiles = 0; + bool m_pad = false; FILE* m_file; public: - ZipWriter(const std::filesystem::path& filePath); + ZipWriter(const std::filesystem::path& filePath, bool alignHeadersby64 = false); ~ZipWriter(); + bool IsOpen() const { return m_file != nullptr; } + void AddFile(const FileDescription& description, const void* buffer); void AddFile(const std::filesystem::path& fileName, const char* inArchiveName); }; diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index d8466bf..78f1dbd 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -5,6 +5,7 @@ */ #include "MeshWriter.hpp" +#include "IO/MemMappedFile.hpp" #include "Scene/Geometry.hpp" #include "Scene/Vertex.hpp" #include "Scene/UsdEncoder.hpp" @@ -24,8 +25,7 @@ namespace OpenVulkano::Scene if (!file.is_open()) throw std::runtime_error("Failed to open file '" + filePath + "' for writing!"); - std::stringstream dummy; - WriteObjContents(geometry, "", file, dummy); + WriteObjContents(geometry, "", file); file.close(); } @@ -42,18 +42,25 @@ namespace OpenVulkano::Scene { OpenVulkano::ArchiveWriter zipWriter(zipPath.c_str()); - std::stringstream objContents, mtlContents; - WriteObjContents(geometry, texturePath, objContents, mtlContents); - - auto objDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("model.obj", objContents.str().size()); - zipWriter.AddFile(objDesc, objContents.str().data()); - - auto mtlDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("material.mtl", mtlContents.str().size()); - zipWriter.AddFile(mtlDesc, mtlContents.str().data()); + const char* materialName = "Material0"; + { + std::stringstream objContents; + WriteObjContents(geometry, materialName, objContents); + auto objContentsStr = objContents.str(); + auto objDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("model.obj", objContentsStr.size()); + zipWriter.AddFile(objDesc, objContentsStr.data()); + } + { + std::stringstream mtlContents; + mtlContents << "newmtl " << materialName << "\n" << ObjMaterialContents; + auto mtlContentsStr = mtlContents.str(); + auto mtlDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("material.mtl", mtlContentsStr.size()); + zipWriter.AddFile(mtlDesc, mtlContentsStr.data()); + } if (!texturePath.empty() && std::filesystem::exists(texturePath)) { - auto textureFile = Utils::ReadFile(texturePath); + auto textureFile = MemMappedFile(texturePath); auto texDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("texture.png", textureFile.Size()); zipWriter.AddFile(texDesc, textureFile.Data()); } @@ -61,16 +68,19 @@ namespace OpenVulkano::Scene void MeshWriter::WriteAsUSDZ(Geometry* geometry, const std::string& texturePath, const std::string& usdzPath) { - OpenVulkano::ZipWriter zipWriter(usdzPath); + OpenVulkano::ZipWriter zipWriter(usdzPath);// NOCHECKIN, true); - std::stringstream usdFile; - WriteUsdContents(usdFile, geometry); - auto usdDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("geometry.usda", usdFile.str().size()); - zipWriter.AddFile(usdDesc, usdFile.str().data()); + { + std::stringstream usdFile; + WriteUsdContents(usdFile, geometry); + auto usdFileStr = usdFile.str(); + auto usdDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("geometry.usda", usdFileStr.size()); + zipWriter.AddFile(usdDesc, usdFileStr.data()); + } if (!texturePath.empty() && std::filesystem::exists(texturePath)) { - auto textureFile = Utils::ReadFile(texturePath); + auto textureFile = MemMappedFile(texturePath); auto texDesc = OpenVulkano::FileDescription::MakeDescriptionForFile("texture.png", textureFile.Size()); zipWriter.AddFile(texDesc, textureFile.Data()); } diff --git a/openVulkanoCpp/Scene/ObjEncoder.hpp b/openVulkanoCpp/Scene/ObjEncoder.hpp index 6323288..2d069cd 100644 --- a/openVulkanoCpp/Scene/ObjEncoder.hpp +++ b/openVulkanoCpp/Scene/ObjEncoder.hpp @@ -14,22 +14,22 @@ namespace OpenVulkano::Scene { - void WriteObjContents(Geometry* geometry, const std::string& texturePath, std::ostream& objContent, std::ostream& mtlContent) - { - bool useTexture = texturePath.size() != 0; - - objContent << "# OBJ file generated by OpenVulkanoCpp\n"; - - if (useTexture) - { - mtlContent << R"(newmtl Material0 + static constexpr std::string_view ObjMaterialContents = R"( Ka 1.000 1.000 1.000 Kd 1.000 1.000 1.000 Ks 0.000 0.000 0.000 map_Ka texture.png map_Kd texture.png )"; - objContent << "mtllib material.mtl\nusemtl Material0\n"; + + void WriteObjContents(Geometry* geometry, const std::string& materialName, std::ostream& objContent) + { + objContent << "# OBJ file generated by OpenVulkanoCpp\n"; + + if (materialName.size() != 0) + { + objContent << "mtllib material.mtl\n"; + objContent << "usemtl " << materialName << "\n"; } for (int i = 0; i < geometry->vertexCount; ++i) diff --git a/openVulkanoCpp/Scene/UsdEncoder.hpp b/openVulkanoCpp/Scene/UsdEncoder.hpp index de1235f..bd795af 100644 --- a/openVulkanoCpp/Scene/UsdEncoder.hpp +++ b/openVulkanoCpp/Scene/UsdEncoder.hpp @@ -50,11 +50,8 @@ def Xform "root" ( { if ((i + 1) % 3 == 0) { + if (i > 2) output << ", "; output << "3"; - if (i < geometry->indexCount - 1) - { - output << ", "; - } } } @@ -63,11 +60,8 @@ def Xform "root" ( for (size_t i = 0; i < geometry->indexCount; ++i) { + if (i > 0) output << ", "; output << geometry->GetIndex(i); - if (i < geometry->indexCount - 1) - { - output << ", "; - } } output << R"(] @@ -78,11 +72,8 @@ def Xform "root" ( for (size_t i = 0; i < geometry->vertexCount; ++i) { const auto& v = geometry->vertices[i]; + if (i > 0) output << ", "; output << "(" << v.normal.x << ", " << v.normal.y << ", " << v.normal.z << ")"; - if (i < geometry->vertexCount - 1) - { - output << ", "; - } } output << R"(] ( @@ -93,11 +84,8 @@ def Xform "root" ( for (size_t i = 0; i < geometry->vertexCount; ++i) { const auto& v = geometry->vertices[i]; + if (i > 0) output << ", "; output << "(" << v.position.x << ", " << v.position.y << ", " << v.position.z << ")"; - if (i < geometry->vertexCount - 1) - { - output << ", "; - } } output << R"(] @@ -109,11 +97,8 @@ def Xform "root" ( { const size_t vertexIndex = geometry->GetIndex(i); const auto& v = geometry->vertices[vertexIndex]; + if (i > 0) output << ", "; output << "(" << v.textureCoordinates.x << ", " << v.textureCoordinates.y << ")"; - if (i < geometry->indexCount - 1) - { - output << ", "; - } } output << R"(] (