OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::MeshBoolean::mcut Namespace Reference

Classes

struct  McutMesh
struct  McutMeshDeleter

Typedefs

using McutMeshPtr = std::unique_ptr<McutMesh, McutMeshDeleter>

Functions

bool empty (const McutMesh &mesh)
void triangle_mesh_to_mcut (const TriangleMesh &src_mesh, McutMesh &srcMesh, const Transform3d &src_nm=Transform3d::Identity())
McutMeshPtr triangle_mesh_to_mcut (const indexed_triangle_set &M)
TriangleMesh mcut_to_triangle_mesh (const McutMesh &mcutmesh)
void merge_mcut_meshes (McutMesh &src, const McutMesh &cut)
MCAPI_ATTR void MCAPI_CALL mcDebugOutput (McDebugSource source, McDebugType type, unsigned int id, McDebugSeverity severity, size_t length, const char *message, const void *userParam)
bool do_boolean_single (McutMesh &srcMesh, const McutMesh &cutMesh, const std::string &boolean_opts)
void do_boolean (McutMesh &srcMesh, const McutMesh &cutMesh, const std::string &boolean_opts)
void make_boolean (const TriangleMesh &src_mesh, const TriangleMesh &cut_mesh, std::vector< TriangleMesh > &dst_mesh, const std::string &boolean_opts)

Class Documentation

◆ Slic3r::MeshBoolean::mcut::McutMesh

struct Slic3r::MeshBoolean::mcut::McutMesh
Collaboration diagram for Slic3r::MeshBoolean::mcut::McutMesh:
Class Members
vector< uint32_t > faceIndicesArray
vector< uint32_t > faceSizesArray
vector< double > vertexCoordsArray

Typedef Documentation

◆ McutMeshPtr

Function Documentation

◆ do_boolean()

void Slic3r::MeshBoolean::mcut::do_boolean ( McutMesh & srcMesh,
const McutMesh & cutMesh,
const std::string & boolean_opts )
943{
944 TriangleMesh tri_src = mcut_to_triangle_mesh(srcMesh);
945 std::vector<indexed_triangle_set> src_parts = its_split(tri_src.its);
946
947 TriangleMesh tri_cut = mcut_to_triangle_mesh(cutMesh);
948 std::vector<indexed_triangle_set> cut_parts = its_split(tri_cut.its);
949
950 if (src_parts.empty() && boolean_opts == "UNION") {
951 srcMesh = cutMesh;
952 return;
953 }
954 if(cut_parts.empty()) return;
955
956 // when src mesh has multiple connected components, mcut refuses to work.
957 // But we can force it to work by spliting the src mesh into disconnected components,
958 // and do booleans seperately, then merge all the results.
959 indexed_triangle_set all_its;
960 if (boolean_opts == "A_NOT_B") {
961 // Each cut can leave the source with several disconnected components, which mcut rejects
962 // in the next dispatch, so re-split after every cut part (e.g. each letter of a text).
963 std::vector<indexed_triangle_set> parts = std::move(src_parts);
964 for (size_t j = 0; j < cut_parts.size(); j++) {
965 auto cut_part = triangle_mesh_to_mcut(cut_parts[j]);
966 std::vector<indexed_triangle_set> next_parts;
967 for (indexed_triangle_set &part : parts) {
968 auto src_part = triangle_mesh_to_mcut(part);
969 if (do_boolean_single(*src_part, *cut_part, boolean_opts)) {
970 TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part);
971 std::vector<indexed_triangle_set> pieces = its_split(tri_part.its);
972 std::move(pieces.begin(), pieces.end(), std::back_inserter(next_parts));
973 } else
974 next_parts.emplace_back(std::move(part));
975 }
976 parts = std::move(next_parts);
977 }
978 for (const indexed_triangle_set &part : parts)
979 its_merge(all_its, part);
980 }
981 else if (boolean_opts == "UNION") {
982 for (size_t i = 0; i < src_parts.size(); i++) {
983 auto src_part = triangle_mesh_to_mcut(src_parts[i]);
984 for (size_t j = 0; j < cut_parts.size(); j++) {
985 auto cut_part = triangle_mesh_to_mcut(cut_parts[j]);
986 do_boolean_single(*src_part, *cut_part, boolean_opts);
987 }
988 TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part);
989 its_merge(all_its, tri_part.its);
990 }
991 }
992 else if (boolean_opts == "INTERSECTION") {
993 for (size_t i = 0; i < src_parts.size(); i++) {
994 for (size_t j = 0; j < cut_parts.size(); j++) {
995 auto src_part = triangle_mesh_to_mcut(src_parts[i]);
996 auto cut_part = triangle_mesh_to_mcut(cut_parts[j]);
997 bool success = do_boolean_single(*src_part, *cut_part, boolean_opts);
998 if (success) {
999 TriangleMesh tri_part = mcut_to_triangle_mesh(*src_part);
1000 its_merge(all_its, tri_part.its);
1001 }
1002 }
1003 }
1004 }
1005 srcMesh = *triangle_mesh_to_mcut(all_its);
1006}
Definition TriangleMesh.hpp:94
indexed_triangle_set its
Definition TriangleMesh.hpp:164
void triangle_mesh_to_mcut(const TriangleMesh &src_mesh, McutMesh &srcMesh, const Transform3d &src_nm=Transform3d::Identity())
Definition MeshBoolean.cpp:680
TriangleMesh mcut_to_triangle_mesh(const McutMesh &mcutmesh)
Definition MeshBoolean.cpp:714
bool do_boolean_single(McutMesh &srcMesh, const McutMesh &cutMesh, const std::string &boolean_opts)
Definition MeshBoolean.cpp:803
void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B)
Definition TriangleMesh.cpp:1448
void its_split(const Its &m, OutputIt out_it)
Definition MeshSplitImpl.hpp:143

References do_boolean_single(), Slic3r::TriangleMesh::its, Slic3r::its_merge(), Slic3r::its_split(), mcut_to_triangle_mesh(), and triangle_mesh_to_mcut().

Referenced by make_boolean(), and Slic3r::csg::detail_mcut::perform_csg().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_boolean_single()

bool Slic3r::MeshBoolean::mcut::do_boolean_single ( McutMesh & srcMesh,
const McutMesh & cutMesh,
const std::string & boolean_opts )
804{
805 // create context
806 McContext context = MC_NULL_HANDLE;
807 McResult err = mcCreateContext(&context, 0);
808 // add debug callback according to https://cutdigital.github.io/mcut.site/tutorials/debugging/
809 mcDebugMessageCallback(context, mcDebugOutput, nullptr);
810 mcDebugMessageControl(
811 context,
812 MC_DEBUG_SOURCE_ALL,
813 MC_DEBUG_TYPE_ERROR,
814 MC_DEBUG_SEVERITY_MEDIUM,
815 true);
816 // We can either let MCUT compute all possible meshes (including patches etc.), or we can
817 // constrain the library to compute exactly the boolean op mesh we want. This 'constrained' case
818 // is done with the following flags.
819 // NOTE#1: you can extend these flags by bitwise ORing with additional flags (see `McDispatchFlags' in mcut.h)
820 // NOTE#2: below order of columns MATTERS
821 const std::map<std::string, McFlags> booleanOpts = {
822 {"A_NOT_B", MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE},
823 {"B_NOT_A", MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW},
824 {"UNION", MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE},
825 {"INTERSECTION", MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW},
826 };
827
828 std::map<std::string, McFlags>::const_iterator it = booleanOpts.find(boolean_opts);
829 McFlags boolOpFlags = it->second;
830
831 if (srcMesh.vertexCoordsArray.empty() && (boolean_opts == "UNION" || boolean_opts == "B_NOT_A")) {
832 srcMesh = cutMesh;
833 mcReleaseContext(context);
834 return true;
835 }
836
837 err = mcDispatch(context,
838 MC_DISPATCH_VERTEX_ARRAY_DOUBLE | // vertices are in array of doubles
839 MC_DISPATCH_ENFORCE_GENERAL_POSITION | // perturb if necessary
840 boolOpFlags, // filter flags which specify the type of output we want
841 // source mesh
842 reinterpret_cast<const void *>(srcMesh.vertexCoordsArray.data()), reinterpret_cast<const uint32_t *>(srcMesh.faceIndicesArray.data()),
843 srcMesh.faceSizesArray.data(), static_cast<uint32_t>(srcMesh.vertexCoordsArray.size() / 3), static_cast<uint32_t>(srcMesh.faceSizesArray.size()),
844 // cut mesh
845 reinterpret_cast<const void *>(cutMesh.vertexCoordsArray.data()), cutMesh.faceIndicesArray.data(), cutMesh.faceSizesArray.data(),
846 static_cast<uint32_t>(cutMesh.vertexCoordsArray.size() / 3), static_cast<uint32_t>(cutMesh.faceSizesArray.size()));
847 if (err != MC_NO_ERROR) {
848 BOOST_LOG_TRIVIAL(debug) << "MCUT mcDispatch fails! err=" << err;
849 mcReleaseContext(context);
850 if (boolean_opts == "UNION") {
851 merge_mcut_meshes(srcMesh, cutMesh);
852 return true;
853 }
854 return false;
855 }
856
857 // query the number of available connected component
858 uint32_t numConnComps;
859 err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &numConnComps);
860 if (err != MC_NO_ERROR || numConnComps==0) {
861 BOOST_LOG_TRIVIAL(debug) << "MCUT mcGetConnectedComponents fails! err=" << err << ", numConnComps" << numConnComps;
862 mcReleaseContext(context);
863 if (numConnComps == 0 && boolean_opts == "UNION") {
864 merge_mcut_meshes(srcMesh, cutMesh);
865 return true;
866 }
867 return false;
868 }
869
870 std::vector<McConnectedComponent> connectedComponents(numConnComps, MC_NULL_HANDLE);
871 err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (uint32_t) connectedComponents.size(), connectedComponents.data(), NULL);
872
873 McutMesh outMesh;
874 int N_vertices = 0;
875 // traversal of all connected components
876 for (int n = 0; n < numConnComps; ++n) {
877 // query the data of each connected component from MCUT
878 McConnectedComponent connComp = connectedComponents[n];
879
880 // query the vertices
881 McSize numBytes = 0;
882 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes);
883 uint32_t ccVertexCount = (uint32_t) (numBytes / (sizeof(double) * 3));
884 std::vector<double> ccVertices((uint64_t) ccVertexCount * 3u, 0);
885 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void *) ccVertices.data(), NULL);
886
887 // query the faces
888 numBytes = 0;
889 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes);
890 std::vector<uint32_t> ccFaceIndices(numBytes / sizeof(uint32_t), 0);
891 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccFaceIndices.data(), NULL);
892 std::vector<uint32_t> faceSizes(ccFaceIndices.size() / 3, 3);
893
894 const uint32_t ccFaceCount = static_cast<uint32_t>(faceSizes.size());
895
896 // Here we show, how to know when connected components, pertain particular boolean operations.
897 McPatchLocation patchLocation = (McPatchLocation) 0;
898 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL);
899
900 McFragmentLocation fragmentLocation = (McFragmentLocation) 0;
901 err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL);
902
903 outMesh.vertexCoordsArray.insert(outMesh.vertexCoordsArray.end(), ccVertices.begin(), ccVertices.end());
904
905 // add offset to face index
906 for (size_t i = 0; i < ccFaceIndices.size(); i++) {
907 ccFaceIndices[i] += N_vertices;
908 }
909
910 int faceVertexOffsetBase = 0;
911
912 // for each face in CC
913 std::vector<Vec3i32> faces(ccFaceCount);
914 for (uint32_t f = 0; f < ccFaceCount; ++f) {
915 bool reverseWindingOrder = (fragmentLocation == MC_FRAGMENT_LOCATION_BELOW) && (patchLocation == MC_PATCH_LOCATION_OUTSIDE);
916 int faceSize = faceSizes.at(f);
917 if (reverseWindingOrder) {
918 std::vector<uint32_t> faceIndex(faceSize);
919 // for each vertex in face
920 for (int v = faceSize - 1; v >= 0; v--) { faceIndex[v] = ccFaceIndices[(uint64_t) faceVertexOffsetBase + v]; }
921 std::copy(faceIndex.begin(), faceIndex.end(), ccFaceIndices.begin() + faceVertexOffsetBase);
922 }
923 faceVertexOffsetBase += faceSize;
924 }
925
926 outMesh.faceIndicesArray.insert(outMesh.faceIndicesArray.end(), ccFaceIndices.begin(), ccFaceIndices.end());
927 outMesh.faceSizesArray.insert(outMesh.faceSizesArray.end(), faceSizes.begin(), faceSizes.end());
928
929 N_vertices += ccVertexCount;
930 }
931
932 // free connected component data
933 err = mcReleaseConnectedComponents(context, 0, NULL);
934 // destroy context
935 err = mcReleaseContext(context);
936
937 srcMesh = outMesh;
938
939 return true;
940}
std::vector< uint32_t > faceSizesArray
Definition MeshBoolean.cpp:673
MCAPI_ATTR void MCAPI_CALL mcDebugOutput(McDebugSource source, McDebugType type, unsigned int id, McDebugSeverity severity, size_t length, const char *message, const void *userParam)
Definition MeshBoolean.cpp:755
std::vector< double > vertexCoordsArray
Definition MeshBoolean.cpp:675
void merge_mcut_meshes(McutMesh &src, const McutMesh &cut)
Definition MeshBoolean.cpp:746
std::vector< uint32_t > faceIndicesArray
Definition MeshBoolean.cpp:674
Definition MeshBoolean.cpp:671
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124

References Slic3r::f(), Slic3r::MeshBoolean::mcut::McutMesh::faceIndicesArray, Slic3r::MeshBoolean::mcut::McutMesh::faceSizesArray, mcDebugOutput(), merge_mcut_meshes(), and Slic3r::MeshBoolean::mcut::McutMesh::vertexCoordsArray.

Referenced by do_boolean().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty()

bool Slic3r::MeshBoolean::mcut::empty ( const McutMesh & mesh)
679{ return mesh.vertexCoordsArray.empty() || mesh.faceIndicesArray.empty(); }

References Slic3r::MeshBoolean::mcut::McutMesh::faceIndicesArray, and Slic3r::MeshBoolean::mcut::McutMesh::vertexCoordsArray.

Referenced by Slic3r::csg::check_csgmesh_booleans().

Here is the caller graph for this function:

◆ make_boolean()

void Slic3r::MeshBoolean::mcut::make_boolean ( const TriangleMesh & src_mesh,
const TriangleMesh & cut_mesh,
std::vector< TriangleMesh > & dst_mesh,
const std::string & boolean_opts )
1009{
1010 McutMesh srcMesh, cutMesh;
1011 triangle_mesh_to_mcut(src_mesh, srcMesh);
1013 //dst_mesh = make_boolean(srcMesh, cutMesh, boolean_opts);
1014 do_boolean(srcMesh, cutMesh, boolean_opts);
1015 TriangleMesh tri_src = mcut_to_triangle_mesh(srcMesh);
1016 if (!tri_src.empty())
1017 dst_mesh.push_back(std::move(tri_src));
1018}
bool empty() const
Definition TriangleMesh.hpp:146
void do_boolean(McutMesh &srcMesh, const McutMesh &cutMesh, const std::string &boolean_opts)
Definition MeshBoolean.cpp:942
void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, indexed_triangle_set *lower, bool triangulate_caps)
Definition TriangleMeshSlicer.cpp:2462

References Slic3r::cut_mesh(), do_boolean(), Slic3r::TriangleMesh::empty(), mcut_to_triangle_mesh(), and triangle_mesh_to_mcut().

Referenced by Slic3r::ModelObject::make_boolean(), and Slic3r::GUI::GLGizmoMeshBoolean::on_render_input_window().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mcDebugOutput()

MCAPI_ATTR void MCAPI_CALL Slic3r::MeshBoolean::mcut::mcDebugOutput ( McDebugSource source,
McDebugType type,
unsigned int id,
McDebugSeverity severity,
size_t length,
const char * message,
const void * userParam )
762{
763 BOOST_LOG_TRIVIAL(debug)<<Slic3r::format("mcut mcDebugOutput message ( %d ): %s ", id, message);
764
765 switch (source) {
766 case MC_DEBUG_SOURCE_API:
767 BOOST_LOG_TRIVIAL(debug)<<("Source: API");
768 break;
769 case MC_DEBUG_SOURCE_KERNEL:
770 BOOST_LOG_TRIVIAL(debug)<<("Source: Kernel");
771 break;
772 }
773
774 switch (type) {
775 case MC_DEBUG_TYPE_ERROR:
776 BOOST_LOG_TRIVIAL(debug)<<("Type: Error");
777 break;
778 case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
779 BOOST_LOG_TRIVIAL(debug)<<("Type: Deprecated Behaviour");
780 break;
781 case MC_DEBUG_TYPE_OTHER:
782 BOOST_LOG_TRIVIAL(debug)<<("Type: Other");
783 break;
784 }
785
786 switch (severity) {
787 case MC_DEBUG_SEVERITY_HIGH:
788 BOOST_LOG_TRIVIAL(debug)<<("Severity: high");
789 break;
790 case MC_DEBUG_SEVERITY_MEDIUM:
791 BOOST_LOG_TRIVIAL(debug)<<("Severity: medium");
792 break;
793 case MC_DEBUG_SEVERITY_LOW:
794 BOOST_LOG_TRIVIAL(debug)<<("Severity: low");
795 break;
796 case MC_DEBUG_SEVERITY_NOTIFICATION:
797 BOOST_LOG_TRIVIAL(debug)<<("Severity: notification");
798 break;
799 }
800}
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:45

References Slic3r::format(), and Slic3r::length().

Referenced by do_boolean_single().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mcut_to_triangle_mesh()

TriangleMesh Slic3r::MeshBoolean::mcut::mcut_to_triangle_mesh ( const McutMesh & mcutmesh)
715{
716 uint32_t ccVertexCount = mcutmesh.vertexCoordsArray.size() / 3;
717 auto &ccVertices = mcutmesh.vertexCoordsArray;
718 auto &ccFaceIndices = mcutmesh.faceIndicesArray;
719 auto &faceSizes = mcutmesh.faceSizesArray;
720 uint32_t ccFaceCount = faceSizes.size();
721 // rearrange vertices/faces and save into result mesh
722 std::vector<Vec3f> vertices(ccVertexCount);
723 for (uint32_t i = 0; i < ccVertexCount; i++) {
724 vertices[i][0] = (float) ccVertices[(uint64_t) i * 3 + 0];
725 vertices[i][1] = (float) ccVertices[(uint64_t) i * 3 + 1];
726 vertices[i][2] = (float) ccVertices[(uint64_t) i * 3 + 2];
727 }
728
729 // output faces
730 int faceVertexOffsetBase = 0;
731
732 // for each face in CC
733 std::vector<Vec3i32> faces(ccFaceCount);
734 for (uint32_t f = 0; f < ccFaceCount; ++f) {
735 int faceSize = faceSizes.at(f);
736
737 // for each vertex in face
738 for (int v = 0; v < faceSize; v++) { faces[f][v] = ccFaceIndices[(uint64_t) faceVertexOffsetBase + v]; }
739 faceVertexOffsetBase += faceSize;
740 }
741
742 TriangleMesh out(vertices, faces);
743 return out;
744}

References Slic3r::f(), Slic3r::MeshBoolean::mcut::McutMesh::faceIndicesArray, Slic3r::MeshBoolean::mcut::McutMesh::faceSizesArray, and Slic3r::MeshBoolean::mcut::McutMesh::vertexCoordsArray.

Referenced by Slic3r::GUI::Plater::combine_mesh_fff(), do_boolean(), make_boolean(), and merge_mcut_meshes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ merge_mcut_meshes()

void Slic3r::MeshBoolean::mcut::merge_mcut_meshes ( McutMesh & src,
const McutMesh & cut )
746 {
747 indexed_triangle_set all_its;
748 TriangleMesh tri_src = mcut_to_triangle_mesh(src);
749 TriangleMesh tri_cut = mcut_to_triangle_mesh(cut);
750 its_merge(all_its, tri_src.its);
751 its_merge(all_its, tri_cut.its);
752 src = *triangle_mesh_to_mcut(all_its);
753 }

References Slic3r::TriangleMesh::its, Slic3r::its_merge(), mcut_to_triangle_mesh(), and triangle_mesh_to_mcut().

Referenced by do_boolean_single().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ triangle_mesh_to_mcut() [1/2]

McutMeshPtr Slic3r::MeshBoolean::mcut::triangle_mesh_to_mcut ( const indexed_triangle_set & M)
707{
708 std::unique_ptr<McutMesh, McutMeshDeleter> out(new McutMesh{});
709 TriangleMesh trimesh(M);
710 triangle_mesh_to_mcut(trimesh, *out.get());
711 return out;
712}

References triangle_mesh_to_mcut().

Here is the call graph for this function:

◆ triangle_mesh_to_mcut() [2/2]

void Slic3r::MeshBoolean::mcut::triangle_mesh_to_mcut ( const TriangleMesh & src_mesh,
McutMesh & srcMesh,
const Transform3d & src_nm = Transform3d::Identity() )
681{
682 // vertices precision convention and copy
683 srcMesh.vertexCoordsArray.reserve(src_mesh.its.vertices.size() * 3);
684 for (int i = 0; i < src_mesh.its.vertices.size(); ++i) {
685 const Vec3d v = src_nm * src_mesh.its.vertices[i].cast<double>();
686 srcMesh.vertexCoordsArray.push_back(v[0]);
687 srcMesh.vertexCoordsArray.push_back(v[1]);
688 srcMesh.vertexCoordsArray.push_back(v[2]);
689 }
690
691 // faces copy
692 srcMesh.faceIndicesArray.reserve(src_mesh.its.indices.size() * 3);
693 srcMesh.faceSizesArray.reserve(src_mesh.its.indices.size());
694 for (int i = 0; i < src_mesh.its.indices.size(); ++i) {
695 const int &f0 = src_mesh.its.indices[i][0];
696 const int &f1 = src_mesh.its.indices[i][1];
697 const int &f2 = src_mesh.its.indices[i][2];
698 srcMesh.faceIndicesArray.push_back(f0);
699 srcMesh.faceIndicesArray.push_back(f1);
700 srcMesh.faceIndicesArray.push_back(f2);
701
702 srcMesh.faceSizesArray.push_back((uint32_t) 3);
703 }
704}
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68

References Slic3r::MeshBoolean::mcut::McutMesh::faceIndicesArray, Slic3r::MeshBoolean::mcut::McutMesh::faceSizesArray, Slic3r::TriangleMesh::its, and Slic3r::MeshBoolean::mcut::McutMesh::vertexCoordsArray.

Referenced by Slic3r::csg::check_csgmesh_booleans(), do_boolean(), Slic3r::csg::get_mcutmesh(), make_boolean(), merge_mcut_meshes(), Slic3r::csg::perform_csgmesh_booleans_mcut(), Slic3r::csg::perform_csgmesh_booleans_mcut(), and triangle_mesh_to_mcut().

Here is the caller graph for this function: