cutdigital / mcut Goto Github PK
View Code? Open in Web Editor NEWA library for detecting and resolving intersections between two surface meshes.
Home Page: https://cutdigital.github.io/mcut.site
License: Other
A library for detecting and resolving intersections between two surface meshes.
Home Page: https://cutdigital.github.io/mcut.site
License: Other
Good day!
I might miss it from documentation and source code, but can I force your library to output faces with 3 points only?
error message : "Floating-polygon partitioning step could not find a usable fpSegment"
Hello,
I woulld like to start testing your lib with a sample mesh (closed volume) / plane intersection, and get the slice (2D) mesh as result, and the boundary as IGES (or at least as a list of points).
Is it already possible, and if yes how ?
Thank you.
I want to use this library in Untiy Game Engine. There are several slicing functionality that we have to implement in our upcoming projects. I wonder if is it possible to convert this project into DLL file and call its methods from Unity C#? I could not get me head around on this as I am new to c++.
I have tested your library, and it looks great ! Only issue is that I'm not able to cut meshes that contain faces with more than 3 vertices, and the library outputs that there is no components. Is this a known issue ? Because I saw in tutorials/HelloWorld/HelloWorld.cpp
a line marked with "triangulation bug"...
I can give you more details about my particular case if you want :).
Thanks for your help !
Hello,
I have a question concerning the future of MCUT.
I want to cut a shape with non-manifold parts and multiples connected components.
I understand that, at the moment, MCUT isn't made to work in these cases.
Do you plan to remove these constraints in a future version of MCUT ?
Thanks !
Hi,
The three tutorials are producing errors:
VertexNormals >> MCUT error: faceVertexOffset != -1
TextureCoordinates >> MCUT error: faceVertexOffset != -1
FaceNormals >> MCUT error: faceVertexOffset != -1
I have tested on several other meshes but most of the time mcut is ending up with some message. There are two meshes in the attached zip file. The csgboolean.cpp is producing this error:
csgboolean.exe source.obj cutter.obj -i
or
csgboolean.exe source.obj cutter.obj -ds
compute INTERSECTION
operator()(...) -> max perturbation iteratons reached (EventID=00000000000decb0)
MCUT error: err == MC_NO_ERROR
Although when working it's producing a very fine cut that's why I'm interested in this library.
Cheers
data.zip
Good day! I am glad that you released a new version of this software and wanted to clarify the results from tutorials I obtain.
I am particularly interested in QuerySeamVerticesSorted
code. The only thing I have changed is I query MC_CONNECTED_COMPONENT_TYPE_SEAM
instead of FRAGMENT
expecting to get just seam of the intersection.
Given .off files from example I would expect getting two separate sequences of vertices, one for each part of the input mesh. However the result I obtain is the following:
sequence = 0
size = 11
is_loop = TRUE
vertices = 7 3 0 15 6 9 1 13 12 8 14
Could you clarify what is the proper way to query the result I expect or the intuition behind the result I get. I have tried using FRAGMENTS
to query the seam and then filter among all results, but it also has given me unreliable results.
Thank you once again!
Hi, I try to read the STL file and then do boolean operations, but it fails.
I made a modification on CSGBollean.cpp and below is my code to read STL:
bool read_stl(std::string filename, std::vector<std::vector<double>> &V, std::vector<std::vector<int>> &F) {
Eigen::MatrixXd V1;
Eigen::MatrixXi F1;
igl::read_triangle_mesh(filename, V1, F1);
for (int i = 0; i < V1.rows(); i++) {
std::vector<double> tmp;
for (int j = 0; j < V1.cols(); j++) {
double x = V1(i, j);
tmp.push_back(x);
}
V.push_back(tmp);
}
for (int i = 0; i < F1.rows(); i++) {
std::vector<int> tmp;
for (int j = 0; j < F1.cols(); j++) {
int x = F1(i, j);
tmp.push_back(x);
}
F.push_back(tmp);
}
return true;
}
I modified the original code to read stl file:
// original
srcMesh.fpath = user_provided_meshes ? argv[1] : DATA_DIR "/cube.obj";
bool srcMeshLoaded = igl::read_triangle_mesh(srcMesh.fpath, srcMesh.V, srcMesh.F);
// my modified
srcMesh.fpath = user_provided_meshes ? argv[1] : DATA_DIR "/test1.stl";
bool srcMeshLoaded = read_stl(srcMesh.fpath, srcMesh.V, srcMesh.F);
I think the above code for reading STL files should be right.
After that, I perform Boolean operations. When the mcDispatch function is called, its return value is -4
, and an error operator()(...) -> invalid source-mesh connectivity
is reported.
This problem also happened in #12 . But it didn't solve my problem. In #12 , you separated the skull into its connected components to then cut cranium with a plane. But in fact, I am quite confused about this piece. What rules do you divide according to?
And you said it is because your source mesh (which is likely the skull mesh) has more than one connected component. I don't really get it, can you explain the connection components a bit more, and how do i divide my stl file into individual connected components.
Here is my test file:
test_file.zip
Hi ! I don't know how to do that :
I take 2 real cubes, withs TexUV, and normals, not 8 vertex but 24, and i try to start playing with that library
i use triangles, so sizefaces are only filled with 3
mcDispatch -> -4
->mcDebugMessageCallback + mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true);
print me that :
MCUT[0:0000000000000000,API:ERROR:HIGH:52] Detected multiple connected components in mesh (N=6)
ok, so i understand that the error say that the 6 faces are independant, and it need to be only 1. but they are not (independent by index, joined by real 3D position)
how can i succeed ?
twoobjs.zip
As basic test I was trying to substract Sub0.obj from Box.obj.
I've tried with other files but without luck, btw I made them in Blender.
When mcut is built with multi-threading (which is off by default) the HelloWorld example segfaults. The other tutorials execute as expected. Do you have any insight as to why this program's inputs are causing this issue?
Thanks - great library by the way!
Hello! I have a question regarding mesh definition. Would it be a problem for the library with repeating vertices in input meshes?
In my situation there is such mesh description: Triangles -> Triangle -> Point -> floats. Meaning I do not know directly which points are repeating. However in your library it might not work if I just put everything with repetitions. Could you clarify this situation?
``Hello, I am looking for a robust Boolean library, I found it is a good choice, but there are some problems. For example, when I Intersection the next two OBJ's, crash occurs.
Assertion failed: 3rd/mcut/source/kernel.cpp, 3567 at '(int)intersection_test_ivtx_list.size() >= 2'
McutMesh mesh_src; mesh_src.Load(src);
McutMesh mesh_cut; mesh_cut.Load(cut);
if (!mesh_src.Available() || !mesh_cut.Available()) {
return nullptr;
}
const McFlags Flags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW;
auto dispatch_ret = ::mcDispatch(
context_,
MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_ENFORCE_GENERAL_POSITION | Flags,
&(mesh_src.vertices_[0]),
&(mesh_src.face_indices_[0]),
&(mesh_src.face_sizes_[0]),
(uint32_t)(mesh_src.vertices_.size() / 3),
(uint32_t)mesh_src.face_sizes_.size(),
&(mesh_cut.vertices_[0]),
&(mesh_cut.face_indices_[0]),
&(mesh_cut.face_sizes_[0]),
(uint32_t)(mesh_cut.vertices_.size() / 3),
(uint32_t)mesh_cut.face_sizes_.size());
if (MC_NO_ERROR != dispatch_ret) {
is_error_ = true;
return nullptr;
}
This causes not logical behaviour.
When providing two non-intersecting meshes to CSGBoolean with UNION flag, there is no result will be generated.
Hi, thanks again for the great library and sorry for asking such a basic question😂
According to the Results section of the tutorial - there are a wide variety of potential outputs (depending on the boolean method): however, I do not quite see how we can specify which of those outputs we want to get.
I suppose those are already all returned inside the connComps
when we query it like below:
uint32_t numConnComps;
std::vector<McConnectedComponent> connComps;
mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps);
connComps.resize(numConnComps);
mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL);
However, I am having difficulty differentiating which component is which. I saw some enums that seems to help differentiating between various components but I am not sure how to use them (also I am not sure whether it's implementation detail or query parameters).
typedef enum McFragmentLocation {
MC_FRAGMENT_LOCATION_ABOVE = 1 << 0, /**< Fragment is located above the cut-mesh. */
MC_FRAGMENT_LOCATION_BELOW = 1 << 1, /**< Fragment is located below the cut-mesh. */
MC_FRAGMENT_LOCATION_UNDEFINED = 1 << 2, /**< Fragment is located neither above nor below the cut-mesh. That is, it was produced due to a partial cut intersection. */
MC_FRAGMENT_LOCATION_ALL = 0xFFFFFFFF /**< Wildcard (match all) . */
} McFragmentLocation;
In short, the question is, given any connComps, e.g. connComps[0]
- how do I know which boolean operation is it resulted from?
Also, I don't know why😅, I can't seem to find the definition for McConnectedComponent
, all I can find is below - is this some kind of C++ magic🥲:
typedef struct McConnectedComponent_T* McConnectedComponent;
Thanks!
TextureCoordinates instance running abnormally in MCUT V1.2.0.
TextureCoordinates instance can run normally in MCUT V1.1.0.
This repository contains modified code from CDT library in internal/cdt.
CDT is distributed under MPL-2 license and it is possible to use it in the GPL project.
The current usage however is not complying with MPL-2.0.
To fix this I suggest:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
LICENSE
file into internal/cdt
folderOptionally, it would be nice to have an attribution and clarification that some files are dual-licensed.
The text could be:
This software is based part on CDT (C++ library for constrained Delaunay triangulation):
https://github.com/artem-ogre/CDT
Copyright © 2019 Leica Geosystems Technology AB
Copyright © The CDT Contributors
Files that were originally under the MPL-2.0 are dual licensed under the MPL-2.0 and the GNU General Public License (GPL) licenses.
Please also note that even commercial users must comply with the license if they introduce further modifications to these files or distribute binaries (see Q8 in the MPL-2.0 FAQ).
I crashed when I tried to partially slice the output from the previous partially slice.
mcflags:
err = mcDispatch(
context,
MC_DISPATCH_VERTEX_ARRAY_DOUBLE
| MC_DISPATCH_ENFORCE_GENERAL_POSITION
| MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE,
triangulated output:
MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION
crash info:
mcutd.dll!mcut::mesh_t::add_face(const std::vector<mcut::vertex_descriptor_t,std::allocatormcut::vertex_descriptor_t> & vi) 行 545 C++
mcutd.dll!indexArrayMeshToHalfedgeMesh::__l31::(std::_Vector_const_iterator<std::_Vector_val<std::Simple_types>> block_start, std::_Vector_const_iterator<std::Vector_val<std::Simple_types>> block_end) 行 534 C++
mcutd.dll!indexArrayMeshToHalfedgeMesh(std::unique_ptr<McDispatchContextInternal,std::default_delete> & ctxtPtr, mcut::mesh_t & halfedgeMesh, double & bboxDiagonal, const void * pVertices, const unsigned int * pFaceIndices, const unsigned int * pFaceSizes, const unsigned int numVertices, const unsigned int numFaces, const mcut::math::vec3 * perturbation) 行 578 C++
mcutd.dll!mcDispatch(McContext_T * context, unsigned int dispatchFlags, const void * pSrcMeshVertices, const unsigned int * pSrcMeshFaceIndices, const unsigned int * pSrcMeshFaceSizes, unsigned int numSrcMeshVertices, unsigned int numSrcMeshFaces, const void * pCutMeshVertices, const unsigned int * pCutMeshFaceIndices, const unsigned int * pCutMeshFaceSizes, unsigned int numCutMeshVertices, unsigned int numCutMeshFaces) 行 2530 C++
I tried cutting using Basiccmdlineapp.exe and encountered a similar problem.
Attached are the relevant information and cutting documents
data.zip
。
C:\workspace\mcut\build\bin\Release>CSGBoolean.exe jaw0.obj tooth16.obj -ds
NOTE: using user provided meshes meshes
Warning: readOBJ() ignored non-comment line 4:
o mcut-jaw-0
source mesh:
vertices=92003
faces=180952
Warning: readOBJ() ignored non-comment line 4:
o mcut-tooth-16
cut mesh:
vertices=12049
faces=24094
Inputs:
Shape A = jaw0.obj'.
Shape B = 'tooth16.obj'
compute A_NOT_B
NOTE: MCUT is copyrighted and may not be sold or included in commercial products without a license.
NOTE: MCUT is copyrighted and may not be sold or included in commercial products without a license.
context_t::prepare_and_submit_API_task::<lambda_4f23217e9abd696bd485e1e67aa5af29>::operator ()(...) -> Floating-polygon partitioning step could not find a usable fpSegment (EventID=00000000000DECB0)
MCUT error: err == MC_NO_ERROR
Hi! I am trying to run CSGBoolean.cpp tutorial project. I am getting below error:
==== Error =======
NOTE: using default meshes
read .obj file: D:/mcut/tutorials/CSGBoolean/data/cube.obj
14 positions
0 normals
0 texture-coords
10 face(s)
44 face indices
error: have 5 vertices when there should be =4
============
I tried changing cube.obj file. But still getting this error. What can Be the cause?
In my project, I also used the open source library curaEngine. I used this open source library to import stl files for slicing and other operations without encountering any problems. But when I converted the grid model in curaEngine to mcut for Boolean operations, mcDispatch reported the error "An invalid value has been passed to the API." This passage was translated by Google. I don’t understand English. Please forgive me for any grammatical errors.
void CURAMesh2CutMes(cura::Mesh& CMesh, InputMesh &cutMesh) { cutMesh.vertexCoordsArray = new std::vector<float>(CMesh.vertices.size() * 3); cutMesh.faceIndicesArray = new std::vector<uint32_t>(CMesh.faces.size() * 3); cutMesh.faceSizesArray = new std::vector<uint32_t>(CMesh.faces.size(), 3); for (size_t vertIndex = 0; vertIndex < CMesh.vertices.size(); vertIndex++) { cutMesh.vertexCoordsArray->at(vertIndex * 3 + 0) = (float)INT2MM(CMesh.vertices[vertIndex].p.x); cutMesh.vertexCoordsArray->at(vertIndex * 3 + 1) = (float)INT2MM(CMesh.vertices[vertIndex].p.y); cutMesh.vertexCoordsArray->at(vertIndex * 3 + 2) = (float)INT2MM(CMesh.vertices[vertIndex].p.z); } for (size_t meshindex = 0; meshindex < CMesh.faces.size(); meshindex++) { cutMesh.faceIndicesArray->at(meshindex * 3 + 0) = CMesh.faces[meshindex].vertex_index[0]; cutMesh.faceIndicesArray->at(meshindex * 3 + 1) = CMesh.faces[meshindex].vertex_index[1]; cutMesh.faceIndicesArray->at(meshindex * 3 + 2) = CMesh.faces[meshindex].vertex_index[2]; } }
I was looking at the tutorial:
however when I try to reference it in code I found this:
typedef enum McConnectedComponentData {
//MC_CONNECTED_COMPONENT_DATA_VERTEX_COUNT = (1 << 0), /**< Number of vertices. */
MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT = (1 << 1), /**< List of vertex coordinates as an array of 32 bit floating-point numbers. */
MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE = (1 << 2), /**< List of vertex coordinates as an array of 64 bit floating-point numbers. */
//MC_CONNECTED_COMPONENT_DATA_FACE_COUNT = (1 << 4), /**< Number of faces. */
MC_CONNECTED_COMPONENT_DATA_FACE = (1 << 5), /**< List of faces as an array of indices. */
I wonder why is MC_CONNECTED_COMPONENT_DATA_VERTEX_COUNT
commented out? Similarly, MC_CONNECTED_COMPONENT_DATA_FACE_COUNT
is commented out as well.
Perhaps I'm doing something wrong but I get strange results when trying to cut a simple box from a bigger box:
the cutter box is not supposed to cut all the way through but just below the surface, so I expect a cavity result.
However this is the result I get:
Attached stl results and a modified HelloWorld I used.
Thank you and sorry if my workflow is flawed.
I read STL file via "libigl STL read" but how can I do a proper cut because, when I read with STL file and convert Eigen matrix into vectors it can't cut it. After I convert the Eigen Matrix it still gives me error code "-4" and not do a cut until I convert them into obj via blender then it does do the cut.
My conversion snippet code is;
`
// V is "MatrixXd" and F is "MatrixXi"
for (int i = 0; i < V.rows(); ++i)
{
std::vector<double> v1;
//std::cout << i << " : " << V.row(i)(0) << " " << V.row(i)(1) << " " << V.row(i)(2) << "\n";
v1.push_back(V.row(i)(0));
v1.push_back(V.row(i)(1));
v1.push_back(V.row(i)(2));
// index 0 ---| -> [0]
// | -> [1]
// | -> [2]
srcMesh.mcutVertices.push_back(v1);
}
for (int i = 0; i < F.rows(); ++i)
{
std::vector<int> v1;
//std::cout << i << " : " << F.row(i)(0) << " " << F.row(i)(1) << " " << F.row(i)(2) << "\n";
v1.push_back(F.row(i)(0));
v1.push_back(F.row(i)(1));
v1.push_back(F.row(i)(2));
srcMesh.mcutFaces.push_back(v1);
}
// copy vertices
for (int i = 0; i < (int)srcMesh.mcutVertices.size(); ++i)
{
const std::vector<double>& v = srcMesh.mcutVertices[i];
my_assert(v.size() == 3);
srcMesh.vertexCoordsArray.push_back(v[0]);
srcMesh.vertexCoordsArray.push_back(v[1]);
srcMesh.vertexCoordsArray.push_back(v[2]);
}
// copy faces
for (int i = 0; i < (int)srcMesh.mcutFaces.size(); ++i)
{
const std::vector<int>& f = srcMesh.mcutFaces[i];
for (int j = 0; j < (int)f.size(); ++j)
{
srcMesh.faceIndicesArray.push_back(f[j]);
}
srcMesh.faceSizesArray.push_back((uint32_t)f.size());
}
`
Attached are two files that cause the memory to explode when using the CSGBoolean
tool to do an "A-B" operation.
Here is the invocation:
./CSGBoolean cur.off pill17.off -ds
I am trying to subtract a "pill" shape from a "cylinder" shape.
cylinder | pill | cylinder and pill |
---|---|---|
note that I'm trying to subtract the "pill" from the cylinder, so this picture is only showing the representation of them together for clarity
Here is a ZIP file with cur.off
and pill17.off
as listed in the above CSGBoolean
invocation:
There could well be a problem with my geometry but, as far as I can tell, it's fine. I'm trying to construct a column with groves in it by subtracting out "pill" shapes. When I take the base cylinder and subtract just the pill17.off
geometry, it works just fine. When I subtract off the pill shapes before trying to subtract pill17.off
, the memory usage explodes and quickly fills 8GB+.
Any suggestions on why this might be occurring would be welcome.
Good day!
I have the following error: mcut/source/frontend.cpp, 2932 at 'untraversed_adj_seam_vertex_count <= 1'
after running tutorial code QuerySeamVerticesSorted
. I am not sure what is going wrong. Files I used are attached below, note that I have changed their extension to upload.
Moreover, this problem occurs with original files too.
There is problem when combining simple model with touching faces.
Discovered that the CMake install code does not actually copy the output binary to the specified CMAKE_INSTALL_PREFIX location.
The variable name that is used doesn't actually exist in the CMake, so the install call doesn't happen.
Will add pull request to fix shortly.
Hello,
Using MC_CONNECTED_COMPONENT_DATA_FACE_MAP
, it is possible to map from output faces to the corresponding faces from the input meshes. I was wondering if it is possible to do the same thing with the triangulated faces ? That is, would it be possible to know, for each triangle of the output mesh, from which input face it originates ?
Thanks for your help !
I'm attempting to read in a mesh from the attached Duck.glb and then cut it with a box. When I run mcDispatch
I get an error complaining that Debugging invalid source-mesh connectivity
. I believe I've traced it back more specifically to this check in check_input_mesh
.
Detected multiple connected components in mesh (N=10)
I'm not clear on what this is telling me. One thought I had was to import the glb into Blender and merge vertices by distance, in case there were multiple disconnected components in the mesh. This did in fact remove some vertices, but I get the same error. Furthermore, I don't see obviously disconnected components in the model.
Any pointers for how to proceed would be much appreciated.
Hello! I am trying to do seam query from cut mesh result and interpret the results
Gratefully, there is an example from your tutorials. I have a question whether in output the seam polygon preserves its winding order? Meaning, can I understand by the order of vertices whether the path is a hole or a solid one?
Two of the same models will appear during the test
Assertion failed: 3rd/mcut/source/kernel.cpp, 3406 at '(int)intersection_test_ivtx_list.size() >= 2'
During operation, it is not very convenient to detect whether the input model is exactly the same.
Is there any good way to avoid this crash?
In the 3rd iteration over the connected components the line at 307:
status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes);
causes an exception in source/frontend.cpp at line 3414 and subsequently 3418 with the following message: 'internal_inputmesh_face_idx < cc_face_count'
I used the 'cube.obj' and 'plane.obj' from the VertexNormals.cpp tutorial. I commented out the asserts and it does seem to be a bandaid fix.
Thank you for acknowledging my message.
Hello,
I'm trying the example of CSG boolean operation on a large scale skull mesh. and It fails..
I would like to purchase a commercial license, but I would like to use it on large scale meshes..
Can you show an example with Cutting a plane with that mesh and also extracting some parts of mesh to mesh intersection ?
Can you also provide an example plane cut with that mesh ?
untitled.zip
Hi,
Thank you so much for this amazing library, the code is very well designed (very similar to CUDA APIs!) and the features are incredibly useful. I've tried out various of MCUT's features on a limited set of inputs, and they work as expected. However, I noticed that the log_msg
macro is used throughout the internal implementations with no quiet
mode or filtering option. Would it be possible to silence the logs, as outputting and flushing things to the console is problematic for performance and usability in other code bases?
Thank you so much again!
Thank you so much for sharing this great library!
I'm wondering if it can be used for checking self-intersection of a mesh.
Hello, I was trying to use mcut "CSGBoolean.cpp" operation in order to learn cutting but after the cut process complete I only wanna see "source mesh" not the "cut mesh", after "cut" process complete I both cutted area and cut mesh(depend on operation I can see different section cut mesh not entire cut mesh before cut) as well. Is there any way to separate them individually ?
Thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.