chores (#833)
* fix comparison between integers with different signedness and implicit narrowing * fix compilation error and formatting * allow build with exception disabled * CI for building without exception * format * another fix * msvc stuff * fix python bindings * update nix * formatting * old llvm somehow likes this better * fix bug * rename ASSERT into DEBUG_ASSERT * remove unused file * use ASSERT and remove obsolete limits * polygon: change to size_t * format * fix sign compare * install optional_assert.h * address comments * fix * fix * fix * fix format
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
Vendored
+1
-1
Submodule bindings/python/third_party/nanobind updated: 1a309ba444...8d7f1ee062
@@ -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
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -48,4 +48,4 @@ std::vector<glm::ivec3> Triangulate(const Polygons &polygons,
|
||||
|
||||
ExecutionParams &PolygonParams();
|
||||
/** @} */
|
||||
} // namespace manifold
|
||||
} // namespace manifold
|
||||
|
||||
+34
-28
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user