* 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
This commit is contained in:
pca006132
2024-06-28 09:36:54 -07:00
committed by GitHub
parent 85d71f5cef
commit b817d07a9d
44 changed files with 493 additions and 487 deletions
+5 -1
View File
@@ -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/
+10 -4
View File
@@ -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()
+3 -3
View File
@@ -227,7 +227,7 @@ glm::vec4 from_c(ManifoldVec4 v) { return glm::vec4(v.x, v.y, v.z, v.w); }
std::vector<glm::vec3> vector_of_vec_array(ManifoldVec3 *vs, size_t length) {
auto vec = std::vector<glm::vec3>();
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<glm::vec3> vector_of_vec_array(ManifoldVec3 *vs, size_t length) {
std::vector<glm::ivec3> vector_of_vec_array(ManifoldIVec3 *vs, size_t length) {
auto vec = std::vector<glm::ivec3>();
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<glm::ivec3> vector_of_vec_array(ManifoldIVec3 *vs, size_t length) {
std::vector<glm::vec4> vector_of_vec_array(ManifoldVec4 *vs, size_t length) {
auto vec = std::vector<glm::vec4>();
for (int i = 0; i < length; ++i) {
for (size_t i = 0; i < length; ++i) {
vec.push_back(from_c(vs[i]));
}
return vec;
+1 -1
View File
@@ -67,7 +67,7 @@ std::vector<glm::vec4> vector_of_vec_array(ManifoldVec4 *vs, size_t length);
template <typename T>
std::vector<T> vector_of_array(T *ts, size_t length) {
auto vec = std::vector<T>();
for (int i = 0; i < length; ++i) {
for (size_t i = 0; i < length; ++i) {
vec.push_back(ts[i]);
}
return vec;
+2 -2
View File
@@ -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,
+6 -7
View File
@@ -58,7 +58,7 @@ extern "C" {
ManifoldSimplePolygon *manifold_simple_polygon(void *mem, ManifoldVec2 *ps,
size_t length) {
auto vec = new (mem) std::vector<glm::vec2>;
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<SimplePolygon>;
auto polys = reinterpret_cast<SimplePolygon **>(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<glm::vec3> 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<Smoothness>();
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));
+106 -90
View File
@@ -68,7 +68,7 @@ struct nb::detail::type_caster<glm::vec<N, T, Q>> {
int size = PyObject_Size(src.ptr()); // negative on failure
if (size != N) return false;
make_caster<T> 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<glm::mat<C, R, T, Q>> {
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> 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<glm::mat<C, R, T, Q>> {
template <class T, int N, glm::qualifier Q>
struct nb::detail::type_caster<std::vector<glm::vec<N, T, Q>>> {
using glm_type = glm::vec<N, T, Q>;
using numpy_type = nb::ndarray<nb::numpy, T, nb::shape<nb::any, N>>;
using numpy_type = nb::ndarray<nb::numpy, T, nb::shape<-1, N>>;
NB_TYPE_CASTER(std::vector<glm_type>,
const_name(glm_name<glm_type>::multi_name));
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
make_caster<numpy_type> 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<size_t>(-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<glm_type> 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<std::vector<glm::vec<N, T, Q>>> {
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<std::vector<glm::vec<N, T, Q>>> {
template <class T, int N, glm::qualifier Q>
struct nb::detail::type_caster<manifold::VecView<glm::vec<N, T, Q>>> {
using glm_type = glm::vec<N, T, Q>;
using numpy_type = nb::ndarray<nb::numpy, T, nb::shape<nb::any, N>>;
using numpy_type = nb::ndarray<nb::numpy, T, nb::shape<-1, N>>;
NB_TYPE_CASTER(manifold::VecView<glm_type>,
const_name(glm_name<glm_type>::multi_name));
@@ -178,9 +178,9 @@ struct nb::detail::type_caster<manifold::VecView<glm::vec<N, T, Q>>> {
make_caster<numpy_type> 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<manifold::VecView<glm::vec<N, T, Q>>> {
}
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<nb::numpy, const float, nb::c_contig>(
oldProps, {static_cast<unsigned long>(oldNumProp)}));
nb::ndarray<float, nb::shape<nb::any>> array;
oldProps, {static_cast<unsigned long>(oldNumProp)},
nb::handle()));
nb::ndarray<float, nb::shape<-1>> array;
std::vector<float> vec;
if (nb::try_cast(result, array)) {
if (array.ndim() != 1 || array.shape(0) != newNumProp)
if (array.ndim() != 1 ||
array.shape(0) != static_cast<size_t>(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<int> sharpened_edges,
[](const MeshGL &mesh, std::vector<size_t> sharpened_edges,
std::vector<float> edge_smoothness) {
if (sharpened_edges.size() != edge_smoothness.size()) {
throw std::runtime_error(
"sharpened_edges.size() != edge_smoothness.size()");
}
std::vector<Smoothness> 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<float, nb::shape<nb::any, nb::any>, nb::c_contig>
&vertProp,
nb::ndarray<uint32_t, nb::shape<nb::any, 3>, nb::c_contig>
&triVerts,
const std::optional<nb::ndarray<uint32_t, nb::shape<nb::any>,
nb::ndarray<float, nb::shape<-1, -1>, nb::c_contig> &vertProp,
nb::ndarray<uint32_t, nb::shape<-1, 3>, nb::c_contig> &triVerts,
const std::optional<nb::ndarray<uint32_t, nb::shape<-1>,
nb::c_contig>> &mergeFromVert,
const std::optional<nb::ndarray<uint32_t, nb::shape<nb::any>,
const std::optional<nb::ndarray<uint32_t, nb::shape<-1>,
nb::c_contig>> &mergeToVert,
const std::optional<nb::ndarray<uint32_t, nb::shape<nb::any>,
nb::c_contig>> &runIndex,
const std::optional<nb::ndarray<uint32_t, nb::shape<nb::any>,
const std::optional<
nb::ndarray<uint32_t, nb::shape<-1>, nb::c_contig>> &runIndex,
const std::optional<nb::ndarray<uint32_t, nb::shape<-1>,
nb::c_contig>> &runOriginalID,
std::optional<nb::ndarray<float, nb::shape<nb::any, 4, 3>,
std::optional<nb::ndarray<float, nb::shape<-1, 4, 3>,
nb::c_contig>> &runTransform,
const std::optional<nb::ndarray<uint32_t, nb::shape<nb::any>,
nb::c_contig>> &faceID,
const std::optional<nb::ndarray<float, nb::shape<nb::any, 3, 4>,
const std::optional<
nb::ndarray<uint32_t, nb::shape<-1>, nb::c_contig>> &faceID,
const std::optional<nb::ndarray<float, nb::shape<-1, 3, 4>,
nb::c_contig>> &halfedgeTangent,
float precision) {
new (self) MeshGL();
MeshGL &out = *self;
out.numProp = vertProp.shape(1);
out.vertProperties = toVector<float>(vertProp.data(), vertProp.size());
new (self) MeshGL();
MeshGL &out = *self;
out.numProp = vertProp.shape(1);
out.vertProperties =
toVector<float>(vertProp.data(), vertProp.size());
out.triVerts = toVector<uint32_t>(triVerts.data(), triVerts.size());
out.triVerts = toVector<uint32_t>(triVerts.data(), triVerts.size());
if (mergeFromVert.has_value())
out.mergeFromVert =
toVector<uint32_t>(mergeFromVert->data(), mergeFromVert->size());
if (mergeFromVert.has_value())
out.mergeFromVert = toVector<uint32_t>(mergeFromVert->data(),
mergeFromVert->size());
if (mergeToVert.has_value())
out.mergeToVert =
toVector<uint32_t>(mergeToVert->data(), mergeToVert->size());
if (mergeToVert.has_value())
out.mergeToVert =
toVector<uint32_t>(mergeToVert->data(), mergeToVert->size());
if (runIndex.has_value())
out.runIndex = toVector<uint32_t>(runIndex->data(), runIndex->size());
if (runIndex.has_value())
out.runIndex =
toVector<uint32_t>(runIndex->data(), runIndex->size());
if (runOriginalID.has_value())
out.runOriginalID =
toVector<uint32_t>(runOriginalID->data(), runOriginalID->size());
if (runOriginalID.has_value())
out.runOriginalID = toVector<uint32_t>(runOriginalID->data(),
runOriginalID->size());
if (runTransform.has_value()) {
out.runTransform =
toVector<float>(runTransform->data(), runTransform->size());
}
if (runTransform.has_value()) {
out.runTransform =
toVector<float>(runTransform->data(), runTransform->size());
}
if (faceID.has_value())
out.faceID = toVector<uint32_t>(faceID->data(), faceID->size());
if (faceID.has_value())
out.faceID = toVector<uint32_t>(faceID->data(), faceID->size());
if (halfedgeTangent.has_value()) {
out.halfedgeTangent =
toVector<float>(halfedgeTangent->data(), halfedgeTangent->size());
}
if (halfedgeTangent.has_value()) {
out.halfedgeTangent = toVector<float>(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<nb::numpy, const float, nb::c_contig>(
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<nb::numpy, const int, nb::c_contig>(
self.triVerts.data(), {self.triVerts.size() / 3, 3});
}, nb::rv_policy::reference_internal)
.def_prop_ro("run_transform",
[](const MeshGL &self) {
return nb::ndarray<nb::numpy, const float, nb::c_contig>(
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<nb::numpy, const float, nb::c_contig>(
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<nb::numpy, const float, nb::c_contig>(
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<nb::numpy, const int, nb::c_contig>(
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<nb::numpy, const float, nb::c_contig>(
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<nb::numpy, const float, nb::c_contig>(
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<float(float, float, float)> &f,
std::vector<float> 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])};
// 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<float(glm::vec3)> cppToPython = [&f](glm::vec3 v) {
return f(v.x, v.y, v.z);
};
Mesh result = LevelSet(cppToPython, bound, edgeLength, level, false);
return MeshGL(result);
std::function<float(glm::vec3)> 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,
+13 -13
View File
@@ -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(<pstl/glue_execution_defs.h>)
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<int, int> findIndex(const Polygons &polys, int i) {
int outer = 0;
std::pair<int, int> 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<int> getChildren(const Polygons &polys, int i) {
std::vector<int> getChildren(const Polygons &polys, size_t i) {
std::vector<int> 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<int> 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<int> 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)) {
-22
View File
@@ -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
Generated
+3 -3
View File
@@ -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": {
+3 -3
View File
@@ -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
];
};
+18 -17
View File
@@ -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];
+2 -2
View File
@@ -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
} // namespace manifold
+2 -2
View File
@@ -38,8 +38,8 @@ class Collider {
// even nodes are leaves, odd nodes are internal, root is 1
Vec<thrust::pair<int, int>> 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);
};
};
+5 -5
View File
@@ -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<int>(leafMorton_.size())) {
return -1;
} else {
int out;
@@ -285,8 +285,8 @@ namespace manifold {
Collider::Collider(const VecView<const Box>& leafBB,
const VecView<const uint32_t>& 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<const T>& queriesIn) const {
*/
void Collider::UpdateBoxes(const VecView<const Box>& 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<Vec<Box>::Iter> leaves(nodeBBox_.begin(), nodeBBox_.end(), 2);
auto policy = autoPolicy(NumInternal());
+22 -28
View File
@@ -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<const PathImpl> shared_paths(const C2::PathsD& ps) {
// forward declaration for mutual recursion
void decompose_hole(const C2::PolyTreeD* outline,
std::vector<C2::PathsD>& 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<C2::PathsD>& polys, int i) {
std::vector<C2::PathsD>& 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<C2::PathsD>& 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<glm::vec2>& 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<glm::vec2>{};
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<glm::vec2>{};
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> CrossSection::Decompose() const {
auto polys = std::vector<C2::PathsD>();
decompose_outline(&tree, polys, 0);
auto n_polys = polys.size();
auto comps = std::vector<CrossSection>(n_polys);
auto comps = std::vector<CrossSection>();
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;
}
+6 -4
View File
@@ -46,14 +46,16 @@ class CsgLeafNode;
struct MeshGL {
/// Number of property vertices
uint32_t NumVert() const {
if (vertProperties.size() / numProp >= std::numeric_limits<int>::max())
throw std::out_of_range("mesh too large");
ASSERT(vertProperties.size() / numProp <
static_cast<size_t>(std::numeric_limits<uint32_t>::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<int>::max())
throw std::out_of_range("mesh too large");
ASSERT(triVerts.size() / 3 <
static_cast<size_t>(std::numeric_limits<uint32_t>::max()),
std::out_of_range("mesh too large for MeshGL"));
return triVerts.size() / 3;
};
+13 -12
View File
@@ -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<int, glm::vec2> Shadow01(
// much faster than standard binary search on large arrays
size_t monobound_quaternary_search(VecView<const int64_t> array, int64_t key) {
if (array.size() == 0) {
return -1;
return std::numeric_limits<size_t>::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<size_t>::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<size_t>::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<int>::max())
throw std::out_of_range("mesh too large");
Vec<int> p0 = p0q2.Copy(false);
p0q2.Resize(0);
Vec<int> q0 = p2q0.Copy(true);
+14 -17
View File
@@ -104,8 +104,6 @@ std::tuple<Vec<int>, Vec<int>> SizeOutput(
ZoneScoped;
Vec<int> sidesPerFacePQ(inP.NumTri() + inQ.NumTri(), 0);
// note: numFaceR <= facePQ2R.size() = sidesPerFacePQ.size() + 1
if (sidesPerFacePQ.size() + 1 >= std::numeric_limits<int>::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<Halfedge> PairUp(std::vector<EdgePos> &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<size_t>(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<size_t>(outR.NumVert()) * static_cast<size_t>(numProp) >=
std::numeric_limits<int>::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();
+21 -20
View File
@@ -79,9 +79,9 @@ namespace manifold {
*/
Manifold Manifold::Smooth(const MeshGL& meshGL,
const std::vector<Smoothness>& 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<float> propertyTolerance(meshGL.numProp - 3, -1);
@@ -121,9 +121,9 @@ Manifold Manifold::Smooth(const MeshGL& meshGL,
*/
Manifold Manifold::Smooth(const Mesh& mesh,
const std::vector<Smoothness>& 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> impl = std::make_shared<Impl>(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<int>(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<glm::ivec3> 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);
+9 -9
View File
@@ -74,7 +74,7 @@ struct UpdateMeshIDs {
struct CheckOverlap {
VecView<const Box> 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<std::shared_ptr<const Manifold::Impl>,
@@ -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<Manifold::Impl> CsgOpNode::BatchBoolean(
std::vector<std::shared_ptr<const Manifold::Impl>> &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<Manifold::Impl>();
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<Box> 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<CsgLeafNode>(children_[i])
->GetImpl()
->bBox_);
+6 -6
View File
@@ -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<SortEntry> 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<int>& 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<bool> vertProcessed(NumVert(), false);
std::vector<bool> 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]) {
+11 -13
View File
@@ -49,7 +49,7 @@ void Manifold::Impl::Face2Tri(const Vec<int>& 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<int>& 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<int>& 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<int>& 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<glm::ivec3> newTris = generalTriangulation(face);
@@ -156,8 +156,6 @@ void Manifold::Impl::Face2Tri(const Vec<int>& 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<int>::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<int>& 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<Halfedge>::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<false, false>(query.cview());
std::unordered_set<int> 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<float>::infinity();
float max = -std::numeric_limits<float>::infinity();
+15 -26
View File
@@ -327,13 +327,9 @@ void DedupePropVerts(manifold::Vec<glm::ivec3>& triProp,
const int numLabels = GetLabels(vertLabels, vert2vert, vert2vert.size());
std::vector<int> 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<float> propertyTolerance) {
Mesh mesh;
mesh.precision = meshGL.precision;
const int numVert = meshGL.NumVert();
const int numTri = meshGL.NumTri();
if (meshGL.numProp > 3 &&
static_cast<size_t>(numVert) * static_cast<size_t>(meshGL.numProp - 3) >=
std::numeric_limits<int>::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<int>(numVert) || to >= static_cast<int>(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<int>(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<float>& propertyTolerance,
bool hasFaceIDs)
: vertPos_(mesh.vertPos), halfedgeTangent_(mesh.halfedgeTangent) {
if (mesh.triVerts.size() >= std::numeric_limits<int>::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<float>& propertyTolerance) {
const int numComponent = GetLabels(components, face2face, NumTri());
Vec<int> 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<float>& propertyTolerance) {
{comp2tri, halfedge_, vertPos_, &components, precision_}));
Vec<TriRef>& 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;
+5 -5
View File
@@ -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();
}
+5 -5
View File
@@ -294,8 +294,8 @@ MeshGL Manifold::GetMeshGL(glm::ivec3 normalIdx) const {
std::vector<std::vector<glm::ivec2>> vertPropPair(impl.NumVert());
out.vertProperties.reserve(numVert * static_cast<size_t>(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;
}
}
+14 -14
View File
@@ -102,7 +102,7 @@ struct CurvatureAngles {
VecView<const glm::vec3> vertPos;
VecView<const glm::vec3> 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<glm::ivec3&, int> inOut) {
void operator()(thrust::tuple<glm::ivec3&, size_t> 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<int>(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<const Halfedge> 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<const glm::vec3> 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(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<float> vertArea(NumVert(), 0);
Vec<float> 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<const glm::ivec3> triVerts) const {
std::numeric_limits<int>::min()),
MinMax());
return minmax[0] >= 0 && minmax[1] < NumVert();
return minmax[0] >= 0 && minmax[1] < static_cast<int>(NumVert());
}
/*
+2 -2
View File
@@ -192,11 +192,11 @@ Vec<TmpEdge> inline CreateTmpEdges(const Vec<Halfedge>& halfedge) {
for_each_n(autoPolicy(edges.size()),
zip(edges.begin(), halfedge.begin(), countAt(0)), edges.size(),
Halfedge2Tmp());
int numEdge =
size_t numEdge =
remove_if<decltype(edges.begin())>(
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;
}
+10 -10
View File
@@ -356,7 +356,7 @@ bool Manifold::Impl::IsMarkedInsideQuad(int halfedge) const {
std::vector<Smoothness> Manifold::Impl::UpdateSharpenedEdges(
const std::vector<Smoothness>& sharpenedEdges) const {
std::unordered_map<int, int> 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<bool> Manifold::Impl::FlatFaces() const {
Vec<int> Manifold::Impl::VertFlatFace(const Vec<bool>& flatFaces) const {
Vec<int> vertFlatFace(NumVert(), -1);
Vec<TriRef> 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<Smoothness> Manifold::Impl::SharpenEdges(
float minSharpAngle, float minSmoothness) const {
std::vector<Smoothness> 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<bool> triIsFlatFace = FlatFaces();
Vec<int> vertFlatFace = VertFlatFace(triIsFlatFace);
Vec<int> 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<bool>& 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<Smoothness> sharpenedEdges) {
Vec<bool> triIsFlatFace = FlatFaces();
Vec<int> vertFlatFace = VertFlatFace(triIsFlatFace);
Vec<glm::vec3> 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<Smoothness> 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<Smoothness> 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<size_t>(pair), 1}};
if (!forward) std::swap(edges[idx].first, edges[idx].second);
} else {
Smoothness& e = forward ? edges[idx].first : edges[idx].second;
+37 -34
View File
@@ -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<int>(NumVert()), topologyErr,
"Vertex index exceeds number of verts!");
DEBUG_ASSERT(extrema.face >= 0, topologyErr, "Face index is negative!");
DEBUG_ASSERT(extrema.face < static_cast<int>(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<int>(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<uint32_t> 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<int>& vertNew2Old, int oldNumVert) {
ZoneScoped;
Vec<int> vertOld2New(oldNumVert);
scatter(autoPolicy(oldNumVert), countAt(0), countAt(NumVert()),
vertNew2Old.begin(), vertOld2New.begin());
scatter(autoPolicy(oldNumVert), countAt(0),
countAt(static_cast<int>(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<int> 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<true>(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<int>(mergeFromVert[i]),
static_cast<int>(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);
+8 -7
View File
@@ -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<glm::ivec3> 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<Barycentric> Manifold::Impl::Subdivide(
Vec<int> 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<int>(part.triVert.size());
});
exclusive_scan(policy, numSubTris, numSubTris + numTri, triOffset.begin(), 0);
Vec<int> interiorOffset(numTri);
+1 -1
View File
@@ -48,4 +48,4 @@ std::vector<glm::ivec3> Triangulate(const Polygons &polygons,
ExecutionParams &PolygonParams();
/** @} */
} // namespace manifold
} // namespace manifold
+34 -28
View File
@@ -42,7 +42,7 @@ struct PolyEdge {
std::vector<PolyEdge> Polygons2Edges(const PolygonsIdx &polys) {
std::vector<PolyEdge> 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<PolyEdge> Triangles2Edges(
}
void CheckTopology(const std::vector<PolyEdge> &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<PolyEdge> 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<size_t>(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<size_t>(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<PolyEdge> &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<glm::ivec3> &triangles,
const PolygonsIdx &polys, float precision) {
std::unordered_map<int, glm::vec2> 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<glm::ivec3> TriangulateConvex(const PolygonsIdx &polys) {
const int numTri = transform_reduce<int>(
const size_t numTri = transform_reduce<size_t>(
autoPolicy(polys.size()), polys.begin(), polys.end(),
[](const SimplePolygonIdx &poly) { return poly.size() - 2; }, 0,
thrust::plus<int>());
thrust::plus<size_t>());
std::vector<glm::ivec3> 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<glm::ivec3> TriangulateIdx(const PolygonsIdx &polys,
float precision) {
std::vector<glm::ivec3> 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<glm::ivec3> 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<glm::ivec3> TriangulateIdx(const PolygonsIdx &polys,
} catch (const std::exception &e) {
#endif
}
#endif
return triangles;
}
+9 -1
View File
@@ -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})
+2 -1
View File
@@ -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_t>(Size());
}
void Insert(Uint64 key, const V& val) {
+13 -3
View File
@@ -15,6 +15,9 @@
#pragma once
#include "public.h"
#if MANIFOLD_EXCEPTIONS
#include <stdexcept>
#endif
#ifdef MANIFOLD_DEBUG
#include <iostream>
@@ -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<EX>(condition, __FILE__, __LINE__, #condition, msg);
#else
#define ASSERT(condition, EX, msg)
#endif
#define DEBUG_ASSERT(condition, EX, msg)
#endif
#if MANIFOLD_EXCEPTIONS
#define ASSERT(condition, EX) \
if (!(condition)) throw(EX);
#else
#define ASSERT(condition, EX)
#endif
+3 -3
View File
@@ -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 <typename T>
void Dump(const std::vector<T>& 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<T>& a, const std::vector<T>& 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;
}
+5 -5
View File
@@ -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<int>& 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<int64_t> view = AsVec64();
auto zBegin = zip(S.begin(), view.begin());
auto zEnd = zip(S.end(), view.end());
@@ -164,8 +164,8 @@ class SparseIndices {
template <typename T>
size_t KeepFinite(Vec<T>& v, Vec<int>& 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<int64_t> view = AsVec64();
auto zBegin = zip(v.begin(), x.begin(), view.begin());
auto zEnd = zip(v.end(), x.end(), view.end());
+15 -20
View File
@@ -13,7 +13,6 @@
// limitations under the License.
#pragma once
#include <exception>
#if TRACY_ENABLE && TRACY_MEMORY_USAGE
#include "tracy/Tracy.hpp"
#else
@@ -62,7 +61,7 @@ class Vec : public VecView<T> {
auto policy = autoPolicy(this->size_);
if (this->size_ != 0) {
this->ptr_ = reinterpret_cast<T *>(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<T> {
auto policy = autoPolicy(this->size_);
if (this->size_ != 0) {
this->ptr_ = reinterpret_cast<T *>(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<T> {
auto policy = autoPolicy(this->size_);
if (this->size_ != 0) {
this->ptr_ = reinterpret_cast<T *>(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<T> {
void reserve(size_t n) {
if (n > capacity_) {
T *newBuffer = reinterpret_cast<T *>(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> {
T *newBuffer = nullptr;
if (this->size_ > 0) {
newBuffer = reinterpret_cast<T *>(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<T> {
VecView<T> view(size_t offset = 0,
size_t length = std::numeric_limits<size_t>::max()) {
if (length == std::numeric_limits<size_t>::max()) {
if (length == std::numeric_limits<size_t>::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<T>(this->ptr_ + offset, length);
}
VecView<const T> cview(
size_t offset = 0,
size_t length = std::numeric_limits<size_t>::max()) const {
if (length == std::numeric_limits<size_t>::max()) {
if (length == std::numeric_limits<size_t>::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<const T>(this->ptr_ + offset, length);
}
@@ -235,6 +228,8 @@ class Vec : public VecView<T> {
T *data() { return this->ptr_; }
const T *data() const { return this->ptr_; }
size_t capacity() const { return capacity_; }
private:
size_t capacity_ = 0;
+11 -15
View File
@@ -14,7 +14,7 @@
#pragma once
#include <stdexcept>
#include "optional_assert.h"
namespace manifold {
@@ -46,16 +46,12 @@ class VecView {
operator VecView<const T>() 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];
}
+5 -5
View File
@@ -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();
+5 -5
View File
@@ -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
}
}
+12 -12
View File
@@ -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<MeshGL>& 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<MeshGL>& 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
#endif