From b817d07a9d556cb489cfc2e453c91672797f3a6e Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sat, 29 Jun 2024 00:36:54 +0800 Subject: [PATCH] chores (#833) * fix comparison between integers with different signedness and implicit narrowing * fix compilation error and formatting * allow build with exception disabled * CI for building without exception * format * another fix * msvc stuff * fix python bindings * update nix * formatting * old llvm somehow likes this better * fix bug * rename ASSERT into DEBUG_ASSERT * remove unused file * use ASSERT and remove obsolete limits * polygon: change to size_t * format * fix sign compare * install optional_assert.h * address comments * fix * fix * fix * fix format --- .github/workflows/manifold.yml | 6 +- CMakeLists.txt | 14 +- bindings/c/conv.cpp | 6 +- bindings/c/include/conv.h | 2 +- bindings/c/include/manifoldc.h | 4 +- bindings/c/manifoldc.cpp | 13 +- bindings/python/manifold3d.cpp | 198 +++++++++++++----------- bindings/python/third_party/nanobind | 2 +- extras/minimize_testcase.cpp | 26 ++-- extras/perf | 22 --- flake.lock | 6 +- flake.nix | 6 +- meshIO/src/meshIO.cpp | 35 +++-- samples/src/scallop.cpp | 4 +- src/collider/include/collider.h | 4 +- src/collider/src/collider.cpp | 10 +- src/cross_section/src/cross_section.cpp | 50 +++--- src/manifold/include/manifold.h | 10 +- src/manifold/src/boolean3.cpp | 25 +-- src/manifold/src/boolean_result.cpp | 31 ++-- src/manifold/src/constructors.cpp | 41 ++--- src/manifold/src/csg_tree.cpp | 18 +-- src/manifold/src/edge_op.cpp | 12 +- src/manifold/src/face_op.cpp | 24 ++- src/manifold/src/impl.cpp | 41 ++--- src/manifold/src/impl.h | 10 +- src/manifold/src/manifold.cpp | 10 +- src/manifold/src/properties.cpp | 28 ++-- src/manifold/src/shared.h | 4 +- src/manifold/src/smoothing.cpp | 20 +-- src/manifold/src/sort.cpp | 71 +++++---- src/manifold/src/subdivision.cpp | 15 +- src/polygon/include/polygon.h | 2 +- src/polygon/src/polygon.cpp | 62 ++++---- src/utilities/CMakeLists.txt | 10 +- src/utilities/include/hashtable.h | 3 +- src/utilities/include/optional_assert.h | 16 +- src/utilities/include/public.h | 6 +- src/utilities/include/sparse.h | 10 +- src/utilities/include/vec.h | 35 ++--- src/utilities/include/vec_view.h | 26 ++-- test/manifold_test.cpp | 10 +- test/smooth_test.cpp | 10 +- test/test_main.cpp | 24 +-- 44 files changed, 494 insertions(+), 488 deletions(-) delete mode 100644 extras/perf diff --git a/.github/workflows/manifold.yml b/.github/workflows/manifold.yml index 4026c0186..010a0534b 100644 --- a/.github/workflows/manifold.yml +++ b/.github/workflows/manifold.yml @@ -107,6 +107,9 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-22.04 if: github.event.pull_request.draft == false + strategy: + matrix: + exception: [ON, OFF] steps: - name: Install dependencies run: | @@ -128,7 +131,7 @@ jobs: source ./emsdk/emsdk_env.sh mkdir build cd build - emcmake cmake -DCMAKE_BUILD_TYPE=Release .. && emmake make + emcmake cmake -DCMAKE_BUILD_TYPE=Release -DMANIFOLD_EXCEPTIONS=${{matrix.exception}} .. && emmake make - name: Test WASM run: | cd build/test @@ -142,6 +145,7 @@ jobs: cp ../manifold.* ./dist/ - name: Upload WASM files uses: actions/upload-artifact@v4 + if: matrix.exception == 'ON' with: name: wasm path: bindings/wasm/examples/dist/ diff --git a/CMakeLists.txt b/CMakeLists.txt index a2af1a33d..d02726bbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ option(MANIFOLD_DEBUG "Enable debug tracing/timing" OFF) option(MANIFOLD_PYBIND "Build python bindings" OFF) option(MANIFOLD_CBIND "Build C (FFI) bindings" ON) option(MANIFOLD_JSBIND "Build js binding" ${EMSCRIPTEN}) +option(MANIFOLD_EXCEPTIONS "Build manifold with exception enabled" ON) option(BUILD_SHARED_LIBS "Build shared library" ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -59,8 +60,13 @@ endif() if(EMSCRIPTEN) message("Building for Emscripten") - set(MANIFOLD_FLAGS -fexceptions -D_LIBCUDACXX_HAS_THREAD_API_EXTERNAL -D_LIBCUDACXX_HAS_THREAD_API_CUDA) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sALLOW_MEMORY_GROWTH=1 -fexceptions -sDISABLE_EXCEPTION_CATCHING=0") + if(MANIFOLD_EXCEPTIONS) + set(MANIFOLD_FLAGS -fexceptions -D_LIBCUDACXX_HAS_THREAD_API_EXTERNAL -D_LIBCUDACXX_HAS_THREAD_API_CUDA) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sALLOW_MEMORY_GROWTH=1 -fexceptions -sDISABLE_EXCEPTION_CATCHING=0") + else() + set(MANIFOLD_FLAGS -D_LIBCUDACXX_HAS_THREAD_API_EXTERNAL -D_LIBCUDACXX_HAS_THREAD_API_CUDA) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sALLOW_MEMORY_GROWTH=1") + endif() set(MANIFOLD_PYBIND OFF) set(BUILD_SHARED_LIBS OFF) endif() @@ -86,10 +92,10 @@ if (MSVC) set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} /DNOMINMAX /bigobj) else() if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(WARNING_FLAGS -Werror -Wall -Wno-sign-compare -Wno-unused -Wno-array-bounds + set(WARNING_FLAGS -Werror -Wall -Wno-unused -Wno-array-bounds -Wno-stringop-overflow -Wno-alloc-size-larger-than) else() - set(WARNING_FLAGS -Werror -Wall -Wno-sign-compare -Wno-unused) + set(WARNING_FLAGS -Werror -Wall -Wno-unused) endif() set(MANIFOLD_FLAGS ${MANIFOLD_FLAGS} ${WARNING_FLAGS}) endif() diff --git a/bindings/c/conv.cpp b/bindings/c/conv.cpp index 4f074639e..253501dec 100644 --- a/bindings/c/conv.cpp +++ b/bindings/c/conv.cpp @@ -227,7 +227,7 @@ glm::vec4 from_c(ManifoldVec4 v) { return glm::vec4(v.x, v.y, v.z, v.w); } std::vector vector_of_vec_array(ManifoldVec3 *vs, size_t length) { auto vec = std::vector(); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec.push_back(from_c(vs[i])); } return vec; @@ -235,7 +235,7 @@ std::vector vector_of_vec_array(ManifoldVec3 *vs, size_t length) { std::vector vector_of_vec_array(ManifoldIVec3 *vs, size_t length) { auto vec = std::vector(); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec.push_back(from_c(vs[i])); } return vec; @@ -243,7 +243,7 @@ std::vector vector_of_vec_array(ManifoldIVec3 *vs, size_t length) { std::vector vector_of_vec_array(ManifoldVec4 *vs, size_t length) { auto vec = std::vector(); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec.push_back(from_c(vs[i])); } return vec; diff --git a/bindings/c/include/conv.h b/bindings/c/include/conv.h index fee7653a1..4635c4f78 100644 --- a/bindings/c/include/conv.h +++ b/bindings/c/include/conv.h @@ -67,7 +67,7 @@ std::vector vector_of_vec_array(ManifoldVec4 *vs, size_t length); template std::vector vector_of_array(T *ts, size_t length) { auto vec = std::vector(); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec.push_back(ts[i]); } return vec; diff --git a/bindings/c/include/manifoldc.h b/bindings/c/include/manifoldc.h index cfc1abd44..9eee01bee 100644 --- a/bindings/c/include/manifoldc.h +++ b/bindings/c/include/manifoldc.h @@ -154,8 +154,8 @@ ManifoldManifold *manifold_sphere(void *mem, float radius, int circular_segments); ManifoldManifold *manifold_of_meshgl(void *mem, ManifoldMeshGL *mesh); ManifoldManifold *manifold_smooth(void *mem, ManifoldMeshGL *mesh, - int *half_edges, float *smoothness, - int n_idxs); + size_t *half_edges, float *smoothness, + size_t n_idxs); ManifoldManifold *manifold_extrude(void *mem, ManifoldPolygons *cs, float height, int slices, float twist_degrees, float scale_x, diff --git a/bindings/c/manifoldc.cpp b/bindings/c/manifoldc.cpp index 60abb4ed3..d8eebdc31 100644 --- a/bindings/c/manifoldc.cpp +++ b/bindings/c/manifoldc.cpp @@ -58,7 +58,7 @@ extern "C" { ManifoldSimplePolygon *manifold_simple_polygon(void *mem, ManifoldVec2 *ps, size_t length) { auto vec = new (mem) std::vector; - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec->push_back({ps[i].x, ps[i].y}); } return to_c(vec); @@ -68,7 +68,7 @@ ManifoldPolygons *manifold_polygons(void *mem, ManifoldSimplePolygon **ps, size_t length) { auto vec = new (mem) std::vector; auto polys = reinterpret_cast(ps); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec->push_back(*polys[i]); } return to_c(vec); @@ -215,7 +215,7 @@ ManifoldManifold *manifold_batch_hull(void *mem, ManifoldManifoldVec *ms) { ManifoldManifold *manifold_hull_pts(void *mem, ManifoldVec3 *ps, size_t length) { std::vector vec(length); - for (int i = 0; i < length; ++i) { + for (size_t i = 0; i < length; ++i) { vec[i] = {ps[i].x, ps[i].y, ps[i].z}; } auto hulled = Manifold::Hull(vec); @@ -366,10 +366,10 @@ ManifoldMeshGL *manifold_meshgl_w_tangents(void *mem, float *vert_props, } ManifoldManifold *manifold_smooth(void *mem, ManifoldMeshGL *mesh, - int *half_edges, float *smoothness, - int n_edges) { + size_t *half_edges, float *smoothness, + size_t n_edges) { auto smooth = std::vector(); - for (int i = 0; i < n_edges; ++i) { + for (size_t i = 0; i < n_edges; ++i) { smooth.push_back({half_edges[i], smoothness[i]}); } auto m = Manifold::Smooth(*from_c(mesh), smooth); @@ -391,7 +391,6 @@ ManifoldManifold *manifold_extrude(void *mem, ManifoldPolygons *cs, } ManifoldManifold *manifold_revolve(void *mem, ManifoldPolygons *cs, - int circular_segments) { auto m = Manifold::Revolve(*from_c(cs), circular_segments); return to_c(new (mem) Manifold(m)); diff --git a/bindings/python/manifold3d.cpp b/bindings/python/manifold3d.cpp index b631fef19..e9d5798cf 100644 --- a/bindings/python/manifold3d.cpp +++ b/bindings/python/manifold3d.cpp @@ -68,7 +68,7 @@ struct nb::detail::type_caster> { int size = PyObject_Size(src.ptr()); // negative on failure if (size != N) return false; make_caster t_cast; - for (size_t i = 0; i < size; i++) { + for (int i = 0; i < size; i++) { if (!t_cast.from_python(src[i], flags, cleanup)) return false; value[i] = t_cast.value; } @@ -92,11 +92,11 @@ struct nb::detail::type_caster> { bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept { int rows = PyObject_Size(src.ptr()); // negative on failure if (rows != R) return false; - for (size_t i = 0; i < R; i++) { + for (int i = 0; i < R; i++) { const nb::object &slice = src[i]; int cols = PyObject_Size(slice.ptr()); // negative on failure if (cols != C) return false; - for (size_t j = 0; j < C; j++) { + for (int j = 0; j < C; j++) { make_caster t_cast; if (!t_cast.from_python(slice[j], flags, cleanup)) return false; value[j][i] = t_cast.value; @@ -124,25 +124,25 @@ struct nb::detail::type_caster> { template struct nb::detail::type_caster>> { using glm_type = glm::vec; - using numpy_type = nb::ndarray>; + using numpy_type = nb::ndarray>; NB_TYPE_CASTER(std::vector, const_name(glm_name::multi_name)); bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept { make_caster arr_cast; if (arr_cast.from_python(src, flags, cleanup)) { - int num_vec = arr_cast.value.shape(0); + size_t num_vec = arr_cast.value.shape(0); value.resize(num_vec); - for (int i = 0; i < num_vec; i++) { + for (size_t i = 0; i < num_vec; i++) { for (int j = 0; j < N; j++) { value[i][j] = arr_cast.value(i, j); } } } else { - int num_vec = PyObject_Size(src.ptr()); // negative on failure - if (num_vec < 0) return false; + size_t num_vec = PyObject_Size(src.ptr()); // negative on failure + if (num_vec == static_cast(-1)) return false; value.resize(num_vec); - for (int i = 0; i < num_vec; i++) { + for (size_t i = 0; i < num_vec; i++) { make_caster vec_cast; if (!vec_cast.from_python(src[i], flags, cleanup)) return false; value[i] = vec_cast.value; @@ -155,13 +155,13 @@ struct nb::detail::type_caster>> { size_t num_vec = vec.size(); T *buffer = new T[num_vec * N]; nb::capsule mem_mgr(buffer, [](void *p) noexcept { delete[](T *) p; }); - for (int i = 0; i < num_vec; i++) { + for (size_t i = 0; i < num_vec; i++) { for (int j = 0; j < N; j++) { buffer[i * N + j] = vec[i][j]; } } numpy_type arr{buffer, {num_vec, N}, std::move(mem_mgr)}; - return ndarray_wrap(arr.handle(), int(ndarray_framework::numpy), policy, + return ndarray_wrap(arr.handle(), ndarray_framework::numpy, policy, cleanup); } }; @@ -170,7 +170,7 @@ struct nb::detail::type_caster>> { template struct nb::detail::type_caster>> { using glm_type = glm::vec; - using numpy_type = nb::ndarray>; + using numpy_type = nb::ndarray>; NB_TYPE_CASTER(manifold::VecView, const_name(glm_name::multi_name)); @@ -178,9 +178,9 @@ struct nb::detail::type_caster>> { make_caster arr_cast; if (!arr_cast.from_python(src, flags, cleanup)) return false; // TODO try 2d iterators if numpy cast fails - int num_vec = arr_cast.value.shape(0); + size_t num_vec = arr_cast.value.shape(0); if (num_vec != value.size()) return false; - for (int i = 0; i < num_vec; i++) { + for (size_t i = 0; i < num_vec; i++) { for (int j = 0; j < N; j++) { value[i][j] = arr_cast.value(i, j); } @@ -189,11 +189,12 @@ struct nb::detail::type_caster>> { } static handle from_cpp(Value vec, rv_policy policy, cleanup_list *cleanup) noexcept { + // do we have ownership issue here? size_t num_vec = vec.size(); static_assert(sizeof(vec[0]) == (N * sizeof(T)), "VecView -> numpy requires packed structs"); - numpy_type arr{&vec[0], {num_vec, N}}; - return ndarray_wrap(arr.handle(), int(ndarray_framework::numpy), policy, + numpy_type arr{&vec[0], {num_vec, N}, nb::handle()}; + return ndarray_wrap(arr.handle(), ndarray_framework::numpy, policy, cleanup); } }; @@ -294,11 +295,13 @@ NB_MODULE(manifold3d, m) { const float *oldProps) { auto result = f(v, nb::ndarray( - oldProps, {static_cast(oldNumProp)})); - nb::ndarray> array; + oldProps, {static_cast(oldNumProp)}, + nb::handle())); + nb::ndarray> array; std::vector vec; if (nb::try_cast(result, array)) { - if (array.ndim() != 1 || array.shape(0) != newNumProp) + if (array.ndim() != 1 || + array.shape(0) != static_cast(newNumProp)) throw std::runtime_error("Invalid vector shape, expected (" + std::to_string(newNumProp) + ")"); for (int i = 0; i < newNumProp; i++) newProps[i] = array(i); @@ -386,14 +389,14 @@ NB_MODULE(manifold3d, m) { "(xmin, ymin, zmin, xmax, ymax, zmax).") .def_static( "smooth", - [](const MeshGL &mesh, std::vector sharpened_edges, + [](const MeshGL &mesh, std::vector sharpened_edges, std::vector edge_smoothness) { if (sharpened_edges.size() != edge_smoothness.size()) { throw std::runtime_error( "sharpened_edges.size() != edge_smoothness.size()"); } std::vector vec(sharpened_edges.size()); - for (int i = 0; i < vec.size(); i++) { + for (size_t i = 0; i < vec.size(); i++) { vec[i] = {sharpened_edges[i], edge_smoothness[i]}; } return Manifold::Smooth(mesh, vec); @@ -448,59 +451,59 @@ NB_MODULE(manifold3d, m) { // affect the original array passed into the function "__init__", [](MeshGL *self, - nb::ndarray, nb::c_contig> - &vertProp, - nb::ndarray, nb::c_contig> - &triVerts, - const std::optional, + nb::ndarray, nb::c_contig> &vertProp, + nb::ndarray, nb::c_contig> &triVerts, + const std::optional, nb::c_contig>> &mergeFromVert, - const std::optional, + const std::optional, nb::c_contig>> &mergeToVert, - const std::optional, - nb::c_contig>> &runIndex, - const std::optional, + const std::optional< + nb::ndarray, nb::c_contig>> &runIndex, + const std::optional, nb::c_contig>> &runOriginalID, - std::optional, + std::optional, nb::c_contig>> &runTransform, - const std::optional, - nb::c_contig>> &faceID, - const std::optional, + const std::optional< + nb::ndarray, nb::c_contig>> &faceID, + const std::optional, nb::c_contig>> &halfedgeTangent, float precision) { - new (self) MeshGL(); - MeshGL &out = *self; - out.numProp = vertProp.shape(1); - out.vertProperties = toVector(vertProp.data(), vertProp.size()); + new (self) MeshGL(); + MeshGL &out = *self; + out.numProp = vertProp.shape(1); + out.vertProperties = + toVector(vertProp.data(), vertProp.size()); - out.triVerts = toVector(triVerts.data(), triVerts.size()); + out.triVerts = toVector(triVerts.data(), triVerts.size()); - if (mergeFromVert.has_value()) - out.mergeFromVert = - toVector(mergeFromVert->data(), mergeFromVert->size()); + if (mergeFromVert.has_value()) + out.mergeFromVert = toVector(mergeFromVert->data(), + mergeFromVert->size()); - if (mergeToVert.has_value()) - out.mergeToVert = - toVector(mergeToVert->data(), mergeToVert->size()); + if (mergeToVert.has_value()) + out.mergeToVert = + toVector(mergeToVert->data(), mergeToVert->size()); - if (runIndex.has_value()) - out.runIndex = toVector(runIndex->data(), runIndex->size()); + if (runIndex.has_value()) + out.runIndex = + toVector(runIndex->data(), runIndex->size()); - if (runOriginalID.has_value()) - out.runOriginalID = - toVector(runOriginalID->data(), runOriginalID->size()); + if (runOriginalID.has_value()) + out.runOriginalID = toVector(runOriginalID->data(), + runOriginalID->size()); - if (runTransform.has_value()) { - out.runTransform = - toVector(runTransform->data(), runTransform->size()); - } + if (runTransform.has_value()) { + out.runTransform = + toVector(runTransform->data(), runTransform->size()); + } - if (faceID.has_value()) - out.faceID = toVector(faceID->data(), faceID->size()); + if (faceID.has_value()) + out.faceID = toVector(faceID->data(), faceID->size()); - if (halfedgeTangent.has_value()) { - out.halfedgeTangent = - toVector(halfedgeTangent->data(), halfedgeTangent->size()); - } + if (halfedgeTangent.has_value()) { + out.halfedgeTangent = toVector(halfedgeTangent->data(), + halfedgeTangent->size()); + } }, nb::arg("vert_properties"), nb::arg("tri_verts"), nb::arg("merge_from_vert") = nb::none(), @@ -510,45 +513,58 @@ NB_MODULE(manifold3d, m) { nb::arg("run_transform") = nb::none(), nb::arg("face_id") = nb::none(), nb::arg("halfedge_tangent") = nb::none(), nb::arg("precision") = 0) - .def_prop_ro("vert_properties", - [](const MeshGL &self) { - return nb::ndarray( - self.vertProperties.data(), - {self.vertProperties.size() / self.numProp, self.numProp}); - }, nb::rv_policy::reference_internal) - .def_prop_ro("tri_verts", - [](const MeshGL &self) { - return nb::ndarray( - self.triVerts.data(), {self.triVerts.size() / 3, 3}); - }, nb::rv_policy::reference_internal) - .def_prop_ro("run_transform", - [](const MeshGL &self) { - return nb::ndarray( - self.runTransform.data(), {self.runTransform.size() / 12, 4, 3}); - }, nb::rv_policy::reference_internal) - .def_prop_ro("halfedge_tangent", - [](const MeshGL &self) { - return nb::ndarray( - self.halfedgeTangent.data(), {self.halfedgeTangent.size() / 12, 3, 4}); - }, nb::rv_policy::reference_internal) + .def_prop_ro( + "vert_properties", + [](const MeshGL &self) { + return nb::ndarray( + self.vertProperties.data(), + {self.vertProperties.size() / self.numProp, self.numProp}, + nb::handle()); + }, + nb::rv_policy::reference_internal) + .def_prop_ro( + "tri_verts", + [](const MeshGL &self) { + return nb::ndarray( + self.triVerts.data(), {self.triVerts.size() / 3, 3}, + nb::handle()); + }, + nb::rv_policy::reference_internal) + .def_prop_ro( + "run_transform", + [](const MeshGL &self) { + return nb::ndarray( + self.runTransform.data(), {self.runTransform.size() / 12, 4, 3}, + nb::handle()); + }, + nb::rv_policy::reference_internal) + .def_prop_ro( + "halfedge_tangent", + [](const MeshGL &self) { + return nb::ndarray( + self.halfedgeTangent.data(), + {self.halfedgeTangent.size() / 12, 3, 4}, nb::handle()); + }, + nb::rv_policy::reference_internal) .def_ro("merge_from_vert", &MeshGL::mergeFromVert) .def_ro("merge_to_vert", &MeshGL::mergeToVert) .def_ro("run_index", &MeshGL::runIndex) .def_ro("run_original_id", &MeshGL::runOriginalID) .def_ro("face_id", &MeshGL::faceID) .def_static( - "level_set", + "level_set", [](const std::function &f, std::vector bounds, float edgeLength, float level = 0.0) { - // Same format as Manifold.bounding_box - Box bound = {glm::vec3(bounds[0], bounds[1], bounds[2]), - glm::vec3(bounds[3], bounds[4], bounds[5])}; - - std::function cppToPython = [&f](glm::vec3 v) { - return f(v.x, v.y, v.z); - }; - Mesh result = LevelSet(cppToPython, bound, edgeLength, level, false); - return MeshGL(result); + // Same format as Manifold.bounding_box + Box bound = {glm::vec3(bounds[0], bounds[1], bounds[2]), + glm::vec3(bounds[3], bounds[4], bounds[5])}; + + std::function cppToPython = [&f](glm::vec3 v) { + return f(v.x, v.y, v.z); + }; + Mesh result = + LevelSet(cppToPython, bound, edgeLength, level, false); + return MeshGL(result); }, nb::arg("f"), nb::arg("bounds"), nb::arg("edgeLength"), nb::arg("level") = 0.0, diff --git a/bindings/python/third_party/nanobind b/bindings/python/third_party/nanobind index 1a309ba44..8d7f1ee06 160000 --- a/bindings/python/third_party/nanobind +++ b/bindings/python/third_party/nanobind @@ -1 +1 @@ -Subproject commit 1a309ba444a47e081dc6213d72345a2fbbd20795 +Subproject commit 8d7f1ee0621c17fa370b704b2100ffa0243d5bfb diff --git a/extras/minimize_testcase.cpp b/extras/minimize_testcase.cpp index 7ccf60df9..fb81d0387 100644 --- a/extras/minimize_testcase.cpp +++ b/extras/minimize_testcase.cpp @@ -61,11 +61,11 @@ inline bool intersect(glm::vec2 p0, glm::vec2 p1, glm::vec2 q0, glm::vec2 q1, // check if removing point j in polygon i will introduce self-intersection // this checks if the new edge j-1 <-> j+1 intersects with any other edges, // assuming the original polygon does not contain self-intersection -bool safeToRemove(const Polygons &polys, int i, int j, float precision) { +bool safeToRemove(const Polygons &polys, size_t i, size_t j, float precision) { if (polys[i].size() == 3) return false; glm::vec2 prev = polys[i][j == 0 ? polys[i].size() - 1 : (j - 1)]; glm::vec2 next = polys[i][j == (polys[i].size() - 1) ? 0 : (j + 1)]; - for (int k = 0; k < polys.size(); k++) { + for (size_t k = 0; k < polys.size(); k++) { auto ll = [&](size_t l) { return l == (polys[k].size() - 1) ? 0 : (l + 1); }; @@ -74,7 +74,7 @@ bool safeToRemove(const Polygons &polys, int i, int j, float precision) { #if MANIFOLD_PAR == 'T' && __has_include() std::execution::par, #endif - countAt((size_t)0), countAt(polys[k].size()), [=](size_t l) { + countAt(0_z), countAt(polys[k].size()), [=](size_t l) { if (i == k && (l == j || ll(l) == j)) return true; return !intersect(prev, next, polysk[l], polysk[ll(l)], precision); @@ -84,8 +84,8 @@ bool safeToRemove(const Polygons &polys, int i, int j, float precision) { return true; } -std::pair findIndex(const Polygons &polys, int i) { - int outer = 0; +std::pair findIndex(const Polygons &polys, size_t i) { + size_t outer = 0; while (i >= polys[outer].size()) i -= polys[outer++].size(); return std::make_pair(outer, i); } @@ -139,9 +139,9 @@ bool rayHit(glm::vec2 point, glm::vec2 q0, glm::vec2 q1) { // this enumerates over the first point in all other polygons, // and check if they are inside the current polygon // this algorithm assumes that polygons are non-intersecting -std::vector getChildren(const Polygons &polys, int i) { +std::vector getChildren(const Polygons &polys, size_t i) { std::vector results; - for (int j = 0; j < polys.size(); j++) { + for (size_t j = 0; j < polys.size(); j++) { if (i == j) continue; glm::vec2 point = polys[j][0]; auto k1 = [&](size_t k) { @@ -173,7 +173,7 @@ void simplify(Polygons &polys, float precision = -1) { removedSomething = false; // try to remove simple polygons - for (int i = 0; i < polys.size(); i++) { + for (size_t i = 0; i < polys.size(); i++) { std::vector children = getChildren(polys, i); // if there are children, we can't remove it or we will mess up with // winding direction... @@ -195,9 +195,9 @@ void simplify(Polygons &polys, float precision = -1) { } } - for (int i = 0; i < polys.size(); i++) { + for (size_t i = 0; i < polys.size(); i++) { std::vector children = getChildren(polys, i); - for (int j = 0; j < polys[i].size(); j++) { + for (size_t j = 0; j < polys[i].size(); j++) { // removed vertex cannot change inclusion relation // we just check if the vertex // x: intersects with j0, j (original edge 1) @@ -205,8 +205,8 @@ void simplify(Polygons &polys, float precision = -1) { // z: intersects with j0, j1 (new edge) // if (x ^ y ^ z) is true, it means that the count % 2 is changed, // and we changed inclusion relation, so vertex j cannot be removed - int j0 = j == 0 ? polys[i].size() - 1 : j - 1; - int j1 = j == polys[i].size() - 1 ? 0 : j + 1; + size_t j0 = j == 0 ? polys[i].size() - 1 : j - 1; + size_t j1 = j == polys[i].size() - 1 ? 0 : j + 1; if (std::any_of(children.begin(), children.end(), [&](int k) { return rayHit(polys[k][0], polys[i][j0], polys[i][j]) ^ rayHit(polys[k][0], polys[i][j], polys[i][j1]) ^ @@ -318,7 +318,7 @@ int main(int argc, char **argv) { SimplePolygon poly; // search for precision first while (std::getline(fin, line)) { - int index = line.find("Precision = "); + size_t index = line.find("Precision = "); if (index != std::string::npos) { std::istringstream iss(line.substr(index + 12)); if (!(iss >> precision)) { diff --git a/extras/perf b/extras/perf deleted file mode 100644 index d2d9cf917..000000000 --- a/extras/perf +++ /dev/null @@ -1,22 +0,0 @@ -2022-02-22 -CPU: -nTri = 512, time = 0.0176101 sec -nTri = 2048, time = 0.0196583 sec -nTri = 8192, time = 0.0355035 sec -nTri = 32768, time = 0.0999017 sec -nTri = 131072, time = 0.334987 sec -nTri = 524288, time = 1.25136 sec -nTri = 2097152, time = 5.81453 sec -nTri = 8388608, time = 26.987 sec - -GPU: -nTri = 512, time = 0.00846689 sec -nTri = 2048, time = 0.0115478 sec -nTri = 8192, time = 0.0222773 sec -nTri = 32768, time = 0.0560136 sec -nTri = 131072, time = 0.176548 sec -nTri = 524288, time = 0.670403 sec -nTri = 2097152, time = 2.60109 sec -nTri = 8388608, time = 10.5697 sec - - diff --git a/flake.lock b/flake.lock index e7334b7ad..de866f1f1 100644 --- a/flake.lock +++ b/flake.lock @@ -53,11 +53,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704722960, - "narHash": "sha256-mKGJ3sPsT6//s+Knglai5YflJUF2DGj7Ai6Ynopz0kI=", + "lastModified": 1717602782, + "narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "317484b1ead87b9c1b8ac5261a8d2dd748a0492d", + "rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 73da2eb73..c07cf3b77 100644 --- a/flake.nix +++ b/flake.nix @@ -72,7 +72,7 @@ { parallel-backend = "none"; } { parallel-backend = "tbb"; - build-tools = with pkgs; [ tbb_2021_8 pkg-config ]; + build-tools = with pkgs; [ tbb pkg-config ]; } ]; in @@ -126,7 +126,7 @@ numpy ]; buildInputs = with pkgs; [ - tbb_2021_8 + tbb glm clipper2 ]; @@ -156,7 +156,7 @@ devShell = pkgs.mkShell { buildInputs = with pkgs; [ cmake - tbb_2021_8 + tbb gtest ]; }; diff --git a/meshIO/src/meshIO.cpp b/meshIO/src/meshIO.cpp index 3e33d3fc6..3021d034e 100644 --- a/meshIO/src/meshIO.cpp +++ b/meshIO/src/meshIO.cpp @@ -91,7 +91,7 @@ void ExportScene(aiScene* scene, const std::string& filename) { delete scene; - ASSERT(result == AI_SUCCESS, userErr, exporter.GetErrorString()); + DEBUG_ASSERT(result == AI_SUCCESS, userErr, exporter.GetErrorString()); } } // namespace @@ -141,20 +141,20 @@ Mesh ImportMesh(const std::string& filename, bool forceCleanup) { const aiScene* scene = importer.ReadFile(filename, flags); - ASSERT(scene, userErr, importer.GetErrorString()); + DEBUG_ASSERT(scene, userErr, importer.GetErrorString()); Mesh mesh_out; - for (int i = 0; i < scene->mNumMeshes; ++i) { + for (size_t i = 0; i < scene->mNumMeshes; ++i) { const aiMesh* mesh_i = scene->mMeshes[i]; - for (int j = 0; j < mesh_i->mNumVertices; ++j) { + for (size_t j = 0; j < mesh_i->mNumVertices; ++j) { const aiVector3D vert = mesh_i->mVertices[j]; mesh_out.vertPos.push_back(isYup ? glm::vec3(vert.z, vert.x, vert.y) : glm::vec3(vert.x, vert.y, vert.z)); } - for (int j = 0; j < mesh_i->mNumFaces; ++j) { + for (size_t j = 0; j < mesh_i->mNumFaces; ++j) { const aiFace face = mesh_i->mFaces[j]; - ASSERT(face.mNumIndices == 3, userErr, - "Non-triangular face in " + filename); + DEBUG_ASSERT(face.mNumIndices == 3, userErr, + "Non-triangular face in " + filename); mesh_out.triVerts.emplace_back(face.mIndices[0], face.mIndices[1], face.mIndices[2]); } @@ -199,8 +199,9 @@ void ExportMesh(const std::string& filename, const MeshGL& mesh, int c = options.mat.normalChannels[i]; validChannels &= c >= 3 && c < (int)mesh.numProp; } - ASSERT(validChannels, userErr, - "When faceted is false, valid normalChannels must be supplied."); + DEBUG_ASSERT( + validChannels, userErr, + "When faceted is false, valid normalChannels must be supplied."); mesh_out->mNormals = new aiVector3D[mesh_out->mNumVertices]; } @@ -211,10 +212,10 @@ void ExportMesh(const std::string& filename, const MeshGL& mesh, validChannels &= c < (int)mesh.numProp; hasColor |= c >= 0; } - ASSERT(validChannels, userErr, "Invalid colorChannels."); + DEBUG_ASSERT(validChannels, userErr, "Invalid colorChannels."); if (hasColor) mesh_out->mColors[0] = new aiColor4D[mesh_out->mNumVertices]; - for (int i = 0; i < mesh_out->mNumVertices; ++i) { + for (size_t i = 0; i < mesh_out->mNumVertices; ++i) { glm::vec3 v; for (int j : {0, 1, 2}) v[j] = mesh.vertProperties[i * mesh.numProp + j]; mesh_out->mVertices[i] = @@ -242,7 +243,7 @@ void ExportMesh(const std::string& filename, const MeshGL& mesh, mesh_out->mNumFaces = mesh.NumTri(); mesh_out->mFaces = new aiFace[mesh_out->mNumFaces]; - for (int i = 0; i < mesh_out->mNumFaces; ++i) { + for (size_t i = 0; i < mesh_out->mNumFaces; ++i) { aiFace& face = mesh_out->mFaces[i]; face.mNumIndices = 3; face.mIndices = new glm::uint[face.mNumIndices]; @@ -284,18 +285,18 @@ void ExportMesh(const std::string& filename, const Mesh& mesh, mesh_out->mNumVertices = mesh.vertPos.size(); mesh_out->mVertices = new aiVector3D[mesh_out->mNumVertices]; if (!options.faceted) { - ASSERT( + DEBUG_ASSERT( mesh.vertNormal.size() == mesh.vertPos.size(), userErr, "vertNormal must be the same length as vertPos when faceted is false."); mesh_out->mNormals = new aiVector3D[mesh_out->mNumVertices]; } if (!options.mat.vertColor.empty()) { - ASSERT(mesh.vertPos.size() == options.mat.vertColor.size(), userErr, - "If present, vertColor must be the same length as vertPos."); + DEBUG_ASSERT(mesh.vertPos.size() == options.mat.vertColor.size(), userErr, + "If present, vertColor must be the same length as vertPos."); mesh_out->mColors[0] = new aiColor4D[mesh_out->mNumVertices]; } - for (int i = 0; i < mesh_out->mNumVertices; ++i) { + for (size_t i = 0; i < mesh_out->mNumVertices; ++i) { const glm::vec3& v = mesh.vertPos[i]; mesh_out->mVertices[i] = isYup ? aiVector3D(v.y, v.z, v.x) : aiVector3D(v.x, v.y, v.z); @@ -313,7 +314,7 @@ void ExportMesh(const std::string& filename, const Mesh& mesh, mesh_out->mNumFaces = mesh.triVerts.size(); mesh_out->mFaces = new aiFace[mesh_out->mNumFaces]; - for (int i = 0; i < mesh_out->mNumFaces; ++i) { + for (size_t i = 0; i < mesh_out->mNumFaces; ++i) { aiFace& face = mesh_out->mFaces[i]; face.mNumIndices = 3; face.mIndices = new glm::uint[face.mNumIndices]; diff --git a/samples/src/scallop.cpp b/samples/src/scallop.cpp index d72d5f495..2b24637f3 100644 --- a/samples/src/scallop.cpp +++ b/samples/src/scallop.cpp @@ -43,7 +43,7 @@ Manifold Scallop() { if (j == 2 * wiggles) j = 0; float smoothness = 1 - sharpness * glm::cos((theta + delta / 2) / 2); - int halfedge = 3 * scallop.triVerts.size() + 1; + size_t halfedge = 3 * scallop.triVerts.size() + 1; sharpenedEdges.push_back({halfedge, smoothness}); scallop.triVerts.push_back({0, 2 + i, 2 + j}); @@ -54,4 +54,4 @@ Manifold Scallop() { return Manifold::Smooth(scallop, sharpenedEdges); } -} // namespace manifold \ No newline at end of file +} // namespace manifold diff --git a/src/collider/include/collider.h b/src/collider/include/collider.h index 97208abdb..bf5235445 100644 --- a/src/collider/include/collider.h +++ b/src/collider/include/collider.h @@ -38,8 +38,8 @@ class Collider { // even nodes are leaves, odd nodes are internal, root is 1 Vec> internalChildren_; - int NumInternal() const { return internalChildren_.size(); }; - int NumLeaves() const { + size_t NumInternal() const { return internalChildren_.size(); }; + size_t NumLeaves() const { return internalChildren_.empty() ? 0 : (NumInternal() + 1); }; }; diff --git a/src/collider/src/collider.cpp b/src/collider/src/collider.cpp index 7a4ed75f5..321818b1f 100644 --- a/src/collider/src/collider.cpp +++ b/src/collider/src/collider.cpp @@ -84,7 +84,7 @@ struct CreateRadixTree { } int PrefixLength(int i, int j) const { - if (j < 0 || j >= leafMorton_.size()) { + if (j < 0 || j >= static_cast(leafMorton_.size())) { return -1; } else { int out; @@ -285,8 +285,8 @@ namespace manifold { Collider::Collider(const VecView& leafBB, const VecView& leafMorton) { ZoneScoped; - ASSERT(leafBB.size() == leafMorton.size(), userErr, - "vectors must be the same length"); + DEBUG_ASSERT(leafBB.size() == leafMorton.size(), userErr, + "vectors must be the same length"); int num_nodes = 2 * leafBB.size() - 1; // assign and allocate members nodeBBox_.resize(num_nodes); @@ -347,8 +347,8 @@ SparseIndices Collider::Collisions(const VecView& queriesIn) const { */ void Collider::UpdateBoxes(const VecView& leafBB) { ZoneScoped; - ASSERT(leafBB.size() == NumLeaves(), userErr, - "must have the same number of updated boxes as original"); + DEBUG_ASSERT(leafBB.size() == NumLeaves(), userErr, + "must have the same number of updated boxes as original"); // copy in leaf node Boxes strided_range::Iter> leaves(nodeBBox_.begin(), nodeBBox_.end(), 2); auto policy = autoPolicy(NumInternal()); diff --git a/src/cross_section/src/cross_section.cpp b/src/cross_section/src/cross_section.cpp index a7bb15c29..d2f9b8402 100644 --- a/src/cross_section/src/cross_section.cpp +++ b/src/cross_section/src/cross_section.cpp @@ -101,7 +101,7 @@ C2::PathsD transform(const C2::PathsD ps, const glm::mat3x2 m) { for (auto path : ps) { auto sz = path.size(); auto s = C2::PathD(sz); - for (int i = 0; i < sz; ++i) { + for (size_t i = 0; i < sz; ++i) { auto idx = invert ? sz - 1 - i : i; s[idx] = v2_to_pd(m * glm::vec3(path[i].x, path[i].y, 1)); } @@ -117,10 +117,10 @@ std::shared_ptr shared_paths(const C2::PathsD& ps) { // forward declaration for mutual recursion void decompose_hole(const C2::PolyTreeD* outline, std::vector& polys, C2::PathsD& poly, - int n_holes, int j); + size_t n_holes, size_t j); void decompose_outline(const C2::PolyTreeD* tree, - std::vector& polys, int i) { + std::vector& polys, size_t i) { auto n_outlines = tree->Count(); if (i < n_outlines) { auto outline = tree->Child(i); @@ -137,7 +137,7 @@ void decompose_outline(const C2::PolyTreeD* tree, void decompose_hole(const C2::PolyTreeD* outline, std::vector& polys, C2::PathsD& poly, - int n_holes, int j) { + size_t n_holes, size_t j) { if (j < n_holes) { auto child = outline->Child(j); decompose_outline(child, polys, 0); @@ -146,7 +146,7 @@ void decompose_hole(const C2::PolyTreeD* outline, } } -void flatten(const C2::PolyTreeD* tree, C2::PathsD& polys, int i) { +void flatten(const C2::PolyTreeD* tree, C2::PathsD& polys, size_t i) { auto n_outlines = tree->Count(); if (i < n_outlines) { auto outline = tree->Child(i); @@ -177,33 +177,28 @@ void HullBacktrack(const glm::vec2& pt, std::vector& stack) { // https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain // This is the same algorithm (Andrew, also called Montone Chain). C2::PathD HullImpl(SimplePolygon& pts) { - int len = pts.size(); + size_t len = pts.size(); if (len < 3) return C2::PathD(); // not enough points to create a polygon std::sort(pts.begin(), pts.end(), V2Lesser); auto lower = std::vector{}; - for (int i = 0; i < len; i++) { - HullBacktrack(pts[i], lower); - lower.push_back(pts[i]); + for (auto& pt : pts) { + HullBacktrack(pt, lower); + lower.push_back(pt); } auto upper = std::vector{}; - for (int i = len - 1; i >= 0; i--) { - HullBacktrack(pts[i], upper); - upper.push_back(pts[i]); + for (auto pt_iter = pts.rbegin(); pt_iter != pts.rend(); pt_iter++) { + HullBacktrack(*pt_iter, upper); + upper.push_back(*pt_iter); } upper.pop_back(); lower.pop_back(); - auto path = C2::PathD(lower.size() + upper.size()); - for (int i = 0; i < lower.size(); i++) { - path[i] = v2_to_pd(lower[i]); - } - auto llen = lower.size(); - int sz = upper.size(); // "fix" -Waggressive-loop-optimizations warning. - for (int i = 0; i < sz; i++) { - path[i + llen] = v2_to_pd(upper[i]); - } + auto path = C2::PathD(); + path.reserve(lower.size() + upper.size()); + for (const auto& l : lower) path.push_back(v2_to_pd(l)); + for (const auto& u : upper) path.push_back(v2_to_pd(u)); return path; } } // namespace @@ -381,12 +376,12 @@ CrossSection CrossSection::BatchBoolean( auto subjs = crossSections[0].GetPaths(); int n_clips = 0; - for (int i = 1; i < crossSections.size(); ++i) { + for (size_t i = 1; i < crossSections.size(); ++i) { n_clips += crossSections[i].GetPaths()->paths_.size(); } auto clips = C2::PathsD(); clips.reserve(n_clips); - for (int i = 1; i < crossSections.size(); ++i) { + for (size_t i = 1; i < crossSections.size(); ++i) { auto ps = crossSections[i].GetPaths(); clips.insert(clips.end(), ps->paths_.begin(), ps->paths_.end()); } @@ -471,12 +466,11 @@ std::vector CrossSection::Decompose() const { auto polys = std::vector(); decompose_outline(&tree, polys, 0); - auto n_polys = polys.size(); - auto comps = std::vector(n_polys); + auto comps = std::vector(); + comps.reserve(polys.size()); // reverse the stack while wrapping - for (int i = 0; i < n_polys; ++i) { - comps[n_polys - i - 1] = CrossSection(shared_paths(polys[i])); - } + for (auto poly = polys.rbegin(); poly != polys.rend(); ++poly) + comps.emplace_back(CrossSection(shared_paths(*poly))); return comps; } diff --git a/src/manifold/include/manifold.h b/src/manifold/include/manifold.h index 8b3697e16..d2391510c 100644 --- a/src/manifold/include/manifold.h +++ b/src/manifold/include/manifold.h @@ -46,14 +46,16 @@ class CsgLeafNode; struct MeshGL { /// Number of property vertices uint32_t NumVert() const { - if (vertProperties.size() / numProp >= std::numeric_limits::max()) - throw std::out_of_range("mesh too large"); + ASSERT(vertProperties.size() / numProp < + static_cast(std::numeric_limits::max()), + std::out_of_range("mesh too large for MeshGL")); return vertProperties.size() / numProp; }; /// Number of triangles uint32_t NumTri() const { - if (vertProperties.size() / numProp >= std::numeric_limits::max()) - throw std::out_of_range("mesh too large"); + ASSERT(triVerts.size() / 3 < + static_cast(std::numeric_limits::max()), + std::out_of_range("mesh too large for MeshGL")); return triVerts.size() / 3; }; diff --git a/src/manifold/src/boolean3.cpp b/src/manifold/src/boolean3.cpp index 5ed8660d3..27e442950 100644 --- a/src/manifold/src/boolean3.cpp +++ b/src/manifold/src/boolean3.cpp @@ -30,7 +30,8 @@ namespace { glm::vec2 Interpolate(glm::vec3 pL, glm::vec3 pR, float x) { const float dxL = x - pL.x; const float dxR = x - pR.x; - ASSERT(dxL * dxR <= 0, logicErr, "Boolean manifold error: not in domain"); + DEBUG_ASSERT(dxL * dxR <= 0, logicErr, + "Boolean manifold error: not in domain"); const bool useL = fabs(dxL) < fabs(dxR); const glm::vec3 dLR = pR - pL; const float lambda = (useL ? dxL : dxR) / dLR.x; @@ -46,7 +47,8 @@ glm::vec4 Intersect(const glm::vec3 &pL, const glm::vec3 &pR, const glm::vec3 &qL, const glm::vec3 &qR) { const float dyL = qL.y - pL.y; const float dyR = qR.y - pR.y; - ASSERT(dyL * dyR <= 0, logicErr, "Boolean manifold error: no intersection"); + DEBUG_ASSERT(dyL * dyR <= 0, logicErr, + "Boolean manifold error: no intersection"); const bool useL = fabs(dyL) < fabs(dyR); const float dx = pR.x - pL.x; float lambda = (useL ? dyL : dyR) / (dyL - dyR); @@ -139,7 +141,7 @@ inline thrust::pair Shadow01( // much faster than standard binary search on large arrays size_t monobound_quaternary_search(VecView array, int64_t key) { if (array.size() == 0) { - return -1; + return std::numeric_limits::max(); } size_t bot = 0; size_t top = array.size(); @@ -236,7 +238,7 @@ struct Kernel11 { if (s11 == 0) { // No intersection xyzz11 = glm::vec4(NAN); } else { - ASSERT(k == 2, logicErr, "Boolean manifold error: s11"); + DEBUG_ASSERT(k == 2, logicErr, "Boolean manifold error: s11"); xyzz11 = Intersect(pRL[0], pRL[1], qRL[0], qRL[1]); const int p1s = halfedgeP[p1].startVert; @@ -328,13 +330,13 @@ struct Kernel02 { if (s02 == 0) { // No intersection z02 = NAN; } else { - ASSERT(k == 2, logicErr, "Boolean manifold error: s02"); + DEBUG_ASSERT(k == 2, logicErr, "Boolean manifold error: s02"); glm::vec3 vertPos = vertPosP[p0]; z02 = Interpolate(yzzRL[0], yzzRL[1], vertPos.y)[1]; if (forward) { if (!Shadows(vertPos.z, z02, expandP * vertNormalP[p0].z)) s02 = 0; } else { - // ASSERT(closestVert != -1, topologyErr, "No closest vert"); + // DEBUG_ASSERT(closestVert != -1, topologyErr, "No closest vert"); if (!Shadows(z02, vertPos.z, expandP * vertNormalP[closestVert].z)) s02 = 0; } @@ -395,7 +397,7 @@ struct Kernel12 { const int64_t key = forward ? SparseIndices::EncodePQ(vert, q2) : SparseIndices::EncodePQ(q2, vert); const size_t idx = monobound_quaternary_search(p0q2, key); - if (idx != -1) { + if (idx != std::numeric_limits::max()) { const int s = s02[idx]; x12 += s * ((vert == edge.startVert) == forward ? 1 : -1); if (k < 2 && (k == 0 || (s != 0) != shadows)) { @@ -416,7 +418,9 @@ struct Kernel12 { const int64_t key = forward ? SparseIndices::EncodePQ(p1, q1F) : SparseIndices::EncodePQ(q1F, p1); const size_t idx = monobound_quaternary_search(p1q1, key); - if (idx != -1) { // s is implicitly zero for anything not found + if (idx != + std::numeric_limits::max()) { // s is implicitly zero for + // anything not found const int s = s11[idx]; x12 -= s * (edge.IsForward() ? 1 : -1); if (k < 2 && (k == 0 || (s != 0) != shadows)) { @@ -436,7 +440,7 @@ struct Kernel12 { if (x12 == 0) { // No intersection v12 = glm::vec3(NAN); } else { - ASSERT(k == 2, logicErr, "Boolean manifold error: v12"); + DEBUG_ASSERT(k == 2, logicErr, "Boolean manifold error: v12"); const glm::vec4 xzyy = Intersect(xzyLR0[0], xzyLR0[1], xzyLR1[0], xzyLR1[1]); v12.x = xzyy[0]; @@ -578,9 +582,6 @@ Boolean3::Boolean3(const Manifold::Impl &inP, const Manifold::Impl &inQ, Intersect12(inQ, inP, s20, p2q0, s11, p1q1, z20, xyzz11, p2q1_, false); PRINT("x21 size = " << x21_.size()); - if (x12_.size() + x21_.size() >= std::numeric_limits::max()) - throw std::out_of_range("mesh too large"); - Vec p0 = p0q2.Copy(false); p0q2.Resize(0); Vec q0 = p2q0.Copy(true); diff --git a/src/manifold/src/boolean_result.cpp b/src/manifold/src/boolean_result.cpp index c6750aca2..9afc6150d 100644 --- a/src/manifold/src/boolean_result.cpp +++ b/src/manifold/src/boolean_result.cpp @@ -104,8 +104,6 @@ std::tuple, Vec> SizeOutput( ZoneScoped; Vec sidesPerFacePQ(inP.NumTri() + inQ.NumTri(), 0); // note: numFaceR <= facePQ2R.size() = sidesPerFacePQ.size() + 1 - if (sidesPerFacePQ.size() + 1 >= std::numeric_limits::max()) - throw std::out_of_range("boolean result too large"); auto sidesPerFaceP = sidesPerFacePQ.view(0, inP.NumTri()); auto sidesPerFaceQ = sidesPerFacePQ.view(inP.NumTri(), inQ.NumTri()); @@ -241,12 +239,13 @@ std::vector PairUp(std::vector &edgePos) { // geometrically valid. If the order does not go start-end-start-end... then // the input and output are not geometrically valid and this algorithm becomes // a heuristic. - ASSERT(edgePos.size() % 2 == 0, topologyErr, - "Non-manifold edge! Not an even number of points."); + DEBUG_ASSERT(edgePos.size() % 2 == 0, topologyErr, + "Non-manifold edge! Not an even number of points."); size_t nEdges = edgePos.size() / 2; auto middle = std::partition(edgePos.begin(), edgePos.end(), [](EdgePos x) { return x.isStart; }); - ASSERT(middle - edgePos.begin() == nEdges, topologyErr, "Non-manifold edge!"); + DEBUG_ASSERT(static_cast(middle - edgePos.begin()) == nEdges, + topologyErr, "Non-manifold edge!"); auto cmp = [](EdgePos a, EdgePos b) { return a.edgePos < b.edgePos; }; std::stable_sort(edgePos.begin(), middle, cmp); std::stable_sort(middle, edgePos.end(), cmp); @@ -544,10 +543,6 @@ void CreateProperties(Manifold::Impl &outR, const Manifold::Impl &inP, propMissIdx[0].resize(inQ.NumPropVert(), -1); propMissIdx[1].resize(inP.NumPropVert(), -1); - if (static_cast(outR.NumVert()) * static_cast(numProp) >= - std::numeric_limits::max()) - throw std::out_of_range("too many vertices"); - outR.meshRelation_.properties.reserve(outR.NumVert() * numProp); int idx = 0; @@ -603,10 +598,10 @@ void CreateProperties(Manifold::Impl &outR, const Manifold::Impl &inP, } else { auto &bin = propIdx[key.y]; bool bFound = false; - for (int k = 0; k < bin.size(); ++k) { - if (bin[k].first == glm::ivec3(key.x, key.z, key.w)) { + for (const auto &b : bin) { + if (b.first == glm::ivec3(key.x, key.z, key.w)) { bFound = true; - outR.meshRelation_.triProperties[tri][i] = bin[k].second; + outR.meshRelation_.triProperties[tri][i] = b.second; break; } } @@ -638,8 +633,8 @@ Manifold::Impl Boolean3::Result(OpType op) const { assemble.Start(); #endif - ASSERT((expandP_ > 0) == (op == OpType::Add), logicErr, - "Result op type not compatible with constructor op type."); + DEBUG_ASSERT((expandP_ > 0) == (op == OpType::Add), logicErr, + "Result op type not compatible with constructor op type."); const int c1 = op == OpType::Intersect ? 0 : 1; const int c2 = op == OpType::Add ? 1 : 0; const int c3 = op == OpType::Intersect ? 1 : -1; @@ -782,7 +777,7 @@ Manifold::Impl Boolean3::Result(OpType op) const { // Level 6 if (ManifoldParams().intermediateChecks) - ASSERT(outR.IsManifold(), logicErr, "polygon mesh is not manifold!"); + DEBUG_ASSERT(outR.IsManifold(), logicErr, "polygon mesh is not manifold!"); outR.Face2Tri(faceEdge, halfedgeRef); @@ -793,7 +788,8 @@ Manifold::Impl Boolean3::Result(OpType op) const { #endif if (ManifoldParams().intermediateChecks) - ASSERT(outR.IsManifold(), logicErr, "triangulated mesh is not manifold!"); + DEBUG_ASSERT(outR.IsManifold(), logicErr, + "triangulated mesh is not manifold!"); CreateProperties(outR, inP_, inQ_); @@ -802,7 +798,8 @@ Manifold::Impl Boolean3::Result(OpType op) const { outR.SimplifyTopology(); if (ManifoldParams().intermediateChecks) - ASSERT(outR.Is2Manifold(), logicErr, "simplified mesh is not 2-manifold!"); + DEBUG_ASSERT(outR.Is2Manifold(), logicErr, + "simplified mesh is not 2-manifold!"); #ifdef MANIFOLD_DEBUG simplify.Stop(); diff --git a/src/manifold/src/constructors.cpp b/src/manifold/src/constructors.cpp index 0e816031a..92548060a 100644 --- a/src/manifold/src/constructors.cpp +++ b/src/manifold/src/constructors.cpp @@ -79,9 +79,9 @@ namespace manifold { */ Manifold Manifold::Smooth(const MeshGL& meshGL, const std::vector& sharpenedEdges) { - ASSERT(meshGL.halfedgeTangent.empty(), std::runtime_error, - "when supplying tangents, the normal constructor should be used " - "rather than Smooth()."); + DEBUG_ASSERT(meshGL.halfedgeTangent.empty(), std::runtime_error, + "when supplying tangents, the normal constructor should be used " + "rather than Smooth()."); // Don't allow any triangle merging. std::vector propertyTolerance(meshGL.numProp - 3, -1); @@ -121,9 +121,9 @@ Manifold Manifold::Smooth(const MeshGL& meshGL, */ Manifold Manifold::Smooth(const Mesh& mesh, const std::vector& sharpenedEdges) { - ASSERT(mesh.halfedgeTangent.empty(), std::runtime_error, - "when supplying tangents, the normal constructor should be used " - "rather than Smooth()."); + DEBUG_ASSERT(mesh.halfedgeTangent.empty(), std::runtime_error, + "when supplying tangents, the normal constructor should be used " + "rather than Smooth()."); Impl::MeshRelationD relation = {(int)ReserveIDs(1)}; std::shared_ptr impl = std::make_shared(mesh, relation); @@ -257,14 +257,14 @@ Manifold Manifold::Extrude(const Polygons& crossSection, float height, auto& triVerts = triVertsDH; int nCrossSection = 0; bool isCone = scaleTop.x == 0.0 && scaleTop.y == 0.0; - int idx = 0; + size_t idx = 0; PolygonsIdx polygonsIndexed; for (auto& poly : crossSection) { nCrossSection += poly.size(); SimplePolygonIdx simpleIndexed; for (const glm::vec2& polyVert : poly) { vertPos.push_back({polyVert.x, polyVert.y, 0.0f}); - simpleIndexed.push_back({polyVert, idx++}); + simpleIndexed.push_back({polyVert, static_cast(idx++)}); } polygonsIndexed.push_back(simpleIndexed); } @@ -274,13 +274,13 @@ Manifold Manifold::Extrude(const Polygons& crossSection, float height, glm::vec2 scale = glm::mix(glm::vec2(1.0f), scaleTop, alpha); glm::mat2 rotation(cosd(phi), sind(phi), -sind(phi), cosd(phi)); glm::mat2 transform = glm::mat2(scale.x, 0.0f, 0.0f, scale.y) * rotation; - int j = 0; - int idx = 0; + size_t j = 0; + size_t idx = 0; for (const auto& poly : crossSection) { - for (int vert = 0; vert < poly.size(); ++vert) { - int offset = idx + nCrossSection * i; - int thisVert = vert + offset; - int lastVert = (vert == 0 ? poly.size() : vert) - 1 + offset; + for (size_t vert = 0; vert < poly.size(); ++vert) { + size_t offset = idx + nCrossSection * i; + size_t thisVert = vert + offset; + size_t lastVert = (vert == 0 ? poly.size() : vert) - 1 + offset; if (i == nDivisions && isCone) { triVerts.push_back({nCrossSection * i + j, lastVert - nCrossSection, thisVert - nCrossSection}); @@ -297,7 +297,8 @@ Manifold Manifold::Extrude(const Polygons& crossSection, float height, } } if (isCone) - for (int j = 0; j < crossSection.size(); ++j) // Duplicate vertex for Genus + for (size_t j = 0; j < crossSection.size(); + ++j) // Duplicate vertex for Genus vertPos.push_back({0.0f, 0.0f, height}); std::vector top = TriangulateIdx(polygonsIndexed); for (const glm::ivec3& tri : top) { @@ -332,7 +333,7 @@ Manifold Manifold::Revolve(const Polygons& crossSection, int circularSegments, Polygons polygons; float radius = 0; for (const SimplePolygon& poly : crossSection) { - int i = 0; + size_t i = 0; while (i < poly.size() && poly[i].x < 0) { ++i; } @@ -340,13 +341,13 @@ Manifold Manifold::Revolve(const Polygons& crossSection, int circularSegments, continue; } polygons.push_back({}); - const int start = i; + const size_t start = i; do { if (poly[i].x >= 0) { polygons.back().push_back(poly[i]); radius = glm::max(radius, poly[i].x); } - const int next = i + 1 == poly.size() ? 0 : i + 1; + const size_t next = i + 1 == poly.size() ? 0 : i + 1; if ((poly[next].x < 0) != (poly[i].x < 0)) { const float y = poly[next].y + poly[next].x * (poly[i].y - poly[next].y) / @@ -394,8 +395,8 @@ Manifold Manifold::Revolve(const Polygons& crossSection, int circularSegments, } } - for (int polyVert = 0; polyVert < poly.size(); ++polyVert) { - const int startPosIndex = vertPos.size(); + for (size_t polyVert = 0; polyVert < poly.size(); ++polyVert) { + const size_t startPosIndex = vertPos.size(); if (!isFullRevolution) startPoses.push_back(startPosIndex); diff --git a/src/manifold/src/csg_tree.cpp b/src/manifold/src/csg_tree.cpp index 9bbb41d28..781896644 100644 --- a/src/manifold/src/csg_tree.cpp +++ b/src/manifold/src/csg_tree.cpp @@ -74,7 +74,7 @@ struct UpdateMeshIDs { struct CheckOverlap { VecView boxes; const size_t i; - bool operator()(int j) { return boxes[i].DoesOverlap(boxes[j]); } + bool operator()(size_t j) { return boxes[i].DoesOverlap(boxes[j]); } }; using SharedImpl = std::variant, @@ -313,7 +313,7 @@ Manifold::Impl CsgLeafNode::Compose( UpdateMeshIDs({offset})); }); - for (int i = 0; i < nodes.size(); i++) { + for (size_t i = 0; i < nodes.size(); i++) { auto &node = nodes[i]; const int offset = i * Manifold::Impl::meshIDCounter_; @@ -457,8 +457,8 @@ std::shared_ptr CsgOpNode::BatchBoolean( std::vector> &results) { ZoneScoped; auto getImplPtr = GetImplPtr(); - ASSERT(operation != OpType::Subtract, logicErr, - "BatchBoolean doesn't support Difference."); + DEBUG_ASSERT(operation != OpType::Subtract, logicErr, + "BatchBoolean doesn't support Difference."); // common cases if (results.size() == 0) return std::make_shared(); if (results.size() == 1) @@ -537,16 +537,16 @@ void CsgOpNode::BatchUnion() const { // with O(n^2) complexity to take too long. // If the number of children exceeded this limit, we will operate on chunks // with size kMaxUnionSize. - constexpr int kMaxUnionSize = 1000; + constexpr size_t kMaxUnionSize = 1000; auto impl = impl_.GetGuard(); auto &children_ = impl->children_; while (children_.size() > 1) { - const int start = (children_.size() > kMaxUnionSize) - ? (children_.size() - kMaxUnionSize) - : 0; + const size_t start = (children_.size() > kMaxUnionSize) + ? (children_.size() - kMaxUnionSize) + : 0; Vec boxes; boxes.reserve(children_.size() - start); - for (int i = start; i < children_.size(); i++) { + for (size_t i = start; i < children_.size(); i++) { boxes.push_back(std::dynamic_pointer_cast(children_[i]) ->GetImpl() ->bBox_); diff --git a/src/manifold/src/edge_op.cpp b/src/manifold/src/edge_op.cpp index 51460b911..d224c05a3 100644 --- a/src/manifold/src/edge_op.cpp +++ b/src/manifold/src/edge_op.cpp @@ -112,7 +112,7 @@ struct SwappableEdge { struct SortEntry { int start; int end; - int index; + size_t index; inline bool operator<(const SortEntry& other) const { return start == other.start ? end < other.end : start < other.start; } @@ -156,14 +156,14 @@ void Manifold::Impl::SimplifyTopology() { ZoneScopedN("DedupeEdge"); Vec entries; entries.reserve(nbEdges / 2); - for (int i = 0; i < nbEdges; ++i) { + for (size_t i = 0; i < nbEdges; ++i) { if (halfedge_[i].IsForward()) { entries.push_back({halfedge_[i].startVert, halfedge_[i].endVert, i}); } } stable_sort(policy, entries.begin(), entries.end()); - for (int i = 0; i < entries.size() - 1; ++i) { + for (size_t i = 0; i < entries.size() - 1; ++i) { if (entries[i].start == entries[i + 1].start && entries[i].end == entries[i + 1].end) { DedupeEdge(entries[i].index); @@ -368,7 +368,7 @@ void Manifold::Impl::UpdateVert(int vert, int startEdge, int endEdge) { current = NextHalfedge(current); halfedge_[current].startVert = vert; current = halfedge_[current].pairedHalfedge; - ASSERT(current != startEdge, logicErr, "infinite loop in decimator!"); + DEBUG_ASSERT(current != startEdge, logicErr, "infinite loop in decimator!"); } } @@ -525,7 +525,7 @@ void Manifold::Impl::CollapseEdge(const int edge, std::vector& edges) { const int vert = halfedge_[current].endVert; const int next = halfedge_[current].pairedHalfedge; - for (int i = 0; i < edges.size(); ++i) { + for (size_t i = 0; i < edges.size(); ++i) { if (vert == halfedge_[edges[i]].endVert) { FormLoop(edges[i], current); start = next; @@ -659,7 +659,7 @@ void Manifold::Impl::SplitPinchedVerts() { ZoneScoped; std::vector vertProcessed(NumVert(), false); std::vector halfedgeProcessed(halfedge_.size(), false); - for (int i = 0; i < halfedge_.size(); ++i) { + for (size_t i = 0; i < halfedge_.size(); ++i) { if (halfedgeProcessed[i]) continue; int vert = halfedge_[i].startVert; if (vertProcessed[vert]) { diff --git a/src/manifold/src/face_op.cpp b/src/manifold/src/face_op.cpp index 7d6a19cff..f2b1e879f 100644 --- a/src/manifold/src/face_op.cpp +++ b/src/manifold/src/face_op.cpp @@ -49,7 +49,7 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, const int firstEdge = faceEdge[face]; const int lastEdge = faceEdge[face + 1]; const int numEdge = lastEdge - firstEdge; - ASSERT(numEdge >= 3, topologyErr, "face has less than three edges."); + DEBUG_ASSERT(numEdge >= 3, topologyErr, "face has less than three edges."); const glm::vec3 normal = faceNormal_[face]; if (numEdge == 3) { // Single triangle @@ -66,8 +66,8 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, std::swap(tri[1], tri[2]); std::swap(ends[1], ends[2]); } - ASSERT(ends[0] == tri[1] && ends[1] == tri[2] && ends[2] == tri[0], - topologyErr, "These 3 edges do not form a triangle!"); + DEBUG_ASSERT(ends[0] == tri[1] && ends[1] == tri[2] && ends[2] == tri[0], + topologyErr, "These 3 edges do not form a triangle!"); addTri(face, tri, normal, halfedgeRef[firstEdge]); } else if (numEdge == 4) { // Pair of triangles @@ -94,9 +94,9 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, tri1[1] = halfedge_[firstEdge + i].startVert; } } - ASSERT(glm::all(glm::greaterThanEqual(tri0, glm::ivec3(0))) && - glm::all(glm::greaterThanEqual(tri1, glm::ivec3(0))), - topologyErr, "non-manifold quad!"); + DEBUG_ASSERT(glm::all(glm::greaterThanEqual(tri0, glm::ivec3(0))) && + glm::all(glm::greaterThanEqual(tri1, glm::ivec3(0))), + topologyErr, "non-manifold quad!"); bool firstValid = triCCW(tri0) && triCCW(tri1); tri0[2] = tri1[1]; tri1[2] = tri0[1]; @@ -143,8 +143,8 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, for_each(autoPolicy(faceEdge.size()), countAt(0_z), countAt(faceEdge.size() - 1), [&](size_t face) { triCount[face] = faceEdge[face + 1] - faceEdge[face] - 2; - ASSERT(triCount[face] >= 1, topologyErr, - "face has less than three edges."); + DEBUG_ASSERT(triCount[face] >= 1, topologyErr, + "face has less than three edges."); if (triCount[face] > 2) group.run([&, face] { std::vector newTris = generalTriangulation(face); @@ -156,8 +156,6 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, // prefix sum computation (assign unique index to each face) and preallocation exclusive_scan(autoPolicy(triCount.size()), triCount.begin(), triCount.end(), triCount.begin(), 0_z); - if (triCount.back() >= std::numeric_limits::max()) - throw std::out_of_range("too many triangles"); triVerts.resize(triCount.back()); triNormal.resize(triCount.back()); triRef.resize(triCount.back()); @@ -186,7 +184,7 @@ void Manifold::Impl::Face2Tri(const Vec& faceEdge, triRef.push_back(r); }, std::placeholders::_1); - for (int face = 0; face < faceEdge.size() - 1; ++face) { + for (size_t face = 0; face < faceEdge.size() - 1; ++face) { processFace2(face); } #endif @@ -221,7 +219,7 @@ PolygonsIdx Manifold::Impl::Face2Polygons(VecView::IterC start, int vert = (start + thisEdge)->startVert; polys.back().push_back({projection * vertPos_[vert], vert}); const auto result = vert_edge.find((start + thisEdge)->endVert); - ASSERT(result != vert_edge.end(), topologyErr, "non-manifold edge"); + DEBUG_ASSERT(result != vert_edge.end(), topologyErr, "non-manifold edge"); thisEdge = result->second; vert_edge.erase(result); } @@ -237,7 +235,7 @@ Polygons Manifold::Impl::Slice(float height) const { collider_.Collisions(query.cview()); std::unordered_set tris; - for (int i = 0; i < collisions.size(); ++i) { + for (size_t i = 0; i < collisions.size(); ++i) { const int tri = collisions.Get(i, 1); float min = std::numeric_limits::infinity(); float max = -std::numeric_limits::infinity(); diff --git a/src/manifold/src/impl.cpp b/src/manifold/src/impl.cpp index eb0d0932f..4f9fbbd83 100644 --- a/src/manifold/src/impl.cpp +++ b/src/manifold/src/impl.cpp @@ -327,13 +327,9 @@ void DedupePropVerts(manifold::Vec& triProp, const int numLabels = GetLabels(vertLabels, vert2vert, vert2vert.size()); std::vector label2vert(numLabels); - for (int v = 0; v < vert2vert.size(); ++v) { - label2vert[vertLabels[v]] = v; - } - for (int tri = 0; tri < triProp.size(); ++tri) { - for (int i : {0, 1, 2}) - triProp[tri][i] = label2vert[vertLabels[triProp[tri][i]]]; - } + for (size_t v = 0; v < vert2vert.size(); ++v) label2vert[vertLabels[v]] = v; + for (auto& prop : triProp) + for (int i : {0, 1, 2}) prop[i] = label2vert[vertLabels[prop[i]]]; } } // namespace @@ -349,13 +345,8 @@ Manifold::Impl::Impl(const MeshGL& meshGL, std::vector propertyTolerance) { Mesh mesh; mesh.precision = meshGL.precision; - const int numVert = meshGL.NumVert(); - const int numTri = meshGL.NumTri(); - - if (meshGL.numProp > 3 && - static_cast(numVert) * static_cast(meshGL.numProp - 3) >= - std::numeric_limits::max()) - throw std::out_of_range("mesh too large"); + const auto numVert = meshGL.NumVert(); + const auto numTri = meshGL.NumTri(); if (meshGL.numProp < 3) { MarkFailure(Error::MissingPositionProperties); @@ -391,7 +382,7 @@ Manifold::Impl::Impl(const MeshGL& meshGL, for (size_t i = 0; i < meshGL.mergeFromVert.size(); ++i) { const int from = meshGL.mergeFromVert[i]; const int to = meshGL.mergeToVert[i]; - if (from >= numVert || to >= numVert) { + if (from >= static_cast(numVert) || to >= static_cast(numVert)) { MarkFailure(Error::MergeIndexOutOfBounds); return; } @@ -400,7 +391,7 @@ Manifold::Impl::Impl(const MeshGL& meshGL, for (size_t i = 0; i < numTri; ++i) { for (const size_t j : {0, 1, 2}) { const int vert = meshGL.triVerts[3 * i + j]; - if (vert < 0 || vert >= numVert) { + if (vert < 0 || vert >= static_cast(numVert)) { MarkFailure(Error::VertexOutOfBounds); return; } @@ -419,23 +410,23 @@ Manifold::Impl::Impl(const MeshGL& meshGL, } } - const int numProp = meshGL.numProp - 3; + const auto numProp = meshGL.numProp - 3; relation.numProp = numProp; relation.properties.resize(meshGL.NumVert() * numProp); // This will have unreferenced duplicate positions that will be removed by // Impl::RemoveUnreferencedVerts(). mesh.vertPos.resize(meshGL.NumVert()); - for (int i = 0; i < meshGL.NumVert(); ++i) { + for (size_t i = 0; i < meshGL.NumVert(); ++i) { for (const int j : {0, 1, 2}) mesh.vertPos[i][j] = meshGL.vertProperties[meshGL.numProp * i + j]; - for (int j = 0; j < numProp; ++j) + for (size_t j = 0; j < numProp; ++j) relation.properties[i * numProp + j] = meshGL.vertProperties[meshGL.numProp * i + 3 + j]; } mesh.halfedgeTangent.resize(meshGL.halfedgeTangent.size() / 4); - for (int i = 0; i < mesh.halfedgeTangent.size(); ++i) { + for (size_t i = 0; i < mesh.halfedgeTangent.size(); ++i) { for (const int j : {0, 1, 2, 3}) mesh.halfedgeTangent[i][j] = meshGL.halfedgeTangent[4 * i + j]; } @@ -452,10 +443,10 @@ Manifold::Impl::Impl(const MeshGL& meshGL, } relation.triRef.resize(meshGL.NumTri()); const int startID = Impl::ReserveIDs(meshGL.runOriginalID.size()); - for (int i = 0; i < meshGL.runOriginalID.size(); ++i) { + for (size_t i = 0; i < meshGL.runOriginalID.size(); ++i) { const int meshID = startID + i; const int originalID = meshGL.runOriginalID[i]; - for (int tri = runIndex[i] / 3; tri < runIndex[i + 1] / 3; ++tri) { + for (size_t tri = runIndex[i] / 3; tri < runIndex[i + 1] / 3; ++tri) { TriRef& ref = relation.triRef[tri]; ref.meshID = meshID; ref.originalID = originalID; @@ -490,8 +481,6 @@ Manifold::Impl::Impl(const Mesh& mesh, const MeshRelationD& relation, const std::vector& propertyTolerance, bool hasFaceIDs) : vertPos_(mesh.vertPos), halfedgeTangent_(mesh.halfedgeTangent) { - if (mesh.triVerts.size() >= std::numeric_limits::max()) - throw std::out_of_range("mesh too large"); meshRelation_ = {relation.originalID, relation.numProp, relation.properties, relation.meshIDtransform}; @@ -652,7 +641,7 @@ void Manifold::Impl::CreateFaces(const std::vector& propertyTolerance) { const int numComponent = GetLabels(components, face2face, NumTri()); Vec comp2tri(numComponent, -1); - for (int tri = 0; tri < NumTri(); ++tri) { + for (size_t tri = 0; tri < NumTri(); ++tri) { const int comp = components[tri]; const int current = comp2tri[comp]; if (current < 0 || triArea[tri] > triArea[current]) { @@ -666,7 +655,7 @@ void Manifold::Impl::CreateFaces(const std::vector& propertyTolerance) { {comp2tri, halfedge_, vertPos_, &components, precision_})); Vec& triRef = meshRelation_.triRef; - for (int tri = 0; tri < NumTri(); ++tri) { + for (size_t tri = 0; tri < NumTri(); ++tri) { const int referenceTri = comp2tri[components[tri]]; if (referenceTri >= 0) { triRef[tri].tri = referenceTri; diff --git a/src/manifold/src/impl.h b/src/manifold/src/impl.h index 2edaf529c..344b14268 100644 --- a/src/manifold/src/impl.h +++ b/src/manifold/src/impl.h @@ -109,11 +109,11 @@ struct Manifold::Impl { bool inverted = false) const; bool IsEmpty() const { return NumVert() == 0; } - int NumVert() const { return vertPos_.size(); } - int NumEdge() const { return halfedge_.size() / 2; } - int NumTri() const { return halfedge_.size() / 3; } - int NumProp() const { return meshRelation_.numProp; } - int NumPropVert() const { + size_t NumVert() const { return vertPos_.size(); } + size_t NumEdge() const { return halfedge_.size() / 2; } + size_t NumTri() const { return halfedge_.size() / 3; } + size_t NumProp() const { return meshRelation_.numProp; } + size_t NumPropVert() const { return NumProp() == 0 ? NumVert() : meshRelation_.properties.size() / NumProp(); } diff --git a/src/manifold/src/manifold.cpp b/src/manifold/src/manifold.cpp index c19489375..26623f27f 100644 --- a/src/manifold/src/manifold.cpp +++ b/src/manifold/src/manifold.cpp @@ -294,8 +294,8 @@ MeshGL Manifold::GetMeshGL(glm::ivec3 normalIdx) const { std::vector> vertPropPair(impl.NumVert()); out.vertProperties.reserve(numVert * static_cast(out.numProp)); - for (int run = 0; run < out.runOriginalID.size(); ++run) { - for (int tri = out.runIndex[run] / 3; tri < out.runIndex[run + 1] / 3; + for (size_t run = 0; run < out.runOriginalID.size(); ++run) { + for (size_t tri = out.runIndex[run] / 3; tri < out.runIndex[run + 1] / 3; ++tri) { const glm::ivec3 triProp = impl.meshRelation_.triProperties[triNew2Old[tri]]; @@ -305,10 +305,10 @@ MeshGL Manifold::GetMeshGL(glm::ivec3 normalIdx) const { auto& bin = vertPropPair[vert]; bool bFound = false; - for (int k = 0; k < bin.size(); ++k) { - if (bin[k].x == prop) { + for (const auto& b : bin) { + if (b.x == prop) { bFound = true; - out.triVerts[3 * tri + i] = bin[k].y; + out.triVerts[3 * tri + i] = b.y; break; } } diff --git a/src/manifold/src/properties.cpp b/src/manifold/src/properties.cpp index 17e89f842..e77a2c737 100644 --- a/src/manifold/src/properties.cpp +++ b/src/manifold/src/properties.cpp @@ -102,7 +102,7 @@ struct CurvatureAngles { VecView vertPos; VecView triNormal; - void operator()(int tri) { + void operator()(size_t tri) { glm::vec3 edge[3]; glm::vec3 edgeLength(0.0); for (int i : {0, 1, 2}) { @@ -161,9 +161,9 @@ struct UpdateProperties { const int meanIdx; // FIXME: race condition - void operator()(thrust::tuple inOut) { + void operator()(thrust::tuple inOut) { glm::ivec3& triProp = thrust::get<0>(inOut); - const int tri = thrust::get<1>(inOut); + const auto tri = thrust::get<1>(inOut); for (const int i : {0, 1, 2}) { const int vert = halfedge[3 * tri + i].startVert; @@ -201,7 +201,7 @@ struct CheckHalfedges { const Halfedge paired = halfedges[halfedge.pairedHalfedge]; bool good = true; - good &= paired.pairedHalfedge == edge; + good &= paired.pairedHalfedge == static_cast(edge); good &= halfedge.startVert != halfedge.endVert; good &= halfedge.startVert == paired.endVert; good &= halfedge.endVert == paired.startVert; @@ -212,7 +212,7 @@ struct CheckHalfedges { struct NoDuplicates { VecView halfedges; - bool operator()(int edge) { + bool operator()(size_t edge) { const Halfedge halfedge = halfedges[edge]; if (halfedge.startVert == -1 && halfedge.endVert == -1 && halfedge.pairedHalfedge == -1) @@ -228,7 +228,7 @@ struct CheckCCW { VecView triNormal; const float tol; - bool operator()(int face) { + bool operator()(size_t face) { if (halfedges[3 * face].pairedHalfedge < 0) return true; const glm::mat3x2 projection = GetAxisAlignedProjection(triNormal[face]); @@ -251,7 +251,7 @@ struct CheckCCW { glm::vec3 V2 = vertPos[halfedges[3 * face + 2].startVert]; glm::vec3 norm = glm::cross(V1 - V0, V2 - V0); printf( - "Tri %d does not match normal, approx height = %g, base = %g\n" + "Tri %ld does not match normal, approx height = %g, base = %g\n" "tol = %g, area2 = %g, base2*tol2 = %g\n" "normal = %g, %g, %g\n" "norm = %g, %g, %g\nverts: %d, %d, %d\n", @@ -293,7 +293,7 @@ bool Manifold::Impl::Is2Manifold() const { Vec halfedge(halfedge_); stable_sort(policy, halfedge.begin(), halfedge.end()); - return all_of(policy, countAt(0), countAt(2 * NumEdge() - 1), + return all_of(policy, countAt(0_z), countAt(2 * NumEdge() - 1), NoDuplicates({halfedge})); } @@ -302,7 +302,7 @@ bool Manifold::Impl::Is2Manifold() const { */ bool Manifold::Impl::MatchesTriNormals() const { if (halfedge_.size() == 0 || faceNormal_.size() != NumTri()) return true; - return all_of(autoPolicy(NumTri()), countAt(0), countAt(NumTri()), + return all_of(autoPolicy(NumTri()), countAt(0_z), countAt(NumTri()), CheckCCW({halfedge_, vertPos_, faceNormal_, 2 * precision_})); } @@ -312,7 +312,7 @@ bool Manifold::Impl::MatchesTriNormals() const { int Manifold::Impl::NumDegenerateTris() const { if (halfedge_.size() == 0 || faceNormal_.size() != NumTri()) return true; return count_if( - autoPolicy(NumTri()), countAt(0), countAt(NumTri()), + autoPolicy(NumTri()), countAt(0_z), countAt(NumTri()), CheckCCW({halfedge_, vertPos_, faceNormal_, -1 * precision_ / 2})); } @@ -324,7 +324,7 @@ Properties Manifold::Impl::GetProperties() const { float volume = 0; float areaCompensation = 0; float volumeCompensation = 0; - for (int i = 0; i < NumTri(); ++i) { + for (size_t i = 0; i < NumTri(); ++i) { auto [area1, volume1] = FaceAreaVolume({halfedge_, vertPos_, precision_})(i); const float t1 = area + area1; @@ -349,7 +349,7 @@ void Manifold::Impl::CalculateCurvature(int gaussianIdx, int meanIdx) { Vec vertArea(NumVert(), 0); Vec degree(NumVert(), 0); auto policy = autoPolicy(NumTri()); - for_each(policy, countAt(0), countAt(NumTri()), + for_each(policy, countAt(0_z), countAt(NumTri()), CurvatureAngles({vertMeanCurvature, vertGaussianCurvature, vertArea, degree, halfedge_, vertPos_, faceNormal_})); for_each_n(policy, @@ -367,7 +367,7 @@ void Manifold::Impl::CalculateCurvature(int gaussianIdx, int meanIdx) { } for_each_n( - policy, zip(meshRelation_.triProperties.begin(), countAt(0)), NumTri(), + policy, zip(meshRelation_.triProperties.begin(), countAt(0_z)), NumTri(), UpdateProperties({meshRelation_.properties, oldProperties, halfedge_, vertMeanCurvature, vertGaussianCurvature, oldNumProp, numProp, gaussianIdx, meanIdx})); @@ -414,7 +414,7 @@ bool Manifold::Impl::IsIndexInBounds(VecView triVerts) const { std::numeric_limits::min()), MinMax()); - return minmax[0] >= 0 && minmax[1] < NumVert(); + return minmax[0] >= 0 && minmax[1] < static_cast(NumVert()); } /* diff --git a/src/manifold/src/shared.h b/src/manifold/src/shared.h index ed457dad5..6a330bcc8 100644 --- a/src/manifold/src/shared.h +++ b/src/manifold/src/shared.h @@ -192,11 +192,11 @@ Vec inline CreateTmpEdges(const Vec& halfedge) { for_each_n(autoPolicy(edges.size()), zip(edges.begin(), halfedge.begin(), countAt(0)), edges.size(), Halfedge2Tmp()); - int numEdge = + size_t numEdge = remove_if( autoPolicy(edges.size()), edges.begin(), edges.end(), TmpInvalid()) - edges.begin(); - ASSERT(numEdge == halfedge.size() / 2, topologyErr, "Not oriented!"); + DEBUG_ASSERT(numEdge == halfedge.size() / 2, topologyErr, "Not oriented!"); edges.resize(numEdge); return edges; } diff --git a/src/manifold/src/smoothing.cpp b/src/manifold/src/smoothing.cpp index 3cc0d9091..4a3ff3263 100644 --- a/src/manifold/src/smoothing.cpp +++ b/src/manifold/src/smoothing.cpp @@ -356,7 +356,7 @@ bool Manifold::Impl::IsMarkedInsideQuad(int halfedge) const { std::vector Manifold::Impl::UpdateSharpenedEdges( const std::vector& sharpenedEdges) const { std::unordered_map oldHalfedge2New; - for (int tri = 0; tri < NumTri(); ++tri) { + for (size_t tri = 0; tri < NumTri(); ++tri) { int oldTri = meshRelation_.triRef[tri].tri; for (int i : {0, 1, 2}) oldHalfedge2New[3 * oldTri + i] = 3 * tri + i; } @@ -404,7 +404,7 @@ Vec Manifold::Impl::FlatFaces() const { Vec Manifold::Impl::VertFlatFace(const Vec& flatFaces) const { Vec vertFlatFace(NumVert(), -1); Vec vertRef(NumVert(), {-1, -1, -1}); - for (int tri = 0; tri < NumTri(); ++tri) { + for (size_t tri = 0; tri < NumTri(); ++tri) { if (flatFaces[tri]) { for (const int j : {0, 1, 2}) { const int vert = halfedge_[3 * tri + j].startVert; @@ -434,9 +434,9 @@ std::vector Manifold::Impl::SharpenEdges( float minSharpAngle, float minSmoothness) const { std::vector sharpenedEdges; const float minRadians = glm::radians(minSharpAngle); - for (int e = 0; e < halfedge_.size(); ++e) { + for (size_t e = 0; e < halfedge_.size(); ++e) { if (!halfedge_[e].IsForward()) continue; - const int pair = halfedge_[e].pairedHalfedge; + const size_t pair = halfedge_[e].pairedHalfedge; const float dihedral = glm::acos(glm::dot(faceNormal_[e / 3], faceNormal_[pair / 3])); if (dihedral > minRadians) { @@ -473,7 +473,7 @@ void Manifold::Impl::SetNormals(int normalIdx, float minSharpAngle) { Vec triIsFlatFace = FlatFaces(); Vec vertFlatFace = VertFlatFace(triIsFlatFace); Vec vertNumSharp(NumVert(), 0); - for (int e = 0; e < halfedge_.size(); ++e) { + for (size_t e = 0; e < halfedge_.size(); ++e) { if (!halfedge_[e].IsForward()) continue; const int pair = halfedge_[e].pairedHalfedge; const int tri1 = e / 3; @@ -763,14 +763,14 @@ void Manifold::Impl::DistributeTangents(const Vec& fixedHalfedges) { const float scale = currentAngle.back() / desiredAngle.back(); float offset = 0; if (current == halfedge) { // only one - find average offset - for (int i = 0; i < currentAngle.size(); ++i) { + for (size_t i = 0; i < currentAngle.size(); ++i) { offset += Wrap(currentAngle[i] - scale * desiredAngle[i]); } offset /= currentAngle.size(); } current = halfedge; - int i = 0; + size_t i = 0; do { current = NextHalfedge(halfedge_[current].pairedHalfedge); if (IsMarkedInsideQuad(current)) continue; @@ -899,7 +899,7 @@ void Manifold::Impl::CreateTangents(std::vector sharpenedEdges) { Vec triIsFlatFace = FlatFaces(); Vec vertFlatFace = VertFlatFace(triIsFlatFace); Vec vertNormal = vertNormal_; - for (int v = 0; v < NumVert(); ++v) { + for (size_t v = 0; v < NumVert(); ++v) { if (vertFlatFace[v] >= 0) { vertNormal[v] = faceNormal_[vertFlatFace[v]]; } @@ -912,7 +912,7 @@ void Manifold::Impl::CreateTangents(std::vector sharpenedEdges) { halfedgeTangent_.swap(tangent); // Add sharpened edges around faces, just on the face side. - for (int tri = 0; tri < NumTri(); ++tri) { + for (size_t tri = 0; tri < NumTri(); ++tri) { if (!triIsFlatFace[tri]) continue; for (const int j : {0, 1, 2}) { const int tri2 = halfedge_[3 * tri + j].pairedHalfedge / 3; @@ -932,7 +932,7 @@ void Manifold::Impl::CreateTangents(std::vector sharpenedEdges) { const int pair = halfedge_[edge.halfedge].pairedHalfedge; const int idx = forward ? edge.halfedge : pair; if (edges.find(idx) == edges.end()) { - edges[idx] = {edge, {pair, 1}}; + edges[idx] = {edge, {static_cast(pair), 1}}; if (!forward) std::swap(edges[idx].first, edges[idx].second); } else { Smoothness& e = forward ? edges[idx].first : edges[idx].second; diff --git a/src/manifold/src/sort.cpp b/src/manifold/src/sort.cpp index a8a706356..8bb91887f 100644 --- a/src/manifold/src/sort.cpp +++ b/src/manifold/src/sort.cpp @@ -245,8 +245,8 @@ void Manifold::Impl::Finish() { if (halfedge_.size() == 0) return; CompactProps(); - ASSERT(halfedge_.size() % 6 == 0, topologyErr, - "Not an even number of faces after sorting faces!"); + DEBUG_ASSERT(halfedge_.size() % 6 == 0, topologyErr, + "Not an even number of faces after sorting faces!"); #ifdef MANIFOLD_DEBUG Halfedge extrema = {0, 0, 0, 0}; @@ -254,25 +254,27 @@ void Manifold::Impl::Finish() { halfedge_.end(), extrema, Extrema()); #endif - ASSERT(extrema.startVert >= 0, topologyErr, "Vertex index is negative!"); - ASSERT(extrema.endVert < NumVert(), topologyErr, - "Vertex index exceeds number of verts!"); - ASSERT(extrema.face >= 0, topologyErr, "Face index is negative!"); - ASSERT(extrema.face < NumTri(), topologyErr, - "Face index exceeds number of faces!"); - ASSERT(extrema.pairedHalfedge >= 0, topologyErr, - "Halfedge index is negative!"); - ASSERT(extrema.pairedHalfedge < 2 * NumEdge(), topologyErr, - "Halfedge index exceeds number of halfedges!"); - ASSERT(meshRelation_.triRef.size() == NumTri() || - meshRelation_.triRef.size() == 0, - logicErr, "Mesh Relation doesn't fit!"); - ASSERT(faceNormal_.size() == NumTri() || faceNormal_.size() == 0, logicErr, - "faceNormal size = " + std::to_string(faceNormal_.size()) + - ", NumTri = " + std::to_string(NumTri())); + DEBUG_ASSERT(extrema.startVert >= 0, topologyErr, + "Vertex index is negative!"); + DEBUG_ASSERT(extrema.endVert < static_cast(NumVert()), topologyErr, + "Vertex index exceeds number of verts!"); + DEBUG_ASSERT(extrema.face >= 0, topologyErr, "Face index is negative!"); + DEBUG_ASSERT(extrema.face < static_cast(NumTri()), topologyErr, + "Face index exceeds number of faces!"); + DEBUG_ASSERT(extrema.pairedHalfedge >= 0, topologyErr, + "Halfedge index is negative!"); + DEBUG_ASSERT(extrema.pairedHalfedge < 2 * static_cast(NumEdge()), + topologyErr, "Halfedge index exceeds number of halfedges!"); + DEBUG_ASSERT(meshRelation_.triRef.size() == NumTri() || + meshRelation_.triRef.size() == 0, + logicErr, "Mesh Relation doesn't fit!"); + DEBUG_ASSERT(faceNormal_.size() == NumTri() || faceNormal_.size() == 0, + logicErr, + "faceNormal size = " + std::to_string(faceNormal_.size()) + + ", NumTri = " + std::to_string(NumTri())); // TODO: figure out why this has a flaky failure and then enable reading // vertNormals from a Mesh. - // ASSERT(vertNormal_.size() == NumVert() || vertNormal_.size() == 0, + // DEBUG_ASSERT(vertNormal_.size() == NumVert() || vertNormal_.size() == 0, // logicErr, // "vertNormal size = " + std::to_string(vertNormal_.size()) + // ", NumVert = " + std::to_string(NumVert())); @@ -280,7 +282,7 @@ void Manifold::Impl::Finish() { CalculateNormals(); collider_ = Collider(faceBox, faceMorton); - ASSERT(Is2Manifold(), logicErr, "mesh is not 2-manifold!"); + DEBUG_ASSERT(Is2Manifold(), logicErr, "mesh is not 2-manifold!"); } /** @@ -288,7 +290,7 @@ void Manifold::Impl::Finish() { */ void Manifold::Impl::SortVerts() { ZoneScoped; - const int numVert = NumVert(); + const auto numVert = NumVert(); Vec vertMorton(numVert); auto policy = autoPolicy(numVert); for_each_n(policy, zip(vertMorton.begin(), vertPos_.cbegin()), numVert, @@ -328,8 +330,9 @@ void Manifold::Impl::SortVerts() { void Manifold::Impl::ReindexVerts(const Vec& vertNew2Old, int oldNumVert) { ZoneScoped; Vec vertOld2New(oldNumVert); - scatter(autoPolicy(oldNumVert), countAt(0), countAt(NumVert()), - vertNew2Old.begin(), vertOld2New.begin()); + scatter(autoPolicy(oldNumVert), countAt(0), + countAt(static_cast(NumVert())), vertNew2Old.begin(), + vertOld2New.begin()); for_each(autoPolicy(oldNumVert), halfedge_.begin(), halfedge_.end(), Reindex({vertOld2New})); } @@ -477,15 +480,15 @@ MeshGL::MeshGL(const Mesh& mesh) { numProp = 3; precision = mesh.precision; vertProperties.resize(numProp * mesh.vertPos.size()); - for (int i = 0; i < mesh.vertPos.size(); ++i) { + for (size_t i = 0; i < mesh.vertPos.size(); ++i) { for (int j : {0, 1, 2}) vertProperties[3 * i + j] = mesh.vertPos[i][j]; } triVerts.resize(3 * mesh.triVerts.size()); - for (int i = 0; i < mesh.triVerts.size(); ++i) { + for (size_t i = 0; i < mesh.triVerts.size(); ++i) { for (int j : {0, 1, 2}) triVerts[3 * i + j] = mesh.triVerts[i][j]; } halfedgeTangent.resize(4 * mesh.halfedgeTangent.size()); - for (int i = 0; i < mesh.halfedgeTangent.size(); ++i) { + for (size_t i = 0; i < mesh.halfedgeTangent.size(); ++i) { for (int j : {0, 1, 2, 3}) halfedgeTangent[4 * i + j] = mesh.halfedgeTangent[i][j]; } @@ -510,14 +513,14 @@ bool MeshGL::Merge() { std::vector merge(NumVert()); std::iota(merge.begin(), merge.end(), 0); - for (int i = 0; i < mergeFromVert.size(); ++i) { + for (size_t i = 0; i < mergeFromVert.size(); ++i) { merge[mergeFromVert[i]] = mergeToVert[i]; } - const int numVert = NumVert(); - const int numTri = NumTri(); + const auto numVert = NumVert(); + const auto numTri = NumTri(); const int next[3] = {1, 2, 0}; - for (int tri = 0; tri < numTri; ++tri) { + for (size_t tri = 0; tri < numTri; ++tri) { for (int i : {0, 1, 2}) { auto edge = std::make_pair(merge[triVerts[3 * tri + next[i]]], merge[triVerts[3 * tri + i]]); @@ -579,19 +582,19 @@ bool MeshGL::Merge() { SparseIndices toMerge = collider.Collisions(vertBox.cview()); UnionFind<> uf(numVert); - for (int i = 0; i < mergeFromVert.size(); ++i) { + for (size_t i = 0; i < mergeFromVert.size(); ++i) { uf.unionXY(static_cast(mergeFromVert[i]), static_cast(mergeToVert[i])); } - for (int i = 0; i < toMerge.size(); ++i) { + for (size_t i = 0; i < toMerge.size(); ++i) { uf.unionXY(openVerts[toMerge.Get(i, false)], openVerts[toMerge.Get(i, true)]); } mergeToVert.clear(); mergeFromVert.clear(); - for (int v = 0; v < numVert; ++v) { - const int mergeTo = uf.find(v); + for (size_t v = 0; v < numVert; ++v) { + const size_t mergeTo = uf.find(v); if (mergeTo != v) { mergeFromVert.push_back(v); mergeToVert.push_back(mergeTo); diff --git a/src/manifold/src/subdivision.cpp b/src/manifold/src/subdivision.cpp index 3c5995bb5..07253e34d 100644 --- a/src/manifold/src/subdivision.cpp +++ b/src/manifold/src/subdivision.cpp @@ -125,9 +125,9 @@ class Partition { } } const int offset = interiorOffset - newVerts.size(); - for (int i = newVerts.size(); i < vertBary.size(); ++i) { - newVerts.push_back(i + offset); - } + size_t old = newVerts.size(); + newVerts.resize(vertBary.size()); + std::iota(newVerts.begin() + old, newVerts.end(), old + offset); const int numTri = triVert.size(); Vec newTriVert(numTri); @@ -281,8 +281,8 @@ class Partition { return edgeOffsets[edge] + (edgeFwd[edge] ? 1 : -1) * idx; }; - ASSERT(glm::all(glm::greaterThanEqual(edgeAdded, glm::ivec4(0))), logicErr, - "negative divisions!"); + DEBUG_ASSERT(glm::all(glm::greaterThanEqual(edgeAdded, glm::ivec4(0))), + logicErr, "negative divisions!"); int corner = -1; int last = 3; @@ -577,8 +577,9 @@ Vec Manifold::Impl::Subdivide( Vec triOffset(numTri); auto numSubTris = thrust::make_transform_iterator( - subTris.begin(), - [](const Partition& part) { return part.triVert.size(); }); + subTris.begin(), [](const Partition& part) { + return static_cast(part.triVert.size()); + }); exclusive_scan(policy, numSubTris, numSubTris + numTri, triOffset.begin(), 0); Vec interiorOffset(numTri); diff --git a/src/polygon/include/polygon.h b/src/polygon/include/polygon.h index 8e5f11f0b..bee6a5b30 100644 --- a/src/polygon/include/polygon.h +++ b/src/polygon/include/polygon.h @@ -48,4 +48,4 @@ std::vector Triangulate(const Polygons &polygons, ExecutionParams &PolygonParams(); /** @} */ -} // namespace manifold \ No newline at end of file +} // namespace manifold diff --git a/src/polygon/src/polygon.cpp b/src/polygon/src/polygon.cpp index 620c5743f..317f4132c 100644 --- a/src/polygon/src/polygon.cpp +++ b/src/polygon/src/polygon.cpp @@ -42,7 +42,7 @@ struct PolyEdge { std::vector Polygons2Edges(const PolygonsIdx &polys) { std::vector halfedges; for (const auto &poly : polys) { - for (int i = 1; i < poly.size(); ++i) { + for (size_t i = 1; i < poly.size(); ++i) { halfedges.push_back({poly[i - 1].idx, poly[i].idx}); } halfedges.push_back({poly.back().idx, poly[0].idx}); @@ -63,20 +63,23 @@ std::vector Triangles2Edges( } void CheckTopology(const std::vector &halfedges) { - ASSERT(halfedges.size() % 2 == 0, topologyErr, "Odd number of halfedges."); + DEBUG_ASSERT(halfedges.size() % 2 == 0, topologyErr, + "Odd number of halfedges."); size_t n_edges = halfedges.size() / 2; std::vector forward(halfedges.size()), backward(halfedges.size()); auto end = std::copy_if(halfedges.begin(), halfedges.end(), forward.begin(), [](PolyEdge e) { return e.endVert > e.startVert; }); - ASSERT(std::distance(forward.begin(), end) == n_edges, topologyErr, - "Half of halfedges should be forward."); + DEBUG_ASSERT( + static_cast(std::distance(forward.begin(), end)) == n_edges, + topologyErr, "Half of halfedges should be forward."); forward.resize(n_edges); end = std::copy_if(halfedges.begin(), halfedges.end(), backward.begin(), [](PolyEdge e) { return e.endVert < e.startVert; }); - ASSERT(std::distance(backward.begin(), end) == n_edges, topologyErr, - "Half of halfedges should be backward."); + DEBUG_ASSERT( + static_cast(std::distance(backward.begin(), end)) == n_edges, + topologyErr, "Half of halfedges should be backward."); backward.resize(n_edges); std::for_each(backward.begin(), backward.end(), @@ -87,10 +90,10 @@ void CheckTopology(const std::vector &halfedges) { }; std::stable_sort(forward.begin(), forward.end(), cmp); std::stable_sort(backward.begin(), backward.end(), cmp); - for (int i = 0; i < n_edges; ++i) { - ASSERT(forward[i].startVert == backward[i].startVert && - forward[i].endVert == backward[i].endVert, - topologyErr, "Not manifold."); + for (size_t i = 0; i < n_edges; ++i) { + DEBUG_ASSERT(forward[i].startVert == backward[i].startVert && + forward[i].endVert == backward[i].endVert, + topologyErr, "Not manifold."); } } @@ -108,16 +111,16 @@ void CheckGeometry(const std::vector &triangles, const PolygonsIdx &polys, float precision) { std::unordered_map vertPos; for (const auto &poly : polys) { - for (int i = 0; i < poly.size(); ++i) { + for (size_t i = 0; i < poly.size(); ++i) { vertPos[poly[i].idx] = poly[i].pos; } } - ASSERT(std::all_of(triangles.begin(), triangles.end(), - [&vertPos, precision](const glm::ivec3 &tri) { - return CCW(vertPos[tri[0]], vertPos[tri[1]], - vertPos[tri[2]], precision) >= 0; - }), - geometryErr, "triangulation is not entirely CCW!"); + DEBUG_ASSERT(std::all_of(triangles.begin(), triangles.end(), + [&vertPos, precision](const glm::ivec3 &tri) { + return CCW(vertPos[tri[0]], vertPos[tri[1]], + vertPos[tri[2]], precision) >= 0; + }), + geometryErr, "triangulation is not entirely CCW!"); } void Dump(const PolygonsIdx &polys) { @@ -145,7 +148,7 @@ void PrintFailure(const std::exception &e, const PolygonsIdx &polys, std::cout << e.what() << std::endl; Dump(polys); std::cout << "produced this triangulation:" << std::endl; - for (int j = 0; j < triangles.size(); ++j) { + for (size_t j = 0; j < triangles.size(); ++j) { std::cout << triangles[j][0] << ", " << triangles[j][1] << ", " << triangles[j][2] << std::endl; } @@ -169,7 +172,7 @@ bool IsConvex(const PolygonsIdx &polys, float precision) { // it's okay because that zero-length edge will also get tested // non-normalized and will trip det == 0. glm::vec2 lastEdge = glm::normalize(firstEdge); - for (int v = 0; v < poly.size(); ++v) { + for (size_t v = 0; v < poly.size(); ++v) { const glm::vec2 edge = v + 1 < poly.size() ? poly[v + 1].pos - poly[v].pos : firstEdge; const float det = determinant2x2(lastEdge, edge); @@ -187,18 +190,18 @@ bool IsConvex(const PolygonsIdx &polys, float precision) { * avoid creating high-degree vertices. */ std::vector TriangulateConvex(const PolygonsIdx &polys) { - const int numTri = transform_reduce( + const size_t numTri = transform_reduce( autoPolicy(polys.size()), polys.begin(), polys.end(), [](const SimplePolygonIdx &poly) { return poly.size() - 2; }, 0, - thrust::plus()); + thrust::plus()); std::vector triangles; triangles.reserve(numTri); for (const SimplePolygonIdx &poly : polys) { - int i = 0; - int k = poly.size() - 1; + size_t i = 0; + size_t k = poly.size() - 1; bool right = true; while (i + 1 < k) { - const int j = right ? i + 1 : k - 1; + const size_t j = right ? i + 1 : k - 1; triangles.push_back({poly[i].idx, poly[j].idx, poly[k].idx}); if (right) { i = j; @@ -230,7 +233,7 @@ class EarClip { EarClip(const PolygonsIdx &polys, float precision) : precision_(precision) { ZoneScoped; - int numVert = 0; + size_t numVert = 0; for (const SimplePolygonIdx &poly : polys) { numVert += poly.size(); } @@ -513,7 +516,7 @@ class EarClip { const int lid = left->mesh_idx; const int rid = right->mesh_idx; - for (int i = 0; i < toTest.size(); ++i) { + for (size_t i = 0; i < toTest.size(); ++i) { const VertItr test = collider.itr[toTest.Get(i, true)]; if (!Clipped(test) && test->mesh_idx != mesh_idx && test->mesh_idx != lid && @@ -899,7 +902,7 @@ class EarClip { v = v->right; } - ASSERT(v->right == v->left, logicErr, "Triangulator error!"); + DEBUG_ASSERT(v->right == v->left, logicErr, "Triangulator error!"); PRINT("Finished poly"); } @@ -949,8 +952,9 @@ std::vector TriangulateIdx(const PolygonsIdx &polys, float precision) { std::vector triangles; float updatedPrecision = precision; +#if MANIFOLD_EXCEPTION try { - float updatedPrecision = precision; +#endif if (IsConvex(polys, precision)) { // fast path triangles = TriangulateConvex(polys); } else { @@ -958,6 +962,7 @@ std::vector TriangulateIdx(const PolygonsIdx &polys, triangles = triangulator.Triangulate(); updatedPrecision = triangulator.GetPrecision(); } +#if MANIFOLD_EXCEPTION #ifdef MANIFOLD_DEBUG if (params.intermediateChecks) { CheckTopology(triangles, polys); @@ -977,6 +982,7 @@ std::vector TriangulateIdx(const PolygonsIdx &polys, } catch (const std::exception &e) { #endif } +#endif return triangles; } diff --git a/src/utilities/CMakeLists.txt b/src/utilities/CMakeLists.txt index 83e7b6ca2..561ee9360 100644 --- a/src/utilities/CMakeLists.txt +++ b/src/utilities/CMakeLists.txt @@ -75,6 +75,12 @@ target_compile_options(${PROJECT_NAME} INTERFACE -DTHRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_${MANIFOLD_PAR} ) +if(MANIFOLD_EXCEPTIONS) + target_compile_options(${PROJECT_NAME} INTERFACE + -DMANIFOLD_EXCEPTIONS=1 + ) +endif() + if(MANIFOLD_DEBUG) target_compile_options(${PROJECT_NAME} INTERFACE -DMANIFOLD_DEBUG) @@ -83,4 +89,6 @@ endif() target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17) install(TARGETS ${PROJECT_NAME} EXPORT manifoldTargets) -install(FILES include/public.h include/vec_view.h include/tri_dist.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}) +install(FILES + include/public.h include/vec_view.h include/tri_dist.h include/optional_assert.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}) diff --git a/src/utilities/include/hashtable.h b/src/utilities/include/hashtable.h index ed0f5538d..7d971d015 100644 --- a/src/utilities/include/hashtable.h +++ b/src/utilities/include/hashtable.h @@ -70,7 +70,8 @@ class HashTableD { int Size() const { return keys_.size(); } bool Full() const { - return used_.load(std::memory_order_relaxed) * 2 > Size(); + return used_.load(std::memory_order_relaxed) * 2 > + static_cast(Size()); } void Insert(Uint64 key, const V& val) { diff --git a/src/utilities/include/optional_assert.h b/src/utilities/include/optional_assert.h index 75f32684a..94d947ef7 100644 --- a/src/utilities/include/optional_assert.h +++ b/src/utilities/include/optional_assert.h @@ -15,6 +15,9 @@ #pragma once #include "public.h" +#if MANIFOLD_EXCEPTIONS +#include +#endif #ifdef MANIFOLD_DEBUG #include @@ -31,8 +34,15 @@ void Assert(bool condition, const char* file, int line, const std::string& cond, throw Ex(output.str()); } } -#define ASSERT(condition, EX, msg) \ +#define DEBUG_ASSERT(condition, EX, msg) \ Assert(condition, __FILE__, __LINE__, #condition, msg); #else -#define ASSERT(condition, EX, msg) -#endif \ No newline at end of file +#define DEBUG_ASSERT(condition, EX, msg) +#endif + +#if MANIFOLD_EXCEPTIONS +#define ASSERT(condition, EX) \ + if (!(condition)) throw(EX); +#else +#define ASSERT(condition, EX) +#endif diff --git a/src/utilities/include/public.h b/src/utilities/include/public.h index a579f3eff..d11a7f806 100644 --- a/src/utilities/include/public.h +++ b/src/utilities/include/public.h @@ -154,7 +154,7 @@ struct Mesh { */ struct Smoothness { /// The halfedge index = 3 * tri + i, referring to Mesh.triVerts[tri][i]. - int halfedge; + size_t halfedge; /// A value between 0 and 1, where 0 is sharp and 1 is the default and the /// curvature is interpolated between these values. The two paired halfedges /// can have different values while maintaining C-1 continuity (except for 0). @@ -678,7 +678,7 @@ inline std::ostream& operator<<(std::ostream& stream, const Rect& box) { template void Dump(const std::vector& vec) { std::cout << "Vec = " << std::endl; - for (int i = 0; i < vec.size(); ++i) { + for (size_t i = 0; i < vec.size(); ++i) { std::cout << i << ", " << vec[i] << ", " << std::endl; } std::cout << std::endl; @@ -692,7 +692,7 @@ void Diff(const std::vector& a, const std::vector& b) { << std::endl; return; } - for (int i = 0; i < a.size(); ++i) { + for (size_t i = 0; i < a.size(); ++i) { if (a[i] != b[i]) std::cout << i << ": " << a[i] << ", " << b[i] << std::endl; } diff --git a/src/utilities/include/sparse.h b/src/utilities/include/sparse.h index 05a711c44..ee048adc2 100644 --- a/src/utilities/include/sparse.h +++ b/src/utilities/include/sparse.h @@ -121,7 +121,7 @@ class SparseIndices { } inline void Add(int p, int q) { - for (int i = 0; i < sizeof(int64_t); ++i) data_.push_back(-1); + for (unsigned int i = 0; i < sizeof(int64_t); ++i) data_.push_back(-1); Set(size() - 1, p, q); } @@ -133,8 +133,8 @@ class SparseIndices { } size_t RemoveZeros(Vec& S) { - ASSERT(S.size() == size(), userErr, - "Different number of values than indicies!"); + DEBUG_ASSERT(S.size() == size(), userErr, + "Different number of values than indicies!"); VecView view = AsVec64(); auto zBegin = zip(S.begin(), view.begin()); auto zEnd = zip(S.end(), view.end()); @@ -164,8 +164,8 @@ class SparseIndices { template size_t KeepFinite(Vec& v, Vec& x) { - ASSERT(x.size() == size(), userErr, - "Different number of values than indicies!"); + DEBUG_ASSERT(x.size() == size(), userErr, + "Different number of values than indicies!"); VecView view = AsVec64(); auto zBegin = zip(v.begin(), x.begin(), view.begin()); auto zEnd = zip(v.end(), x.end(), view.end()); diff --git a/src/utilities/include/vec.h b/src/utilities/include/vec.h index 5409843d9..59db747fb 100644 --- a/src/utilities/include/vec.h +++ b/src/utilities/include/vec.h @@ -13,7 +13,6 @@ // limitations under the License. #pragma once -#include #if TRACY_ENABLE && TRACY_MEMORY_USAGE #include "tracy/Tracy.hpp" #else @@ -62,7 +61,7 @@ class Vec : public VecView { auto policy = autoPolicy(this->size_); if (this->size_ != 0) { this->ptr_ = reinterpret_cast(malloc(this->size_ * sizeof(T))); - if (this->ptr_ == nullptr) throw std::bad_alloc(); + ASSERT(this->ptr_ != nullptr, std::bad_alloc()); TracyAllocS(this->ptr_, this->size_ * sizeof(T), 3); uninitialized_copy(policy, vec.begin(), vec.end(), this->ptr_); } @@ -74,7 +73,7 @@ class Vec : public VecView { auto policy = autoPolicy(this->size_); if (this->size_ != 0) { this->ptr_ = reinterpret_cast(malloc(this->size_ * sizeof(T))); - if (this->ptr_ == nullptr) throw std::bad_alloc(); + ASSERT(this->ptr_ != nullptr, std::bad_alloc()); TracyAllocS(this->ptr_, this->size_ * sizeof(T), 3); uninitialized_copy(policy, vec.begin(), vec.end(), this->ptr_); } @@ -113,7 +112,7 @@ class Vec : public VecView { auto policy = autoPolicy(this->size_); if (this->size_ != 0) { this->ptr_ = reinterpret_cast(malloc(this->size_ * sizeof(T))); - if (this->ptr_ == nullptr) throw std::bad_alloc(); + ASSERT(this->ptr_ != nullptr, std::bad_alloc()); TracyAllocS(this->ptr_, this->size_ * sizeof(T), 3); uninitialized_copy(policy, other.begin(), other.end(), this->ptr_); } @@ -157,7 +156,7 @@ class Vec : public VecView { void reserve(size_t n) { if (n > capacity_) { T *newBuffer = reinterpret_cast(malloc(n * sizeof(T))); - if (newBuffer == nullptr) throw std::bad_alloc(); + ASSERT(newBuffer != nullptr, std::bad_alloc()); TracyAllocS(newBuffer, n * sizeof(T), 3); if (this->size_ > 0) uninitialized_copy(autoPolicy(this->size_), this->ptr_, @@ -186,7 +185,7 @@ class Vec : public VecView { T *newBuffer = nullptr; if (this->size_ > 0) { newBuffer = reinterpret_cast(malloc(this->size_ * sizeof(T))); - if (newBuffer == nullptr) throw std::bad_alloc(); + ASSERT(newBuffer != nullptr, std::bad_alloc()); TracyAllocS(newBuffer, this->size_ * sizeof(T), 3); uninitialized_copy(autoPolicy(this->size_), this->ptr_, this->ptr_ + this->size_, newBuffer); @@ -201,28 +200,22 @@ class Vec : public VecView { VecView view(size_t offset = 0, size_t length = std::numeric_limits::max()) { - if (length == std::numeric_limits::max()) { + if (length == std::numeric_limits::max()) length = this->size_ - offset; - if (length < 0) throw std::out_of_range("Vec::view out of range"); - } else if (offset + length > this->size_ || offset < 0) { - throw std::out_of_range("Vec::view out of range"); - } else if (length < 0) { - throw std::out_of_range("Vec::view negative length is not allowed"); - } + ASSERT(length >= 0, std::out_of_range("Vec::view out of range")); + ASSERT(offset + length <= this->size_ && offset >= 0, + std::out_of_range("Vec::view out of range")); return VecView(this->ptr_ + offset, length); } VecView cview( size_t offset = 0, size_t length = std::numeric_limits::max()) const { - if (length == std::numeric_limits::max()) { + if (length == std::numeric_limits::max()) length = this->size_ - offset; - if (length < 0) throw std::out_of_range("Vec::cview out of range"); - } else if (offset + length > this->size_ || offset < 0) { - throw std::out_of_range("Vec::cview out of range"); - } else if (length < 0) { - throw std::out_of_range("Vec::cview negative length is not allowed"); - } + ASSERT(length >= 0, std::out_of_range("Vec::cview out of range")); + ASSERT(offset + length <= this->size_ && offset >= 0, + std::out_of_range("Vec::cview out of range")); return VecView(this->ptr_ + offset, length); } @@ -235,6 +228,8 @@ class Vec : public VecView { T *data() { return this->ptr_; } const T *data() const { return this->ptr_; } + size_t capacity() const { return capacity_; } + private: size_t capacity_ = 0; diff --git a/src/utilities/include/vec_view.h b/src/utilities/include/vec_view.h index dd70cd330..74708ffff 100644 --- a/src/utilities/include/vec_view.h +++ b/src/utilities/include/vec_view.h @@ -14,7 +14,7 @@ #pragma once -#include +#include "optional_assert.h" namespace manifold { @@ -46,16 +46,12 @@ class VecView { operator VecView() const { return {ptr_, size_}; } inline const T &operator[](size_t i) const { - if (i >= size_) { - throw std::out_of_range("Vec out of range"); - } + ASSERT(i < size_, std::out_of_range("Vec out of range")); return ptr_[i]; } inline T &operator[](size_t i) { - if (i >= size_) { - throw std::out_of_range("Vec out of range"); - } + ASSERT(i < size_, std::out_of_range("Vec out of range")); return ptr_[i]; } @@ -69,26 +65,26 @@ class VecView { Iter end() { return ptr_ + size_; } const T &front() const { - if (size_ == 0) - throw std::out_of_range("attempt to take the front of an empty vector"); + ASSERT(size_ != 0, + std::out_of_range("Attempt to take the front of an empty vector")); return ptr_[0]; } const T &back() const { - if (size_ == 0) - throw std::out_of_range("attempt to take the back of an empty vector"); + ASSERT(size_ != 0, + std::out_of_range("Attempt to take the back of an empty vector")); return ptr_[size_ - 1]; } T &front() { - if (size_ == 0) - throw std::out_of_range("attempt to take the front of an empty vector"); + ASSERT(size_ != 0, + std::out_of_range("Attempt to take the front of an empty vector")); return ptr_[0]; } T &back() { - if (size_ == 0) - throw std::out_of_range("attempt to take the back of an empty vector"); + ASSERT(size_ != 0, + std::out_of_range("Attempt to take the back of an empty vector")); return ptr_[size_ - 1]; } diff --git a/test/manifold_test.cpp b/test/manifold_test.cpp index 551cc6e80..ed06e21be 100644 --- a/test/manifold_test.cpp +++ b/test/manifold_test.cpp @@ -55,12 +55,12 @@ TEST(Manifold, GetMeshGL) { MeshGL meshGL_out = manifold.GetMeshGL(); ASSERT_EQ(meshGL_out.NumVert(), mesh_out.vertPos.size()); ASSERT_EQ(meshGL_out.NumTri(), mesh_out.triVerts.size()); - for (int i = 0; i < meshGL_out.NumVert(); ++i) { + for (size_t i = 0; i < meshGL_out.NumVert(); ++i) { for (const int j : {0, 1, 2}) { ASSERT_EQ(meshGL_out.vertProperties[3 * i + j], mesh_out.vertPos[i][j]); } } - for (int i = 0; i < meshGL_out.NumTri(); ++i) { + for (size_t i = 0; i < meshGL_out.NumTri(); ++i) { for (const int j : {0, 1, 2}) ASSERT_EQ(meshGL_out.triVerts[3 * i + j], mesh_out.triVerts[i][j]); } @@ -241,7 +241,7 @@ Polygons RotatePolygons(Polygons polys, const int index) { TEST(Manifold, Revolve) { Polygons polys = SquareHole(); Manifold vug; - for (int i = 0; i < polys[0].size(); i++) { + for (size_t i = 0; i < polys[0].size(); i++) { Polygons rotatedPolys = RotatePolygons(polys, i); vug = Manifold::Revolve(rotatedPolys, 48); EXPECT_EQ(vug.Genus(), -1); @@ -273,7 +273,7 @@ TEST(Manifold, PartialRevolveOnYAxis) { Polygons offsetPolys = SquareHole(10.0f); Manifold revolute; - for (int i = 0; i < polys[0].size(); i++) { + for (size_t i = 0; i < polys[0].size(); i++) { Polygons rotatedPolys = RotatePolygons(polys, i); revolute = Manifold::Revolve(rotatedPolys, 48, 180); EXPECT_EQ(revolute.Genus(), 1); @@ -290,7 +290,7 @@ TEST(Manifold, PartialRevolveOffset) { Polygons polys = SquareHole(10.0f); Manifold revolute; - for (int i = 0; i < polys[0].size(); i++) { + for (size_t i = 0; i < polys[0].size(); i++) { Polygons rotatedPolys = RotatePolygons(polys, i); revolute = Manifold::Revolve(rotatedPolys, 48, 180); auto prop = revolute.GetProperties(); diff --git a/test/smooth_test.cpp b/test/smooth_test.cpp index 22f9b7846..4951bfbaa 100644 --- a/test/smooth_test.cpp +++ b/test/smooth_test.cpp @@ -35,7 +35,7 @@ TEST(Smooth, Tetrahedron) { MeshGL out = smooth.CalculateCurvature(-1, 0).GetMeshGL(); float maxMeanCurvature = 0; - for (int i = 3; i < out.vertProperties.size(); i += 4) { + for (size_t i = 3; i < out.vertProperties.size(); i += 4) { maxMeanCurvature = glm::max(maxMeanCurvature, glm::abs(out.vertProperties[i])); } @@ -60,7 +60,7 @@ TEST(Smooth, RefineQuads) { const MeshGL baseline = WithPositionColors(cylinder); float maxDiff = 0; - for (int i = 0; i < out.vertProperties.size(); ++i) { + for (size_t i = 0; i < out.vertProperties.size(); ++i) { maxDiff = glm::max( maxDiff, glm::abs(out.vertProperties[i] - baseline.vertProperties[i])); } @@ -118,7 +118,7 @@ TEST(Smooth, ToLength) { MeshGL out = smooth.CalculateCurvature(-1, 0).GetMeshGL(); float maxMeanCurvature = 0; - for (int i = 3; i < out.vertProperties.size(); i += 4) { + for (size_t i = 3; i < out.vertProperties.size(); i += 4) { maxMeanCurvature = glm::max(maxMeanCurvature, glm::abs(out.vertProperties[i])); } @@ -309,7 +309,7 @@ TEST(Smooth, Torus) { .CalculateNormals(1); MeshGL out = smooth.GetMeshGL(); float maxMeanCurvature = 0; - for (int i = 0; i < out.vertProperties.size(); i += 7) { + for (size_t i = 0; i < out.vertProperties.size(); i += 7) { glm::vec3 v(out.vertProperties[i], out.vertProperties[i + 1], out.vertProperties[i + 2]); glm::vec3 p(v.x, v.y, 0); @@ -372,4 +372,4 @@ TEST(Smooth, SineSurface) { ExportMesh("smoothSineSurface.glb", smoothed.GetMeshGL(), options2); } #endif -} \ No newline at end of file +} diff --git a/test/test_main.cpp b/test/test_main.cpp index d747ddea3..ab7dba0ed 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -176,7 +176,7 @@ MeshGL CubeSTL() { MeshGL cube; cube.numProp = 6; - for (int tri = 0, vert = 0; tri < cubeIn.NumTri(); tri++) { + for (size_t tri = 0, vert = 0; tri < cubeIn.NumTri(); tri++) { glm::mat3 triPos; for (const int i : {0, 1, 2}) { cube.triVerts.push_back(vert++); @@ -249,14 +249,14 @@ MeshGL WithNormals(const Manifold& in) { out.runOriginalID = {Manifold::ReserveIDs(1)}; out.numProp = 6; out.vertProperties.resize(out.numProp * mesh.vertPos.size()); - for (int i = 0; i < mesh.vertPos.size(); ++i) { + for (size_t i = 0; i < mesh.vertPos.size(); ++i) { for (int j : {0, 1, 2}) { out.vertProperties[6 * i + j] = mesh.vertPos[i][j]; out.vertProperties[6 * i + 3 + j] = mesh.vertNormal[i][j]; } } out.triVerts.resize(3 * mesh.triVerts.size()); - for (int i = 0; i < mesh.triVerts.size(); ++i) { + for (size_t i = 0; i < mesh.triVerts.size(); ++i) { for (int j : {0, 1, 2}) out.triVerts[3 * i + j] = mesh.triVerts[i][j]; } return out; @@ -319,12 +319,12 @@ void CheckFinite(const MeshGL& mesh) { void Identical(const Mesh& mesh1, const Mesh& mesh2) { ASSERT_EQ(mesh1.vertPos.size(), mesh2.vertPos.size()); - for (int i = 0; i < mesh1.vertPos.size(); ++i) + for (size_t i = 0; i < mesh1.vertPos.size(); ++i) for (int j : {0, 1, 2}) ASSERT_NEAR(mesh1.vertPos[i][j], mesh2.vertPos[i][j], 0.0001); ASSERT_EQ(mesh1.triVerts.size(), mesh2.triVerts.size()); - for (int i = 0; i < mesh1.triVerts.size(); ++i) + for (size_t i = 0; i < mesh1.triVerts.size(); ++i) ASSERT_EQ(mesh1.triVerts[i], mesh2.triVerts[i]); } @@ -334,22 +334,22 @@ void RelatedGL(const Manifold& out, const std::vector& originals, const glm::ivec3 normalIdx = updateNormals ? glm::ivec3(3, 4, 5) : glm::ivec3(0); MeshGL output = out.GetMeshGL(normalIdx); - for (int run = 0; run < output.runOriginalID.size(); ++run) { + for (size_t run = 0; run < output.runOriginalID.size(); ++run) { const float* m = output.runTransform.data() + 12 * run; const glm::mat4x3 transform = output.runTransform.empty() ? glm::mat4x3(1.0f) : glm::mat4x3(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11]); - int i = 0; + size_t i = 0; for (; i < originals.size(); ++i) { ASSERT_EQ(originals[i].runOriginalID.size(), 1); if (originals[i].runOriginalID[0] == output.runOriginalID[run]) break; } ASSERT_LT(i, originals.size()); const MeshGL& inMesh = originals[i]; - for (int tri = output.runIndex[run] / 3; tri < output.runIndex[run + 1] / 3; - ++tri) { + for (uint32_t tri = output.runIndex[run] / 3; + tri < output.runIndex[run + 1] / 3; ++tri) { if (!output.faceID.empty()) { ASSERT_LT(tri, output.faceID.size()); } @@ -394,7 +394,7 @@ void RelatedGL(const Manifold& out, const std::vector& originals, ASSERT_NEAR(glm::length(normal), 1, 0.0001); ASSERT_GT(glm::dot(normal, outNormal), 0); } else { - for (int p = 3; p < inMesh.numProp; ++p) { + for (size_t p = 3; p < inMesh.numProp; ++p) { const float propOut = output.vertProperties[vert * output.numProp + p]; @@ -427,7 +427,7 @@ void ExpectMeshes(const Manifold& manifold, return a.NumVert() != b.NumVert() ? a.NumVert() > b.NumVert() : a.NumTri() > b.NumTri(); }); - for (int i = 0; i < manifolds.size(); ++i) { + for (size_t i = 0; i < manifolds.size(); ++i) { EXPECT_EQ(manifolds[i].NumVert(), meshSize[i].numVert); EXPECT_EQ(manifolds[i].NumTri(), meshSize[i].numTri); EXPECT_EQ(manifolds[i].NumProp(), meshSize[i].numProp); @@ -476,4 +476,4 @@ Manifold ReadMesh(const std::string& filename) { std::string dir = file.substr(0, file.rfind('/')); return Manifold(ImportMesh(dir + "/models/" + filename)); } -#endif \ No newline at end of file +#endif