diff --git a/src/ldrawloader.cpp b/src/ldrawloader.cpp index e942128..7e1fb74 100644 --- a/src/ldrawloader.cpp +++ b/src/ldrawloader.cpp @@ -25,10 +25,15 @@ #include "ldrawloader.hpp" +#include + +#include +#include +#include + #include -#include -#include -#include + +#include #define LDR_DEBUG_FLAG_FILELOAD 1 #define LDR_DEBUG_FLAG 0 @@ -526,7 +531,7 @@ class Mesh sides[i] = vec_normalize(vec_sub(positions[triangles[t * 3 + i]], positions[triangles[t * 3 + (i + 1) % 3]])); } for(uint32_t i = 0; i < 3; i++) { - float angle = fabsf(vec_dot(vec_neg(sides[i]), sides[(i + 1) % 3])); + float angle = std::fabs(vec_dot(vec_neg(sides[i]), sides[(i + 1) % 3])); if(angle < minAngle) { minAngle = angle; corner = i; @@ -2094,7 +2099,7 @@ class MeshUtils } // just in case things go beyond south - if(isnan(chamferModifier) || isinf(chamferModifier) || (edgeA.isOpen() && edgeB.isOpen())) { + if(std::isnan(chamferModifier) || std::isinf(chamferModifier) || (edgeA.isOpen() && edgeB.isOpen())) { chamferModifier = 0; } @@ -2500,7 +2505,7 @@ class MeshUtils i = i; } - memset(localOutIdx.data(), LDR_INVALID_IDX, maxOutCount * sizeof(uint32_t)); + std::memset(localOutIdx.data(), LDR_INVALID_IDX, maxOutCount * sizeof(uint32_t)); for(uint32_t o = 0; o < outInfo.count; o++) { uint32_t rvtx = builder.vtxOutIndices[outInfo.begin + o]; @@ -2960,10 +2965,31 @@ LdrResult Loader::registerInternalPart(const char* filename, const std::string& return result; } +std::filesystem::path normalizePath(const std::string& messyPath) +{ + std::vector path_copy{messyPath.begin(), messyPath.end()}; +#if defined(WINDOWS) || defined(WIN32) + // Do nothing here. +#else + for (size_t i = 0 ; i < path_copy.size() ; ++i) { + if (path_copy[i] == '\\') { + path_copy[i] = '/'; + } + } +#endif + std::filesystem::path path{path_copy.begin(), path_copy.end()}; + std::filesystem::path canonicalPath = std::filesystem::weakly_canonical(path); + return canonicalPath.make_preferred(); +} + bool Loader::findLibraryFile(const char* filename, std::string& foundname, bool allowPrimitives, bool& isPrimitive) { + auto fname{normalizePath(filename)}; + for(uint32_t i = allowPrimitives ? (m_config.partHiResPrimitives ? 0 : 1) : PRIMITIVE_PATHS; i < SEARCH_PATHS; i++) { - foundname = m_searchPaths[i] + filename; + std::filesystem::path p{m_searchPaths[i]}; + p /= fname; + foundname = p.lexically_normal().native(); FILE* f = fopen(foundname.c_str(), "rb"); bool found = f != nullptr; @@ -3531,7 +3557,7 @@ LdrResult Loader::loadData(LdrPart& part, LdrRenderPart& renderPart, const char* float distC = vec_length(vec_sub(vecA, vecC)); float dist = std::min(std::min(distA, distB), distC); - float dotA = fabsf(vec_dot(vec_normalize(vec_sub(vecB, vecA)), vec_normalize(vec_sub(vecC, vecA)))); + float dotA = std::fabs(vec_dot(vec_normalize(vec_sub(vecB, vecA)), vec_normalize(vec_sub(vecC, vecA)))); if(dotA <= Loader::NO_AREA_TRIANGLE_DOT && dist > Loader::MIN_MERGE_EPSILON) { uint32_t vidx = (uint32_t)builder.positions.size(); uint32_t tidx = (uint32_t)builder.triangles.size() / 3; @@ -3581,8 +3607,8 @@ LdrResult Loader::loadData(LdrPart& part, LdrRenderPart& renderPart, const char* material = fixupMaterialID(material); - float dotA = fabsf(vec_dot(vec_normalize(vec_sub(vecB, vecA)), vec_normalize(vec_sub(vecC, vecA)))); - float dotD = fabsf(vec_dot(vec_normalize(vec_sub(vecA, vecD)), vec_normalize(vec_sub(vecC, vecD)))); + float dotA = std::fabs(vec_dot(vec_normalize(vec_sub(vecB, vecA)), vec_normalize(vec_sub(vecC, vecA)))); + float dotD = std::fabs(vec_dot(vec_normalize(vec_sub(vecA, vecD)), vec_normalize(vec_sub(vecC, vecD)))); if(dotA <= Loader::NO_AREA_TRIANGLE_DOT || dotD <= Loader::NO_AREA_TRIANGLE_DOT) { uint32_t vidx = (uint32_t)builder.positions.size(); uint32_t tidx = (uint32_t)builder.triangles.size() / 3; @@ -4404,7 +4430,7 @@ void Loader::fixPart(LdrPartID partid) fillBuilderPart(builder, partid); deinitPart(part); - memset(&part, 0, sizeof(LdrPart)); + std::memset(&part, 0, sizeof(LdrPart)); MeshUtils::fixBuilderPart(builder, m_config); @@ -4653,7 +4679,7 @@ void Loader::BuilderPart::getCanonicalQuad(uint32_t t, uint32_t quad[4]) const LDR_API void ldrGetDefaultCreateInfo(LdrLoaderCreateInfo* info) { - memset(info, 0, sizeof(LdrLoaderCreateInfo)); + std::memset(info, 0, sizeof(LdrLoaderCreateInfo)); info->partHiResPrimitives = LDR_FALSE; info->partFixMode = LDR_PART_FIX_NONE; info->partFixTjunctions = LDR_TRUE; diff --git a/src/ldrawloader.h b/src/ldrawloader.h index 815ad24..8d9157a 100644 --- a/src/ldrawloader.h +++ b/src/ldrawloader.h @@ -28,6 +28,7 @@ #pragma once #include +#include // size_t // LDR_CFG_THREADSAFE // Enabled: you can load parts/models from multiple threads @@ -93,7 +94,16 @@ extern "C" { #define LDR_INVALID_IDX uint32_t(~0) #define LDR_INVALID_SHAPETYPE 0 +#if defined(WINDOWS) || defined(WIN32) #define LDR_RESTRICT __restrict +#else +// XXX: This isn't the perfect soluton. Looks like GCC/Clang are strict about +// qv-qualifiers producing incompatible types, which messes with function +// resultion when values are marked LDR_RESTRICT and then passed to +// functions where the parameters are not marked. +// So to keep things simple for now, disable this. +#define LDR_RESTRICT +#endif typedef enum LdrResult : int32_t { diff --git a/src/ldrawloader.hpp b/src/ldrawloader.hpp index 25ced07..15c2f61 100644 --- a/src/ldrawloader.hpp +++ b/src/ldrawloader.hpp @@ -35,6 +35,9 @@ #include #endif +#include +#include + #include #include #include @@ -329,7 +332,7 @@ struct Loader BitArray() {} BitArray(uint32_t num, bool value) { resize(num, value); } - void clear() { memset(data, 0, sizeof(uint64_t) * (num_allocated / 64)); } + void clear() { std::memset(data, 0, sizeof(uint64_t) * (num_allocated / 64)); } uint32_t size() const { return num; } @@ -344,7 +347,7 @@ struct Loader uint32_t idx = num_old / 64; uint32_t num_delta = numNew - num_old; - memset(data + idx, value ? 0xFFFFFFFF : 0, sizeof(uint64_t) * (num_delta / 64)); + std::memset(data + idx, value ? 0xFFFFFFFF : 0, sizeof(uint64_t) * (num_delta / 64)); } }