From a708d142823f6dc14f5bec30e61c0e9ba852a5a6 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Tue, 14 Nov 2023 17:44:31 +0000 Subject: [PATCH 01/23] update and clean up AdjacentFaces tutorial --- CMakeLists.txt | 86 +-- tutorials/AdjacentFaces/AdjacentFaces.cpp | 837 ++++++++++++++-------- tutorials/AdjacentFaces/CMakeLists.txt | 29 - tutorials/CMakeLists.txt | 67 +- tutorials/HelloWorld/CMakeLists.txt | 24 - tutorials/HelloWorld/HelloWorld.cpp | 440 ++++++------ 6 files changed, 783 insertions(+), 700 deletions(-) delete mode 100644 tutorials/AdjacentFaces/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 41a0a39..97c6537 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,4 @@ # -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# -############################################################################################ -# # You can configure MCUT with the following CMake options: # # MCUT_BUILD_AS_SHARED_LIB [default=ON] - Build MCUT as a shared/dynamic library (.so/.dll). @@ -233,57 +211,29 @@ if(${MCUT_BUILD_TESTS} OR ${MCUT_BUILD_TUTORIALS}) endif() FetchContent_Populate( - libigl - GIT_REPOSITORY https://github.com/libigl/libigl.git - GIT_TAG v2.3.0 - GIT_PROGRESS TRUE + mio + GIT_REPOSITORY https://github.com/cutdigital/mio.git + GIT_TAG main ) - #set(libigl_include_dir ${CMAKE_BINARY_DIR}/libigl-src/include) - set(libigl_include_dir ${libigl_SOURCE_DIR}/include) - - set(LIBIGL_EIGEN_VERSION 3.3.7 CACHE STRING "Default version of Eigen used by libigl.") - - # used by tests & tutorials - #download_project(PROJ eigen - # GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - # GIT_TAG ${LIBIGL_EIGEN_VERSION} - # ${UPDATE_DISCONNECTED_IF_AVAILABLE} - #) - FetchContent_Declare( - eigen - GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git - GIT_TAG ${LIBIGL_EIGEN_VERSION} - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - ) + set(mio_include_dir ${mio_SOURCE_DIR}/include) - set(EIGEN_BUILD_DOC OFF) - # note: To disable eigen tests, - # you should put this code in a add_subdirectory to avoid to change - # BUILD_TESTING for your own project too since variables are directory - # scoped - set(BUILD_TESTING OFF) - set(EIGEN_BUILD_PKGCONFIG OFF) - set( OFF) - FetchContent_MakeAvailable(eigen) - - #set(eigen_include_dir ${CMAKE_BINARY_DIR}/eigen-src) - set(eigen_include_dir ${eigen_SOURCE_DIR}) -endif() + add_subdirectory(${mio_SOURCE_DIR}) -# -# tests -# -if(MCUT_BUILD_TESTS) - add_subdirectory(tests) -endif() + # + # tests + # + if(MCUT_BUILD_TESTS) + #add_subdirectory(tests) + endif() + + # + # tutorials + # + if(MCUT_BUILD_TUTORIALS) + add_subdirectory(tutorials) + endif() -# -# tutorials -# -if(MCUT_BUILD_TUTORIALS) - add_subdirectory(tutorials) endif() # diff --git a/tutorials/AdjacentFaces/AdjacentFaces.cpp b/tutorials/AdjacentFaces/AdjacentFaces.cpp index 4d2916a..1370138 100644 --- a/tutorials/AdjacentFaces/AdjacentFaces.cpp +++ b/tutorials/AdjacentFaces/AdjacentFaces.cpp @@ -1,40 +1,44 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdjacentFaces.cpp + * + * \brief: + * This tutorial shows how to query adjacent faces of any face of a connected + * component. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: + * The tutorial is presented in the context of merging neighbouring faces of a + * connected component that share some property (e.g. an ID tag), where this + * property is _derived_ from origin/birth faces. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -This tutorial shows how to query adjacent faces of any face of a connected component. - -The tutorial is presented in the context of merging neighouring faces of a -connected component that share some property (e.g. an ID tag), where -this property is _derived_ from origin/birth faces. - -A group of faces that share the property and define a connected patch will be merged -into a single face. This is useful in situations where e.g. one has to triangulate the -faces of an input mesh before cutting and then recover the untriangulated faces afterwards. - -We assume that all faces to be merged are coplanar. -*/ + * A group of faces that share the property and define a connected patch will + * be merged into a single face. This is useful in situations where e.g. one + * has to triangulate the faces of an input mesh before cutting and then + * recover the untriangulated faces afterwards. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include @@ -44,38 +48,105 @@ We assume that all faces to be merged are coplanar. #include #include -// libigl dependencies -#include -#include - -#define my_assert(cond) if(!(cond)){fprintf(stderr, "MCUT error: %s\n", #cond );std::exit(1);} - -void writeOBJ( - const std::string& path, - const double* ccVertices, - const int ccVertexCount, - const uint32_t* ccFaceIndices, - const uint32_t* faceSizes, - const uint32_t ccFaceCount); -void readOBJ(const std::string& path, std::vector& V, std::vector& F, std::vector& Fsizes); -uint32_t getAdjFacesBaseOffset(const uint32_t faceIdx, const uint32_t* faceAdjFacesSizes); -uint32_t getFaceIndicesBaseOffset(const uint32_t faceIdx, const uint32_t* faceSizes); +McUint32 getAdjFacesBaseOffset(const McUint32 faceIdx, const McUint32* faceAdjFacesSizes); + +McUint32 getFaceIndicesBaseOffset(const McUint32 faceIdx, const McUint32* faceSizes); + void mergeAdjacentMeshFacesByProperty( - std::vector& meshFaceIndicesOUT, - std::vector& meshFaceSizesOUT, - const std::vector& meshFaces, - const std::vector& meshFaceSizes, - const std::vector& meshFaceAdjFace, - const std::vector& meshFaceAdjFaceSizes, - const std::map>& tagToMeshFace, - const std::map& meshFaceToTag); - -int main() + std::vector& meshFaceIndicesOUT, + std::vector& meshFaceSizesOUT, + const std::vector& meshFaces, + const std::vector& meshFaceSizes, + const std::vector& meshFaceAdjFace, + const std::vector& meshFaceAdjFaceSizes, + const std::map>& tagToMeshFace, + const std::map& meshFaceToTag); + +McInt32 main() { - std::vector srcMeshVertices; - std::vector srcMeshFaceIndices; - std::vector srcMeshFaceSizes; - readOBJ(DATA_DIR "/triangulatedGrid4x4.obj", srcMeshVertices, srcMeshFaceIndices, srcMeshFaceSizes); + // structure for our source- and cut-mesh that are loaded from file + struct MeshArrays + { + McDouble* pVertices = NULL; + McDouble* pNormals = NULL; + McDouble* pTexCoords = NULL; + + McUint32* pFaceSizes = NULL; + McUint32* pFaceVertexIndices = NULL; + McUint32* pFaceVertexTexCoordIndices = NULL; + McUint32* pFaceVertexNormalIndices = NULL; + + McUint32 numVertices = 0; + McUint32 numNormals = 0; + McUint32 numTexCoords = 0; + McUint32 numFaces = 0; + + ~MeshArrays() + { + if(pVertices) + { + free(pVertices); + pVertices = nullptr; + } + + if(pNormals) + { + free(pNormals); + pNormals = nullptr; + } + + if(pTexCoords) + { + free(pTexCoords); + pTexCoords = nullptr; + } + + if(pFaceSizes) + { + free(pFaceSizes); + pFaceSizes = nullptr; + } + + if(pFaceVertexIndices) + { + free(pFaceVertexIndices); + pFaceVertexIndices = nullptr; + } + + if(pFaceVertexTexCoordIndices) + { + free(pFaceVertexTexCoordIndices); + pFaceVertexTexCoordIndices = nullptr; + } + + if(pFaceVertexNormalIndices) + { + free(pFaceVertexNormalIndices); + pFaceVertexNormalIndices = nullptr; + } + + numVertices = 0; + numNormals = 0; + numTexCoords = 0; + numFaces = 0; + } + } srcMesh, cutMesh; + + // + // read-in the source-mesh from file + // + mioReadOBJ(DATA_DIR "/triangulatedGrid4x4.obj", + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); // A map denoting the adjacent faces of the source mesh that share some property // (a tag/number) that we will use to merge adjacent faces. @@ -83,7 +154,7 @@ int main() // Faces in each group are merged into one face/polygon. // Groups which are adjacent and share a tag are also merged. - std::map srcMeshFaceToTag = { + std::map srcMeshFaceToTag = { // Bottom-right quadrant faces // group 0 { 0, 0 }, @@ -122,73 +193,124 @@ int main() { 17, 0xBEEF } }; - std::map> tagToSrcMeshFaces; - for (std::map::const_iterator i = srcMeshFaceToTag.cbegin(); i != srcMeshFaceToTag.cend(); ++i) { + std::map> tagToSrcMeshFaces; + for (std::map::const_iterator i = srcMeshFaceToTag.cbegin(); i != srcMeshFaceToTag.cend(); ++i) { tagToSrcMeshFaces[i->second].push_back(i->first); } - std::vector cutMeshVertices; - std::vector cutMeshFaceIndices; - std::vector cutMeshFaceSizes; - readOBJ(DATA_DIR "/quad.obj", cutMeshVertices, cutMeshFaceIndices, cutMeshFaceSizes); - + // + // read-in the cut-mesh from file + // + + mioReadOBJ(DATA_DIR "/quad.obj", + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); + + // // create a context - // ------------------- + // + McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); - my_assert(err == MC_NO_ERROR); - // do the cutting (boolean ops) - // ------------------------------- + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); + + if (status != MC_NO_ERROR) + { + fprintf(stderr, "mcCreateContext failed (%d)\n", (McInt32)status); + exit(1); + } + + // + // do the cutting + // - err = mcDispatch( + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_FACE_MAP, // source mesh - reinterpret_cast(srcMeshVertices.data()), - reinterpret_cast(srcMeshFaceIndices.data()), - srcMeshFaceSizes.data(), - static_cast(srcMeshVertices.size() / 3), - static_cast(srcMeshFaceSizes.size()), + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, // cut mesh - reinterpret_cast(cutMeshVertices.data()), - reinterpret_cast(cutMeshFaceIndices.data()), - cutMeshFaceSizes.data(), - static_cast(cutMeshVertices.size() / 3), - static_cast(cutMeshFaceSizes.size())); - - my_assert(err == MC_NO_ERROR); - - // query the number of available connected component - // -------------------------------------------------- - uint32_t numConnComps; - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); - my_assert(err == MC_NO_ERROR); - - printf("connected components: %d\n", (int)numConnComps); - - if (numConnComps == 0) { + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, "mcDispatch failed (%d)\n", (McInt32)status); + exit(1); + } + + // + // query the number of available connected components + // + + McUint32 connectedComponentCount = 0; + + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", (McInt32)status); + exit(1); + } + + printf("connected components: %d\n", (McInt32)connectedComponentCount); + + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - my_assert(numConnComps > 0); - - std::vector connectedComponents(numConnComps, MC_NULL_HANDLE); - connectedComponents.resize(numConnComps); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connectedComponents.size(), connectedComponents.data(), NULL); - - my_assert(err == MC_NO_ERROR); - - // query the data of each connected component from MCUT - // ------------------------------------------------------- + std::vector connectedComponents(connectedComponentCount, MC_NULL_HANDLE); + connectedComponents.resize(connectedComponentCount); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", + (McInt32)status); + exit(1); + } + + // + // query the data of each connected component + // + + for (McInt32 c = 0; c < (McInt32)connectedComponentCount; ++c) { + + McConnectedComponent cc = connectedComponents[c]; + + // + // type + // + McConnectedComponentType type; - for (int c = 0; c < (int)numConnComps; ++c) { - McConnectedComponent connComp = connectedComponents[c]; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &type, NULL); - McConnectedComponentType type; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &type, NULL); - my_assert(err == MC_NO_ERROR); + if(status != MC_NO_ERROR) + { + fprintf( + stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_TYPE) failed (%d)\n", + (McInt32)status); + exit(1); + } if (!(type == MC_CONNECTED_COMPONENT_TYPE_INPUT || type == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT)) { // we only care about the input source mesh, and the "fragment" connected components @@ -196,103 +318,243 @@ int main() } if (type == MC_CONNECTED_COMPONENT_TYPE_INPUT) { + McInputOrigin origin; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &origin, NULL); - my_assert(err == MC_NO_ERROR); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &origin, NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_ORIGIN)" + "failed (%d)\n", + (McInt32)status); + exit(1); + } + if (origin == MC_INPUT_ORIGIN_CUTMESH) { continue; // we only care about the source mesh } } - // query the vertices - // ---------------------- + // + // vertices + // McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); - std::vector ccVertices((McSize)ccVertexCount * 3u, 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (%d)\n", (McInt32)status); + exit(1); + } + + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices((McSize)ccVertexCount * 3u, 0); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (McVoid*)ccVertices.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + // + // faces + // - // query the faces - // ------------------- - - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face sizes - // ------------------------ numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceSizes(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + // + // face sizes + // - const uint32_t ccFaceCount = static_cast(ccFaceSizes.size()); + numBytes = 0; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + std::vector ccFaceSizes(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); { char buf[512]; sprintf(buf, OUTPUT_DIR "/cc%d.obj", c); - writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndices[0], &ccFaceSizes[0], ccFaceCount); + //writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndices[0], &ccFaceSizes[0], ccFaceCount); + + mioWriteOBJ(buf, + &ccVertices[0], + nullptr, + nullptr, + &ccFaceSizes[0], + &ccFaceIndices[0], + nullptr, + nullptr, + ccVertexCount, + 0, + 0, + ccFaceCount); } - // query the face map - // ------------------ - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); - my_assert(err == MC_NO_ERROR); + // + // face map + // - // query the face adjacency - // ------------------------ + numBytes = 0; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_MAP) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + std::vector ccFaceMap(numBytes / sizeof(McUint32), 0); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_MAP) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + // + // face adjacency info + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceAdjFaces(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE, numBytes, ccFaceAdjFaces.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face adjacency sizes - // ------------------------------- + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + std::vector ccFaceAdjFaces(numBytes / sizeof(McUint32), 0); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE, numBytes, ccFaceAdjFaces.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + // + // face adjacency sizes (number of adjacent faces per face) + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceAdjFacesSizes(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE, numBytes, ccFaceAdjFacesSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); - + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE, 0, NULL, &numBytes); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + std::vector ccFaceAdjFacesSizes(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE, numBytes, ccFaceAdjFacesSizes.data(), NULL); + + if(status != MC_NO_ERROR) + { + fprintf(stderr, + "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_ADJACENT_FACE_SIZE" + "SIZE) " + "failed (%d)\n", + (McInt32)status); + exit(1); + } + + // // resolve mapping between tags and CC faces + // + // NOTE: only those CC face whose origin face was tagged will themselves be tagged. - std::map> tagToCcFaces; - std::map ccFaceToTag; - - for (int ccFaceID = 0; ccFaceID < (int)ccFaceCount; ++ccFaceID) { - int imFaceID = ccFaceMap[ccFaceID]; - std::map::const_iterator srcMeshFaceToTagIter = srcMeshFaceToTag.find(imFaceID); + + std::map> tagToCcFaces; + std::map ccFaceToTag; + + for (McInt32 ccFaceID = 0; ccFaceID < (McInt32)ccFaceCount; ++ccFaceID) { + + McInt32 imFaceID = ccFaceMap[ccFaceID]; + std::map::const_iterator srcMeshFaceToTagIter = srcMeshFaceToTag.find(imFaceID); bool faceWasTagged = (srcMeshFaceToTagIter != srcMeshFaceToTag.cend()); if (faceWasTagged) { - const int tag = srcMeshFaceToTagIter->second; + const McInt32 tag = srcMeshFaceToTagIter->second; ccFaceToTag[ccFaceID] = tag; tagToCcFaces[tag].push_back(ccFaceID); } } - for (std::map::const_iterator i = srcMeshFaceToTag.cbegin(); i != srcMeshFaceToTag.cend(); ++i) { + for (std::map::const_iterator i = srcMeshFaceToTag.cbegin(); i != srcMeshFaceToTag.cend(); ++i) { tagToSrcMeshFaces[i->second].push_back(i->first); } - std::vector ccFaceIndicesMerged; - std::vector ccFaceSizesMerged; + std::vector ccFaceIndicesMerged; + std::vector ccFaceSizesMerged; mergeAdjacentMeshFacesByProperty( ccFaceIndicesMerged, @@ -308,159 +570,126 @@ int main() char buf[512]; sprintf(buf, OUTPUT_DIR "/cc%d-merged.obj", c); // NOTE: For the sake of simplicity, we keep unreferenced vertices. - writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndicesMerged[0], &ccFaceSizesMerged[0], (uint32_t)ccFaceSizesMerged.size()); + //writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndicesMerged[0], &ccFaceSizesMerged[0], (McUint32)ccFaceSizesMerged.size()); + + mioWriteOBJ(buf, + &ccVertices[0], + nullptr, + nullptr, + &ccFaceSizesMerged[0], + &ccFaceIndicesMerged[0], + nullptr, + nullptr, + ccVertexCount, + 0, + 0, + (McUint32)ccFaceSizesMerged.size()); } } + // // free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, (uint32_t)connectedComponents.size(), connectedComponents.data()); - my_assert(err == MC_NO_ERROR); + // - // destroy context - // ------------------ - err = mcReleaseContext(context); - - my_assert(err == MC_NO_ERROR); + status = mcReleaseConnectedComponents(context, (McUint32)connectedComponents.size(), connectedComponents.data()); - return 0; -} - -void writeOBJ( - const std::string& path, - const double* ccVertices, - const int ccVertexCount, - const uint32_t* ccFaceIndices, - const uint32_t* faceSizes, - const uint32_t ccFaceCount) -{ - printf("write file: %s\n", path.c_str()); - - std::ofstream file(path); - - // write vertices and normals - for (uint32_t i = 0; i < (uint32_t)ccVertexCount; ++i) { - double x = ccVertices[(McSize)i * 3 + 0]; - double y = ccVertices[(McSize)i * 3 + 1]; - double z = ccVertices[(McSize)i * 3 + 2]; - file << "v " << x << " " << y << " " << z << std::endl; - } + if(status != MC_NO_ERROR) + { + fprintf(stderr, "mcReleaseConnectedComponents failed (%d)\n", (McInt32)status); + exit(1); + } - int faceVertexOffsetBase = 0; - - // for each face in CC - for (uint32_t f = 0; f < ccFaceCount; ++f) { - - int faceSize = faceSizes[f]; - file << "f "; - // for each vertex in face - for (int v = 0; (v < faceSize); v++) { - const int ccVertexIdx = ccFaceIndices[(McSize)faceVertexOffsetBase + v]; - file << (ccVertexIdx + 1) << " "; - } // for (int v = 0; v < faceSize; ++v) { - file << std::endl; - - faceVertexOffsetBase += faceSize; - } -} - -void readOBJ(const std::string& path, std::vector& V, std::vector& F, std::vector& Fsizes) -{ - std::vector> V_; - std::vector> F_; - - igl::read_triangle_mesh(path, V_, F_); + // + // destroy context + // + + status = mcReleaseContext(context); - for (int i = 0; i < (int)V_.size(); ++i) { - V.push_back(V_[i][0]); - V.push_back(V_[i][1]); - V.push_back(V_[i][2]); - } + if(status != MC_NO_ERROR) + { + fprintf(stderr, "mcReleaseContext failed (%d)\n", (McInt32)status); + exit(1); + } - for (int i = 0; i < (int)F_.size(); ++i) { - F.push_back((uint32_t)F_[i][0]); - F.push_back((uint32_t)F_[i][1]); - F.push_back((uint32_t)F_[i][2]); - Fsizes.push_back(3); - } + return 0; } -uint32_t getAdjFacesBaseOffset(const uint32_t faceIdx, const uint32_t* faceAdjFacesSizes) +McUint32 getAdjFacesBaseOffset(const McUint32 faceIdx, const McUint32* faceAdjFacesSizes) { - uint32_t baseOffset = 0; - for (uint32_t f = 0; f < faceIdx; ++f) { + McUint32 baseOffset = 0; + for (McUint32 f = 0; f < faceIdx; ++f) { baseOffset += faceAdjFacesSizes[f]; } return baseOffset; } -uint32_t getFaceIndicesBaseOffset(const uint32_t faceIdx, const uint32_t* faceSizes) +McUint32 getFaceIndicesBaseOffset(const McUint32 faceIdx, const McUint32* faceSizes) { - uint32_t baseOffset = 0; - for (uint32_t f = 0; f < faceIdx; ++f) { + McUint32 baseOffset = 0; + for (McUint32 f = 0; f < faceIdx; ++f) { baseOffset += faceSizes[f]; } return baseOffset; }; void mergeAdjacentMeshFacesByProperty( - std::vector& meshFaceIndicesOUT, - std::vector& meshFaceSizesOUT, - const std::vector& meshFaces, - const std::vector& meshFaceSizes, - const std::vector& meshFaceAdjFace, - const std::vector& meshFaceAdjFaceSizes, - const std::map>& tagToMeshFace, - const std::map& meshFaceToTag) + std::vector& meshFaceIndicesOUT, + std::vector& meshFaceSizesOUT, + const std::vector& meshFaces, + const std::vector& meshFaceSizes, + const std::vector& meshFaceAdjFace, + const std::vector& meshFaceAdjFaceSizes, + const std::map>& tagToMeshFace, + const std::map& meshFaceToTag) { // for each tag - for (std::map>::const_iterator iter = tagToMeshFace.cbegin(); iter != tagToMeshFace.cend(); ++iter) { + for (std::map>::const_iterator iter = tagToMeshFace.cbegin(); iter != tagToMeshFace.cend(); ++iter) { // NOTE: may contain faces that form disjoint patches i.e. not all faces // are merged into one. It is possible to create more than one new face // after the merging where the resulting faces after merging are not adjacent. - std::vector meshFacesWithSameTag = iter->second; // copy! + std::vector meshFacesWithSameTag = iter->second; // copy! // merge the faces that are adjacent - std::vector> adjacentFaceLists; // i.e. each element is a patch/collection of adjacent faces + std::vector> adjacentFaceLists; // i.e. each element is a patch/collection of adjacent faces do { - adjacentFaceLists.push_back(std::vector()); // add new patch - std::vector& curAdjFaceList = adjacentFaceLists.back(); + adjacentFaceLists.push_back(std::vector()); // add new patch + std::vector& curAdjFaceList = adjacentFaceLists.back(); // queue of adjacent faces - std::deque adjFaceQueue; + std::deque adjFaceQueue; adjFaceQueue.push_back(meshFacesWithSameTag.back()); // start with any meshFacesWithSameTag.pop_back(); do { - uint32_t cur = adjFaceQueue.front(); + McUint32 cur = adjFaceQueue.front(); adjFaceQueue.pop_front(); - const int numAdjFaces = meshFaceAdjFaceSizes[cur]; - const int ccFaceAdjFacesBaseOffset = getAdjFacesBaseOffset(cur, meshFaceAdjFaceSizes.data()); + const McInt32 numAdjFaces = meshFaceAdjFaceSizes[cur]; + const McInt32 ccFaceAdjFacesBaseOffset = getAdjFacesBaseOffset(cur, meshFaceAdjFaceSizes.data()); curAdjFaceList.push_back(cur); // for each adjacent face of current face - for (int i = 0; i < numAdjFaces; ++i) { - const uint32_t adjFaceID = meshFaceAdjFace[(size_t)ccFaceAdjFacesBaseOffset + i]; + for (McInt32 i = 0; i < numAdjFaces; ++i) { + const McUint32 adjFaceID = meshFaceAdjFace[(size_t)ccFaceAdjFacesBaseOffset + i]; - std::vector::const_iterator curAdjFaceListIter = std::find(curAdjFaceList.cbegin(), curAdjFaceList.cend(), adjFaceID); + std::vector::const_iterator curAdjFaceListIter = std::find(curAdjFaceList.cbegin(), curAdjFaceList.cend(), adjFaceID); bool alreadyAddedToCurAdjFaceList = (curAdjFaceListIter != curAdjFaceList.cend()); if (!alreadyAddedToCurAdjFaceList) { // does the adjacent face share a Tag..? - std::vector::const_iterator fiter = std::find(iter->second.cbegin(), iter->second.cend(), adjFaceID); + std::vector::const_iterator fiter = std::find(iter->second.cbegin(), iter->second.cend(), adjFaceID); bool haveSharedTag = (fiter != iter->second.cend()); if (haveSharedTag) { - std::deque::const_iterator queueIter = std::find(adjFaceQueue.cbegin(), adjFaceQueue.cend(), adjFaceID); + std::deque::const_iterator queueIter = std::find(adjFaceQueue.cbegin(), adjFaceQueue.cend(), adjFaceID); bool alreadyAddedToAdjFaceQueue = (queueIter != adjFaceQueue.end()); if (!alreadyAddedToAdjFaceQueue) { adjFaceQueue.push_back(adjFaceID); // add it! - std::vector::iterator facesWithSharedTagIter = std::find(meshFacesWithSameTag.begin(), meshFacesWithSameTag.end(), adjFaceID); + std::vector::iterator facesWithSharedTagIter = std::find(meshFacesWithSameTag.begin(), meshFacesWithSameTag.end(), adjFaceID); if (facesWithSharedTagIter != meshFacesWithSameTag.cend()) { meshFacesWithSameTag.erase(facesWithSharedTagIter); // remove since we have now associated with patch. } @@ -472,35 +701,35 @@ void mergeAdjacentMeshFacesByProperty( } while (!adjFaceQueue.empty()); } while (!meshFacesWithSameTag.empty()); - for (std::vector>::const_iterator adjacentFaceListsIter = adjacentFaceLists.cbegin(); + for (std::vector>::const_iterator adjacentFaceListsIter = adjacentFaceLists.cbegin(); adjacentFaceListsIter != adjacentFaceLists.cend(); ++adjacentFaceListsIter) { // Unordered list of halfedges which define the boundary of our new // face - std::vector> halfedgePool; + std::vector> halfedgePool; - for (int f = 0; f < (int)adjacentFaceListsIter->size(); ++f) { + for (McInt32 f = 0; f < (McInt32)adjacentFaceListsIter->size(); ++f) { - const uint32_t meshFaceID = adjacentFaceListsIter->at(f); - const uint32_t meshFaceVertexCount = meshFaceSizes[meshFaceID]; - const uint32_t baseIdx = getFaceIndicesBaseOffset(meshFaceID, meshFaceSizes.data()); - const int numFaceEdges = (int)meshFaceVertexCount; // NOTE: a polygon has the same number of vertices as its edges. + const McUint32 meshFaceID = adjacentFaceListsIter->at(f); + const McUint32 meshFaceVertexCount = meshFaceSizes[meshFaceID]; + const McUint32 baseIdx = getFaceIndicesBaseOffset(meshFaceID, meshFaceSizes.data()); + const McInt32 numFaceEdges = (McInt32)meshFaceVertexCount; // NOTE: a polygon has the same number of vertices as its edges. // for each edge of face - for (int faceEdgeID = 0; faceEdgeID < numFaceEdges; ++faceEdgeID) { + for (McInt32 faceEdgeID = 0; faceEdgeID < numFaceEdges; ++faceEdgeID) { - const int srcIdx = faceEdgeID; - const int tgtIdx = (faceEdgeID + 1) % meshFaceVertexCount; - const uint32_t srcVertexIdx = meshFaces[(size_t)baseIdx + srcIdx]; - const uint32_t tgtVertexIdx = meshFaces[(size_t)baseIdx + tgtIdx]; + const McInt32 srcIdx = faceEdgeID; + const McInt32 tgtIdx = (faceEdgeID + 1) % meshFaceVertexCount; + const McUint32 srcVertexIdx = meshFaces[(size_t)baseIdx + srcIdx]; + const McUint32 tgtVertexIdx = meshFaces[(size_t)baseIdx + tgtIdx]; - std::vector>::iterator fiter = std::find_if( + std::vector>::iterator fiter = std::find_if( halfedgePool.begin(), halfedgePool.end(), - [&](const std::pair& elem) { - return ((uint32_t)elem.first == srcVertexIdx && (uint32_t)elem.second == tgtVertexIdx) || // - ((uint32_t)elem.second == srcVertexIdx && (uint32_t)elem.first == tgtVertexIdx); + [&](const std::pair& elem) { + return ((McUint32)elem.first == srcVertexIdx && (McUint32)elem.second == tgtVertexIdx) || // + ((McUint32)elem.second == srcVertexIdx && (McUint32)elem.first == tgtVertexIdx); }); const bool opposite_halfedge_exists = (fiter != halfedgePool.cend()); @@ -513,17 +742,17 @@ void mergeAdjacentMeshFacesByProperty( } } - std::map> vertexToHalfedges; + std::map> vertexToHalfedges; - for (int i = 0; i < (int)halfedgePool.size(); ++i) { - std::pair halfedge = halfedgePool[i]; + for (McInt32 i = 0; i < (McInt32)halfedgePool.size(); ++i) { + std::pair halfedge = halfedgePool[i]; vertexToHalfedges[halfedge.first].push_back(i); vertexToHalfedges[halfedge.second].push_back(i); } - std::vector polygon; - std::map>::const_iterator cur; - std::map>::const_iterator next = vertexToHalfedges.cbegin(); // could start from any + std::vector polygon; + std::map>::const_iterator cur; + std::map>::const_iterator next = vertexToHalfedges.cbegin(); // could start from any do { cur = next; @@ -531,13 +760,13 @@ void mergeAdjacentMeshFacesByProperty( polygon.push_back(cur->first); // find next (pick the halfedge whose "source" is the current vertex) - std::vector halfedges = cur->second; + std::vector halfedges = cur->second; - for (int i = 0; i < 2; ++i) { - std::pair edge = halfedgePool[halfedges[i]]; - if (edge.first == cur->first && std::find(polygon.cbegin(), polygon.cend(), (uint32_t)edge.second) == polygon.cend()) { + for (McInt32 i = 0; i < 2; ++i) { + std::pair edge = halfedgePool[halfedges[i]]; + if (edge.first == cur->first && std::find(polygon.cbegin(), polygon.cend(), (McUint32)edge.second) == polygon.cend()) { next = vertexToHalfedges.find(edge.second); - my_assert(next != vertexToHalfedges.cend()); + assert(next != vertexToHalfedges.cend()); break; } } @@ -545,19 +774,19 @@ void mergeAdjacentMeshFacesByProperty( } while (next != vertexToHalfedges.cend()); meshFaceIndicesOUT.insert(meshFaceIndicesOUT.end(), polygon.cbegin(), polygon.cend()); - meshFaceSizesOUT.push_back((uint32_t)polygon.size()); + meshFaceSizesOUT.push_back((McUint32)polygon.size()); } } // Now we add the untagged faces into the new mesh (the ones which did not need merging) - for (int meshFaceID = 0; meshFaceID < (int)meshFaceSizes.size(); ++meshFaceID) { + for (McInt32 meshFaceID = 0; meshFaceID < (McInt32)meshFaceSizes.size(); ++meshFaceID) { bool faceWasMerged = meshFaceToTag.find(meshFaceID) != meshFaceToTag.cend(); if (!faceWasMerged) { - const uint32_t baseIdx = getFaceIndicesBaseOffset(meshFaceID, meshFaceSizes.data()); - const uint32_t meshFaceVertexCount = meshFaceSizes[meshFaceID]; + const McUint32 baseIdx = getFaceIndicesBaseOffset(meshFaceID, meshFaceSizes.data()); + const McUint32 meshFaceVertexCount = meshFaceSizes[meshFaceID]; - for (int i = 0; i < (int)meshFaceVertexCount; ++i) { + for (McInt32 i = 0; i < (McInt32)meshFaceVertexCount; ++i) { meshFaceIndicesOUT.push_back(meshFaces[(size_t)baseIdx + i]); } diff --git a/tutorials/AdjacentFaces/CMakeLists.txt b/tutorials/AdjacentFaces/CMakeLists.txt deleted file mode 100644 index 42ed69b..0000000 --- a/tutorials/AdjacentFaces/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(AdjacentFaces AdjacentFaces.cpp) - -target_link_libraries(AdjacentFaces mcut ) -target_include_directories(AdjacentFaces PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir}) -target_compile_definitions(AdjacentFaces PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}") -target_compile_options(AdjacentFaces PRIVATE ${compilation_flags}) -target_compile_definitions(AdjacentFaces PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index ee29431..309e77f 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -1,44 +1,33 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - cmake_minimum_required(VERSION 3.1) + project(mcut_tutorials) -#add_subdirectory(BasicGuiApp) -add_subdirectory(BasicCmdLineApp) -add_subdirectory(HelloWorld) -add_subdirectory(TextureCoordinates) -add_subdirectory(VertexNormals) -add_subdirectory(FaceNormals) -add_subdirectory(CSGBoolean) -add_subdirectory(AdjacentFaces) -add_subdirectory(Triangulation) -add_subdirectory(TriangulatedFaceMaps) -add_subdirectory(EventCallback) -add_subdirectory(MultipleContextsInParallel) -add_subdirectory(ReversedConnectedComponentFaces) -add_subdirectory(PlanarSectioning) -add_subdirectory(QuerySeamVerticesUnsorted) -add_subdirectory(QuerySeamVerticesSorted) -add_subdirectory(InOutQuery) +function(create_tutorial_target tutorial_name) + add_executable(${tutorial_name} "${CMAKE_CURRENT_SOURCE_DIR}/${tutorial_name}/${tutorial_name}.cpp") + target_link_libraries(${tutorial_name} mcut mio) + target_include_directories(${tutorial_name} PRIVATE ${MCUT_INCLUDE_DIR} ${mio_include_dir}) + target_compile_definitions(${tutorial_name} PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/${tutorial_name}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}") + target_compile_options(${tutorial_name} PRIVATE ${compilation_flags}) + target_compile_definitions(${tutorial_name} PRIVATE ${preprocessor_defs}) +endfunction() + +create_tutorial_target(AdjacentFaces) + +#add_subdirectory(BasicCmdLineApp) +#add_subdirectory(HelloWorld) +#add_subdirectory(TextureCoordinates) +#add_subdirectory(VertexNormals) +#add_subdirectory(FaceNormals) +#add_subdirectory(CSGBoolean) +#add_subdirectory(AdjacentFaces) +#add_subdirectory(Triangulation) +#add_subdirectory(TriangulatedFaceMaps) +#add_subdirectory(EventCallback) +#add_subdirectory(MultipleContextsInParallel) +#add_subdirectory(ReversedConnectedComponentFaces) +#add_subdirectory(PlanarSectioning) +#add_subdirectory(QuerySeamVerticesUnsorted) +#add_subdirectory(QuerySeamVerticesSorted) +#add_subdirectory(InOutQuery) diff --git a/tutorials/HelloWorld/CMakeLists.txt b/tutorials/HelloWorld/CMakeLists.txt index 50278df..2ed2385 100644 --- a/tutorials/HelloWorld/CMakeLists.txt +++ b/tutorials/HelloWorld/CMakeLists.txt @@ -1,27 +1,3 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) add_executable(HelloWorld HelloWorld.cpp) target_link_libraries(HelloWorld mcut ${extra_libs}) diff --git a/tutorials/HelloWorld/HelloWorld.cpp b/tutorials/HelloWorld/HelloWorld.cpp index ca47567..83ec7dd 100644 --- a/tutorials/HelloWorld/HelloWorld.cpp +++ b/tutorials/HelloWorld/HelloWorld.cpp @@ -1,29 +1,31 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ - -/* -Simple "hello world" program using MCUT. -Input meshes are defined in-source but output meshes are saved as .off files -*/ + * HelloWorld.cpp + * + * \brief: + * Simple "hello world" program using MCUT. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" @@ -32,274 +34,240 @@ Input meshes are defined in-source but output meshes are saved as .off files #include -#define my_assert(cond) \ - if (!(cond)) { \ - fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ - } - void writeOFF( const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces); + McFloat* pVertices, + McUint32* pFaceIndices, + McUint32* pFaceSizes, + McUint32 numVertices, + McUint32 numFaces); -int main() +McInt32 main() { - // 1. Create meshes. - // ----------------- - -#if 0 - // the cube - // -------- - float cubeVertices[] = { - -5, -5, 5, // 0 - 5, -5, 5, // 1 - 5, 5, 5, //2 - -5, 5, 5, //3 - -5, -5, -5, //4 - 5, -5, -5, //5 - 5, 5, -5, //6 - -5, 5, -5 //7 - }; - uint32_t cubeFaces[] = { - 0, 1, 2, 3, //0 - 7, 6, 5, 4, //1 - 1, 5, 6, 2, //2 - 0, 3, 7, 4, //3 - 3, 2, 6, 7, //4 - 4, 5, 1, 0 //5 - }; - uint32_t cubeFaceSizes[] = { - 4, 4, 4, 4, 4, 4}; - uint32_t numCubeVertices = 8; - uint32_t numCubeFaces = 6; - - // the cut mesh - // --------- - float cutMeshVertices[] = { - -20, -4, 0, //0 - 0, 20, 20, //1 - 20, -4, 0, //2 - 0, 20, -20 //3 + // + // Create meshes to intersect + // + + // the source-mesh (a cube) + + McFloat srcMeshVertices[] = { + -5, -5, 5, // vertex 0 + 5, -5, 5, // vertex 1 + 5, 5, 5, // vertex 2 + -5, 5, 5, // vertex 3 + -5, -5, -5, // vertex 4 + 5, -5, -5, // vertex 5 + 5, 5, -5, // vertex 6 + -5, 5, -5 // vertex 7 }; - uint32_t cutMeshFaces[] = { - 0, 1, 2, //0 - 0, 2, 3 //1 - }; - //uint32_t cutMeshFaceSizes[] = { - // 3, 3}; - uint32_t numCutMeshVertices = 4; - uint32_t numCutMeshFaces = 2; -#else // triangulation bug fix - - // Shape to Cut: - double cubeVertices[] = { - -1, -1, 1, // 0 - 1, -1, 1, // 1 - -1, 1, 1, // 2 - 1, 1, 1, // 3 - -1, -1, -1, // 4 - 1, -1, -1, // 5 - -1, 1, -1, // 6 - 1, 1, -1 // 7 - }; - uint32_t cubeFaces[] = { - 0, 3, 2, // 0 - 0, 1, 3, // 1 - 1, 7, 3, // 2 - 1, 5, 7, // 3 - 5, 6, 7, // 4 - 5, 4, 6, // 5 - 4, 2, 6, // 6 - 4, 0, 2, // 7 - 2, 7, 6, // 8 - 2, 3, 7, // 9 - 4, 1, 0, // 10 - 4, 5, 1, // 11 + McUint32 srcMeshFaces[] = { + 0, 1, 2, 3, // face 0 + 7, 6, 5, 4, // face 1 + 1, 5, 6, 2, // face 2 + 0, 3, 7, 4, // face 3 + 3, 2, 6, 7, // face 4 + 4, 5, 1, 0 // face 5 }; - int numCubeVertices = 8; - int numCubeFaces = 12; + + McUint32 srcMeshFaceSizes[] = { 4, 4, 4, 4, 4, 4}; - uint32_t cubeFaceSizes[] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; + McUint32 srcMeshVertexCount = 8; + McUint32 srcMeshFaceCount = 6; - // Cutting Shape: + // the cut mesh (a quad formed of two triangles) - double cutMeshVertices[] = { - -1.2, 1.6, 0.994070, - 1.4, -1.3, 0.994070, - -1.2, 1.6, -1.005929, - 1.4, -1.3, -1.005929 + McFloat cutMeshVertices[] = { + -20, -4, 0, // vertex 0 + 0, 20, 20, // vertex 1 + 20, -4, 0, // vertex 2 + 0, 20, -20 // vertex 3 }; - uint32_t cutMeshFaces[] = { - 1, 2, 0, - 1, 3, 2 + McUint32 cutMeshFaces[] = { + 0, 1, 2, // face 0 + 0, 2, 3 // face 1 }; - uint32_t numCutMeshVertices = 4; - uint32_t numCutMeshFaces = 2; -#endif - // 2. create a context - // ------------------- + // McUint32 cutMeshFaceSizes[] = { 3, 3}; + + McUint32 cutMeshVertexCount = 4; + McUint32 cutMeshFaceCount = 2; + + // + // create a context + // + McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - if (err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "could not create context (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // 3. do the magic! - // ---------------- - err = mcDispatch( + // + // do the cutting + // + + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE, - cubeVertices, - cubeFaces, - cubeFaceSizes, - numCubeVertices, - numCubeFaces, + srcMeshVertices, + srcMeshFaces, + srcMeshFaceSizes, + srcMeshVertexCount, + srcMeshFaceCount, cutMeshVertices, cutMeshFaces, - nullptr, // cutMeshFaceSizes, // no need to give 'faceSizes' parameter since cut-mesh is a triangle mesh - numCutMeshVertices, - numCutMeshFaces); + nullptr, // cutMeshFaceSizes, // no need to give 'cutMeshFaceSizes' parameter since the cut-mesh is a triangle mesh + cutMeshVertexCount, + cutMeshFaceCount); - if (err != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "dispatch call failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // 4. query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnComps; - std::vector connComps; + // + // query the number of available connected components after the cut + // - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); + McUint32 connectedComponentCount; + std::vector connectedComponents; - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); + + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - if (numConnComps == 0) { + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); - exit(0); + exit(EXIT_FAILURE); } - connComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); // allocate for the amount we want to get - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- - - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + // + // query the data of each connected component + // - McSize numBytes = 0; + for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { + + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id + McSize bytesToAllocate = 0; - // query the vertices - // ---------------------- + // + // vertices + // - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &bytesToAllocate); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(float) * 3)); - - std::vector vertices(numberOfVertices * 3u); + McUint32 ccVertexCount = (McUint32)(bytesToAllocate / (sizeof(McFloat) * 3ull)); + std::vector ccVertices(ccVertexCount * 3u); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void*)vertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, bytesToAllocate, (McVoid*)ccVertices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // query the faces - // ------------------- + // + // faces + // - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + bytesToAllocate = 0; - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &bytesToAllocate); + + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - std::vector faceIndices; - faceIndices.resize(numBytes / sizeof(uint32_t)); + std::vector faceIndices; + faceIndices.resize(bytesToAllocate / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, faceIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, bytesToAllocate, (McVoid*)faceIndices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // query the face sizes - // ------------------------ - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); + // + // face sizes (vertices per face) + // + + bytesToAllocate = 0; + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &bytesToAllocate); + + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - std::vector faceSizes; - faceSizes.resize(numBytes / sizeof(uint32_t)); + std::vector faceSizes; + faceSizes.resize(bytesToAllocate / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, bytesToAllocate, (McVoid*)faceSizes.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } + // + // save to cc to file (.off) + // + char fnameBuf[32]; - sprintf(fnameBuf, "conncomp%d.off", i); - // save to mesh file (.off) - // ------------------------ + sprintf(fnameBuf, "cc%d.off", i); writeOFF(fnameBuf, - (float*)vertices.data(), - (uint32_t*)faceIndices.data(), - (uint32_t*)faceSizes.data(), - (uint32_t)vertices.size() / 3, - (uint32_t)faceSizes.size()); + (McFloat*)ccVertices.data(), + (McUint32*)faceIndices.data(), + (McUint32*)faceSizes.data(), + (McUint32)ccVertices.size() / 3u, + (McUint32)faceSizes.size()); } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // + + status = mcReleaseConnectedComponents(context, 0, NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseConnectedComponents failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + // + // free memory of context + // + + status = mcReleaseContext(context); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)err); - exit(1); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseContext failed (%d)\n", (McInt32)status); + exit(EXIT_FAILURE); } return 0; @@ -308,11 +276,11 @@ int main() // write mesh to .off file void writeOFF( const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces) + McFloat* pVertices, + McUint32* pFaceIndices, + McUint32* pFaceSizes, + McUint32 numVertices, + McUint32 numFaces) { fprintf(stdout, "write: %s\n", fpath); @@ -320,24 +288,24 @@ void writeOFF( if (file == NULL) { fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); + exit(EXIT_FAILURE); } fprintf(file, "OFF\n"); fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - float* vptr = pVertices + (i * 3); + McInt32 i; + for (i = 0; i < (McInt32)numVertices; ++i) { + McFloat* vptr = pVertices + (i * 3); fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); } - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - uint32_t faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - uint32_t* fptr = pFaceIndices + faceBaseOffset + j; + McInt32 faceBaseOffset = 0; + for (i = 0; i < (McInt32)numFaces; ++i) { + McUint32 faceVertexCount = pFaceSizes[i]; + fprintf(file, "%d", (McInt32)faceVertexCount); + McInt32 j; + for (j = 0; j < (McInt32)faceVertexCount; ++j) { + McUint32* fptr = pFaceIndices + faceBaseOffset + j; fprintf(file, " %d", *fptr); } fprintf(file, "\n"); From cceee19795d60bb4d12e5a5488ee640c059f5d2f Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Wed, 15 Nov 2023 18:13:27 +0000 Subject: [PATCH 02/23] clean-up FaceNormals tutorial --- tutorials/AdjacentFaces/AdjacentFaces.cpp | 113 +- tutorials/CMakeLists.txt | 2 +- tutorials/FaceNormals/CMakeLists.txt | 27 - tutorials/FaceNormals/FaceNormals.cpp | 1148 +++++++++++++-------- 4 files changed, 734 insertions(+), 556 deletions(-) delete mode 100644 tutorials/FaceNormals/CMakeLists.txt diff --git a/tutorials/AdjacentFaces/AdjacentFaces.cpp b/tutorials/AdjacentFaces/AdjacentFaces.cpp index 1370138..6722f4a 100644 --- a/tutorials/AdjacentFaces/AdjacentFaces.cpp +++ b/tutorials/AdjacentFaces/AdjacentFaces.cpp @@ -64,73 +64,21 @@ void mergeAdjacentMeshFacesByProperty( McInt32 main() { - // structure for our source- and cut-mesh that are loaded from file - struct MeshArrays - { - McDouble* pVertices = NULL; - McDouble* pNormals = NULL; - McDouble* pTexCoords = NULL; - - McUint32* pFaceSizes = NULL; - McUint32* pFaceVertexIndices = NULL; - McUint32* pFaceVertexTexCoordIndices = NULL; - McUint32* pFaceVertexNormalIndices = NULL; - - McUint32 numVertices = 0; - McUint32 numNormals = 0; - McUint32 numTexCoords = 0; - McUint32 numFaces = 0; - - ~MeshArrays() - { - if(pVertices) - { - free(pVertices); - pVertices = nullptr; - } - - if(pNormals) - { - free(pNormals); - pNormals = nullptr; - } - - if(pTexCoords) - { - free(pTexCoords); - pTexCoords = nullptr; - } - - if(pFaceSizes) - { - free(pFaceSizes); - pFaceSizes = nullptr; - } - - if(pFaceVertexIndices) - { - free(pFaceVertexIndices); - pFaceVertexIndices = nullptr; - } - - if(pFaceVertexTexCoordIndices) - { - free(pFaceVertexTexCoordIndices); - pFaceVertexTexCoordIndices = nullptr; - } - - if(pFaceVertexNormalIndices) - { - free(pFaceVertexNormalIndices); - pFaceVertexNormalIndices = nullptr; - } - - numVertices = 0; - numNormals = 0; - numTexCoords = 0; - numFaces = 0; - } - } srcMesh, cutMesh; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; // // read-in the source-mesh from file @@ -229,9 +177,7 @@ McInt32 main() exit(1); } - // - // do the cutting - // + status = mcDispatch( context, @@ -249,11 +195,17 @@ McInt32 main() cutMesh.numVertices, cutMesh.numFaces); - if(status != MC_NO_ERROR) - { - fprintf(stderr, "mcDispatch failed (%d)\n", (McInt32)status); - exit(1); - } + if(status != MC_NO_ERROR) + { + fprintf(stderr, "mcDispatch failed (%d)\n", (McInt32)status); + exit(1); + } + + // + // MCUT is not longer using mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); // // query the number of available connected components @@ -299,7 +251,7 @@ McInt32 main() // // type // - McConnectedComponentType type; + McConnectedComponentType type = (McConnectedComponentType)0; status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &type, NULL); @@ -319,7 +271,7 @@ McInt32 main() if (type == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - McInputOrigin origin; + McInputOrigin origin = (McInputOrigin)0; status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &origin, NULL); @@ -425,8 +377,7 @@ McInt32 main() { char buf[512]; sprintf(buf, OUTPUT_DIR "/cc%d.obj", c); - //writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndices[0], &ccFaceSizes[0], ccFaceCount); - + mioWriteOBJ(buf, &ccVertices[0], nullptr, @@ -569,9 +520,9 @@ McInt32 main() { char buf[512]; sprintf(buf, OUTPUT_DIR "/cc%d-merged.obj", c); + // NOTE: For the sake of simplicity, we keep unreferenced vertices. - //writeOBJ(buf, &ccVertices[0], ccVertexCount, &ccFaceIndicesMerged[0], &ccFaceSizesMerged[0], (McUint32)ccFaceSizesMerged.size()); - + mioWriteOBJ(buf, &ccVertices[0], nullptr, diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 309e77f..963fd63 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -12,6 +12,7 @@ function(create_tutorial_target tutorial_name) endfunction() create_tutorial_target(AdjacentFaces) +create_tutorial_target(FaceNormals) #add_subdirectory(BasicCmdLineApp) #add_subdirectory(HelloWorld) @@ -19,7 +20,6 @@ create_tutorial_target(AdjacentFaces) #add_subdirectory(VertexNormals) #add_subdirectory(FaceNormals) #add_subdirectory(CSGBoolean) -#add_subdirectory(AdjacentFaces) #add_subdirectory(Triangulation) #add_subdirectory(TriangulatedFaceMaps) #add_subdirectory(EventCallback) diff --git a/tutorials/FaceNormals/CMakeLists.txt b/tutorials/FaceNormals/CMakeLists.txt deleted file mode 100644 index b9cf1a3..0000000 --- a/tutorials/FaceNormals/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(FaceNormals FaceNormals.cpp) -target_link_libraries(FaceNormals mcut ${extra_libs}) -target_include_directories(FaceNormals PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_definitions(FaceNormals PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}" ${preprocessor_defs}) -target_compile_options(FaceNormals PRIVATE ${compilation_flags}) \ No newline at end of file diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 9fdda28..3bbfdc1 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -1,513 +1,767 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -This tutorial shows how to propagate per-face normals (flat shading) from input meshes and onto the output -connected components after cutting. -*/ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * AdjacentFaces.cpp + * + * \brief: + * This tutorial shows how to propagate per-face normals (flat shading) + * from an input mesh and onto the output connected component(s) after cutting. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include +#include #include -// libigl dependencies -#include -#include -#include -#include -#include - -#define my_assert(cond) if(!(cond)){fprintf(stderr, "MCUT error: %s\n", #cond );std::exit(1);} - -struct InputMesh { - // variables for reading .obj file data with libigl - std::vector> V, TC, N; - std::vector> F, FTC, FN; - std::vector> FM; - - // variables for mesh data in a format suited for MCUT - std::string fpath; // path to mesh file - std::vector faceSizesArray; // vertices per face - std::vector faceIndicesArray; // face indices - std::vector vertexCoordsArray; // vertex coords +#include + +#define my_assert(cond) \ + if(!(cond)) \ + { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::exit(1); \ + } + +struct vec3 +{ + union + { + struct + { + McDouble x, y, z; + }; + McDouble u, v, w; + }; + + vec3 operator*(const McDouble c) const { + vec3 out; + out.x = x *c; + out.y = y *c; + out.z = z *c; + return out; + } + + vec3 operator+(const vec3& rhs) const { + vec3 out; + out.x = x + rhs.x; + out.y = y + rhs.y; + out.z = z + rhs.z; + return out; + } + + vec3 operator-(const vec3& rhs) const + { + vec3 out; + out.x = x - rhs.x; + out.y = y - rhs.y; + out.z = z - rhs.z; + return out; + } }; +inline McDouble +getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x3, McDouble y3) +{ + return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2); +} + +vec3 crossProduct(vec3& u, const vec3& v) +{ + vec3 out; + out.x = u.y * v.z - u.z * v.y; + out.x = u.z * v.x - u.x * v.z; + out.x = u.x * v.y - u.y * v.x; + return out; +} + +// Compute barycentric coordinates (u, v, w) for point p with respect to triangle (a, b, c) +vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec3& c) +{ + // Unnormalized triangle normal + vec3 m = crossProduct(b - a, c - a); + // Nominators and one-over-denominator for u and v ratios + McDouble nu, nv, ood; + // Absolute components for determining projection plane + McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); + + // Compute areas in plane of largest projection + if(x >= y && x >= z) + { + // x is largest, project to the yz plane + nu = getTriangleArea2D(p.y, p.z, b.y, b.z, c.y, c.z); + // Area of PBC in yz plane + nv = getTriangleArea2D(p.y, p.z, c.y, c.z, a.y, a.z); + // Area of PCA in yz plane + ood = 1.0f / m.x; // 1/(2*area of ABC in yz plane + } + else if(y >= x && y >= z) + { + // y is largest, project to the xz plane + nu = getTriangleArea2D(p.x, p.z, b.x, b.z, c.x, c.z); + nv = getTriangleArea2D(p.x, p.z, c.x, c.z, a.x, a.z); + ood = 1.0f / -m.y; + } + else + { + // z is largest, project to the xy plane + nu = getTriangleArea2D(p.x, p.y, b.x, b.y, c.x, c.y); + nv = getTriangleArea2D(p.x, p.y, c.x, c.y, a.x, a.y); + ood = 1.0f / m.z; + } + + vec3 result; + result.u = nu * ood; + result.v = nv * ood; + result.w = 1.0f - result.u - result.v; + return result; +} + // basic comparison of doubles -bool compare(double x, double y) +bool are_equal(McDouble x, McDouble y) { - return std::fabs(x - y) < 1e-6; + const McDouble eps = 1e-6; + const McDouble diff = (x > y) ? (x - y) : (y - x); + + return diff < eps; } +// assigns a string name to a connected component based on it unique properties +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + bool isFragment, + McFragmentLocation fragmentLocation); + int main() { - // load meshes. - // ----------------- - InputMesh srcMesh; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; + + // + // read-in the source-mesh from file + // + mioReadOBJ(DATA_DIR "/cube.obj", + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(DATA_DIR "/plane.obj", + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); + + // + // create a context + // + + McContext context = MC_NULL_HANDLE; + + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); + + my_assert(status == MC_NO_ERROR); + + // + // do the cutting + // + + status = mcDispatch( + context, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | + MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals + // source mesh + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + my_assert(status == MC_NO_ERROR); - // read file - srcMesh.fpath = DATA_DIR "/cube.obj"; - bool srcMeshLoaded = igl::readOBJ(srcMesh.fpath, srcMesh.V, srcMesh.TC, srcMesh.N, srcMesh.F, srcMesh.FTC, srcMesh.FN); + // + // query the number of available connected components + // - if (!srcMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", srcMesh.fpath.c_str()); - std::exit(1); - } + McUint32 connectedComponentCount; - // copy vertices - for (int i = 0; i < (int)srcMesh.V.size(); ++i) { - const std::vector& v = srcMesh.V[i]; - my_assert(v.size() == 3); - srcMesh.vertexCoordsArray.push_back(v[0]); - srcMesh.vertexCoordsArray.push_back(v[1]); - srcMesh.vertexCoordsArray.push_back(v[2]); - } + status = mcGetConnectedComponents( + context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - // copy faces - for (int i = 0; i < (int)srcMesh.F.size(); ++i) { - const std::vector& f = srcMesh.F[i]; - my_assert(f.size() == 3); // we assume triangle meshes for simplicity - for (int j = 0; j < (int)f.size(); ++j) { - srcMesh.faceIndicesArray.push_back(f[j]); - } + my_assert(status == MC_NO_ERROR); - srcMesh.faceSizesArray.push_back((uint32_t)f.size()); - } + printf("connected components: %u\n", connectedComponentCount); - printf("source mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)srcMesh.V.size(), (int)srcMesh.F.size()); + if(connectedComponentCount == 0) + { + fprintf(stdout, "no connected components found\n"); + exit(0); // should not happen! + } - InputMesh cutMesh; + std::vector connectedComponents(connectedComponentCount, MC_NULL_HANDLE); - // read file - cutMesh.fpath = DATA_DIR "/plane.obj"; - bool cutMeshLoaded = igl::readOBJ(cutMesh.fpath, cutMesh.V, cutMesh.TC, cutMesh.N, cutMesh.F, cutMesh.FTC, cutMesh.FN); + status = mcGetConnectedComponents(context, + MC_CONNECTED_COMPONENT_TYPE_ALL, + (McUint32)connectedComponents.size(), + connectedComponents.data(), + NULL); - if (!cutMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", cutMesh.fpath.c_str()); - std::exit(1); - } + my_assert(status == MC_NO_ERROR); - // copy vertices - for (int i = 0; i < (int)cutMesh.V.size(); ++i) { - const std::vector& v = cutMesh.V[i]; - my_assert(v.size() == 3); - cutMesh.vertexCoordsArray.push_back(v[0]); - cutMesh.vertexCoordsArray.push_back(v[1]); - cutMesh.vertexCoordsArray.push_back(v[2]); - } + // + // query the data of each connected component + // - // copy faces - for (int i = 0; i < (int)cutMesh.F.size(); ++i) { - const std::vector& f = cutMesh.F[i]; - my_assert(f.size() == 3); - for (int j = 0; j < (int)f.size(); ++j) { - cutMesh.faceIndicesArray.push_back(f[j]); - } + for(McUint32 i = 0; i < (McUint32)connectedComponents.size(); ++i) + { + McConnectedComponent cc = connectedComponents[i]; // connected compoene - cutMesh.faceSizesArray.push_back((uint32_t)f.size()); - } + // + // vertices + // - printf("cut mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)cutMesh.V.size(), (int)cutMesh.F.size()); + McSize numBytes = 0; - // create an MCUT context - // ------------------------- - McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); - // do the cutting - // ----------------- - err = mcDispatch( - context, - MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals - // source mesh - reinterpret_cast(srcMesh.vertexCoordsArray.data()), - reinterpret_cast(srcMesh.faceIndicesArray.data()), - srcMesh.faceSizesArray.data(), - static_cast(srcMesh.vertexCoordsArray.size() / 3), - static_cast(srcMesh.faceSizesArray.size()), - // cut mesh - reinterpret_cast(cutMesh.vertexCoordsArray.data()), - cutMesh.faceIndicesArray.data(), - cutMesh.faceSizesArray.data(), - static_cast(cutMesh.vertexCoordsArray.size() / 3), - static_cast(cutMesh.faceSizesArray.size())); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices(ccVertexCount * 3u, 0.0); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, + numBytes, + (void*)ccVertices.data(), + NULL); - // query the number of available connected component (all types) - // ---------------------------------------------------------------- + my_assert(status == MC_NO_ERROR); - uint32_t numConnectedComponents; + // + // faces + // - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents); - my_assert(err == MC_NO_ERROR); + numBytes = 0; - printf("connected components: %d\n", (int)numConnectedComponents); + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - if (numConnectedComponents == 0) { - fprintf(stdout, "no connected components found\n"); - exit(0); - } + my_assert(status == MC_NO_ERROR); - std::vector connectedComponents(numConnectedComponents, 0); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connectedComponents.size(), connectedComponents.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the data of each connected component from MCUT - // ------------------------------------------------------- - - for (int i = 0; i < (int)connectedComponents.size(); ++i) { - McConnectedComponent connComp = connectedComponents[i]; // connected compoene - - // query the vertices - // ---------------------- - - McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); - std::vector ccVertices((size_t)ccVertexCount * 3u, 0.0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the faces - // ------------------- - - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face sizes - // ------------------------ - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector faceSizes(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the vertex map - // ------------------------ - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccVertexMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face map - // ----------------------- - const uint32_t ccFaceCount = static_cast(faceSizes.size()); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // resolve fragment name - // ------------------------- - - // Here we create a name the connected component based on its properties - - // get type - McConnectedComponentType ccType; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &ccType, NULL); - my_assert(err == MC_NO_ERROR); - - std::string name; - McFragmentLocation fragmentLocation = (McFragmentLocation)0; - McPatchLocation patchLocation = (McPatchLocation)0; - bool isFragment = false; - - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) { - name += "seam"; - } else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - name += "input"; - } else { - isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - name += isFragment ? "frag" : "patch"; - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += patchLocation == MC_PATCH_LOCATION_INSIDE ? ".inside" : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".outside" : ".undefined"); - - if (isFragment) { - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE ? ".above" : ".below"; // missing loc="undefined" case - - McFragmentSealType sType = (McFragmentSealType)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, sizeof(McFragmentSealType), &sType, NULL); - my_assert(err == MC_NO_ERROR); - name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".complete" : ".none"; - } - } - - bool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - - // connected-components is not a fragment && it is a seam - if (!ccIsFromSrcMesh) { - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) { - // get origin - McSeamOrigin ccOrig = (McSeamOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McSeamOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - - ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - McInputOrigin ccOrig = (McInputOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } - } - - int faceVertexOffsetBase = 0; - - std::vector ccNormals; // our normals (what we want) - - // CC-vertex-index-to-normal-indices. - // Its possible to map to more than one normal since such coordinates are specified to per-face. - std::map> ccVertexIndexToNormalIndices; - std::vector ccFaceVertexNormalIndices; // normal indices reference by each face - - // for each face in cc - for (int f = 0; f < (int)ccFaceCount; ++f) { - - // get the [origin] input-mesh face index (Note: this index may be offsetted - // to distinguish between source-mesh and cut-mesh faces). - const uint32_t imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh face index (we don't know yet) - // ** This is how we infer which mapped indices belong to the source-mesh or the cut-mesh. - const bool faceIsFromSrcMesh = (imFaceIdxRaw < (uint32_t)srcMesh.F.size()); - bool flipNormalsOnFace = false; - // Now compute the actual input mesh face index (accounting for offset) - uint32_t imFaceIdx = imFaceIdxRaw; - - if (!faceIsFromSrcMesh) { // if the current face is from the cut-mesh - imFaceIdx = (imFaceIdxRaw - (uint32_t)srcMesh.F.size()); // accounting for offset - // check if we need to flip normals on the face - flipNormalsOnFace = (isFragment && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); - } - - int faceSize = faceSizes.at(f); /// number of vertices in face - - // for each vertex in face - for (int v = 0; v < faceSize; ++v) { - - const int ccVertexIdx = ccFaceIndices.at((McSize)faceVertexOffsetBase + v); - const uint32_t imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); - bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.V.size()); - const bool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); // i.e. a vertex along the cut-path (an intersection point) - uint32_t imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset - - if (!vertexIsFromSrcMesh) { - imVertexIdx = (imVertexIdxRaw - (std::uint32_t)srcMesh.V.size()); // account for offset - } + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0u); - const InputMesh* inputMeshPtr = faceIsFromSrcMesh ? &srcMesh : &cutMesh; - - // the face from which the current cc face came ("birth face") - const std::vector& imFace = inputMeshPtr->F[imFaceIdx]; - - Eigen::Vector3d normal; // the normal of the current vertex - - if (isSeamVertex) { // normal completely unknown and must be computed - - // interpolate texture coords from input-mesh values - // -------------------------------------------------- - - // coordinates of current point - double x(ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); - double y(ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); - double z(ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); - - // vertices of the origin face (i.e. the face from which the current face came from). - // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation - // will be more complex, which is unnecessary for now. - const std::vector& a = inputMeshPtr->V[imFace[0]]; - const std::vector& b = inputMeshPtr->V[imFace[1]]; - const std::vector& c = inputMeshPtr->V[imFace[2]]; - - // compute the barycentric coords of our seam vertex on the origin face - Eigen::MatrixXd P; // our vertex - P.resize(1, 3); - P << x, y, z; - // the origin face vertices added into Eigen matrices for libIGL - Eigen::MatrixXd A; - A.resize(1, 3); - A << a[0], a[1], a[2]; - Eigen::MatrixXd B; - B.resize(1, 3); - B << b[0], b[1], b[2]; - Eigen::MatrixXd C; - C.resize(1, 3); - C << c[0], c[1], c[2]; - - // our barycentric coords - Eigen::MatrixXd L; - - igl::barycentric_coordinates(P, A, B, C, L); - - // compute the normal of our vertex by interpolation - // ------------------------------------------------- - - // indices of the normals that are used by the origin face "imFaceIdx" - const std::vector& imFaceNormalIndices = inputMeshPtr->FN[imFaceIdx]; - my_assert(imFaceNormalIndices.size() == 3); - - // normals of vertices in the origin face - const std::vector& Na_ = inputMeshPtr->N[imFaceNormalIndices[0]]; - const std::vector& Nb_ = inputMeshPtr->N[imFaceNormalIndices[1]]; - const std::vector& Nc_ = inputMeshPtr->N[imFaceNormalIndices[2]]; - // simple conversion to Eigen's Vector3d type - const Eigen::Vector3d Na(Na_[0], Na_[1], Na_[2]); - const Eigen::Vector3d Nb(Nb_[0], Nb_[1], Nb_[2]); - const Eigen::Vector3d Nc(Nc_[0], Nc_[1], Nc_[2]); - const Eigen::Vector3d baryCoords = L.row(0); - - // interpolate using barycentric coords - normal = (Na * baryCoords.x()) + (Nb * baryCoords.y()) + (Nc * baryCoords.z()); - - // NOTE: if all three vertices have the same normal (index) then there is no need for interpolation - // we'd just copy that value from the respective input mesh. - - } else { // the normal is known must be inferred from input mesh - - // the index of the mapped-to index in the input mesh - int imFaceVertexOffset = -1; - for (int p = 0; p < (int)imFace.size(); ++p) { - if (imFace[p] == (int)imVertexIdx) { - imFaceVertexOffset = p; - break; - } - } + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(imFaceVertexOffset != -1); + my_assert(status == MC_NO_ERROR); - // get the normal index of the vertex - int imNormalIdx = inputMeshPtr->FN[imFaceIdx][imFaceVertexOffset]; - // copy the normal value from the input mesh - const std::vector& n = inputMeshPtr->N[imNormalIdx]; - my_assert(n.size() == 3); - normal = Eigen::Vector3d(n[0], n[1], n[2]); - } + // + // face sizes + // - // When MCUT seal's holes, it uses polygons directly from the cut mesh. These polygons - // may require to be flipped sometimes when holes are filled (e.g. when a fragment is - // "above"). Thus, we cannot just copy/interpolate the normal from the origin mesh in - // such cases, we must also flip (negate) it. - if (flipNormalsOnFace) { - normal *= -1.0; - } + numBytes = 0; - // Do some book-keeping to prevent us from duplicate the normals that we write to file. - int normalIndex = -1; + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - // has a normal with the same value already been computed? - std::vector::const_iterator fiter = std::find_if( - ccNormals.cbegin(), ccNormals.cend(), - [&](const Eigen::Vector3d& e) { return compare(e.x(), normal.x()) && compare(e.y(), normal.y()) && compare(e.z(), normal.z()); }); + my_assert(status == MC_NO_ERROR); - if (fiter != ccNormals.cend()) { - normalIndex = (int)std::distance(ccNormals.cbegin(), fiter); - } + std::vector ccFaceSizes(numBytes / sizeof(McUint32), 0u); - if (normalIndex == -1) { // normal not yet stored for CC vertex in face - normalIndex = (int)ccNormals.size(); - ccNormals.push_back(normal); - } + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); - ccFaceVertexNormalIndices.push_back(normalIndex); - } // for (int v = 0; v < faceSize; ++v) { + my_assert(status == MC_NO_ERROR); - faceVertexOffsetBase += faceSize; - } // for (int f = 0; f < ccFaceCount; ++f) { + // + // vertex map + // - // save connected component (mesh) to an .obj file - // ----------------------------------------------- + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - char fnameBuf[64]; - sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); - std::string fpath(DATA_DIR "/" + std::string(fnameBuf)); + my_assert(status == MC_NO_ERROR); - printf("write file: %s\n", fpath.c_str()); + std::vector ccVertexMap(numBytes / sizeof(McUint32), 0u); - std::ofstream file(fpath); + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, + numBytes, + ccVertexMap.data(), + NULL); - // write vertices + my_assert(status == MC_NO_ERROR); - for (int p = 0; p < (int)ccVertexCount; ++p) { - double x = ccVertices[(McSize)p * 3 + 0]; - double y = ccVertices[(McSize)p * 3 + 1]; - double z = ccVertices[(McSize)p * 3 + 2]; - file << std::setprecision(std::numeric_limits::digits10 + 1) << "v " << x << " " << y << " " << z << std::endl; - } + // + // face map + // - // write normals + const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); - for (int p = 0; p < (int)ccNormals.size(); ++p) { - Eigen::Vector3d n = ccNormals[p]; - file << "vn " << std::setprecision(std::numeric_limits::digits10 + 1) << n.x() << " " << n.y() << " " << n.z() << std::endl; - } + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - // write faces (with normal indices) + my_assert(status == MC_NO_ERROR); - faceVertexOffsetBase = 0; - for (int k = 0; k < (int)ccFaceCount; ++k) { - int faceSize = faceSizes.at(k); + std::vector ccFaceMap(numBytes / sizeof(McUint32), 0); - file << "f "; - for (int j = 0; j < faceSize; ++j) { - const int idx = faceVertexOffsetBase + j; - const int ccVertexIdx = ccFaceIndices.at(static_cast(idx)); - file << (ccVertexIdx + 1) << "//" << ccFaceVertexNormalIndices[idx] + 1 << " "; - } - file << std::endl; + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); - faceVertexOffsetBase += faceSize; - } - } + my_assert(status == MC_NO_ERROR); + + // + // resolve fragment name + // + + // Here we create a name for the connected component based on its properties + + bool isFragment = false; + McFragmentLocation fragmentLocation = (McFragmentLocation)0; + + std::string name = resolve_cc_name_string(context, cc, isFragment, fragmentLocation); + + McUint32 faceVertexOffsetBase = 0; + + std::vector ccNormals; // our normals (what we want) + + // CC-vertex-index-to-normal-indices. + // Its possible to map to more than one normal since such coordinates are specified to per-face. + //std::map> ccVertexIndexToNormalIndices; + + std::vector ccFaceVertexNormalIndices; // normal indices reference by each face of cc + + // for each face in cc + for(McUint32 f = 0; f < (McUint32)ccFaceCount; ++f) + { + + // get the [origin] input-mesh face index (Note: this index may be offsetted + // to distinguish between source-mesh and cut-mesh faces). + const McUint32 imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh face index (we don't know yet) + // ** This is how we infer which mapped indices belong to the source-mesh or the cut-mesh. + const bool faceIsFromSrcMesh = (imFaceIdxRaw < (McUint32)srcMesh.numFaces); + bool flipNormalsOnFace = false; + // Now compute the actual input mesh face index (accounting for offset) + McUint32 imFaceIdx = imFaceIdxRaw; + + if(!faceIsFromSrcMesh) + { // if the current face is from the cut-mesh + imFaceIdx = (imFaceIdxRaw - (McUint32)srcMesh.numFaces); // accounting for offset + // check if we need to flip normals on the face + flipNormalsOnFace = (isFragment && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); + } + + McUint32 faceSize = ccFaceSizes.at(f); /// number of vertices in face + + // for each vertex in face + for(McUint32 v = 0; v < faceSize; ++v) + { + + const McUint32 ccVertexIdx = ccFaceIndices.at((McSize)faceVertexOffsetBase + v); + const McUint32 imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); + bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.numVertices); + // i.e. a vertex along the cut-path (an intersection point) + const bool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); + McUint32 imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset + + if(!vertexIsFromSrcMesh) + { + // account for offset + imVertexIdx = (imVertexIdxRaw - (McUint32)srcMesh.numVertices); + } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + const MioMesh* inputMeshPtr = faceIsFromSrcMesh ? &srcMesh : &cutMesh; - my_assert(err == MC_NO_ERROR); + // the face from which the current cc face came ("birth face") + //const std::vector& imFace = inputMeshPtr->F[imFaceIdx]; + // NOTE: there is a presumption here that the input mesh is a triangle-mesh! + const McUint32* imFace = inputMeshPtr->pFaceVertexIndices + (imFaceIdx * 3); - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + vec3 normal; // the normal of the current vertex - my_assert(err == MC_NO_ERROR); + if(isSeamVertex) + { // normal completely unknown and must be computed - return 0; + // interpolate texture coords from input-mesh values + // -------------------------------------------------- + + // coordinates of current point (whose barycentric coord we want) + vec3 p; + p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); + p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); + p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); + + // vertices of the origin face (i.e. the face from which the current face came from). + // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation + // will be more complex, which is unnecessary for now. + vec3 a; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[0]*3; + a.x = ptr[0]; + a.y = ptr[1]; + a.z = ptr[2]; + } + vec3 b; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[1]*3; + b.x = ptr[0]; + b.y = ptr[1]; + b.z = ptr[2]; + } + + vec3 c; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[2]*3; + c.x = ptr[0]; + c.y= ptr[1]; + c.z = ptr[2]; + } + + const vec3 bary = getBarycentricCoords(p, a, b, c); + + // + // compute the normal of our vertex by interpolation + // + + // indices of the normals that are used by the vertices defining the origin face "imFaceIdx" + const McUint32* imFaceNormalIndices = inputMeshPtr->pFaceVertexNormalIndices + (imFaceIdx*3); //inputMeshPtr->FN[imFaceIdx]; + + // normal coordinates of vertices in the origin face + + vec3 normalA; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0]*3); + normalA.x = ptr[0]; + normalA.y = ptr[1]; + normalA.z = ptr[2]; + } + vec3 normalB; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1]*3); + normalB.x = ptr[0]; + normalB.y = ptr[1]; + normalB.z = ptr[2]; + } + vec3 normalC; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2]*3); + normalC.x = ptr[0]; + normalC.y = ptr[1]; + normalC.z = ptr[2]; + } + + // interpolate at point "p" using barycentric coords + normal = (normalA * bary.x) + (normalB * bary.y ) + (normalC * bary.z); + + // NOTE: if all three vertices have the same normal (index) then there is no need for interpolation + // we'd just copy that value from the respective input mesh. + } + else + { // the normal is known and can therefore be inferred from the input mesh + + // the index of the mapped-to index in the input mesh + McIndex imFaceVertexOffset = MC_UNDEFINED_VALUE; + + // for each vertex in face + for(McUint32 p = 0; p < inputMeshPtr->pFaceSizes[imFaceIdx]; ++p) + { + if(imFace[p] == imVertexIdx) + { + imFaceVertexOffset = p; + break; + } + } + + my_assert(imFaceVertexOffset != MC_UNDEFINED_VALUE); + + // get the normal index of the vertex + McUint32 imNormalIdx = inputMeshPtr->pFaceVertexNormalIndices[imFaceIdx*3 + imFaceVertexOffset]; + // copy the normal value from the input mesh + const McDouble* ptr = inputMeshPtr->pNormals + (imNormalIdx * 3); + + normal.x = ptr[0]; + normal.y = ptr[1]; + normal.z = ptr[2]; + } + + // When MCUT seal's holes, it uses polygons directly from the cut mesh. These polygons + // may require to be flipped sometimes when holes are filled (e.g. when a fragment is + // "above"). Thus, we cannot just copy/interpolate the normal from the origin mesh in + // such cases, we must also flip (negate) it. + + if(flipNormalsOnFace) + { + normal = normal * -1.0; + } + + // + // Do some book-keeping to prevent us from duplicating the normals that we write to file. + // + + // has a normal with the same value already been computed? + // pointer to the location of the existing (i.e. already computed) normal, which matches "normal" + const McDouble* pNormalIter = nullptr; + + // for each normal vector (in the list that we have so far) + for(McUint32 n = 0; n < ccNormals.size() / 3; ++n) + { + const McDouble* pNormal = ccNormals.data() + (n * 3); + const bool haveMatch = are_equal(normal.x, pNormal[0]) && + are_equal(normal.y, pNormal[1]) && + are_equal(normal.z, pNormal[2]); + if(haveMatch) + { + pNormalIter = pNormal; + break; + } + } + + std::ptrdiff_t normalIndex = -1; + + if(pNormalIter != nullptr) + { + normalIndex = (pNormalIter - ccNormals.data()) / 3; + + my_assert(normalIndex >=0); + } + else{ + normalIndex = ccNormals.size()/3; + + ccNormals.push_back(pNormalIter[0]); + ccNormals.push_back(pNormalIter[1]); + ccNormals.push_back(pNormalIter[2]); + } + + ccFaceVertexNormalIndices.push_back(normalIndex); + } // for (int v = 0; v < faceSize; ++v) { + + faceVertexOffsetBase += faceSize; + } // for (int f = 0; f < ccFaceCount; ++f) { + + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + + // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); + std::string fpath(DATA_DIR "/" + std::string(fnameBuf)); + + mioWriteOBJ( + fpath.c_str(), + ccVertices.data(), + ccNormals.data(), + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + ccFaceVertexNormalIndices.data(), + ccVertexCount, + ccNormals.size()/3, + 0, // numTexCoords + ccFaceCount); + } + + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, 0, NULL); + + my_assert(status == MC_NO_ERROR); + + // + // destroy context + // + status = mcReleaseContext(context); + + my_assert(status == MC_NO_ERROR); + + return 0; +} + +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + bool isFragment, + McFragmentLocation fragmentLocation) +{ + // get type + McConnectedComponentType ccType; + + McResult status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_TYPE, + sizeof(McConnectedComponentType), + &ccType, + NULL); + + my_assert(status == MC_NO_ERROR); + + std::string name; + McPatchLocation patchLocation = (McPatchLocation)0; + + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + name += "seam"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + name += "input"; + } + else + { + isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + name += isFragment ? "frag" : "patch"; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, + sizeof(McPatchLocation), + &patchLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += patchLocation == MC_PATCH_LOCATION_INSIDE + ? ".ploc=in" + : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".ploc=out" : ".ploc=undef"); + + if(isFragment) + { + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, + sizeof(McFragmentLocation), + &fragmentLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE + ? ".floc=abv" + : ".floc=blw"; // missing loc="undefined" case + + McFragmentSealType sType = (McFragmentSealType)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, + sizeof(McFragmentSealType), + &sType, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".seal=yes" : ".seal=no"; + } + } + + bool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + // connected-components is not a fragment && it is a seam + if(!ccIsFromSrcMesh) + { + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + // get origin + McSeamOrigin ccOrig = (McSeamOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McSeamOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); + name += ccIsFromSrcMesh ? ".orig=s" : ".orig=c"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + McInputOrigin ccOrig = (McInputOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McInputOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); + name += ccIsFromSrcMesh ? ".orig=s" : ".orig=c"; + } + } + + return name; } From 2ea0bd5740929f6b9e56e2ab571d13c8936b207b Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Thu, 16 Nov 2023 11:01:24 +0000 Subject: [PATCH 03/23] fix minor bug --- tutorials/AdjacentFaces/AdjacentFaces.cpp | 4 +- tutorials/CMakeLists.txt | 1 - tutorials/FaceNormals/FaceNormals.cpp | 51 ++++++++++++----------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/tutorials/AdjacentFaces/AdjacentFaces.cpp b/tutorials/AdjacentFaces/AdjacentFaces.cpp index 6722f4a..438b939 100644 --- a/tutorials/AdjacentFaces/AdjacentFaces.cpp +++ b/tutorials/AdjacentFaces/AdjacentFaces.cpp @@ -177,8 +177,6 @@ McInt32 main() exit(1); } - - status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_FACE_MAP, @@ -232,7 +230,7 @@ McInt32 main() connectedComponents.resize(connectedComponentCount); status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if(status != MC_NO_ERROR) + if(status != MC_NO_ERROR) { fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 963fd63..b9c6791 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -18,7 +18,6 @@ create_tutorial_target(FaceNormals) #add_subdirectory(HelloWorld) #add_subdirectory(TextureCoordinates) #add_subdirectory(VertexNormals) -#add_subdirectory(FaceNormals) #add_subdirectory(CSGBoolean) #add_subdirectory(Triangulation) #add_subdirectory(TriangulatedFaceMaps) diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 3bbfdc1..64718d1 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -45,6 +45,7 @@ std::exit(1); \ } +// simple structure representing a 3d vector and the operator we will perform with it struct vec3 { union @@ -57,28 +58,28 @@ struct vec3 }; vec3 operator*(const McDouble c) const { - vec3 out; - out.x = x *c; - out.y = y *c; - out.z = z *c; - return out; + vec3 result; + result.x = x * c; + result.y = y * c; + result.z = z * c; + return result; } vec3 operator+(const vec3& rhs) const { - vec3 out; - out.x = x + rhs.x; - out.y = y + rhs.y; - out.z = z + rhs.z; - return out; + vec3 result; + result.x = x + rhs.x; + result.y = y + rhs.y; + result.z = z + rhs.z; + return result; } vec3 operator-(const vec3& rhs) const { - vec3 out; - out.x = x - rhs.x; - out.y = y - rhs.y; - out.z = z - rhs.z; - return out; + vec3 result; + result.x = x - rhs.x; + result.y = y - rhs.y; + result.z = z - rhs.z; + return result; } }; @@ -88,7 +89,7 @@ getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2); } -vec3 crossProduct(vec3& u, const vec3& v) +vec3 crossProduct(const vec3& u, const vec3& v) { vec3 out; out.x = u.y * v.z - u.z * v.y; @@ -101,11 +102,11 @@ vec3 crossProduct(vec3& u, const vec3& v) vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec3& c) { // Unnormalized triangle normal - vec3 m = crossProduct(b - a, c - a); + const vec3 m = crossProduct(b - a, c - a); // Nominators and one-over-denominator for u and v ratios McDouble nu, nv, ood; // Absolute components for determining projection plane - McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); + const McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); // Compute areas in plane of largest projection if(x >= y && x >= z) @@ -140,7 +141,7 @@ vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec } // basic comparison of doubles -bool are_equal(McDouble x, McDouble y) +bool are_equal(const McDouble& x, const McDouble &y) { const McDouble eps = 1e-6; const McDouble diff = (x > y) ? (x - y) : (y - x); @@ -151,8 +152,8 @@ bool are_equal(McDouble x, McDouble y) // assigns a string name to a connected component based on it unique properties std::string resolve_cc_name_string(McContext context, McConnectedComponent cc, - bool isFragment, - McFragmentLocation fragmentLocation); + bool &isFragment, + McFragmentLocation& fragmentLocation); int main() { @@ -381,7 +382,7 @@ int main() bool isFragment = false; McFragmentLocation fragmentLocation = (McFragmentLocation)0; - std::string name = resolve_cc_name_string(context, cc, isFragment, fragmentLocation); + const std::string name = resolve_cc_name_string(context, cc, isFragment, fragmentLocation); McUint32 faceVertexOffsetBase = 0; @@ -648,11 +649,11 @@ int main() std::string resolve_cc_name_string(McContext context, McConnectedComponent cc, - bool isFragment, - McFragmentLocation fragmentLocation) + bool &isFragment, + McFragmentLocation &fragmentLocation) { // get type - McConnectedComponentType ccType; + McConnectedComponentType ccType = (McConnectedComponentType)0; McResult status = mcGetConnectedComponentData(context, cc, From a6e3211ab35ab3d1f73437c755d7ed9a20b6808a Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Thu, 16 Nov 2023 11:59:24 +0000 Subject: [PATCH 04/23] finish rewrite of the FaceNormals tutorial --- source/frontend.cpp | 2 +- tutorials/FaceNormals/FaceNormals.cpp | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/source/frontend.cpp b/source/frontend.cpp index f2f9cae..2fb137e 100644 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -3222,7 +3222,7 @@ void get_connected_component_data_impl_detail( for (std::vector::const_iterator f_iter = block_start_; f_iter != block_end_; ++f_iter) { - if ((elem_offset + 1) >= elems_to_copy) { + if ((elem_offset + 1) > elems_to_copy) { break; } diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 64718d1..2091a22 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -54,7 +54,10 @@ struct vec3 { McDouble x, y, z; }; - McDouble u, v, w; + struct + { + McDouble u, v, w; + }; }; vec3 operator*(const McDouble c) const { @@ -93,8 +96,8 @@ vec3 crossProduct(const vec3& u, const vec3& v) { vec3 out; out.x = u.y * v.z - u.z * v.y; - out.x = u.z * v.x - u.x * v.z; - out.x = u.x * v.y - u.y * v.x; + out.y = u.z * v.x - u.x * v.z; + out.z = u.x * v.y - u.y * v.x; return out; } @@ -590,9 +593,9 @@ int main() else{ normalIndex = ccNormals.size()/3; - ccNormals.push_back(pNormalIter[0]); - ccNormals.push_back(pNormalIter[1]); - ccNormals.push_back(pNormalIter[2]); + ccNormals.push_back(normal.x); + ccNormals.push_back(normal.y); + ccNormals.push_back(normal.z); } ccFaceVertexNormalIndices.push_back(normalIndex); @@ -601,12 +604,6 @@ int main() faceVertexOffsetBase += faceSize; } // for (int f = 0; f < ccFaceCount; ++f) { - // - // We no longer need the mem of input meshes, so we can free it! - // - mioFreeMesh(&srcMesh); - mioFreeMesh(&cutMesh); - // // save connected component (mesh) to an .obj file // @@ -630,6 +627,12 @@ int main() ccFaceCount); } + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + // // free connected component data // From abf809d55ae27b03474be82d86a8f63597d01681 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Wed, 10 Jan 2024 10:16:55 +0000 Subject: [PATCH 05/23] update VertexNormals tutorial --- tutorials/CMakeLists.txt | 1 + tutorials/FaceNormals/FaceNormals.cpp | 63 +- tutorials/VertexNormals/VertexNormals.cpp | 1083 +++++++++++++-------- 3 files changed, 720 insertions(+), 427 deletions(-) diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index b9c6791..0d0092b 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -13,6 +13,7 @@ endfunction() create_tutorial_target(AdjacentFaces) create_tutorial_target(FaceNormals) +create_tutorial_target(VertexNormals) #add_subdirectory(BasicCmdLineApp) #add_subdirectory(HelloWorld) diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 2091a22..4727266 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * AdjacentFaces.cpp + * FaceNormals.cpp * * \brief: * This tutorial shows how to propagate per-face normals (flat shading) @@ -45,7 +45,7 @@ std::exit(1); \ } -// simple structure representing a 3d vector and the operator we will perform with it +// simple structure representing a 3d vector and the operations we will perform with it struct vec3 { union @@ -61,7 +61,7 @@ struct vec3 }; vec3 operator*(const McDouble c) const { - vec3 result; + vec3 result = {}; result.x = x * c; result.y = y * c; result.z = z * c; @@ -69,7 +69,7 @@ struct vec3 } vec3 operator+(const vec3& rhs) const { - vec3 result; + vec3 result = {}; result.x = x + rhs.x; result.y = y + rhs.y; result.z = z + rhs.z; @@ -78,7 +78,7 @@ struct vec3 vec3 operator-(const vec3& rhs) const { - vec3 result; + vec3 result = {}; result.x = x - rhs.x; result.y = y - rhs.y; result.z = z - rhs.z; @@ -94,7 +94,7 @@ getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x vec3 crossProduct(const vec3& u, const vec3& v) { - vec3 out; + vec3 out = {}; out.x = u.y * v.z - u.z * v.y; out.y = u.z * v.x - u.x * v.z; out.z = u.x * v.y - u.y * v.x; @@ -107,7 +107,7 @@ vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec // Unnormalized triangle normal const vec3 m = crossProduct(b - a, c - a); // Nominators and one-over-denominator for u and v ratios - McDouble nu, nv, ood; + McDouble nu = 0.0, nv = 0.0, ood = 0.0; // Absolute components for determining projection plane const McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); @@ -136,7 +136,7 @@ vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec ood = 1.0f / m.z; } - vec3 result; + vec3 result = {}; result.u = nu * ood; result.v = nv * ood; result.w = 1.0f - result.u - result.v; @@ -376,24 +376,18 @@ int main() my_assert(status == MC_NO_ERROR); - // - // resolve fragment name - // - + // // Here we create a name for the connected component based on its properties + // and save whether its a fragment, and if so the location of this fragment + // bool isFragment = false; McFragmentLocation fragmentLocation = (McFragmentLocation)0; - const std::string name = resolve_cc_name_string(context, cc, isFragment, fragmentLocation); - - McUint32 faceVertexOffsetBase = 0; - - std::vector ccNormals; // our normals (what we want) - - // CC-vertex-index-to-normal-indices. - // Its possible to map to more than one normal since such coordinates are specified to per-face. - //std::map> ccVertexIndexToNormalIndices; + McUint32 faceVertexOffsetBase = 0; // offset of vertex in face + // our array normals (what we want). This is the list that will be referred to by + // the face-vertices of the cc (each face will have vertex indices and normal indices) + std::vector ccNormals; std::vector ccFaceVertexNormalIndices; // normal indices reference by each face of cc @@ -446,13 +440,14 @@ int main() vec3 normal; // the normal of the current vertex if(isSeamVertex) - { // normal completely unknown and must be computed + { // normal completely unknown and must be inferred - // interpolate texture coords from input-mesh values - // -------------------------------------------------- + // + // interpolate from input-mesh values + // - // coordinates of current point (whose barycentric coord we want) - vec3 p; + // coordinates of current point (whose barycentric coords we want) + vec3 p = {0.0, 0.0,0.0}; p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); @@ -460,14 +455,14 @@ int main() // vertices of the origin face (i.e. the face from which the current face came from). // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation // will be more complex, which is unnecessary for now. - vec3 a; + vec3 a = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[0]*3; a.x = ptr[0]; a.y = ptr[1]; a.z = ptr[2]; } - vec3 b; + vec3 b = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[1]*3; b.x = ptr[0]; @@ -475,11 +470,11 @@ int main() b.z = ptr[2]; } - vec3 c; + vec3 c = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[2]*3; c.x = ptr[0]; - c.y= ptr[1]; + c.y = ptr[1]; c.z = ptr[2]; } @@ -494,21 +489,21 @@ int main() // normal coordinates of vertices in the origin face - vec3 normalA; + vec3 normalA = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0]*3); normalA.x = ptr[0]; normalA.y = ptr[1]; normalA.z = ptr[2]; } - vec3 normalB; + vec3 normalB = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1]*3); normalB.x = ptr[0]; normalB.y = ptr[1]; normalB.z = ptr[2]; } - vec3 normalC; + vec3 normalC = {0.0, 0.0, 0.0}; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2]*3); normalC.x = ptr[0]; @@ -610,7 +605,7 @@ int main() char fnameBuf[64]; sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); - std::string fpath(DATA_DIR "/" + std::string(fnameBuf)); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); mioWriteOBJ( fpath.c_str(), diff --git a/tutorials/VertexNormals/VertexNormals.cpp b/tutorials/VertexNormals/VertexNormals.cpp index e9e4575..541356b 100644 --- a/tutorials/VertexNormals/VertexNormals.cpp +++ b/tutorials/VertexNormals/VertexNormals.cpp @@ -1,418 +1,556 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -This tutorial show how to propagate per-vertex normals (smooth shading) from input meshes and onto the output -connected components after cutting -*/ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * VertexNormals.cpp + * + * \brief: + * This tutorial shows how to propagate per-vertex normals (e.g. for smooth + * shading) from input meshes and onto the output connected components after + * cutting. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include #include -// libigl dependencies -#include -#include -#include -#include -#include - +#include +#include // std::sqrt #define my_assert(cond) \ if (!(cond)) \ { \ fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ + std::abort(); \ } -struct InputMesh +// simple structure representing a 3d vector and the operations we will perform with it +struct vec3 { - // variables for reading .obj file data with libigl - std::vector> V, TC, N; - std::vector> F, FTC, FN; - std::vector> FM; - - // variables for mesh data in a format suited for MCUT - std::string fpath; // path to mesh file - std::vector faceSizesArray; // vertices per face - std::vector faceIndicesArray; // face indices - std::vector vertexCoordsArray; // vertex coords + union + { + struct + { + McDouble x, y, z; + }; + struct + { + McDouble u, v, w; + }; + }; + + vec3 operator*(const McDouble c) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x * c; + result.y = y * c; + result.z = z * c; + return result; + } + + vec3 operator+(const vec3& rhs) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x + rhs.x; + result.y = y + rhs.y; + result.z = z + rhs.z; + return result; + } + + vec3 operator-(const vec3& rhs) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x - rhs.x; + result.y = y - rhs.y; + result.z = z - rhs.z; + return result; + } }; -int main() +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation); + + +inline McDouble +getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x3, McDouble y3) { - // 1. load meshes. + return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2); +} + +vec3 crossProduct(const vec3& u, const vec3& v) +{ + vec3 out = {0.0, 0.0, 0.0}; + out.x = u.y * v.z - u.z * v.y; + out.y = u.z * v.x - u.x * v.z; + out.z = u.x * v.y - u.y * v.x; + return out; +} + +// Compute barycentric coordinates (u, v, w) for point p with respect to triangle (a, b, c) +vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec3& c) +{ + // Unnormalized triangle normal + const vec3 m = crossProduct(b - a, c - a); + // Nominators and one-over-denominator for u and v ratios + McDouble nu=0.0, nv=0.0, ood=0.0; + // Absolute components for determining projection plane + const McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); + + // Compute areas in plane of largest projection + if(x >= y && x >= z) + { + // x is largest, project to the yz plane + nu = getTriangleArea2D(p.y, p.z, b.y, b.z, c.y, c.z); + // Area of PBC in yz plane + nv = getTriangleArea2D(p.y, p.z, c.y, c.z, a.y, a.z); + // Area of PCA in yz plane + ood = 1.0f / m.x; // 1/(2*area of ABC in yz plane + } + else if(y >= x && y >= z) + { + // y is largest, project to the xz plane + nu = getTriangleArea2D(p.x, p.z, b.x, b.z, c.x, c.z); + nv = getTriangleArea2D(p.x, p.z, c.x, c.z, a.x, a.z); + ood = 1.0f / -m.y; + } + else + { + // z is largest, project to the xy plane + nu = getTriangleArea2D(p.x, p.y, b.x, b.y, c.x, c.y); + nv = getTriangleArea2D(p.x, p.y, c.x, c.y, a.x, a.y); + ood = 1.0f / m.z; + } + + vec3 result = {0.0, 0.0, 0.0}; + result.u = nu * ood; + result.v = nv * ood; + result.w = 1.0f - result.u - result.v; + return result; +} + +McInt32 main() +{ + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; + + // + // read-in the source-mesh from file + // + mioReadOBJ(DATA_DIR "/cube.obj", + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(DATA_DIR "/plane.obj", + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); + + // + // create a context + // + + McContext context = MC_NULL_HANDLE; + + McResult status = mcCreateContext(&context, MC_DEBUG); + + my_assert(status == MC_NO_ERROR); + + // 3. do the cutting // ----------------- - InputMesh srcMesh; + status = mcDispatch( + context, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals + // source mesh + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); - // read file - srcMesh.fpath = DATA_DIR "/cube.obj"; - bool srcMeshLoaded = igl::readOBJ(srcMesh.fpath, srcMesh.V, srcMesh.TC, srcMesh.N, srcMesh.F, srcMesh.FTC, srcMesh.FN); + my_assert(status == MC_NO_ERROR); - if (!srcMeshLoaded) - { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", srcMesh.fpath.c_str()); - std::exit(1); - } + // + // query the number of available connected components + // - // copy vertices - for (int i = 0; i < (int)srcMesh.V.size(); ++i) - { - const std::vector &v = srcMesh.V[i]; - my_assert(v.size() == 3); - srcMesh.vertexCoordsArray.push_back(v[0]); - srcMesh.vertexCoordsArray.push_back(v[1]); - srcMesh.vertexCoordsArray.push_back(v[2]); - } + McUint32 connectedComponentCount; - // copy faces - for (int i = 0; i < (int)srcMesh.F.size(); ++i) - { - const std::vector &f = srcMesh.F[i]; - my_assert(f.size() == 3); // we assume triangle meshes for simplicity - for (int j = 0; j < (int)f.size(); ++j) - { - srcMesh.faceIndicesArray.push_back(f[j]); - } + status = mcGetConnectedComponents( + context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - srcMesh.faceSizesArray.push_back((uint32_t)f.size()); - } + my_assert(status == MC_NO_ERROR); - printf("source mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)srcMesh.V.size(), (int)srcMesh.F.size()); + printf("connected components: %u\n", connectedComponentCount); - InputMesh cutMesh; + if(connectedComponentCount == 0) + { + fprintf(stdout, "no connected components found\n"); + exit(0); // should not happen! + } - // read file - cutMesh.fpath = DATA_DIR "/plane.obj"; - bool cutMeshLoaded = igl::readOBJ(cutMesh.fpath, cutMesh.V, cutMesh.TC, cutMesh.N, cutMesh.F, cutMesh.FTC, cutMesh.FN); + std::vector connectedComponents(connectedComponentCount, MC_NULL_HANDLE); - if (!cutMeshLoaded) - { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", cutMesh.fpath.c_str()); - std::exit(1); - } + status = mcGetConnectedComponents(context, + MC_CONNECTED_COMPONENT_TYPE_ALL, + (McUint32)connectedComponents.size(), + connectedComponents.data(), + NULL); - // copy vertices - for (int i = 0; i < (int)cutMesh.V.size(); ++i) - { - const std::vector &v = cutMesh.V[i]; - my_assert((int)v.size() == 3); - cutMesh.vertexCoordsArray.push_back(v[0]); - cutMesh.vertexCoordsArray.push_back(v[1]); - cutMesh.vertexCoordsArray.push_back(v[2]); - } + my_assert(status == MC_NO_ERROR); - // copy faces - for (int i = 0; i < (int)cutMesh.F.size(); ++i) + // query the data of each connected component from MCUT + // ------------------------------------------------------- + + for(McUint32 ci = 0; ci < (McUint32)connectedComponents.size(); ++ci) { - const std::vector &f = cutMesh.F[i]; - my_assert(f.size() == 3); - for (int j = 0; j < (int)f.size(); ++j) - { - cutMesh.faceIndicesArray.push_back(f[j]); - } + McConnectedComponent cc = connectedComponents[ci]; // connected component id - cutMesh.faceSizesArray.push_back((uint32_t)f.size()); - } + // + // vertices + // - printf("cut mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)cutMesh.V.size(), (int)cutMesh.F.size()); + McSize numBytes = 0; - // 2. create a context - // ------------------- - McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); - // 3. do the cutting - // ----------------- - err = mcDispatch( - context, - MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals - // source mesh - reinterpret_cast(srcMesh.vertexCoordsArray.data()), - reinterpret_cast(srcMesh.faceIndicesArray.data()), - srcMesh.faceSizesArray.data(), - static_cast(srcMesh.vertexCoordsArray.size() / 3), - static_cast(srcMesh.faceSizesArray.size()), - // cut mesh - reinterpret_cast(cutMesh.vertexCoordsArray.data()), - cutMesh.faceIndicesArray.data(), - cutMesh.faceSizesArray.data(), - static_cast(cutMesh.vertexCoordsArray.size() / 3), - static_cast(cutMesh.faceSizesArray.size())); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices(ccVertexCount * 3u, 0.0); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, + numBytes, + (void*)ccVertices.data(), + NULL); - // query the number of available connected component (all types) - // ---------------------------------------------------------------- - uint32_t numConnComps; + my_assert(status == MC_NO_ERROR); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); - my_assert(err == MC_NO_ERROR); + // + // faces + // - printf("connected components: %d\n", (int)numConnComps); + numBytes = 0; - std::vector connComps(numConnComps, 0); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - // query the data of each connected component from MCUT - // ------------------------------------------------------- + my_assert(status == MC_NO_ERROR); - for (int ci = 0; ci < (int)connComps.size(); ++ci) - { - McConnectedComponent connComp = connComps[ci]; // connected component id - - // query the ccVertices - // ---------------------- - - McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); - - std::vector ccVertices((size_t)ccVertexCount * 3u, 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void *)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the faces - // ------------------- - - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face sizes - // ------------------------ - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector faceSizes(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the vertex map - // ------------------------ - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccVertexMap; - ccVertexMap.resize(numBytes / sizeof(uint32_t)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face map - // ------------------------ - const uint32_t ccFaceCount = static_cast(faceSizes.size()); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // resolve fragment name - // ------------------------- + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0u); - // Here we create a name the connected component based on its properties + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - // get type - McConnectedComponentType ccType; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &ccType, NULL); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); - std::string name; - McFragmentLocation fragmentLocation = (McFragmentLocation)0; - McPatchLocation patchLocation = (McPatchLocation)0; - bool isFragment = false; + // + // face sizes + // - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) - { - name += "seam"; - } - else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) - { - name += "input"; - } - else - { - isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - name += isFragment ? "frag" : "patch"; + numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += patchLocation == MC_PATCH_LOCATION_INSIDE ? ".inside" : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".outside" : ".undefined"); + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (isFragment) - { + my_assert(status == MC_NO_ERROR); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE ? ".above" : ".below"; // missing loc="undefined" case + std::vector ccFaceSizes(numBytes / sizeof(McUint32), 0u); - McFragmentSealType sType = (McFragmentSealType)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, sizeof(McFragmentSealType), &sType, NULL); - my_assert(err == MC_NO_ERROR); - name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".complete" : ".none"; - } - } + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); - bool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + my_assert(status == MC_NO_ERROR); - // connected-components is not a fragment && it is a seam - if (!ccIsFromSrcMesh) - { - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) - { - // get origin - McSeamOrigin ccOrig = (McSeamOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McSeamOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); + // + // vertex map + // - ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); - } - else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) - { - McInputOrigin ccOrig = (McInputOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); - } - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + std::vector ccVertexMap(numBytes / sizeof(McUint32), 0u); + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, + numBytes, + ccVertexMap.data(), + NULL); + + my_assert(status == MC_NO_ERROR); + + // + // face map + // + + const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); - int faceVertexOffsetBase = 0; + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - std::vector ccVertexNormals(ccVertexCount, Eigen::Vector3d(0., 0., 0.)); + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceMap(numBytes / sizeof(McUint32), 0); + + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // Here we create a name for the connected component based on its properties + // and save whether its a fragment, and if so the location of this fragment + // + + McBool isFragment = false; + McFragmentLocation fragmentLocation = (McFragmentLocation)0; + const std::string name = resolve_cc_name_string(context, cc, isFragment, fragmentLocation); + + McInt32 faceVertexOffsetBase = 0; + + std::vector ccVertexNormals(ccVertexCount, {0., 0., 0.}); + std::vector ccFaceVertexNormalIndices; // each vertex get its own (averaged) normal from neighbouring faces + // intersection points do not have a normal value that can be copied (inferred) from an input - // mesh, it has to be computed by interpolating normals on the origin face in the input mesh. - // We keep a reference count to compute averaged normal per intersection point. - std::map ccSeamVertexToRefCount; - std::vector ccFaceVertexNormalIndices; - std::vector ccReversedFaces; + // mesh, it has to be computed by interpolating normals on the origin/proginator face in the input mesh. + // We keep a reference count to compute averaged normals per intersection point. + std::map ccSeamVertexToRefCount; + + //std::vector ccReversedFaces; // for each face in CC - for (int f = 0; f < (int)ccFaceCount; ++f) + for (McInt32 f = 0; f < (McInt32)ccFaceCount; ++f) { // input mesh face index (which may be offsetted!) - const uint32_t imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh + const McUint32 imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh // input mesh face index (actual index value, accounting for offset) - uint32_t imFaceIdx = imFaceIdxRaw; - bool faceIsFromSrcMesh = (imFaceIdxRaw < (std::uint32_t)srcMesh.F.size()); - bool flipNormalsOnFace = false; + McUint32 imFaceIdx = imFaceIdxRaw; + const McBool faceIsFromSrcMesh = (imFaceIdxRaw < (McUint32)srcMesh.numFaces); + McBool flipNormalsOnFace = MC_FALSE; if (!faceIsFromSrcMesh) { - imFaceIdx = imFaceIdxRaw - (std::uint32_t)srcMesh.F.size(); // accounting for offset - flipNormalsOnFace = (isFragment && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); + imFaceIdx = imFaceIdxRaw - srcMesh.numFaces; // accounting for offset + + my_assert(imFaceIdx < (srcMesh.numFaces + cutMesh.numFaces)); // in case of underflow + + flipNormalsOnFace = (isFragment == MC_TRUE && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); } - int faceSize = (int)faceSizes.at(f); + const McUint32 faceSize = (McUint32)ccFaceSizes.at(f); + + my_assert(faceSize >= 3); // for each vertex in face - for (int v = 0; v < faceSize; ++v) + for(McUint32 v = 0; v < faceSize; ++v) { - - const int ccVertexIdx = ccFaceIndices[(McSize)faceVertexOffsetBase + v]; + const McUint32 ccVertexIdx = ccFaceIndices[(McSize)faceVertexOffsetBase + v]; // input mesh (source mesh or cut mesh) vertex index (which may be offsetted) - const uint32_t imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); - bool vertexIsFromSrcMesh = (imVertexIdxRaw < (std::uint32_t)srcMesh.V.size()); - const bool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); - uint32_t imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset + const McUint32 imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); + const McBool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.numVertices); + const McBool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); + McUint32 imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset if (!vertexIsFromSrcMesh) { - imVertexIdx = (imVertexIdxRaw - (std::uint32_t)srcMesh.V.size()); // account for offset + imVertexIdx = (imVertexIdxRaw - srcMesh.numVertices); // account for offset + my_assert(imVertexIdx < cutMesh.numVertices || isSeamVertex); } - const InputMesh *inputMeshPtr = &srcMesh; // assume origin face is from source mesh + const MioMesh *inputMeshPtr = &srcMesh; // assume origin face is from source mesh - if (!faceIsFromSrcMesh) + if (!faceIsFromSrcMesh) // is cut-mesh face { inputMeshPtr = &cutMesh; } - // the face on which the current cc face came from - const std::vector &imFace = inputMeshPtr->F[imFaceIdx]; + // indices of the normals that are used by "imFaceIdx" + const McUint32* imFaceNormalIndices = inputMeshPtr->pFaceVertexNormalIndices + (imFaceIdx * 3); - if (isSeamVertex) - { // normal is unknown and must be computed - - // interpolate texture coords from source-mesh values - - // 1. get the origin face of the current cc face - - double x(ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); - double y(ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); - double z(ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); - - // vertices of the origin face - const std::vector &a = inputMeshPtr->V[imFace[0]]; - const std::vector &b = inputMeshPtr->V[imFace[1]]; - const std::vector &c = inputMeshPtr->V[imFace[2]]; - - // barycentric coords of our intersection point on the origin face - Eigen::MatrixXd P; - P.resize(1, 3); - P << x, y, z; - Eigen::MatrixXd A; - A.resize(1, 3); - A << a[0], a[1], a[2]; - Eigen::MatrixXd B; - B.resize(1, 3); - B << b[0], b[1], b[2]; - Eigen::MatrixXd C; - C.resize(1, 3); - C << c[0], c[1], c[2]; - Eigen::MatrixXd L; - - igl::barycentric_coordinates(P, A, B, C, L); - - // compute the normal of our intersection point by interpolation - // ------------------------------------------------------------- - - // indices of the normals that are used by "imFaceIdx" - const std::vector &imFaceNormalIndices = inputMeshPtr->FN[imFaceIdx]; - my_assert(imFaceNormalIndices.size() == 3); - - // normals of vertices in origin face - const std::vector &Na_ = inputMeshPtr->N[imFaceNormalIndices[0]]; - const std::vector &Nb_ = inputMeshPtr->N[imFaceNormalIndices[1]]; - const std::vector &Nc_ = inputMeshPtr->N[imFaceNormalIndices[2]]; - - const Eigen::Vector3d Na(Na_[0], Na_[1], Na_[2]); - const Eigen::Vector3d Nb(Nb_[0], Nb_[1], Nb_[2]); - const Eigen::Vector3d Nc(Nc_[0], Nc_[1], Nc_[2]); - const Eigen::Vector3d baryCoords = L.row(0); + // the input-mesh face from which the current cc face came + // NOTE: there is a presumption here that the input mesh is a triangle-mesh! + const McUint32* imFaceVertexIndices = inputMeshPtr->pFaceVertexIndices + (imFaceIdx*3); + if (isSeamVertex) + { // normal is unknown and must be inferred + + // interpolate normal vector components from input-mesh values + + // coordinates of current point (whose barycentric coords we want) + vec3 p = {0.0, 0.0, 0.0}; + p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); + p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); + p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); + + /*McDouble x(ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); + McDouble y(ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); + McDouble z(ccVertices[((McSize)ccVertexIdx * 3u) + 2u]);*/ + + // // vertices of the origin face + //const std::vector& a = inputMeshPtr->V[imFace[0]]; + // const std::vector &b = inputMeshPtr->V[imFace[1]]; + // const std::vector &c = inputMeshPtr->V[imFace[2]]; + + // // barycentric coords of our intersection point on the origin face + // Eigen::MatrixXd P; + // P.resize(1, 3); + // P << x, y, z; + // Eigen::MatrixXd A; + // A.resize(1, 3); + // A << a[0], a[1], a[2]; + // Eigen::MatrixXd B; + // B.resize(1, 3); + // B << b[0], b[1], b[2]; + // Eigen::MatrixXd C; + // C.resize(1, 3); + // C << c[0], c[1], c[2]; + // Eigen::MatrixXd L; + + // igl::barycentric_coordinates(P, A, B, C, L); + + // vertices of the origin face (i.e. the face from which the current face came from). + // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation + // will be more complex, which is unnecessary for now. + vec3 a = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[0] * 3; + a.x = ptr[0]; + a.y = ptr[1]; + a.z = ptr[2]; + } + vec3 b = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[1] * 3; + b.x = ptr[0]; + b.y = ptr[1]; + b.z = ptr[2]; + } + + vec3 c = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[2] * 3; + c.x = ptr[0]; + c.y = ptr[1]; + c.z = ptr[2]; + } + + const vec3 bary = getBarycentricCoords(p, a, b, c); + + + + //inputMeshPtr->FN[imFaceIdx]; + //my_assert(imFaceNormalIndices.size() == 3); + + //// normals of vertices in origin face + //const std::vector &Na_ = inputMeshPtr->N[imFaceNormalIndices[0]]; + //const std::vector &Nb_ = inputMeshPtr->N[imFaceNormalIndices[1]]; + //const std::vector &Nc_ = inputMeshPtr->N[imFaceNormalIndices[2]]; + + //const Eigen::Vector3d Na(Na_[0], Na_[1], Na_[2]); + //const Eigen::Vector3d Nb(Nb_[0], Nb_[1], Nb_[2]); + //const Eigen::Vector3d Nc(Nc_[0], Nc_[1], Nc_[2]); + //const Eigen::Vector3d baryCoords = L.row(0); + + // normal coordinates of vertices in the origin face + + vec3 normalA = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0] * 3); + normalA.x = ptr[0]; + normalA.y = ptr[1]; + normalA.z = ptr[2]; + } + vec3 normalB = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1] * 3); + normalB.x = ptr[0]; + normalB.y = ptr[1]; + normalB.z = ptr[2]; + } + vec3 normalC = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2] * 3); + normalC.x = ptr[0]; + normalC.y = ptr[1]; + normalC.z = ptr[2]; + } + + // interpolate using barycentric coords - Eigen::Vector3d normal = (Na * baryCoords.x()) + (Nb * baryCoords.y()) + (Nc * baryCoords.z()) * (flipNormalsOnFace ? -1.0 : 1.0); + //Eigen::Vector3d normal = (Na * baryCoords.x()) + (Nb * baryCoords.y()) + (Nc * baryCoords.z()) * (flipNormalsOnFace ? -1.0 : 1.0); + // interpolate at point "p" using barycentric coords + const vec3 normal = ((normalA * bary.u) + (normalB * bary.v) + (normalC * bary.w)) * (flipNormalsOnFace ? -1.0 : 1.0); - ccVertexNormals[ccVertexIdx] += normal; + ccVertexNormals[ccVertexIdx] = ccVertexNormals[ccVertexIdx] + normal; // accumulate (so that we can later compute the average) if (ccSeamVertexToRefCount.find(ccVertexIdx) == ccSeamVertexToRefCount.cend()) { @@ -426,13 +564,17 @@ int main() else { // normal must be inferred from input mesh - if (ccVertexNormals[ccVertexIdx].norm() == 0) + vec3& normal = ccVertexNormals[ccVertexIdx]; + + if(normal.x == McDouble(0.0) && normal.y == McDouble(0.0) && + normal.z == McDouble(0.0)) // not yet copied/defined { - int faceVertexOffset = -1; + McInt32 faceVertexOffset = -1; + // for each vertex index in face - for (int i = 0; i < (int)imFace.size(); ++i) + for(McUint32 i = 0; i < 3; ++i) { - if ((int)imFace[i] == (int)imVertexIdx) + if ( imFaceVertexIndices[i] == imVertexIdx) { faceVertexOffset = i; break; @@ -441,82 +583,237 @@ int main() my_assert(faceVertexOffset != -1); - int imNormalIdx = inputMeshPtr->FN[imFaceIdx][faceVertexOffset]; - const std::vector &n = inputMeshPtr->N[imNormalIdx]; - my_assert(n.size() == 3); - Eigen::Vector3d normal = Eigen::Vector3d(n[0], n[1], n[2]) * (flipNormalsOnFace ? -1.0 : 1.0); - - ccVertexNormals[ccVertexIdx] = normal; + const McUint32 imNormalIdx = imFaceNormalIndices[faceVertexOffset]; + //const std::vector &n = inputMeshPtr->N[imNormalIdx]; + const McDouble* imNormal = inputMeshPtr->pNormals + (imNormalIdx * 3); + //my_assert(n.size() == 3); + //Eigen::Vector3d normal = Eigen::Vector3d(n[0], n[1], n[2]) * (flipNormalsOnFace ? -1.0 : 1.0); + normal.x = imNormal[0]; + normal.y = imNormal[1]; + normal.z = imNormal[2]; + //ccVertexNormals[ccVertexIdx] = normal; } } - } // for (int v = 0; v < faceSize; ++v) { - - faceVertexOffsetBase += faceSize; - } // for (int f = 0; f < ccFaceCount; ++f) { + + } // for (McInt32 v = 0; v < faceSize; ++v) { + faceVertexOffsetBase += faceSize; + } // for (McInt32 f = 0; f < ccFaceCount; ++f) { - for (std::map::const_iterator it = ccSeamVertexToRefCount.cbegin(); it != ccSeamVertexToRefCount.cend(); ++it) + // for each seam-vertex + for (std::map::const_iterator it = ccSeamVertexToRefCount.cbegin(); it != ccSeamVertexToRefCount.cend(); ++it) { - const int ccSeamVertexIndex = it->first; - const int refCount = it->second; + const McInt32 ccSeamVertexIndex = it->first; + const McInt32 refCount = it->second; my_assert(refCount >= 1); - ccVertexNormals[ccSeamVertexIndex] /= (double)refCount; // average + vec3& normal = ccVertexNormals[ccSeamVertexIndex]; + normal = normal * (1.0/((McDouble) refCount)); // average + + // squared length + const McDouble len2 = (normal.x * normal.x) + (normal.y * normal.y) + (normal.z * normal.z); + const McDouble len = std::sqrt(len2); // length + + normal = normal * (1.0 / len); // re-normalize } + ccFaceVertexNormalIndices = ccFaceIndices; // since number of vertices is the same as number of normals + // save cc mesh to .obj file // ------------------------- char fnameBuf[64]; sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), ci); - std::string fpath(DATA_DIR "/" + std::string(fnameBuf)); - - printf("write file: %s\n", fpath.c_str()); - - std::ofstream file(fpath); - - // write vertices and normals - - for (int i = 0; i < (int)ccVertexCount; ++i) - { - double x = ccVertices[(McSize)i * 3 + 0]; - double y = ccVertices[(McSize)i * 3 + 1]; - double z = ccVertices[(McSize)i * 3 + 2]; - file << "v " << std::setprecision(std::numeric_limits::digits10 + 1) << x << " " << y << " " << z << std::endl; - - Eigen::Vector3d n = ccVertexNormals[i]; - file << "vn " << std::setprecision(std::numeric_limits::digits10 + 1) << n.x() << " " << n.y() << " " << n.z() << std::endl; - } - - // write faces (with normal indices) - - faceVertexOffsetBase = 0; - for (int i = 0; i < (int)ccFaceCount; ++i) - { - int faceSize = faceSizes.at(i); - - file << "f "; - for (int j = 0; j < faceSize; ++j) - { - const int idx = faceVertexOffsetBase + j; - const int ccVertexIdx = ccFaceIndices[idx]; - file << (ccVertexIdx + 1) << "//" << (ccVertexIdx + 1) << " "; - } - file << std::endl; - - faceVertexOffsetBase += faceSize; - } + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + mioWriteOBJ(fpath.c_str(), + ccVertices.data(), + (McDouble*)ccVertexNormals.data(), + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + ccFaceVertexNormalIndices.data(), + ccVertexCount, + (McUint32)ccVertexNormals.size(), + 0, // numTexCoords + ccFaceCount); + + //printf("write file: %s\n", fpath.c_str()); + + //std::ofstream file(fpath); + + //// write vertices and normals + + //for (McInt32 i = 0; i < (McInt32)ccVertexCount; ++i) + //{ + // McDouble x = ccVertices[(McSize)i * 3 + 0]; + // McDouble y = ccVertices[(McSize)i * 3 + 1]; + // McDouble z = ccVertices[(McSize)i * 3 + 2]; + // file << "v " << std::setprecision(std::numeric_limits::digits10 + 1) << x << " " << y << " " << z << std::endl; + + // Eigen::Vector3d n = ccVertexNormals[i]; + // file << "vn " << std::setprecision(std::numeric_limits::digits10 + 1) << n.x() << " " << n.y() << " " << n.z() << std::endl; + //} + + //// write faces (with normal indices) + + //faceVertexOffsetBase = 0; + //for (McInt32 i = 0; i < (McInt32)ccFaceCount; ++i) + //{ + // McInt32 faceSize = faceSizes.at(i); + + // file << "f "; + // for (McInt32 j = 0; j < faceSize; ++j) + // { + // const McInt32 idx = faceVertexOffsetBase + j; + // const McInt32 ccVertexIdx = ccFaceIndices[idx]; + // file << (ccVertexIdx + 1) << "//" << (ccVertexIdx + 1) << " "; + // } + // file << std::endl; + + // faceVertexOffsetBase += faceSize; + //} } - // free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); - my_assert(err == MC_NO_ERROR); + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, 0, NULL); - // destroy context - // ------------------ - err = mcReleaseContext(context); + my_assert(status == MC_NO_ERROR); + + // + // destroy context + // + status = mcReleaseContext(context); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); return 0; } + + +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation) +{ + // get type + McConnectedComponentType ccType = (McConnectedComponentType)0; + + McResult status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_TYPE, + sizeof(McConnectedComponentType), + &ccType, + NULL); + + my_assert(status == MC_NO_ERROR); + + std::string name; + McPatchLocation patchLocation = (McPatchLocation)0; + + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + name += "seam"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + name += "input"; + } + else + { + isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + name += isFragment ? "frag" : "patch"; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, + sizeof(McPatchLocation), + &patchLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += patchLocation == MC_PATCH_LOCATION_INSIDE + ? ".ploc=in" + : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".ploc=out" : ".ploc=undef"); + + if(isFragment) + { + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, + sizeof(McFragmentLocation), + &fragmentLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE + ? ".floc=abv" + : ".floc=blw"; // missing loc="undefined" case + + McFragmentSealType sType = (McFragmentSealType)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, + sizeof(McFragmentSealType), + &sType, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".seal=yes" : ".seal=no"; + } + } + + McBool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + // connected-components is not a fragment && it is a seam + if(!ccIsFromSrcMesh) + { + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + // get origin + McSeamOrigin ccOrig = (McSeamOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McSeamOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); + name += ccIsFromSrcMesh ? ".orig=s" : ".orig=c"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + McInputOrigin ccOrig = (McInputOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McInputOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); + name += ccIsFromSrcMesh ? ".orig=s" : ".orig=c"; + } + } + + return name; +} \ No newline at end of file From 8da0a81a888c367f51dae03bdef961d683a96ae8 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Wed, 10 Jan 2024 10:17:13 +0000 Subject: [PATCH 06/23] add clang format file --- .clang-format | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e2c4fe9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,129 @@ +# Checkout config tool: https://zed0.co.uk/clang-format-configurator/ +# Or http://cf.monofraps.net/ +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# https://github.com/01org/parameter-framework/blob/master/.clang-format + +# Tested on: clang-format version 6.0.1 + + +# Common settings +BasedOnStyle: WebKit +TabWidth: 4 +IndentWidth: 4 +UseTab: Always +ColumnLimit: 100 + +# Other languages JavaScript, Proto + +--- +Language: Cpp + +# http://releases.llvm.org/6.0.1/tools/clang/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code +# int formatted_code; +# // clang-format off +# void unformatted_code ; +# // clang-format on +# void formatted_code_again; + +DisableFormat: false +Standard: Cpp11 + +AccessModifierOffset: -4 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false + +# Configure each individual brace in BraceWrapping +BreakBeforeBraces: Custom +# Control of individual brace wrapping cases +BraceWrapping: { + AfterClass: 'true' + AfterControlStatement: 'true' + AfterEnum : 'true' + AfterFunction : 'true' + AfterNamespace : 'true' + AfterStruct : 'true' + AfterUnion : 'true' + BeforeCatch : 'true' + BeforeElse : 'true' + IndentBraces : 'false' + AfterExternBlock : 'true' + SplitEmptyFunction : 'false' + SplitEmptyRecord : 'false' + SplitEmptyNamespace : 'true' +} + +BreakAfterJavaFieldAnnotations: true +BreakBeforeInheritanceComma: false +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakStringLiterals: true + +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +SpaceBeforeCpp11BracedList: false +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IndentCaseLabels: false +FixNamespaceComments: true +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +JavaScriptQuotes: Double +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 + +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceAfterTemplateKeyword: true +SpaceBeforeInheritanceColon: true + +SortUsingDeclarations: true +SortIncludes: true + +# Comments are for developers, they should arrange them +ReflowComments: false + +IncludeBlocks: Preserve +IndentPPDirectives: AfterHash +--- From 4f350d100e3d7d1d971c754c0d48f9aa0ab74434 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Fri, 12 Jan 2024 21:44:48 +0000 Subject: [PATCH 07/23] update more tutorial files --- tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp | 727 ++++--------- tutorials/BasicCmdLineApp/CMakeLists.txt | 28 - tutorials/CMakeLists.txt | 15 +- tutorials/CSGBoolean/CMakeLists.txt | 28 - tutorials/CSGBoolean/CSGBoolean.cpp | 533 ++++++---- tutorials/FaceNormals/FaceNormals.cpp | 2 +- tutorials/HelloWorld/CMakeLists.txt | 6 - tutorials/HelloWorld/HelloWorld.cpp | 183 ++-- tutorials/TextureCoordinates/CMakeLists.txt | 27 - .../TextureCoordinates/TextureCoordinates.cpp | 988 +++++++++++------- tutorials/VertexNormals/CMakeLists.txt | 27 - tutorials/VertexNormals/VertexNormals.cpp | 95 +- 12 files changed, 1228 insertions(+), 1431 deletions(-) delete mode 100644 tutorials/BasicCmdLineApp/CMakeLists.txt delete mode 100644 tutorials/CSGBoolean/CMakeLists.txt delete mode 100644 tutorials/HelloWorld/CMakeLists.txt delete mode 100644 tutorials/TextureCoordinates/CMakeLists.txt delete mode 100644 tutorials/VertexNormals/CMakeLists.txt diff --git a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp index 973ae39..2da063b 100644 --- a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp +++ b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp @@ -1,83 +1,70 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * BasicCmdLineApp.cpp + * + * \brief: + * This tutorial shows how to implement a basic command line application + * with mcut. This simple app accepts two input meshes and computes their + * intersection to then dump the output connected components after cutting. + * The accepted file formats are: + * - obj + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" -#include -#include // PRId64 +#include "mio/mio.h" + +#include +#include #include +#include // PRId64 #include #include -#include -#include -// libigl dependencies -#include -#include -#include -#include -#include - -#define stringize(s) #s -#define XSTR(s) stringize(s) - -#define ASSERT(a) \ - do { \ - if (0 == (a)) { \ - std::fprintf(stderr, \ - "Assertion failed: %s, " \ - "%d at \'%s\'\n", \ - __FILE__, \ - __LINE__, \ - XSTR(a)); \ - std::abort(); \ - } \ - } while (0) +#define my_assert(cond) \ + if(!(cond)) \ + { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::exit(1); \ + } #define mcCheckError(errCode) mcCheckError_(errCode, __FILE__, __LINE__) -void mcCheckError_(McResult err, const char* file, int line); +void mcCheckError_(McResult status, const char* file, McUint32 line); void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned int id, + McUint32 id, McDebugSeverity severity, size_t length, const char* message, const void* userParam); -void readMesh(const std::string& path, std::vector& V, std::vector& F, std::vector& Fsizes); -void writeOBJ( - const std::string& path, - const float* ccVertices, - const int ccVertexCount, - const uint32_t* ccFaceIndices, - const uint32_t* faceSizes, - const uint32_t ccFaceCount); - -int main(int argc, char* argv[]) +McUint32 main(McUint32 argc, char* argv[]) { bool help = false; - for (int i = 0; help == false && i < argc; ++i) { + for (McUint32 i = 0; help == false && i < argc; ++i) { if (!strcmp("--help", argv[i]) || !strcmp("-h", argv[i])) { help = true; } @@ -91,188 +78,255 @@ int main(int argc, char* argv[]) const char* srcMeshFilePath = argv[1]; const char* cutMeshFilePath = argv[2]; - std::cout << "source-mesh file:" << srcMeshFilePath << std::endl; - std::cout << "cut-mesh file:" << cutMeshFilePath << std::endl; - - // load meshes - // ----------- - std::vector srcMeshVertices; - std::vector srcMeshFaceIndices; - std::vector srcMeshFaceSizes; - readMesh(srcMeshFilePath, srcMeshVertices, srcMeshFaceIndices, srcMeshFaceSizes); + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; - printf("src-mesh vertices=%d faces=%d\n", (int)srcMeshVertices.size()/3, (int)srcMeshFaceSizes.size()); - - std::vector cutMeshVertices; - std::vector cutMeshFaceIndices; - std::vector cutMeshFaceSizes; - readMesh(cutMeshFilePath, cutMeshVertices, cutMeshFaceIndices, cutMeshFaceSizes); + // + // read-in the source-mesh from file + // + mioReadOBJ(srcMeshFilePath, + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(cutMeshFilePath, + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); - printf("cut-mesh vertices=%d faces=%d\n", (int)cutMeshVertices.size()/3, (int)cutMeshFaceSizes.size()); + // + // create a context + // + McContext context = MC_NULL_HANDLE; - // init dispatch context - // --------------------- - McContext context; -#ifdef NDEBUG - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); + #ifdef NDEBUG + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); #else - McResult err = mcCreateContext(&context, MC_DEBUG); + McResult status = mcCreateContext(&context, MC_DEBUG); #endif - mcCheckError(err); + mcCheckError(status); + // // config debug output - // ----------------------- + // + McSize numBytes = 0; McFlags contextFlags; - err = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); - mcCheckError(err); - ASSERT(sizeof(McFlags) == numBytes); + status = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); - err = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); - mcCheckError(err); + mcCheckError(status); - if (contextFlags & MC_DEBUG) { + my_assert(sizeof(McFlags) == numBytes); + + status = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + + mcCheckError(status); + + if (contextFlags & MC_DEBUG) { // did the user enable debugging mode? mcDebugMessageCallback(context, mcDebugOutput, nullptr); mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); } + // + // do the cutting + // - // do the cutting - // -------------- - err = mcDispatch( + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, // source mesh - srcMeshVertices.data(), - srcMeshFaceIndices.data(), - srcMeshFaceSizes.data(), - (uint32_t)srcMeshVertices.size() / 3, - (uint32_t)srcMeshFaceSizes.size(), - // cut mesh - cutMeshVertices.data(), - cutMeshFaceIndices.data(), - cutMeshFaceSizes.data(), - (uint32_t)cutMeshVertices.size() / 3, - (uint32_t)cutMeshFaceSizes.size()); - - mcCheckError(err); - - uint32_t numConnComps; - std::vector pConnComps; + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + mcCheckError(status); + + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + + McUint32 connectedComponentCount; + std::vector connectedComponents; // we want to query all available connected components: - // --> fragments, patches and seamed - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); - mcCheckError(err); + // --> fragments, patches, seams and inputs + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); + + mcCheckError(status); - if (numConnComps == 0) { + if (connectedComponentCount == 0) { printf("no connected components found\n"); std::exit(0); } - pConnComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)pConnComps.size(), pConnComps.data(), NULL); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - mcCheckError(err); + mcCheckError(status); // // query connected component data // - for (int i = 0; i < (int)pConnComps.size(); ++i) { - McConnectedComponent connCompId = pConnComps[i]; // connected compoenent id + for (McUint32 i = 0; i < (McUint32)connectedComponents.size(); ++i) { - printf("connected component: %d\n", i); + McConnectedComponent cc = connectedComponents[i]; // handle - // vertex array - numBytes = 0; - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - mcCheckError(err); - uint32_t numberOfVertices = (McUint32)(numBytes / (sizeof(double)*3)); - ASSERT(numberOfVertices >= 3); - std::vector vertices((size_t)numberOfVertices * 3u); + // + // ccVertices + // + + McSize numBytes = 0; + + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices(ccVertexCount * 3u, 0.0); - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)vertices.data(), NULL); - mcCheckError(err); + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, + numBytes, + (void*)ccVertices.data(), + NULL); - printf("vertices: %d\n", (int)vertices.size() / 3); + my_assert(status == MC_NO_ERROR); #if 1 // triangulated output - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - ASSERT(err == MC_NO_ERROR); - std::vector faceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, faceIndices.data(), NULL); - ASSERT(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - std::vector faceSizes(faceIndices.size()/3, 3); + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccFaceIndices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceSizes(ccFaceIndices.size()/3, 3); #else // nontriangulated output // face indices numBytes = 0; - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - mcCheckError(err); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + mcCheckError(status); - ASSERT(numBytes > 0); + my_assert(numBytes > 0); - std::vector faceIndices; - faceIndices.resize(numBytes / sizeof(uint32_t)); + std::vector ccFaceIndices; + ccFaceIndices.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, faceIndices.data(), NULL); - mcCheckError(err); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); + mcCheckError(status); // face sizes numBytes = 0; - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - mcCheckError(err); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + mcCheckError(status); - ASSERT(numBytes > 0); + my_assert(numBytes > 0); - std::vector faceSizes; - faceSizes.resize(numBytes / sizeof(uint32_t)); + std::vector ccFaceSizes; + ccFaceSizes.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - mcCheckError(err); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); + mcCheckError(status); #endif - printf("faces: %d\n", (int)faceSizes.size()); - - char fnameBuf[512]; - sprintf(fnameBuf, "cc%d.obj", i); - - std::vector f; - for(uint32_t j =0; j < (uint32_t)vertices.size(); ++j) - f.push_back((float)vertices[j]); - writeOBJ(fnameBuf, - (float*)f.data(), - (uint32_t)vertices.size() / 3, - (uint32_t*)faceIndices.data(), - (uint32_t*)faceSizes.data(), - (uint32_t)faceSizes.size()); + + // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, "conncomp%d.obj", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + mioWriteOBJ( + fpath.c_str(), + ccVertices.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); } - // destroy internal data associated with each connected component - err = mcReleaseConnectedComponents(context, (uint32_t)pConnComps.size(), pConnComps.data()); - mcCheckError(err); + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, 0, NULL); - // destroy context - err = mcReleaseContext(context); - mcCheckError(err); + my_assert(status == MC_NO_ERROR); + + // + // destroy context + // + status = mcReleaseContext(context); + + my_assert(status == MC_NO_ERROR); return 0; } void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned int id, + McUint32 id, McDebugSeverity severity, size_t length, const char* message, const void* userParam) { - - //printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - //printf("userParam=%p\n", userParam); - std::string debug_src; switch (source) { case MC_DEBUG_SOURCE_API: @@ -284,6 +338,7 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, case MC_DEBUG_SOURCE_ALL: break; } + std::string debug_type; switch (type) { case MC_DEBUG_TYPE_ERROR: @@ -323,10 +378,10 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(),severity_str.c_str(), length, message); } -void mcCheckError_(McResult err, const char* file, int line) +void mcCheckError_(McResult status, const char* file, McUint32 line) { std::string error; - switch (err) { + switch (status) { case MC_OUT_OF_MEMORY: error = "MC_OUT_OF_MEMORY"; break; @@ -343,326 +398,8 @@ void mcCheckError_(McResult err, const char* file, int line) error = "UNKNOWN"; break; } - if (err) { + if (status) { std::cout << error << " | " << file << " (" << line << ")" << std::endl; } -} - -// libIGL's "writeOBJ" function fails when dealing with facex with > 4 vertices. -void writeOBJ( - const std::string& path, - const float* ccVertices, - const int ccVertexCount, - const uint32_t* ccFaceIndices, - const uint32_t* faceSizes, - const uint32_t ccFaceCount) -{ - printf("write file: %s\n", path.c_str()); - - std::ofstream file(path); - - // write vertices and normals - for (uint32_t i = 0; i < (uint32_t)ccVertexCount; ++i) { - double x = ccVertices[(McSize)i * 3 + 0]; - double y = ccVertices[(McSize)i * 3 + 1]; - double z = ccVertices[(McSize)i * 3 + 2]; - file << "v " << x << " " << y << " " << z << std::endl; - } - - int faceVertexOffsetBase = 0; - - // for each face in CC - for (uint32_t f = 0; f < ccFaceCount; ++f) { - - int faceSize = faceSizes[f]; - file << "f "; - // for each vertex in face - for (int v = 0; (v < faceSize); v++) { - const int ccVertexIdx = ccFaceIndices[(McSize)faceVertexOffsetBase + v]; - file << (ccVertexIdx + 1) << " "; - } // for (int v = 0; v < faceSize; ++v) { - file << std::endl; - - faceVertexOffsetBase += faceSize; - } -} -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } - - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** lineBuf, size_t* len) -{ - while (getline(lineBuf, len, file)) { - if (strlen(*lineBuf) > 1 && (*lineBuf)[0] != '#') { - return true; - } - } - return false; -} - - void readOFF( - const char* fpath, - float** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces) -{ - // using "rb" instead of "r" to prevent linefeed conversion - // See: https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* lineBuf = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(lineBuf, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(lineBuf, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (float*)malloc(sizeof(float) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (float)(*numVertices); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - float x, y, z; - sscanf(lineBuf, "%f %f %f", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - char* lineBufShifted = lineBuf; - int j = 0; - - while (j < n) { // parse remaining numbers on lineBuf - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number - - int val; - sscanf(lineBufShifted, "%d", &val); - - (*pFaceIndices)[indexOffset + j] = val; - j++; - } - - indexOffset += n; - } - - free(lineBuf); - - fclose(file); -} -void readMesh(const std::string& path, std::vector& V, std::vector& F, std::vector& Fsizes) -{ - printf("read: %s\n", path.c_str()); - - Eigen::MatrixXd Vmat; - Eigen::MatrixXi Fmat; - - if (path.find(".obj") != std::string::npos) { - igl::readOBJ(path, Vmat, Fmat); - - for (int i = 0; i < (int)Vmat.rows(); ++i) { - const Eigen::VectorXd v = Vmat.row(i); - V.push_back((double)v(0)); - V.push_back((double)v(1)); - V.push_back((double)v(2)); - } - - for (int i = 0; i < (int)Fmat.rows(); ++i) { - const Eigen::VectorXi f = Fmat.row(i); - for (int j = 0; j < (int)f.rows(); ++j) { - F.push_back((uint32_t)f(j)); - } - - Fsizes.push_back((uint32_t)f.rows()); - } - } - else if(path.find(".off") != std::string::npos){ - float* pVertices=nullptr; - unsigned int* pFaceIndices=nullptr; - unsigned int* pFaceSizes=nullptr; - unsigned int numVertices=0; - unsigned int numFaces=0; - - readOFF(path.c_str(), &pVertices, &pFaceIndices, - &pFaceSizes, - &numVertices, - &numFaces); - - for (int i = 0; i < (int)numVertices; ++i) { - V.push_back(pVertices[i*3+0]); - V.push_back(pVertices[i*3+1]); - V.push_back(pVertices[i*3+2]); - } - int off = 0; - for (int i = 0; i < (int)numFaces; ++i) { - unsigned int faceSize = pFaceSizes[i]; - - for (int j = 0; j < (int)faceSize; ++j) { - F.push_back(pFaceIndices[off + j]); - } - off +=faceSize; - Fsizes.push_back(faceSize); - } - - free(pVertices); - pVertices=nullptr; - free(pFaceIndices); - pFaceIndices=nullptr; - free(pFaceSizes); - pFaceSizes=nullptr; - } - else{ - printf("error: expected .obj or .off file\n"); - std::exit(1); - } - } diff --git a/tutorials/BasicCmdLineApp/CMakeLists.txt b/tutorials/BasicCmdLineApp/CMakeLists.txt deleted file mode 100644 index 8707c1c..0000000 --- a/tutorials/BasicCmdLineApp/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(BasicCmdLineApp BasicCmdLineApp.cpp) -message(STATUS "extra_libs = ${extra_libs}") -target_link_libraries(BasicCmdLineApp mcut ${extra_libs}) -target_include_directories(BasicCmdLineApp PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_options(BasicCmdLineApp PRIVATE ${compilation_flags}) -target_compile_definitions(BasicCmdLineApp PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 0d0092b..3354c52 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -14,12 +14,11 @@ endfunction() create_tutorial_target(AdjacentFaces) create_tutorial_target(FaceNormals) create_tutorial_target(VertexNormals) +create_tutorial_target(TextureCoordinates) # untested +create_tutorial_target(BasicCmdLineApp) +create_tutorial_target(HelloWorld) +create_tutorial_target(CSGBoolean) -#add_subdirectory(BasicCmdLineApp) -#add_subdirectory(HelloWorld) -#add_subdirectory(TextureCoordinates) -#add_subdirectory(VertexNormals) -#add_subdirectory(CSGBoolean) #add_subdirectory(Triangulation) #add_subdirectory(TriangulatedFaceMaps) #add_subdirectory(EventCallback) @@ -30,4 +29,10 @@ create_tutorial_target(VertexNormals) #add_subdirectory(QuerySeamVerticesSorted) #add_subdirectory(InOutQuery) +# +# TODO +# +#add_subdirectory(ConnectedComponentProperties) +#add_subdirectory(EnableDebugMode) + diff --git a/tutorials/CSGBoolean/CMakeLists.txt b/tutorials/CSGBoolean/CMakeLists.txt deleted file mode 100644 index fc95b8e..0000000 --- a/tutorials/CSGBoolean/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(CSGBoolean CSGBoolean.cpp) -target_link_libraries(CSGBoolean mcut ${extra_libs}) -target_include_directories(CSGBoolean PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_definitions(CSGBoolean PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") -target_compile_options(CSGBoolean PRIVATE ${compilation_flags}) -target_compile_definitions(CSGBoolean PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/CSGBoolean/CSGBoolean.cpp b/tutorials/CSGBoolean/CSGBoolean.cpp index ae47178..5da69a9 100644 --- a/tutorials/CSGBoolean/CSGBoolean.cpp +++ b/tutorials/CSGBoolean/CSGBoolean.cpp @@ -1,24 +1,41 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * CSGBoolean.cpp + * + * \brief: + * This tutorial shows how to compute Boolean operations between two meshes + * that represent solids with MCUT (Constructive Solid Geometry). + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + +#include "mcut/mcut.h" +#include "mio/mio.h" + +#include +#include +#include +#include +#include #if defined(_WIN32) #define _CRT_SECURE_NO_WARNINGS 1 @@ -34,40 +51,31 @@ std::exit(1); \ } -/* -This tutorial shows how to compute boolean operations using MCUT. -*/ - -#include "mcut/mcut.h" - -#include -#include -#include -#include -// libigl dependencies -#include -#include -#include -#include -#include - -struct InputMesh { - // variables for reading .obj file data with libigl - std::vector> V; - std::vector> F; - - // variables for mesh data in a format suited for MCUT - std::string fpath; // path to mesh file - std::vector faceSizesArray; // vertices per face - std::vector faceIndicesArray; // face indices - std::vector vertexCoordsArray; // vertex coords -}; +void MCAPI_PTR mcDebugOutput(McDebugSource source, + McDebugType type, + McUint32 id, + McDebugSeverity severity, + size_t length, + const char* message, + const void* userParam); int main(int argc, const char* argv[]) { - // load meshes. - // ----------------- - InputMesh srcMesh; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; const bool user_provided_meshes = argc > 1; if (user_provided_meshes && argc < 3) { @@ -85,64 +93,42 @@ int main(int argc, const char* argv[]) printf("NOTE: using default meshes\n"); } - srcMesh.fpath = user_provided_meshes ? argv[1] : DATA_DIR "/cube.obj"; - bool srcMeshLoaded = igl::read_triangle_mesh(srcMesh.fpath, srcMesh.V, srcMesh.F); - - if (!srcMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", srcMesh.fpath.c_str()); - std::exit(1); - } - - // copy vertices - for (int i = 0; i < (int)srcMesh.V.size(); ++i) { - const std::vector& v = srcMesh.V[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.F.size(); ++i) { - const std::vector& f = srcMesh.F[i]; - for (int j = 0; j < (int)f.size(); ++j) { - srcMesh.faceIndicesArray.push_back(f[j]); - } - - srcMesh.faceSizesArray.push_back((uint32_t)f.size()); - } - - printf("source mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)srcMesh.V.size(), (int)srcMesh.F.size()); - - InputMesh cutMesh; - cutMesh.fpath = user_provided_meshes ? argv[2] : DATA_DIR "/torus.obj"; - bool cutMeshLoaded = igl::read_triangle_mesh(cutMesh.fpath, cutMesh.V, cutMesh.F); - - if (!cutMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", cutMesh.fpath.c_str()); - std::exit(1); - } - - // copy vertices - for (int i = 0; i < (int)cutMesh.V.size(); ++i) { - const std::vector& v = cutMesh.V[i]; - my_assert(v.size() == 3); - cutMesh.vertexCoordsArray.push_back(v[0]); - cutMesh.vertexCoordsArray.push_back(v[1]); - cutMesh.vertexCoordsArray.push_back(v[2]); - } - - // copy faces - for (int i = 0; i < (int)cutMesh.F.size(); ++i) { - const std::vector& f = cutMesh.F[i]; - for (int j = 0; j < (int)f.size(); ++j) { - cutMesh.faceIndicesArray.push_back(f[j]); - } - - cutMesh.faceSizesArray.push_back((uint32_t)f.size()); - } - - printf("cut mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)cutMesh.V.size(), (int)cutMesh.F.size()); + const char* srcMeshFilePath = user_provided_meshes ? argv[1] : DATA_DIR "/cube.obj"; + + // + // read-in the source-mesh from file + // + mioReadOBJ(srcMeshFilePath, + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + const char* cutMeshFilePath = user_provided_meshes ? argv[2] : DATA_DIR "/torus.obj"; + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(cutMeshFilePath, + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); std::string boolOpStr = "*"; @@ -163,19 +149,49 @@ int main(int argc, const char* argv[]) else{ printf("NOTE: computing all boolean ops.\n"); } + + // // create a context - // ------------------- + // McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); - my_assert(err == MC_NO_ERROR); + // a debug context is created in a you load your own (possibly faulty) meshes + McResult status = mcCreateContext(&context, MC_DEBUG); + + my_assert(status == MC_NO_ERROR); + + // + // config debug output + // + + McSize numBytes = 0; + McFlags contextFlags; + + status = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); + + my_assert(status == MC_NO_ERROR); + + my_assert(sizeof(McFlags) == numBytes); + + status = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + + my_assert(status == MC_NO_ERROR); + + if (contextFlags & MC_DEBUG) { // did the user enable debugging mode? + mcDebugMessageCallback(context, mcDebugOutput, nullptr); + mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); + } + + // // do the cutting (boolean ops) - // ----------------------------- - printf("\nInputs: \n\tShape A = %s'.\n\tShape B = '%s'\n\n", srcMesh.fpath.c_str(), cutMesh.fpath.c_str()); + // + + printf("\nInputs: \n\tSolid-A = %s'.\n\tSolid-B = '%s'\n\n", srcMeshFilePath, cutMeshFilePath); // We can either let MCUT compute all possible meshes (including patches etc.), or we can - // constrain the library to compute exactly the boolean op mesh we want. This 'constrained' case - // is done with the following flags. + // constrain the library runtime to compute exactly the boolean op mesh we want. This 'constrained' + // case is done with the flags that follow below. + // // NOTE: you can extend these flags by bitwise ORing with additional flags (see `McDispatchFlags' in mcut.h) const std::map booleanOps = { { "A_NOT_B", MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE }, @@ -184,7 +200,9 @@ int main(int argc, const char* argv[]) { "INTERSECTION", MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW } }; + // for each supported type of boolean operation for (std::map::const_iterator boolOpIter = booleanOps.cbegin(); boolOpIter != booleanOps.cend(); ++boolOpIter) { + if (boolOpIter->first != boolOpStr && boolOpStr != "*") { continue; } @@ -192,114 +210,145 @@ int main(int argc, const char* argv[]) const McFlags boolOpFlags = boolOpIter->second; const std::string boolOpName = boolOpIter->first; - printf("compute %s\n", boolOpName.c_str()); + printf("operation %s\n", boolOpName.c_str()); - err = mcDispatch( + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | // vertices are in array of doubles MC_DISPATCH_ENFORCE_GENERAL_POSITION | // perturb if necessary boolOpFlags, // filter flags which specify the type of output we want // source mesh - reinterpret_cast(srcMesh.vertexCoordsArray.data()), - reinterpret_cast(srcMesh.faceIndicesArray.data()), - srcMesh.faceSizesArray.data(), - static_cast(srcMesh.vertexCoordsArray.size() / 3), - static_cast(srcMesh.faceSizesArray.size()), + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, // cut mesh - reinterpret_cast(cutMesh.vertexCoordsArray.data()), - cutMesh.faceIndicesArray.data(), - cutMesh.faceSizesArray.data(), - static_cast(cutMesh.vertexCoordsArray.size() / 3), - static_cast(cutMesh.faceSizesArray.size())); - - my_assert(err == MC_NO_ERROR); - - // query the number of available connected component - // -------------------------------------------------- - uint32_t numConnComps; - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &numConnComps); - my_assert(err == MC_NO_ERROR); - - printf("connected components: %d\n", (int)numConnComps); - - if (numConnComps == 0) { + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + my_assert(status == MC_NO_ERROR); + + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + + // + // query the number of available fragments + // NOTE: a boolean operation shall always give fragments as output + // + + McUint32 connectedComponentCount = 0; + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &connectedComponentCount); + my_assert(status == MC_NO_ERROR); + + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - // my_assert(numConnComps == 1); // exactly 1 result (for this example) + std::vector connectedComponents(connectedComponentCount, MC_NULL_HANDLE); + + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - std::vector connectedComponents(numConnComps, MC_NULL_HANDLE); - connectedComponents.resize(numConnComps); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (uint32_t)connectedComponents.size(), connectedComponents.data(), NULL); + my_assert(status == MC_NO_ERROR); - my_assert(err == MC_NO_ERROR); + // + // query the data of the output connected component from MCUT + // - // query the data of each connected component from MCUT - // ------------------------------------------------------- + McConnectedComponent cc = connectedComponents[0]; - McConnectedComponent connComp = connectedComponents[0]; - - // query the vertices - // ---------------------- + // + // vertices + // McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); - std::vector ccVertices((McSize)ccVertexCount * 3u, 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the faces - // ------------------- + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices((McSize)ccVertexCount * 3u, 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // faces + // numBytes = 0; #if 1 // triangulated faces - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); - std::vector faceSizes(ccFaceIndices.size() / 3, 3); + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccFaceIndices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceSizes(ccFaceIndices.size() / 3, 3); #else // non-triangulated faces (i.e. N-gons) - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // face sizes + // - // query the face sizes - // ------------------------ numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector faceSizes(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceSizes(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); + + my_assert(status == MC_NO_ERROR); #endif - const uint32_t ccFaceCount = static_cast(faceSizes.size()); + const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); /// ------------------------------------------------------------------------------------ - // Here we show, how to know when connected components, pertain particular boolean operations. + // Here we show, how to know when connected components pertain particular boolean operations. McPatchLocation patchLocation = (McPatchLocation)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL); + my_assert(status == MC_NO_ERROR); McFragmentLocation fragmentLocation = (McFragmentLocation)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); + my_assert(status == MC_NO_ERROR); + + // + // reverse the vertex winding order, if required + // + if((fragmentLocation == MC_FRAGMENT_LOCATION_BELOW) && (patchLocation == MC_PATCH_LOCATION_OUTSIDE)) + { + std::reverse(ccFaceIndices.begin(), ccFaceIndices.end()); + } - // save cc mesh to .obj file - // ------------------------- + // + // save connected component (mesh) to an .obj file + // auto extract_fname = [](const std::string& full_path) { // get filename @@ -310,50 +359,96 @@ int main(int argc, const char* argv[]) return file_without_extension; }; - std::string fpath(OUTPUT_DIR "/" + extract_fname(srcMesh.fpath) + "_" + extract_fname(cutMesh.fpath) + "_" + boolOpName + ".obj"); + const std::string fpath(OUTPUT_DIR "/" + extract_fname(srcMeshFilePath) + "_" + extract_fname(cutMeshFilePath) + "_" + boolOpName + ".obj"); + + mioWriteOBJ( + fpath.c_str(), + ccVertices.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); + + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, (McUint32)connectedComponents.size(), connectedComponents.data()); + + my_assert(status == MC_NO_ERROR); + } - printf("write file: %s\n", fpath.c_str()); + // + // destroy context + // + status = mcReleaseContext(context); - std::ofstream file(fpath); + my_assert(status == MC_NO_ERROR); - // write vertices and normals - for (uint32_t i = 0; i < ccVertexCount; ++i) { - double x = ccVertices[(McSize)i * 3 + 0]; - double y = ccVertices[(McSize)i * 3 + 1]; - double z = ccVertices[(McSize)i * 3 + 2]; - file << "v " << std::setprecision(std::numeric_limits::digits10 + 1) << x << " " << y << " " << z << std::endl; - } + return 0; +} - int faceVertexOffsetBase = 0; - - // for each face in CC - for (uint32_t f = 0; f < ccFaceCount; ++f) { - bool reverseWindingOrder = (fragmentLocation == MC_FRAGMENT_LOCATION_BELOW) && (patchLocation == MC_PATCH_LOCATION_OUTSIDE); - int faceSize = faceSizes.at(f); - file << "f "; - // for each vertex in face - for (int v = (reverseWindingOrder ? (faceSize - 1) : 0); - (reverseWindingOrder ? (v >= 0) : (v < faceSize)); - v += (reverseWindingOrder ? -1 : 1)) { - const int ccVertexIdx = ccFaceIndices[(McSize)faceVertexOffsetBase + v]; - file << (ccVertexIdx + 1) << " "; - } // for (int v = 0; v < faceSize; ++v) { - file << std::endl; - - faceVertexOffsetBase += faceSize; - } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, (uint32_t)connectedComponents.size(), connectedComponents.data()); - my_assert(err == MC_NO_ERROR); +void MCAPI_PTR mcDebugOutput(McDebugSource source, + McDebugType type, + McUint32 id, + McDebugSeverity severity, + size_t length, + const char* message, + const void* userParam) +{ + std::string debug_src; + switch (source) { + case MC_DEBUG_SOURCE_API: + debug_src = "API"; + break; + case MC_DEBUG_SOURCE_KERNEL: + debug_src = "KERNEL"; + break; + case MC_DEBUG_SOURCE_ALL: + break; } - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + std::string debug_type; + switch (type) { + case MC_DEBUG_TYPE_ERROR: + debug_type = "ERROR"; + break; + case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + debug_type = "DEPRECATION"; + break; + case MC_DEBUG_TYPE_OTHER: + //printf("Type: Other"); + debug_type = "OTHER"; + break; + case MC_DEBUG_TYPE_ALL: + break; + + } - my_assert(err == MC_NO_ERROR); + std::string severity_str; + + switch (severity) { + case MC_DEBUG_SEVERITY_HIGH: + severity_str = "HIGH"; + break; + case MC_DEBUG_SEVERITY_MEDIUM: + severity_str = "MEDIUM"; + break; + case MC_DEBUG_SEVERITY_LOW: + severity_str = "LOW"; + break; + case MC_DEBUG_SEVERITY_NOTIFICATION: + severity_str = "NOTIFICATION"; + break; + case MC_DEBUG_SEVERITY_ALL: + break; + } - return 0; + printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(),severity_str.c_str(), length, message); } diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 4727266..c8348dd 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -604,7 +604,7 @@ int main() // char fnameBuf[64]; - sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); + sprintf(fnameBuf, ("OUT_" + name + "-%d.obj").c_str(), i); std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); mioWriteOBJ( diff --git a/tutorials/HelloWorld/CMakeLists.txt b/tutorials/HelloWorld/CMakeLists.txt deleted file mode 100644 index 2ed2385..0000000 --- a/tutorials/HelloWorld/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ - -add_executable(HelloWorld HelloWorld.cpp) -target_link_libraries(HelloWorld mcut ${extra_libs}) -target_include_directories(HelloWorld PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(HelloWorld PRIVATE ${compilation_flags}) -target_compile_definitions(HelloWorld PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/HelloWorld/HelloWorld.cpp b/tutorials/HelloWorld/HelloWorld.cpp index 83ec7dd..399a96a 100644 --- a/tutorials/HelloWorld/HelloWorld.cpp +++ b/tutorials/HelloWorld/HelloWorld.cpp @@ -28,19 +28,20 @@ **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include +#include -void writeOFF( - const char* fpath, - McFloat* pVertices, - McUint32* pFaceIndices, - McUint32* pFaceSizes, - McUint32 numVertices, - McUint32 numFaces); +#define my_assert(cond) \ + if(!(cond)) \ + { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::abort(); \ + } McInt32 main() { @@ -101,10 +102,7 @@ McInt32 main() McContext context = MC_NULL_HANDLE; McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - if (status != MC_NO_ERROR) { - fprintf(stderr, "could not create context (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // do the cutting @@ -112,7 +110,7 @@ McInt32 main() status = mcDispatch( context, - MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + MC_DISPATCH_VERTEX_ARRAY_FLOAT, srcMeshVertices, srcMeshFaces, srcMeshFaceSizes, @@ -124,10 +122,7 @@ McInt32 main() cutMeshVertexCount, cutMeshFaceCount); - if (status != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // query the number of available connected components after the cut @@ -138,10 +133,7 @@ McInt32 main() status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - if (status != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); @@ -152,10 +144,7 @@ McInt32 main() status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (status != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // query the data of each connected component @@ -164,88 +153,86 @@ McInt32 main() for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { McConnectedComponent cc = connectedComponents[i]; // connected compoenent id - McSize bytesToAllocate = 0; + McSize numBytes = 0; // // vertices // - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &bytesToAllocate); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); - if (status != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); - McUint32 ccVertexCount = (McUint32)(bytesToAllocate / (sizeof(McFloat) * 3ull)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McFloat) * 3ull)); std::vector ccVertices(ccVertexCount * 3u); - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, bytesToAllocate, (McVoid*)ccVertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (McVoid*)ccVertices.data(), NULL); - if (status != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // faces // - bytesToAllocate = 0; + numBytes = 0; - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &bytesToAllocate); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - if (status != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); - std::vector faceIndices; - faceIndices.resize(bytesToAllocate / sizeof(McUint32)); + std::vector ccFaceIndices; + ccFaceIndices.resize(numBytes / sizeof(McUint32)); - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, bytesToAllocate, (McVoid*)faceIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, (McVoid*)ccFaceIndices.data(), NULL); - if (status != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // face sizes (vertices per face) // - bytesToAllocate = 0; + numBytes = 0; - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &bytesToAllocate); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (status != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); - std::vector faceSizes; - faceSizes.resize(bytesToAllocate / sizeof(McUint32)); + std::vector ccFaceSizes; + ccFaceSizes.resize(numBytes / sizeof(McUint32)); - status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, bytesToAllocate, (McVoid*)faceSizes.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, (McVoid*)ccFaceSizes.data(), NULL); - if (status != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // - // save to cc to file (.off) - // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, "conncomp%d.obj", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); - char fnameBuf[32]; + // "mioWriteOBJ" expects a vertex array of doubles. So we temporarilly create one. + std::vector ccVertices64(ccVertices.size(), McDouble(0.0)); + + for(McUint32 v =0; v < (McUint32)ccVertices.size(); ++v) + { + ccVertices64[v] = (McDouble)ccVertices[v]; + } - sprintf(fnameBuf, "cc%d.off", i); - writeOFF(fnameBuf, - (McFloat*)ccVertices.data(), - (McUint32*)faceIndices.data(), - (McUint32*)faceSizes.data(), - (McUint32)ccVertices.size() / 3u, - (McUint32)faceSizes.size()); + mioWriteOBJ( + fpath.c_str(), + ccVertices64.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); } // @@ -254,10 +241,7 @@ McInt32 main() status = mcReleaseConnectedComponents(context, 0, NULL); - if (status != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); // // free memory of context @@ -265,52 +249,7 @@ McInt32 main() status = mcReleaseContext(context); - if (status != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (%d)\n", (McInt32)status); - exit(EXIT_FAILURE); - } + my_assert (status == MC_NO_ERROR); return 0; } - -// write mesh to .off file -void writeOFF( - const char* fpath, - McFloat* pVertices, - McUint32* pFaceIndices, - McUint32* pFaceSizes, - McUint32 numVertices, - McUint32 numFaces) -{ - fprintf(stdout, "write: %s\n", fpath); - - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(EXIT_FAILURE); - } - - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - McInt32 i; - for (i = 0; i < (McInt32)numVertices; ++i) { - McFloat* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } - - McInt32 faceBaseOffset = 0; - for (i = 0; i < (McInt32)numFaces; ++i) { - McUint32 faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (McInt32)faceVertexCount); - McInt32 j; - for (j = 0; j < (McInt32)faceVertexCount; ++j) { - McUint32* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - fclose(file); -} diff --git a/tutorials/TextureCoordinates/CMakeLists.txt b/tutorials/TextureCoordinates/CMakeLists.txt deleted file mode 100644 index 46a397c..0000000 --- a/tutorials/TextureCoordinates/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(TextureCoordinates TextureCoordinates.cpp) -target_link_libraries(TextureCoordinates mcut ${extra_libs}) -target_include_directories(TextureCoordinates PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_definitions(TextureCoordinates PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}" ${preprocessor_defs}) -target_compile_options(TextureCoordinates PRIVATE ${compilation_flags}) \ No newline at end of file diff --git a/tutorials/TextureCoordinates/TextureCoordinates.cpp b/tutorials/TextureCoordinates/TextureCoordinates.cpp index 7046f8e..0839c16 100644 --- a/tutorials/TextureCoordinates/TextureCoordinates.cpp +++ b/tutorials/TextureCoordinates/TextureCoordinates.cpp @@ -1,372 +1,445 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -This tutorial shows how to propagate per-face texture coordinates from input meshes and onto the output -connected components after cutting. -*/ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * TextureCoordinates.cpp + * + * \brief: + * This tutorial shows how to propagate per-vertex texture (i.e. uv) coordinates + * from the input meshes and unto the output connected components after cutting. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include #include -// libigl dependencies -#include -#include -#include -#include -#include +#include +#include #define my_assert(cond) \ if (!(cond)) \ { \ fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ + std::abort(); \ } -struct InputMesh -{ - Eigen::MatrixXd corner_normals; - Eigen::MatrixXi fNormIndices; - - Eigen::MatrixXd UV_V; - Eigen::MatrixXi UV_F; - Eigen::MatrixXd V; - Eigen::MatrixXi F; - std::vector> FM; - - // variables for mesh data in a format suited for MCUT - std::string fpath; // path to mesh file - std::vector faceSizesArray; // vertices per face - std::vector faceIndicesArray; // face indices - std::vector vertexCoordsArray; // vertex coords -}; // basic comparison of doubles -bool compare(double x, double y) +McBool compare(McDouble x, McDouble y) { return std::fabs(x - y) < 1e-6; } -int main() +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation, + McBool& isDerivedFromSrcMesh); +// simple structure representing a 2d vector and the operations we will perform with it +struct vec2 { - // load meshes. - // ----------------- - InputMesh srcMesh; + union + { + struct + { + McDouble x, y; + }; + struct + { + McDouble u, v; + }; + }; + + vec2 operator*(const McDouble c) const + { + vec2 result = {0.0, 0.0}; + result.x = x * c; + result.y = y * c; + return result; + } + + vec2 operator+(const vec2& rhs) const + { + vec2 result = {0.0, 0.0}; + result.x = x + rhs.x; + result.y = y + rhs.y; + return result; + } + + vec2 operator-(const vec2& rhs) const + { + vec2 result = {0.0, 0.0}; + result.x = x - rhs.x; + result.y = y - rhs.y; + return result; + } +}; - // read file - srcMesh.fpath = DATA_DIR "/a_.obj"; /* DATA_DIR "/a.obj"*/ - bool srcMeshLoaded = igl::readOBJ(srcMesh.fpath, srcMesh.V, srcMesh.UV_V, srcMesh.corner_normals, srcMesh.F, srcMesh.UV_F, srcMesh.fNormIndices); +// simple structure representing a 3d vector and the operations we will perform with it +struct vec3 +{ + union + { + struct + { + McDouble x, y, z; + }; + struct + { + McDouble u, v, w; + }; + }; + + vec3 operator*(const McDouble c) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x * c; + result.y = y * c; + result.z = z * c; + return result; + } + + vec3 operator+(const vec3& rhs) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x + rhs.x; + result.y = y + rhs.y; + result.z = z + rhs.z; + return result; + } + + vec3 operator-(const vec3& rhs) const + { + vec3 result = {0.0, 0.0, 0.0}; + result.x = x - rhs.x; + result.y = y - rhs.y; + result.z = z - rhs.z; + return result; + } +}; - if (!srcMeshLoaded) - { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", srcMesh.fpath.c_str()); - std::exit(1); - } +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation); - // copy vertices - for (int i = 0; i < srcMesh.V.rows(); ++i) - { - const Eigen::Vector3d &v = srcMesh.V.row(i); - my_assert(v.size() == 3); - srcMesh.vertexCoordsArray.push_back(v.x()); - srcMesh.vertexCoordsArray.push_back(v.y()); - srcMesh.vertexCoordsArray.push_back(v.z()); - } +inline McDouble +getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x3, McDouble y3) +{ + return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2); +} - // copy faces - for (int i = 0; i < srcMesh.F.rows(); ++i) - { - const Eigen::VectorXi &f = srcMesh.F.row(i); - srcMesh.faceIndicesArray.push_back(f.x()); - srcMesh.faceIndicesArray.push_back(f.y()); - srcMesh.faceIndicesArray.push_back(f.z()); - srcMesh.faceSizesArray.push_back((uint32_t)f.rows()); - } +vec3 crossProduct(const vec3& u, const vec3& v) +{ + vec3 out = {0.0, 0.0, 0.0}; + out.x = u.y * v.z - u.z * v.y; + out.y = u.z * v.x - u.x * v.z; + out.z = u.x * v.y - u.y * v.x; + return out; +} - printf("source mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)srcMesh.V.rows(), (int)srcMesh.F.rows()); +// Compute barycentric coordinates (u, v, w) for point p with respect to triangle (a, b, c) +vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec3& c) +{ + // Unnormalized triangle normal + const vec3 m = crossProduct(b - a, c - a); + // Nominators and one-over-denominator for u and v ratios + McDouble nu = 0.0, nv = 0.0, ood = 0.0; + // Absolute components for determining projection plane + const McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); + + // Compute areas in plane of largest projection + if(x >= y && x >= z) + { + // x is largest, project to the yz plane + nu = getTriangleArea2D(p.y, p.z, b.y, b.z, c.y, c.z); + // Area of PBC in yz plane + nv = getTriangleArea2D(p.y, p.z, c.y, c.z, a.y, a.z); + // Area of PCA in yz plane + ood = 1.0f / m.x; // 1/(2*area of ABC in yz plane + } + else if(y >= x && y >= z) + { + // y is largest, project to the xz plane + nu = getTriangleArea2D(p.x, p.z, b.x, b.z, c.x, c.z); + nv = getTriangleArea2D(p.x, p.z, c.x, c.z, a.x, a.z); + ood = 1.0f / -m.y; + } + else + { + // z is largest, project to the xy plane + nu = getTriangleArea2D(p.x, p.y, b.x, b.y, c.x, c.y); + nv = getTriangleArea2D(p.x, p.y, c.x, c.y, a.x, a.y); + ood = 1.0f / m.z; + } + + vec3 result = {0.0, 0.0, 0.0}; + result.u = nu * ood; + result.v = nv * ood; + result.w = 1.0f - result.u - result.v; + return result; +} - InputMesh cutMesh; - // read file - cutMesh.fpath = DATA_DIR "/b_.obj"; /*DATA_DIR "/b.obj";*/ - bool cutMeshLoaded = igl::readOBJ(cutMesh.fpath, cutMesh.V, cutMesh.UV_V, cutMesh.corner_normals, cutMesh.F, cutMesh.UV_F, cutMesh.fNormIndices); +McInt32 main() +{ + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; + + // + // read-in the source-mesh from file + // + mioReadOBJ(DATA_DIR "/a.obj", + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(DATA_DIR "/b.obj", + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); + + // + // create a context + // + McContext context = MC_NULL_HANDLE; - if (!cutMeshLoaded) - { - std::fprintf(stderr, "error: could not load cut mesh --> %s\n", cutMesh.fpath.c_str()); - std::exit(1); - } + McResult status = mcCreateContext(&context, MC_DEBUG); - // copy vertices - for (int i = 0; i < cutMesh.V.rows(); ++i) - { - const Eigen::Vector3d &v = cutMesh.V.row(i); - cutMesh.vertexCoordsArray.push_back(v.x()); - cutMesh.vertexCoordsArray.push_back(v.y()); - cutMesh.vertexCoordsArray.push_back(v.z()); - } + my_assert(status == MC_NO_ERROR); - // copy faces - for (int i = 0; i < cutMesh.F.rows(); ++i) - { - const Eigen::VectorXi &f = cutMesh.F.row(i); - cutMesh.faceIndicesArray.push_back(f.x()); - cutMesh.faceIndicesArray.push_back(f.y()); - cutMesh.faceIndicesArray.push_back(f.z()); - cutMesh.faceSizesArray.push_back((uint32_t)f.rows()); - } + // + // do the cutting + // + status = mcDispatch( + context, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, + // source mesh + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); - printf("cut mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)cutMesh.V.rows(), (int)cutMesh.F.rows()); + my_assert(status == MC_NO_ERROR); - // create a context - // ------------------- - McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); + // + // query the number of available connected components + // + McUint32 connectedComponentCount = 0; - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - // do the cutting - // ----------------- - err = mcDispatch( - context, - MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, - // source mesh - reinterpret_cast(srcMesh.vertexCoordsArray.data()), - reinterpret_cast(srcMesh.faceIndicesArray.data()), - srcMesh.faceSizesArray.data(), - static_cast(srcMesh.vertexCoordsArray.size() / 3), - static_cast(srcMesh.faceSizesArray.size()), - // cut mesh - reinterpret_cast(cutMesh.vertexCoordsArray.data()), - cutMesh.faceIndicesArray.data(), - cutMesh.faceSizesArray.data(), - static_cast(cutMesh.vertexCoordsArray.size() / 3), - static_cast(cutMesh.faceSizesArray.size())); - - my_assert(err == MC_NO_ERROR); - - // query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnectedComponents; - - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents); - my_assert(err == MC_NO_ERROR); - - printf("connected components: %d\n", (int)numConnectedComponents); - - if (numConnectedComponents == 0) + my_assert(status == MC_NO_ERROR); + + printf("connected components: %d\n", (McInt32)connectedComponentCount); + + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - std::vector connectedComponents(numConnectedComponents, 0); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connectedComponents.size(), connectedComponents.data(), NULL); - my_assert(err == MC_NO_ERROR); + std::vector connectedComponents(connectedComponentCount, 0); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); + my_assert(status == MC_NO_ERROR); - // query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)numConnectedComponents; ++i) + for (McInt32 i = 0; i < (McInt32)connectedComponentCount; ++i) { - McConnectedComponent connComp = connectedComponents[i]; // connected compoenent id + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id McSize numBytes = 0; - // query the ccVertices - // ------------------------ + // + // vertices + // - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + const McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); + std::vector ccVertices((McSize)ccVertexCount * 3u, 0); - std::vector ccVertices((size_t)ccVertexCount * 3u, 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void *)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void *)ccVertices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // faces + // - // query the faces - // ------------------- numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face sizes - // ------------------------ + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // face sizes + // + numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector faceSizes(numBytes / sizeof(uint32_t), 0); - faceSizes.resize(numBytes / sizeof(uint32_t)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the vertex map - // ------------------------ - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccVertexMap(numBytes / sizeof(uint32_t)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the face map - // ------------------------ - const uint32_t ccFaceCount = static_cast(faceSizes.size()); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // resolve connected component name - // --------------------------------- - - // Here we create a name the connected component based on its properties - - // get type - McConnectedComponentType ccType; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &ccType, NULL); - my_assert(err == MC_NO_ERROR); - - std::string name; - McFragmentLocation fragmentLocation = (McFragmentLocation)0; - McPatchLocation pathLocation = (McPatchLocation)0; - bool isFragment = false; - - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) - { - name += "seam"; - } - else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) - { - name += "input"; - } - else - { - isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - name += isFragment ? "frag" : "patch"; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &pathLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += pathLocation == MC_PATCH_LOCATION_INSIDE ? ".inside" : (pathLocation == MC_PATCH_LOCATION_OUTSIDE ? ".outside" : ".undefined"); + my_assert(status == MC_NO_ERROR); - if (isFragment) - { + std::vector ccFaceSizes(numBytes / sizeof(McUint32), 0); + ccFaceSizes.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE ? ".above" : ".below"; // missing loc="undefined" case + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); - McFragmentSealType sType = (McFragmentSealType)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, sizeof(McFragmentSealType), &sType, NULL); - my_assert(err == MC_NO_ERROR); - name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".complete" : ".none"; - } - } + my_assert(status == MC_NO_ERROR); - bool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + // + // vertex map + // - // connected-components is not a fragment && it is a seam - if (!ccIsFromSrcMesh) - { - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) - { - // get origin - McSeamOrigin ccOrig = (McSeamOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McSeamOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } - else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) - { - McInputOrigin ccOrig = (McInputOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } - } + my_assert(status == MC_NO_ERROR); - int faceVertexOffsetBase = 0; + std::vector ccVertexMap(numBytes / sizeof(McUint32)); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); - char fnameBuf[64]; - sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); - std::string fname(fnameBuf); - std::string fpath(DATA_DIR "/" + fname); - printf("write file: %s\n", fpath.c_str()); - std::ofstream file(fpath); + my_assert(status == MC_NO_ERROR); + + // + // face map + // - file << (ccIsFromSrcMesh ? "mtllib a.mtl" : "mtllib b.mtl") << std::endl; + const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes); - std::vector ccTexCoords; - // CC vertex index to texture coordinate index/indices. - // Its possible to map to more than texture coordinates since such coordinates are specified to per-face. - std::map> ccVertexIndexToTexCoordIndices; - std::vector ccFaceVertexTexCoordIndices; + my_assert(status == MC_NO_ERROR); + + std::vector ccFaceMap(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, numBytes, ccFaceMap.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // Here we create a name for the connected component based on its properties + // and save whether its a fragment, and if so the location of this fragment + // + + McBool isFragment = MC_FALSE; + McBool isDerivedFromSrcMesh = MC_FALSE; + McFragmentLocation fragmentLocation = (McFragmentLocation)0; + const std::string name = + resolve_cc_name_string(context, cc, isFragment, fragmentLocation, isDerivedFromSrcMesh); + + McInt32 faceVertexOffsetBase = 0; + + char fnameBuf[64]; + sprintf(fnameBuf, ("OUT_" + name + "%d.obj").c_str(), i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + std::vector ccTexCoords; // output texture coordinates + std::vector ccFaceVertexTexCoordIndices; // for each face in CC - for (int f = 0; f < (int)ccFaceCount; ++f) + for (McInt32 f = 0; f < (McInt32)ccFaceCount; ++f) { - // input mesh face index (which may be offsetted!) - const uint32_t imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh + const McUint32 imFaceIdxRaw = ccFaceMap.at(f); // source- or cut-mesh // input mesh face index (actual index value, accounting for offset) - uint32_t imFaceIdx = imFaceIdxRaw; - bool faceIsFromSrcMesh = (imFaceIdxRaw < (uint32_t)srcMesh.F.rows()); + McUint32 imFaceIdx = imFaceIdxRaw; + McBool faceIsFromSrcMesh = (imFaceIdxRaw < (McUint32)srcMesh.numFaces); if (!faceIsFromSrcMesh) { - imFaceIdx = imFaceIdxRaw - (uint32_t)srcMesh.F.rows(); // accounting for offset + imFaceIdx = imFaceIdxRaw - (McUint32)srcMesh.numFaces; // accounting for offset } - int faceSize = faceSizes.at(f); + McInt32 faceSize = ccFaceSizes.at(f); // for each vertex in face - for (int v = 0; v < (int)faceSize; ++v) + for (McInt32 v = 0; v < (McInt32)faceSize; ++v) { - - const int ccVertexIdx = ccFaceIndices.at((McSize)faceVertexOffsetBase + v); + const McInt32 ccVertexIdx = ccFaceIndices.at((McSize)faceVertexOffsetBase + v); // input mesh (source mesh or cut mesh) vertex index (which may be offsetted) - const uint32_t imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); - bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.V.rows()); - const bool vertexIsIntersectionPoint = (imVertexIdxRaw == MC_UNDEFINED_VALUE); - uint32_t imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset + const McUint32 imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); + const McBool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.numVertices); + const McBool vertexIsIntersectionPoint = (imVertexIdxRaw == MC_UNDEFINED_VALUE); + McUint32 imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset if (!vertexIsFromSrcMesh) { - imVertexIdx = (imVertexIdxRaw - (uint32_t)srcMesh.V.rows()); // account for offset + imVertexIdx = (imVertexIdxRaw - (McUint32)srcMesh.numVertices); // account for offset } - const InputMesh *inputMeshPtr = &srcMesh; // assume origin face is from source mesh + const MioMesh *inputMeshPtr = &srcMesh; // assume origin face is from source mesh if (!faceIsFromSrcMesh) { @@ -374,66 +447,84 @@ int main() } // the face on which the current cc face came from - const Eigen::Vector3i &imFace = inputMeshPtr->F.row(imFaceIdx); + const McIndex* imFaceVertexIndices = inputMeshPtr->pFaceVertexIndices + (imFaceIdx * 3); - Eigen::Vector2d texCoord; + vec2 texCoord = {0.0, 0.0}; if (vertexIsIntersectionPoint) { // texture coords unknown and must be computed + // // interpolate texture coords from source-mesh values - - // 1. get the origin face of the current cc face - - double x(ccVertices[((McSize)ccVertexIdx * 3) + 0]); - double y(ccVertices[((McSize)ccVertexIdx * 3) + 1]); - double z(ccVertices[((McSize)ccVertexIdx * 3) + 2]); - - // vertices of the origin face - const Eigen::Vector3d &a = inputMeshPtr->V.row(imFace.x()); - const Eigen::Vector3d &b = inputMeshPtr->V.row(imFace.y()); - const Eigen::Vector3d &c = inputMeshPtr->V.row(imFace.z()); - - // barycentric coords of our intersection point on the origin face - Eigen::MatrixXd P; - P.resize(1, 3); - P << x, y, z; - Eigen::MatrixXd A; - A.resize(1, 3); - A << a.x(), a.y(), a.z(); - Eigen::MatrixXd B; - B.resize(1, 3); - B << b.x(), b.y(), b.z(); - Eigen::MatrixXd C; - C.resize(1, 3); - C << c.x(), c.y(), c.z(); - Eigen::MatrixXd L; - - igl::barycentric_coordinates(P, A, B, C, L); + // + + // coordinates of current point (whose barycentric coords we want) + vec3 p = {0.0, 0.0, 0.0}; + p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); + p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); + p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); + + // vertices of the origin face (i.e. the face from which the current face came from). + // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation + // will be more complex, which is unnecessary for now. + vec3 a = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[0] * 3; + a.x = ptr[0]; + a.y = ptr[1]; + a.z = ptr[2]; + } + vec3 b = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[1] * 3; + b.x = ptr[0]; + b.y = ptr[1]; + b.z = ptr[2]; + } + + vec3 c = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[2] * 3; + c.x = ptr[0]; + c.y = ptr[1]; + c.z = ptr[2]; + } + + const vec3 bary = getBarycentricCoords(p, a, b, c); // compute the texture coordinates of our intersection point by interpolation // -------------------------------------------------------------------------- - // indices of the texture coords that are used by "imFaceIdx" - const Eigen::VectorXi &imFaceUVIndices = inputMeshPtr->UV_F.row(imFaceIdx); + // indices of the 2d texture coords that are used by "imFaceIdx" (3 indices per face) + const McUint32* imFaceUVIndices = inputMeshPtr->pFaceVertexTexCoordIndices + (imFaceIdx * 3); // texture coordinates of vertices of origin face - const Eigen::Vector2d &TCa = inputMeshPtr->UV_V.row(imFaceUVIndices(0)); - const Eigen::Vector2d &TCb = inputMeshPtr->UV_V.row(imFaceUVIndices(1)); - const Eigen::Vector2d &TCc = inputMeshPtr->UV_V.row(imFaceUVIndices(2)); - const Eigen::Vector3d &baryCoords = L.row(0); + const vec2 ta = { + inputMeshPtr->pTexCoords[imFaceUVIndices[0]*2 + 0], + inputMeshPtr->pTexCoords[imFaceUVIndices[0]* 2 + 1] + }; + + const vec2 tb = { + inputMeshPtr->pTexCoords[imFaceUVIndices[1] * 2 + 0], + inputMeshPtr->pTexCoords[imFaceUVIndices[1] * 2 + 1] + }; + + const vec2 tc = { + inputMeshPtr->pTexCoords[imFaceUVIndices[2] * 2 + 0], + inputMeshPtr->pTexCoords[imFaceUVIndices[2] * 2 + 1] + }; // interpolate using barycentric coords - texCoord = (TCa * baryCoords.x()) + (TCb * baryCoords.y()) + (TCc * baryCoords.z()); + texCoord = (ta * bary.u) + (tb * bary.v) + (tc * bary.w); } else - { // texture coords are known must be inferred from input mesh + { // texture coords are known and can therefore be inferred from input mesh - int faceVertexOffset = -1; - // for each vertex index in face - for (int p = 0; p < (int)imFace.rows(); ++p) + McInt32 faceVertexOffset = -1; + // for each vertex index in face (assuming 3 vertices) + for (McInt32 p = 0; p < (McInt32)3; ++p) { - if ((int)imFace(p) == (int)imVertexIdx) + if((McInt32)imFaceVertexIndices[p] == (McInt32)imVertexIdx) { faceVertexOffset = p; break; @@ -442,84 +533,211 @@ int main() my_assert(faceVertexOffset != -1); - int texCoordsIdx = inputMeshPtr->UV_F.row(imFaceIdx)(faceVertexOffset); - texCoord = inputMeshPtr->UV_V.row(texCoordsIdx); + McUint32 texCoordsIdx = *(inputMeshPtr->pFaceVertexTexCoordIndices + (imFaceIdx * 3) + faceVertexOffset); //UV_F.row(imFaceIdx)(faceVertexOffset); + + texCoord = { + inputMeshPtr->pTexCoords[texCoordsIdx * 2 + 0], + inputMeshPtr->pTexCoords[texCoordsIdx * 2 + 1], + };// UV_V.row(texCoordsIdx); } - int texCoordIndex = -1; + // + // do some book-keeping so that we do not store duplicates + // + + McInt32 texCoordIndex = -1; - std::vector::const_iterator fiter = std::find_if( - ccTexCoords.cbegin(), ccTexCoords.cend(), - [&](const Eigen::Vector2d &e) - { return compare(e.x(), texCoord.x()) && compare(e.y(), texCoord.y()); }); + std::vector::const_iterator fiter = std::find_if( + ccTexCoords.cbegin(), ccTexCoords.cend(), [&](const vec2& e) + { return compare(e.x , texCoord.x ) && compare(e.y , texCoord.y ); }); if (fiter != ccTexCoords.cend()) { - texCoordIndex = (int)std::distance(ccTexCoords.cbegin(), fiter); + texCoordIndex = (McInt32)std::distance(ccTexCoords.cbegin(), fiter); } if (texCoordIndex == -1) { // tex coord not yet stored for CC vertex in face - texCoordIndex = (int)ccTexCoords.size(); + texCoordIndex = (McInt32)ccTexCoords.size(); ccTexCoords.push_back(texCoord); } ccFaceVertexTexCoordIndices.push_back(texCoordIndex); - } // for (int v = 0; v < faceSize; ++v) { + } // for (McInt32 v = 0; v < faceSize; ++v) { faceVertexOffsetBase += faceSize; - } // for (int f = 0; f < ccFaceCount; ++f) { + } // for (McInt32 f = 0; f < ccFaceCount; ++f) { + + // + // Save mesh to (.obj) file with texture coordinates + // + // NOTE: In order to actually view the output mesh with the propagated texture coordinates, + // the output file must be [manually edited] by adding "mtllib .mtl" as the first (non-comment) + // line of the file. The placeholder "" should be replace with either "a" or "b" + // depending on whether the respective output mesh was derived from the source-mesh ("a.obj") or + // the cut-mesh ("b.obj"). You can know from-which input mesh an output CC was derived based on + // the file name. + // + + mioWriteOBJ(fpath.c_str(), + ccVertices.data(), + nullptr, //pNormals + (McDouble*)ccTexCoords.data(), + ccFaceSizes.data(), + ccFaceIndices.data(), + ccFaceVertexTexCoordIndices.data(), // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, // numNormals + (McUint32)ccTexCoords.size(), + ccFaceCount); + } - // save cc mesh to .obj file - // ------------------------- + // + // We no longer need the mem of input meshes, so we can free them! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); - // write vertices - for (int k = 0; k < (int)ccVertexCount; ++k) - { - double x = ccVertices[(McSize)k * 3 + 0]; - double y = ccVertices[(McSize)k * 3 + 1]; - double z = ccVertices[(McSize)k * 3 + 2]; - file << std::setprecision(std::numeric_limits::digits10 + 1) << "v " << x << " " << y << " " << z << std::endl; - } + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, 0, NULL); - // write tex coords (including duplicates i.e. per face texture coords) + my_assert(status == MC_NO_ERROR); - for (int k = 0; k < (int)ccTexCoords.size(); ++k) - { - Eigen::Vector2d uv = ccTexCoords[k]; //faceTexCoords[j]; - file << "vt " << std::setprecision(std::numeric_limits::digits10 + 1) << uv.x() << " " << uv.y() << std::endl; // texcoords have same index as positions - } + // + // destroy context + // + status = mcReleaseContext(context); - // write faces - faceVertexOffsetBase = 0; - for (int k = 0; k < (int)ccFaceCount; ++k) - { - int faceSize = faceSizes.at(k); + my_assert(status == MC_NO_ERROR); - file << "f "; - for (int j = 0; j < (int)faceSize; ++j) - { - const int idx = faceVertexOffsetBase + j; - const int ccVertexIdx = ccFaceIndices.at(static_cast(idx)); - file << (ccVertexIdx + 1) << "/" << ccFaceVertexTexCoordIndices[idx] + 1 << " "; - } - file << std::endl; - - faceVertexOffsetBase += faceSize; - } - } - - // free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); - - my_assert(err == MC_NO_ERROR); + return 0; +} - // destroy context - // ------------------ - err = mcReleaseContext(context); - my_assert(err == MC_NO_ERROR); - return 0; -} +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation, + McBool& isDerivedFromSrcMesh) +{ + isDerivedFromSrcMesh = MC_FALSE; + + // get type + McConnectedComponentType ccType = (McConnectedComponentType)0; + + McResult status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_TYPE, + sizeof(McConnectedComponentType), + &ccType, + NULL); + + my_assert(status == MC_NO_ERROR); + + std::string name; + McPatchLocation patchLocation = (McPatchLocation)0; + + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + name += "seam"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + name += "input"; + } + else + { + isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + name += isFragment ? "frag" : "patch"; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, + sizeof(McPatchLocation), + &patchLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += patchLocation == MC_PATCH_LOCATION_INSIDE + ? ".ploc=in" + : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".ploc=out" : ".ploc=undef"); + + if(isFragment) + { + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, + sizeof(McFragmentLocation), + &fragmentLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE + ? ".floc=abv" + : ".floc=blw"; // missing loc="undefined" case + + McFragmentSealType sType = (McFragmentSealType)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, + sizeof(McFragmentSealType), + &sType, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".seal=yes" : ".seal=no"; + } + } + + isDerivedFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + // connected-components is not a fragment && it is a seam + if(!isDerivedFromSrcMesh) + { + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + // get origin + McSeamOrigin ccOrig = (McSeamOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McSeamOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + isDerivedFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); + name += isDerivedFromSrcMesh ? ".orig=s" : ".orig=c"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + McInputOrigin ccOrig = (McInputOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McInputOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + isDerivedFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); + name += isDerivedFromSrcMesh ? ".orig=s" : ".orig=c"; + } + } + + return name; +} \ No newline at end of file diff --git a/tutorials/VertexNormals/CMakeLists.txt b/tutorials/VertexNormals/CMakeLists.txt deleted file mode 100644 index c40e5db..0000000 --- a/tutorials/VertexNormals/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(VertexNormals VertexNormals.cpp) -target_link_libraries(VertexNormals mcut ${extra_libs}) -target_include_directories(VertexNormals PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_definitions(VertexNormals PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}" ${preprocessor_defs}) -target_compile_options(VertexNormals PRIVATE ${compilation_flags}) \ No newline at end of file diff --git a/tutorials/VertexNormals/VertexNormals.cpp b/tutorials/VertexNormals/VertexNormals.cpp index 541356b..6fb2f99 100644 --- a/tutorials/VertexNormals/VertexNormals.cpp +++ b/tutorials/VertexNormals/VertexNormals.cpp @@ -212,8 +212,9 @@ McInt32 main() my_assert(status == MC_NO_ERROR); - // 3. do the cutting - // ----------------- + // + // do the cutting + // status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals @@ -261,8 +262,9 @@ McInt32 main() my_assert(status == MC_NO_ERROR); - // query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // for(McUint32 ci = 0; ci < (McUint32)connectedComponents.size(); ++ci) { @@ -450,32 +452,6 @@ McInt32 main() p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); - - /*McDouble x(ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); - McDouble y(ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); - McDouble z(ccVertices[((McSize)ccVertexIdx * 3u) + 2u]);*/ - - // // vertices of the origin face - //const std::vector& a = inputMeshPtr->V[imFace[0]]; - // const std::vector &b = inputMeshPtr->V[imFace[1]]; - // const std::vector &c = inputMeshPtr->V[imFace[2]]; - - // // barycentric coords of our intersection point on the origin face - // Eigen::MatrixXd P; - // P.resize(1, 3); - // P << x, y, z; - // Eigen::MatrixXd A; - // A.resize(1, 3); - // A << a[0], a[1], a[2]; - // Eigen::MatrixXd B; - // B.resize(1, 3); - // B << b[0], b[1], b[2]; - // Eigen::MatrixXd C; - // C.resize(1, 3); - // C << c[0], c[1], c[2]; - // Eigen::MatrixXd L; - - // igl::barycentric_coordinates(P, A, B, C, L); // vertices of the origin face (i.e. the face from which the current face came from). // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation @@ -505,21 +481,6 @@ McInt32 main() const vec3 bary = getBarycentricCoords(p, a, b, c); - - - //inputMeshPtr->FN[imFaceIdx]; - //my_assert(imFaceNormalIndices.size() == 3); - - //// normals of vertices in origin face - //const std::vector &Na_ = inputMeshPtr->N[imFaceNormalIndices[0]]; - //const std::vector &Nb_ = inputMeshPtr->N[imFaceNormalIndices[1]]; - //const std::vector &Nc_ = inputMeshPtr->N[imFaceNormalIndices[2]]; - - //const Eigen::Vector3d Na(Na_[0], Na_[1], Na_[2]); - //const Eigen::Vector3d Nb(Nb_[0], Nb_[1], Nb_[2]); - //const Eigen::Vector3d Nc(Nc_[0], Nc_[1], Nc_[2]); - //const Eigen::Vector3d baryCoords = L.row(0); - // normal coordinates of vertices in the origin face vec3 normalA = {0.0, 0.0, 0.0}; @@ -545,8 +506,6 @@ McInt32 main() } - // interpolate using barycentric coords - //Eigen::Vector3d normal = (Na * baryCoords.x()) + (Nb * baryCoords.y()) + (Nc * baryCoords.z()) * (flipNormalsOnFace ? -1.0 : 1.0); // interpolate at point "p" using barycentric coords const vec3 normal = ((normalA * bary.u) + (normalB * bary.v) + (normalC * bary.w)) * (flipNormalsOnFace ? -1.0 : 1.0); @@ -584,14 +543,10 @@ McInt32 main() my_assert(faceVertexOffset != -1); const McUint32 imNormalIdx = imFaceNormalIndices[faceVertexOffset]; - //const std::vector &n = inputMeshPtr->N[imNormalIdx]; const McDouble* imNormal = inputMeshPtr->pNormals + (imNormalIdx * 3); - //my_assert(n.size() == 3); - //Eigen::Vector3d normal = Eigen::Vector3d(n[0], n[1], n[2]) * (flipNormalsOnFace ? -1.0 : 1.0); normal.x = imNormal[0]; normal.y = imNormal[1]; normal.z = imNormal[2]; - //ccVertexNormals[ccVertexIdx] = normal; } } @@ -621,7 +576,7 @@ McInt32 main() // ------------------------- char fnameBuf[64]; - sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), ci); + sprintf(fnameBuf, ("OUT_" + name + "-%d.obj").c_str(), ci); std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); mioWriteOBJ(fpath.c_str(), @@ -636,42 +591,6 @@ McInt32 main() (McUint32)ccVertexNormals.size(), 0, // numTexCoords ccFaceCount); - - //printf("write file: %s\n", fpath.c_str()); - - //std::ofstream file(fpath); - - //// write vertices and normals - - //for (McInt32 i = 0; i < (McInt32)ccVertexCount; ++i) - //{ - // McDouble x = ccVertices[(McSize)i * 3 + 0]; - // McDouble y = ccVertices[(McSize)i * 3 + 1]; - // McDouble z = ccVertices[(McSize)i * 3 + 2]; - // file << "v " << std::setprecision(std::numeric_limits::digits10 + 1) << x << " " << y << " " << z << std::endl; - - // Eigen::Vector3d n = ccVertexNormals[i]; - // file << "vn " << std::setprecision(std::numeric_limits::digits10 + 1) << n.x() << " " << n.y() << " " << n.z() << std::endl; - //} - - //// write faces (with normal indices) - - //faceVertexOffsetBase = 0; - //for (McInt32 i = 0; i < (McInt32)ccFaceCount; ++i) - //{ - // McInt32 faceSize = faceSizes.at(i); - - // file << "f "; - // for (McInt32 j = 0; j < faceSize; ++j) - // { - // const McInt32 idx = faceVertexOffsetBase + j; - // const McInt32 ccVertexIdx = ccFaceIndices[idx]; - // file << (ccVertexIdx + 1) << "//" << (ccVertexIdx + 1) << " "; - // } - // file << std::endl; - - // faceVertexOffsetBase += faceSize; - //} } // From 5cf36f71bed304f643b4aff3074d736f23add078 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Mon, 15 Jan 2024 09:15:09 +0000 Subject: [PATCH 08/23] update Triangulation tutorial --- tutorials/CMakeLists.txt | 3 +- tutorials/CSGBoolean/CSGBoolean.cpp | 15 +- tutorials/Triangulation/CMakeLists.txt | 27 -- tutorials/Triangulation/Triangulation.cpp | 325 +++++++++------------- tutorials/VertexNormals/VertexNormals.cpp | 1 + 5 files changed, 147 insertions(+), 224 deletions(-) delete mode 100644 tutorials/Triangulation/CMakeLists.txt diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 3354c52..c79b45c 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -18,8 +18,9 @@ create_tutorial_target(TextureCoordinates) # untested create_tutorial_target(BasicCmdLineApp) create_tutorial_target(HelloWorld) create_tutorial_target(CSGBoolean) +create_tutorial_target(Triangulation) -#add_subdirectory(Triangulation) +# #add_subdirectory(TriangulatedFaceMaps) #add_subdirectory(EventCallback) #add_subdirectory(MultipleContextsInParallel) diff --git a/tutorials/CSGBoolean/CSGBoolean.cpp b/tutorials/CSGBoolean/CSGBoolean.cpp index 5da69a9..a702d58 100644 --- a/tutorials/CSGBoolean/CSGBoolean.cpp +++ b/tutorials/CSGBoolean/CSGBoolean.cpp @@ -78,6 +78,7 @@ int main(int argc, const char* argv[]) MioMesh cutMesh = srcMesh; const bool user_provided_meshes = argc > 1; + if (user_provided_meshes && argc < 3) { fprintf(stderr, "usage: \n" "The possible values for the arguments are:\n" @@ -155,7 +156,7 @@ int main(int argc, const char* argv[]) // McContext context = MC_NULL_HANDLE; - // a debug context is created in a you load your own (possibly faulty) meshes + // a debug context is created in case you load your own (possibly faulty) meshes McResult status = mcCreateContext(&context, MC_DEBUG); my_assert(status == MC_NO_ERROR); @@ -232,12 +233,6 @@ int main(int argc, const char* argv[]) my_assert(status == MC_NO_ERROR); - // - // We no longer need the mem of input meshes, so we can free it! - // - mioFreeMesh(&srcMesh); - mioFreeMesh(&cutMesh); - // // query the number of available fragments // NOTE: a boolean operation shall always give fragments as output @@ -383,6 +378,12 @@ int main(int argc, const char* argv[]) my_assert(status == MC_NO_ERROR); } + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + // // destroy context // diff --git a/tutorials/Triangulation/CMakeLists.txt b/tutorials/Triangulation/CMakeLists.txt deleted file mode 100644 index 7d04663..0000000 --- a/tutorials/Triangulation/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(Triangulation Triangulation.cpp) -target_link_libraries(Triangulation mcut ${extra_libs}) -target_include_directories(Triangulation PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(Triangulation PRIVATE ${compilation_flags}) -target_compile_definitions(Triangulation PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/Triangulation/Triangulation.cpp b/tutorials/Triangulation/Triangulation.cpp index 4a18291..f788679 100644 --- a/tutorials/Triangulation/Triangulation.cpp +++ b/tutorials/Triangulation/Triangulation.cpp @@ -1,60 +1,60 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -Simple "Triangulation" program using MCUT. -Input meshes are defined in-source but output meshes are saved as .off files -*/ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * VertexNormals.cpp + * + * \brief: + * This tutorial shows how to query faces of output connected components + * that are triangulated. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include +#include #define my_assert(cond) \ if (!(cond)) \ { \ fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ + std::abort(); \ } -void writeOFF( - const char *fpath, - float *pVertices, - uint32_t *pFaceIndices, - uint32_t *pFaceSizes, - uint32_t numVertices, - uint32_t numFaces); int main() { - // 1. Create meshes. - // ----------------- - - // the cube - // -------- - float cubeVertices[] = { + // + // Create meshes. + // + + // + // source mesh (cube) + // + McFloat cubeVertices[] = { -5, -5, 5, // 0 5, -5, 5, // 1 5, 5, 5, //2 @@ -64,7 +64,7 @@ int main() 5, 5, -5, //6 -5, 5, -5 //7 }; - uint32_t cubeFaces[] = { + McUint32 cubeFaces[] = { 0, 1, 2, 3, //0 7, 6, 5, 4, //1 1, 5, 6, 2, //2 @@ -72,42 +72,42 @@ int main() 3, 2, 6, 7, //4 4, 5, 1, 0 //5 }; - uint32_t cubeFaceSizes[] = { + McUint32 cubeFaceSizes[] = { 4, 4, 4, 4, 4, 4}; - uint32_t numCubeVertices = 8; - uint32_t numCubeFaces = 6; + McUint32 numCubeVertices = 8; + McUint32 numCubeFaces = 6; - // the cut mesh - // --------- - float cutMeshVertices[] = { + // + // cut-mesh (quad with two triangles) + // + McFloat cutMeshVertices[] = { -20, -4, 0, //0 0, 20, 20, //1 20, -4, 0, //2 0, 20, -20 //3 }; - uint32_t cutMeshFaces[] = { + McUint32 cutMeshFaces[] = { 0, 1, 2, //0 0, 2, 3 //1 }; - uint32_t cutMeshFaceSizes[] = { + McUint32 cutMeshFaceSizes[] = { 3, 3}; - uint32_t numCutMeshVertices = 4; - uint32_t numCutMeshFaces = 2; + McUint32 numCutMeshVertices = 4; + McUint32 numCutMeshFaces = 2; - // 2. create a context - // ------------------- + // + // Create a context + // McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "could not create context (err=%d)\n", (int)err); - exit(1); - } + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - // 3. do the magic! - // ---------------- - err = mcDispatch( + my_assert(status == MC_NO_ERROR); + + // + // do the magic! + // + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_FLOAT, cubeVertices, @@ -121,175 +121,122 @@ int main() numCutMeshVertices, numCutMeshFaces); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "dispatch call failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - // 4. query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnComps; - std::vector connComps; + // + // query the number of available connected components + // - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); + McUint32 connectedComponentCount; + std::vector connectedComponents; - if (err != MC_NO_ERROR) - { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - if (numConnComps == 0) + my_assert(status == MC_NO_ERROR); + + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - connComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)connComps.size(); ++i) + for (int i = 0; i < (int)connectedComponents.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id McSize numBytes = 0; - // query the vertices - // ---------------------- + // + // ccVertices + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(float) * 3)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices * 3u); + std::vector ccVertices(ccVertexCount * 3u); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void *)vertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void *)ccVertices.data(), NULL); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - // query the faces - // ------------------- + // + // (triangulated) faces + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - std::vector triangulationIndices; - triangulationIndices.resize(numBytes / sizeof(uint32_t)); + std::vector ccTriangleFaceIndices; + ccTriangleFaceIndices.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, triangulationIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccTriangleFaceIndices.data(), NULL); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert(status == MC_NO_ERROR); - std::vector faceSizes(triangulationIndices.size()/3, 3); + std::vector ccFaceSizes(ccTriangleFaceIndices.size()/3, 3); - char fnameBuf[32]; - sprintf(fnameBuf, "conncomp%d.off", i); - - // save to mesh file (.off) - // ------------------------ - writeOFF(fnameBuf, - (float *)vertices.data(), - (uint32_t *)triangulationIndices.data(), - (uint32_t *)faceSizes.data(), - (uint32_t)vertices.size() / 3, - (uint32_t)faceSizes.size()); - } + // + // save connected component (mesh) to an .obj file + // - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + char fnameBuf[64]; + sprintf(fnameBuf, "conncomp%d.obj", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); - if (err != MC_NO_ERROR) - { - fprintf(stderr, "mcReleaseConnectedComponents failed (err=%d)\n", (int)err); - exit(1); - } + // "mioWriteOBJ" expects a vertex array of doubles. So we temporarilly create one. + std::vector ccVertices64(ccVertices.size(), McDouble(0.0)); - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + for(McUint32 v =0; v < (McUint32)ccVertices.size(); ++v) + { + ccVertices64[v] = (McDouble)ccVertices[v]; + } - if (err != MC_NO_ERROR) - { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)err); - exit(1); + mioWriteOBJ( + fpath.c_str(), + ccVertices64.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccTriangleFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); } - return 0; -} + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // -// write mesh to .off file -void writeOFF( - const char *fpath, - float *pVertices, - uint32_t *pFaceIndices, - uint32_t *pFaceSizes, - uint32_t numVertices, - uint32_t numFaces) -{ - FILE *file = fopen(fpath, "w"); + status = mcReleaseConnectedComponents(context, 0, NULL); - if (file == NULL) - { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } + my_assert (status == MC_NO_ERROR); - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) - { - float *vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } + // + // free memory of context + // + + status = mcReleaseContext(context); - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) - { - uint32_t faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) - { - uint32_t *fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } + my_assert (status == MC_NO_ERROR); - fclose(file); + return 0; } diff --git a/tutorials/VertexNormals/VertexNormals.cpp b/tutorials/VertexNormals/VertexNormals.cpp index 6fb2f99..be7f73a 100644 --- a/tutorials/VertexNormals/VertexNormals.cpp +++ b/tutorials/VertexNormals/VertexNormals.cpp @@ -38,6 +38,7 @@ #include #include #include // std::sqrt + #define my_assert(cond) \ if (!(cond)) \ { \ From fedea397b3dc43e185b7b1398d0506b6a93fd48b Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Tue, 16 Jan 2024 20:01:04 +0000 Subject: [PATCH 09/23] update all tutorials to remove libigl as a dependency --- source/frontend.cpp | 6 +- tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp | 2 +- tutorials/CMakeLists.txt | 18 +- tutorials/EventCallback/CMakeLists.txt | 30 - tutorials/EventCallback/EventCallback.cpp | 372 +++-- tutorials/FaceNormals/FaceNormals.cpp | 2 +- tutorials/HelloWorld/HelloWorld.cpp | 2 +- tutorials/InOutQuery/CMakeLists.txt | 30 - tutorials/InOutQuery/InOutQuery.cpp | 547 ++------ .../MultipleContextsInParallel/CMakeLists.txt | 30 - .../MultipleContextsInParallel.cpp | 632 +++------ tutorials/PlanarSectioning/CMakeLists.txt | 30 - .../PlanarSectioning/PlanarSectioning.cpp | 298 ++-- .../QuerySeamVerticesSorted/CMakeLists.txt | 30 - .../QuerySeamVerticesSorted.cpp | 1240 +++-------------- .../QuerySeamVerticesUnsorted/CMakeLists.txt | 30 - .../QuerySeamVerticesUnsorted.cpp | 724 +++------- .../CMakeLists.txt | 30 - .../ReversedConnectedComponentFaces.cpp | 347 ++--- tutorials/TriangulatedFaceMaps/CMakeLists.txt | 27 - .../TriangulatedFaceMaps.cpp | 1094 +++++++++------ 21 files changed, 1907 insertions(+), 3614 deletions(-) delete mode 100644 tutorials/EventCallback/CMakeLists.txt delete mode 100644 tutorials/InOutQuery/CMakeLists.txt delete mode 100644 tutorials/MultipleContextsInParallel/CMakeLists.txt delete mode 100644 tutorials/PlanarSectioning/CMakeLists.txt delete mode 100644 tutorials/QuerySeamVerticesSorted/CMakeLists.txt delete mode 100644 tutorials/QuerySeamVerticesUnsorted/CMakeLists.txt delete mode 100644 tutorials/ReversedConnectedComponentFaces/CMakeLists.txt delete mode 100644 tutorials/TriangulatedFaceMaps/CMakeLists.txt diff --git a/source/frontend.cpp b/source/frontend.cpp index 2fb137e..ab74f9a 100644 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -2788,7 +2788,7 @@ void get_connected_component_data_impl_detail( } break; case MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE: { if (cc_uptr->type == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - throw std::invalid_argument("cannot query seam vertices on connected component of type 'input'"); + throw std::invalid_argument("cannot query seam vertices on connected component of type 'MC_CONNECTED_COMPONENT_TYPE_INPUT'"); } const std::shared_ptr& cc = cc_uptr->kernel_hmesh_data->mesh; @@ -2845,7 +2845,7 @@ void get_connected_component_data_impl_detail( // and we build (collect all vertices of) its respective sequence by walking to // the left and right side/neighbours. // The fact that we walk left and right implies that two dijoint draft sequences - // will be found which will need to be merge later. These disjoint draft sequences + // will be found which will need to be merged later. These disjoint draft sequences // are stored in "disjoint_vertex_sequences_of_same_seam". const McUint32 seed_vertex_descr = (McUint32)seed_fiter->first; @@ -2929,7 +2929,7 @@ void get_connected_component_data_impl_detail( } } - MCUT_ASSERT(untraversed_adj_seam_vertex_count <= 1); + //MCUT_ASSERT(untraversed_adj_seam_vertex_count <= 1); // no further neighbours to walk/traverse but the stack still has seam vertices to be walked. // This implies we have an open loop, and that we have finished finding the first disjoint part diff --git a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp index 2da063b..b1e8d8b 100644 --- a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp +++ b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp @@ -133,7 +133,7 @@ McUint32 main(McUint32 argc, char* argv[]) McContext context = MC_NULL_HANDLE; - #ifdef NDEBUG +#ifdef NDEBUG McResult status = mcCreateContext(&context, MC_NULL_HANDLE); #else McResult status = mcCreateContext(&context, MC_DEBUG); diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index c79b45c..8c24a04 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -19,16 +19,14 @@ create_tutorial_target(BasicCmdLineApp) create_tutorial_target(HelloWorld) create_tutorial_target(CSGBoolean) create_tutorial_target(Triangulation) - -# -#add_subdirectory(TriangulatedFaceMaps) -#add_subdirectory(EventCallback) -#add_subdirectory(MultipleContextsInParallel) -#add_subdirectory(ReversedConnectedComponentFaces) -#add_subdirectory(PlanarSectioning) -#add_subdirectory(QuerySeamVerticesUnsorted) -#add_subdirectory(QuerySeamVerticesSorted) -#add_subdirectory(InOutQuery) +create_tutorial_target(TriangulatedFaceMaps) +create_tutorial_target(EventCallback) +create_tutorial_target(ReversedConnectedComponentFaces) +create_tutorial_target(QuerySeamVerticesUnsorted) +create_tutorial_target(QuerySeamVerticesSorted) +create_tutorial_target(MultipleContextsInParallel) +create_tutorial_target(PlanarSectioning) +create_tutorial_target(InOutQuery) # # TODO diff --git a/tutorials/EventCallback/CMakeLists.txt b/tutorials/EventCallback/CMakeLists.txt deleted file mode 100644 index 4990a71..0000000 --- a/tutorials/EventCallback/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(EventCallback EventCallback.cpp) -target_link_libraries(EventCallback mcut ${extra_libs}) -target_include_directories(EventCallback PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(EventCallback PRIVATE ${compilation_flags}) -target_compile_definitions(EventCallback PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/EventCallback/EventCallback.cpp b/tutorials/EventCallback/EventCallback.cpp index e1bdfcc..479f5f3 100644 --- a/tutorials/EventCallback/EventCallback.cpp +++ b/tutorials/EventCallback/EventCallback.cpp @@ -1,36 +1,41 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ - -/* -Simple "hello world" program using MCUT. -Input meshes are defined in-source but output meshes are saved as .off files -*/ + * FaceNormals.cpp + * + * \brief: + * This tutorial shows how to call the asynchronious mcDisptach function and + * assign a callback that is invoked when the mcDisptach call is complete. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include +#include #define my_assert(cond) \ if (!(cond)) { \ @@ -38,23 +43,16 @@ Input meshes are defined in-source but output meshes are saved as .off files std::exit(1); \ } -void writeOFF( - const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces); - struct CallbackData { - int a; + McInt32 a; const char* b; }; -// This callback function is called (asynchroniously) by MCUT when the associated event has finished execution -void myCallbackFunction(McEvent event, void* data) +// This callback function will be called asynchroniously w.r.t the client application. +// Moreover, it is invoked by MCUT when the associated event has finished execution. +McVoid myCallbackFunction(McEvent event, McVoid* data) { - printf("callback invoked!\n"); + printf("Callback invoked!\n"); printf("event handle = %p\n", event); @@ -63,14 +61,15 @@ void myCallbackFunction(McEvent event, void* data) printf("callback data ptr: a=%d b=%s\n", cd_ptr->a, cd_ptr->b); } -int main() +McInt32 main() { - // 1. Create meshes. - // ----------------- + // + // Create meshes to intersect + // - // the cube - // -------- - float cubeVertices[] = { + // the source-mesh (a cube) + + McFloat cubeVertices[] = { -5, -5, 5, // 0 5, -5, 5, // 1 5, 5, 5, // 2 @@ -80,7 +79,7 @@ int main() 5, 5, -5, // 6 -5, 5, -5 // 7 }; - uint32_t cubeFaces[] = { + McUint32 cubeFaces[] = { 0, 1, 2, 3, // 0 7, 6, 5, 4, // 1 1, 5, 6, 2, // 2 @@ -88,39 +87,40 @@ int main() 3, 2, 6, 7, // 4 4, 5, 1, 0 // 5 }; - uint32_t cubeFaceSizes[] = { + McUint32 cubeFaceSizes[] = { 4, 4, 4, 4, 4, 4 }; - uint32_t numCubeVertices = 8; - uint32_t numCubeFaces = 6; + McUint32 numCubeVertices = 8; + McUint32 numCubeFaces = 6; - // the cut mesh - // --------- - float cutMeshVertices[] = { + // the cut mesh (a quad formed of two triangles) + McFloat cutMeshVertices[] = { -20, -4, 0, // 0 0, 20, 20, // 1 20, -4, 0, // 2 0, 20, -20 // 3 }; - uint32_t cutMeshFaces[] = { + McUint32 cutMeshFaces[] = { 0, 1, 2, // 0 0, 2, 3 // 1 }; - // uint32_t cutMeshFaceSizes[] = { - // 3, 3}; - uint32_t numCutMeshVertices = 4; - uint32_t numCutMeshFaces = 2; + McUint32 cutMeshFaceSizes[] = { + 3, 3}; + McUint32 numCutMeshVertices = 4; + McUint32 numCutMeshFaces = 2; // 2. create a context // ------------------- McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - if (err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (err=%d)\n", (int)err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "could not create context (status=%d)\n", (McInt32)status); exit(1); } + // + // do the cutting // // NOTE: non-blocking/asynchronious dispatch call. // @@ -129,9 +129,9 @@ int main() McEvent dispatchEvent = MC_NULL_HANDLE; - err = mcEnqueueDispatch( + status = mcEnqueueDispatch( context, - MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, + MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_ENFORCE_GENERAL_POSITION, cubeVertices, cubeFaces, cubeFaceSizes, @@ -139,67 +139,57 @@ int main() numCubeFaces, cutMeshVertices, cutMeshFaces, - nullptr, + cutMeshFaceSizes, numCutMeshVertices, numCutMeshFaces, // new parameters 0, NULL, &dispatchEvent); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcEnqueueDispatch failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); // - // The following logic reads as follows: + // The following logic can be understood to execute as follows: // Call the function "myCallbackFunction" when "dispatchEvent" has finished // CallbackData callbackData; callbackData.a = 42; callbackData.b = "I found the answer to life"; - err = mcSetEventCallback(dispatchEvent, myCallbackFunction, (void*)&callbackData); + status = mcSetEventCallback(dispatchEvent, myCallbackFunction, (McVoid*)&callbackData); - // 4. query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnComps; - std::vector connComps; + // + // query the number of available connected components after the cut + // + McUint32 connectedComponentCount; + std::vector connectedComponents; #if 1 // // block until the "dispatchEvent" has finished // - err = mcWaitForEvents(1, &dispatchEvent); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcWaitForEvents(1, &dispatchEvent); + my_assert (status == MC_NO_ERROR); // - // By waiting for an event (with mcWaitForEvents), we are able to query that event for its execution - // status to find out if the actual operation run without any errors (i.e. errors due - // to something more nuanced like a missing vertex in an index list). + // By waiting for an event (with "mcWaitForEvents"), we are able to probe that event for its execution + // status to find out if the associated operation (i.e. "mcEnqueueDispatch") run without any errors (i.e. errors due + // to something wrong with the input meshes). // McResult dispatchRuntimeStatus = MC_NO_ERROR; - err = mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &dispatchRuntimeStatus, NULL); + + status = mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &dispatchRuntimeStatus, NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); if (dispatchRuntimeStatus != MC_NO_ERROR) { - fprintf(stderr, "mcEnqueueDispatch failed internally (err=%d)\n", (int)dispatchRuntimeStatus); + fprintf(stderr, "mcEnqueueDispatch failed internally (status=%d)\n", (McInt32)dispatchRuntimeStatus); exit(1); } - // invoke next operation (blocks until "numConnComps" is set) - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); + // invoke next operation (blocks until "connectedComponentCount" is set) + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); #else // @@ -207,149 +197,145 @@ int main() // McEvent ccQueryEvent = MC_NULL_HANDLE; - // Note: Any API call that can "emit" an event can also wait on an event, and vice versa - err = mcEnqueueGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps, 1, &dispatchEvent, &ccQueryEvent); + // Note: An API call that can "emit" an event can also wait on an event, and vice versa + status = mcEnqueueGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount, 1, &dispatchEvent, &ccQueryEvent); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcEnqueueGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps, 1, &dispatchEvent, &ccQueryEvent) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); // // block until the "ccQueryEvent" has finished // - err = mcWaitForEvents(1, &ccQueryEvent); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcWaitForEvents(1, &ccQueryEvent) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcWaitForEvents(1, &ccQueryEvent); + + my_assert (status == MC_NO_ERROR); #endif - if (numConnComps == 0) { + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - connComps.resize(numConnComps); - - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); + connectedComponents.resize(connectedComponentCount); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + my_assert (status == MC_NO_ERROR); - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + // + // query the data of each connected component + // + for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id McSize numBytes = 0; - // query the vertices - // ---------------------- + // + // vertices + // - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(float) * 3)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McFloat) * 3ull)); + std::vector ccVertices(ccVertexCount * 3u); - std::vector vertices(numberOfVertices * 3u); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (McVoid*)ccVertices.data(), NULL); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void*)vertices.data(), NULL); + my_assert (status == MC_NO_ERROR); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + // + // faces + // - // query the faces - // ------------------- + numBytes = 0; - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - std::vector faceIndices; - faceIndices.resize(numBytes / sizeof(uint32_t)); + std::vector ccFaceIndices; + ccFaceIndices.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, faceIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, (McVoid*)ccFaceIndices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); + + // + // face sizes (vertices per face) + // - // query the face sizes - // ------------------------ numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); - } - std::vector faceSizes; - faceSizes.resize(numBytes / sizeof(uint32_t)); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + + my_assert (status == MC_NO_ERROR); + + std::vector ccFaceSizes; + ccFaceSizes.resize(numBytes / sizeof(McUint32)); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, (McVoid*)ccFaceSizes.data(), NULL); + + my_assert (status == MC_NO_ERROR); + + // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, "OUT_conncomp%d.obj", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); + // "mioWriteOBJ" expects a vertex array of doubles. So we temporarilly create one. + std::vector ccVertices64(ccVertices.size(), McDouble(0.0)); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); + for(McUint32 v =0; v < (McUint32)ccVertices.size(); ++v) + { + ccVertices64[v] = (McDouble)ccVertices[v]; } - char fnameBuf[32]; - sprintf(fnameBuf, "conncomp%d.off", i); - - // save to mesh file (.off) - // ------------------------ - writeOFF(fnameBuf, - (float*)vertices.data(), - (uint32_t*)faceIndices.data(), - (uint32_t*)faceSizes.data(), - (uint32_t)vertices.size() / 3, - (uint32_t)faceSizes.size()); + mioWriteOBJ( + fpath.c_str(), + ccVertices64.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (err=%d)\n", (int)err); - exit(1); - } + status = mcReleaseConnectedComponents(context, 0, NULL); - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + my_assert(status == MC_NO_ERROR); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)err); - exit(1); - } + // + // free memory of context + // + + status = mcReleaseContext(context); + + my_assert(status == MC_NO_ERROR); return 0; } // write mesh to .off file -void writeOFF( +McVoid writeOFF( const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces) + McFloat* pVertices, + McUint32* pFaceIndices, + McUint32* pFaceSizes, + McUint32 numVertices, + McUint32 numFaces) { fprintf(stdout, "write: %s\n", fpath); @@ -362,19 +348,19 @@ void writeOFF( fprintf(file, "OFF\n"); fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - float* vptr = pVertices + (i * 3); + McInt32 i; + for (i = 0; i < (McInt32)numVertices; ++i) { + McFloat* vptr = pVertices + (i * 3); fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); } - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - uint32_t faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - uint32_t* fptr = pFaceIndices + faceBaseOffset + j; + McInt32 faceBaseOffset = 0; + for (i = 0; i < (McInt32)numFaces; ++i) { + McUint32 faceVertexCount = pFaceSizes[i]; + fprintf(file, "%d", (McInt32)faceVertexCount); + McInt32 j; + for (j = 0; j < (McInt32)faceVertexCount; ++j) { + McUint32* fptr = pFaceIndices + faceBaseOffset + j; fprintf(file, " %d", *fptr); } fprintf(file, "\n"); diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index c8348dd..2f18939 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -42,7 +42,7 @@ if(!(cond)) \ { \ fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ + std::abort(); \ } // simple structure representing a 3d vector and the operations we will perform with it diff --git a/tutorials/HelloWorld/HelloWorld.cpp b/tutorials/HelloWorld/HelloWorld.cpp index 399a96a..425a653 100644 --- a/tutorials/HelloWorld/HelloWorld.cpp +++ b/tutorials/HelloWorld/HelloWorld.cpp @@ -209,7 +209,7 @@ McInt32 main() // char fnameBuf[64]; - sprintf(fnameBuf, "conncomp%d.obj", i); + sprintf(fnameBuf, "OUT_conncomp%d.obj", i); std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); // "mioWriteOBJ" expects a vertex array of doubles. So we temporarilly create one. diff --git a/tutorials/InOutQuery/CMakeLists.txt b/tutorials/InOutQuery/CMakeLists.txt deleted file mode 100644 index 9135512..0000000 --- a/tutorials/InOutQuery/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(InOutQuery InOutQuery.cpp) -target_link_libraries(InOutQuery mcut ${extra_libs}) -target_include_directories(InOutQuery PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(InOutQuery PRIVATE ${compilation_flags}) -target_compile_definitions(InOutQuery PRIVATE ${preprocessor_defs} -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") \ No newline at end of file diff --git a/tutorials/InOutQuery/InOutQuery.cpp b/tutorials/InOutQuery/InOutQuery.cpp index ad29163..2aeadb3 100644 --- a/tutorials/InOutQuery/InOutQuery.cpp +++ b/tutorials/InOutQuery/InOutQuery.cpp @@ -1,36 +1,51 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * PlanarSectioning.cpp + * + * \brief: + * This tutorial shows how to determine the spatial configuration that + * mcut found the input meshes to be in. That is, it shows you how to + * know whether e.g. the source-mesh is enclosed inside of the cut-mesh, + * which may be a possible reason for mcut producing zero output. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" -#include -#include -#include // PRId64 +#include "mio/mio.h" + #include #include #include #include -#include #include +#define my_assert(cond) \ + if (!(cond)) { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::abort(); \ + } + void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, McDebugType type, unsigned int id, @@ -39,59 +54,53 @@ void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, const char* message, const void* userParam); -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces); - -void writeOFF( - const char* fpath, - const double* pVertices, - const uint32_t* pFaceIndices, - const uint32_t* pFaceSizes, - const uint32_t numVertices, - const uint32_t numFaces); - int main() { - double* srcMeshVertices = NULL; - uint32_t* srcMeshFaceIndices = NULL; - uint32_t* srcMeshFaceSizes = NULL; - uint32_t srcMeshNumFaces = 0; - uint32_t srcMeshNumVertices = 0; - - double* cutMeshVertices = NULL; - uint32_t* cutMeshFaceIndices = NULL; - uint32_t* cutMeshFaceSizes = NULL; - uint32_t cutMeshNumFaces = 0; - uint32_t cutMeshNumVertices = 0; - - McResult api_err = MC_NO_ERROR; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; - // + // + // read-in the source-mesh from file + // + + mioReadOFF(DATA_DIR "/cube.off", + &srcMesh.pVertices, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceSizes, + &srcMesh.numVertices, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file // NOTE: the icosphere (cut-mesh) provided lies inside the cube (source-mesh) - // - - const char* srcMeshFilePath = DATA_DIR "/cube.off"; - const char* cutMeshFilePath = DATA_DIR "/icosphere.off"; + // - printf(">> source-mesh file: %s\n", srcMeshFilePath); - readOFF(srcMeshFilePath, &srcMeshVertices, &srcMeshFaceIndices, &srcMeshFaceSizes, &srcMeshNumVertices, &srcMeshNumFaces); - printf(">> vertices=%u faces=%u\n", srcMeshNumVertices, srcMeshNumFaces); - - printf(">> cut-mesh file: %s\n", cutMeshFilePath); - readOFF(cutMeshFilePath, &cutMeshVertices, &cutMeshFaceIndices, &cutMeshFaceSizes, &cutMeshNumVertices, &cutMeshNumFaces); - printf(">> vertices=%u faces=%u\n", cutMeshNumVertices, cutMeshNumFaces); + mioReadOFF(DATA_DIR "/icosphere.off", + &cutMesh.pVertices, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceSizes, + &cutMesh.numVertices, + &cutMesh.numFaces); McContext context = MC_NULL_HANDLE; - api_err = mcCreateContextWithHelpers(&context, MC_DEBUG, 2); + McResult status = mcCreateContextWithHelpers(&context, MC_DEBUG, 2); - if (api_err != MC_NO_ERROR) { - printf("mcCreateContext failed (err=%d)", (int)api_err); + if (status != MC_NO_ERROR) { + printf("mcCreateContext failed (err=%d)", (int)status); exit(1); } @@ -101,56 +110,56 @@ int main() McFlags contextFlags = MC_NULL_HANDLE; - api_err = mcGetInfo(context, MC_CONTEXT_FLAGS, sizeof(McFlags), &contextFlags, nullptr); + status = mcGetInfo(context, MC_CONTEXT_FLAGS, sizeof(McFlags), &contextFlags, nullptr); - if (api_err != MC_NO_ERROR) { - printf("1:mcGetInfo(MC_CONTEXT_FLAGS) failed (err=%d)", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); if (contextFlags & MC_DEBUG) { - api_err = mcDebugMessageCallback(context, mcDebugOutputCALLBACK, nullptr); + status = mcDebugMessageCallback(context, mcDebugOutputCALLBACK, nullptr); - if (api_err != MC_NO_ERROR) { - printf("mcDebugMessageCallback failed (err=%d)", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - api_err = mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); + status = mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); - if (api_err != MC_NO_ERROR) { - printf("mcDebugMessageControl failed (err=%d)", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); } // // invoke dispatch to do the cutting // - api_err = mcDispatch( + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | - /* This flag is now required. Otherwise, MCUT will not check for the [type of intersection] when the inputs do not intersect to produce a cut. - If this flag is not specified, then querying the intersection type will return either 1) a stale value from some other - dispatch call (for which the flag was specified) or 2) "MC_DISPATCH_INTERSECTION_TYPE_MAX_ENUM" which is the default value. */ + /* + This flag is now required. Otherwise, MCUT will not check for + the [Type of Intersection] when the inputs do not intersect + (i.e. in order to produce a cut). If this flag is not specified, + then querying the intersection type will return either 1) a + stale value from some other dispatch call (for which the flag + was specified) or 2) "MC_DISPATCH_INTERSECTION_TYPE_MAX_ENUM" + which is the default value. + */ MC_DISPATCH_INCLUDE_INTERSECTION_TYPE , // source mesh - (const McVoid*)srcMeshVertices, - (const McUint32*)srcMeshFaceIndices, - (const McUint32*)srcMeshFaceSizes, - (McUint32)srcMeshNumVertices, - (McUint32)srcMeshNumFaces, - // cut mesh - (const McVoid*)cutMeshVertices, - (const McUint32*)cutMeshFaceIndices, - (const McUint32*)cutMeshFaceSizes, - (McUint32)cutMeshNumVertices, - (McUint32)cutMeshNumFaces); - - if (api_err != MC_NO_ERROR) { - printf("mcEnqueueDispatch failed (err=%d)\n", (int)api_err); - return api_err; - } + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + my_assert (status == MC_NO_ERROR); + + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); McUint32 numConnComps = 0; @@ -159,27 +168,21 @@ int main() // Note: we can also skip this step and immediately request "MC_CONTEXT_DISPATCH_INTERSECTION_TYPE" // - api_err = mcGetConnectedComponents( + status = mcGetConnectedComponents( context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); - if (api_err != MC_NO_ERROR) { - printf("mcEnqueueGetConnectedComponents failed (err=%d)\n", (int)api_err); - return api_err; - } + my_assert (status == MC_NO_ERROR); printf("have %u connected components\n", numConnComps); McSize bytes = 0; - api_err = mcGetInfo(context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, 0, NULL, &bytes); + status = mcGetInfo(context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, 0, NULL, &bytes); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcGetInfo failed (err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); if (bytes != sizeof(McDispatchIntersectionType)) { @@ -188,12 +191,9 @@ int main() McDispatchIntersectionType intersectionType; - api_err = mcGetInfo(context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &intersectionType, 0); + status = mcGetInfo(context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &intersectionType, 0); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcGetInfo failed (err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); // // Once we know the type of intersection (via "intersectionType"), we can go ahead @@ -202,44 +202,43 @@ int main() // std::string intersectionTypeStr; - switch (intersectionType) - { - case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD: - { - intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_STANDARD"; // input meshes were intersecting to give a cut (as per standard MCUT procedure) - }break; - case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH: - { - // the source-mesh was found to lie inside of the cut-mesh, which implies that the cut-mesh is a watertght (i.e. 2-manifold) surface mesh. - // The source-mesh can be a watertight- or open mesh. - intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH"; - }break; - case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH: - { - // the cut-mesh was found to lie inside of the source-mesh, which implies that the source-mesh is a watertght (i.e. 2-manifold) surface mesh. - // The cut-mesh can be a watertight- or open mesh. - intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH"; - }break; - case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE: - { - // The input meshes do not intersect to produce a cut, and neither mesh encloses the other. - // That is, they are apart, which means that the set-intersection of the space they enclose is empty. - intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_NONE"; - }break; - default: - intersectionTypeStr = "UNKNOWN"; // something strange happened (unlikely) - break; + switch (intersectionType) + { + case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD: + { + intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_STANDARD"; // input meshes were intersecting to give a cut (as per standard MCUT procedure) + }break; + case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH: + { + // the source-mesh was found to lie inside of the cut-mesh, which implies that the cut-mesh is a watertght (i.e. 2-manifold) surface mesh. + // The source-mesh can be a watertight- or open mesh. + intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH"; + }break; + case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH: + { + // the cut-mesh was found to lie inside of the source-mesh, which implies that the source-mesh is a watertght (i.e. 2-manifold) surface mesh. + // The cut-mesh can be a watertight- or open mesh. + intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH"; + }break; + case McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE: + { + // The input meshes do not intersect to produce a cut, and neither mesh encloses the other. + // That is, they are apart, which means that the set-intersection of the space they enclose is empty. + intersectionTypeStr = "MC_DISPATCH_INTERSECTION_TYPE_NONE"; + }break; + default: + intersectionTypeStr = "UNKNOWN"; // something strange happened (unlikely) + break; } printf("Intersection type = %s\n", intersectionTypeStr.c_str()); - + + // // destroy context - api_err = mcReleaseContext(context); + // + status = mcReleaseContext(context); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); return 0; } @@ -329,257 +328,3 @@ void mcCheckError_(McResult err, const char* file, int line) std::cout << error << " | " << file << " (" << line << ")" << std::endl; } } - -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } - - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** lineBuf, size_t* len) -{ - while (getline(lineBuf, len, file)) { - if (strlen(*lineBuf) > 1 && (*lineBuf)[0] != '#') { - return true; - } - } - return false; -} - -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces) -{ - // using "rb" instead of "r" to prevent linefeed conversion - // See: https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* lineBuf = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(lineBuf, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(lineBuf, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (double*)malloc(sizeof(double) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (double)(*numVertices); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - double x, y, z; - sscanf(lineBuf, "%lf %lf %lf", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - char* lineBufShifted = lineBuf; - int j = 0; - - while (j < n) { // parse remaining numbers on lineBuf - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number - - int val; - sscanf(lineBufShifted, "%d", &val); - - (*pFaceIndices)[indexOffset + j] = val; - j++; - } - - indexOffset += n; - } - - free(lineBuf); - - fclose(file); -} - -void writeOFF( - const char* fpath, - const double* pVertices, - const uint32_t* pFaceIndices, - const uint32_t* pFaceSizes, - const uint32_t numVertices, - const uint32_t numFaces) -{ - fprintf(stdout, "write: %s\n", fpath); - - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - const double* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } - - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - uint32_t faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - const uint32_t* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - fclose(file); -} \ No newline at end of file diff --git a/tutorials/MultipleContextsInParallel/CMakeLists.txt b/tutorials/MultipleContextsInParallel/CMakeLists.txt deleted file mode 100644 index 74b05ea..0000000 --- a/tutorials/MultipleContextsInParallel/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(MultipleContextsInParallel MultipleContextsInParallel.cpp) -target_link_libraries(MultipleContextsInParallel mcut ${extra_libs}) -target_include_directories(MultipleContextsInParallel PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(MultipleContextsInParallel PRIVATE ${compilation_flags}) -target_compile_definitions(MultipleContextsInParallel PRIVATE ${preprocessor_defs} -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") \ No newline at end of file diff --git a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp index 2bce752..f35d670 100644 --- a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp +++ b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp @@ -1,26 +1,37 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * MultipleContextsInParallel.cpp + * + * \brief: + * This tutorial shows how to setup MCUT to run with multiple contexts in + * parallel. This allows users to dispatch multiple cutting tasks in parallel. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" + #include #include #include // PRId64 @@ -39,22 +50,6 @@ void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, const char* message, const void* userParam); -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces); - -void writeOFF( - const char* fpath, - const double* pVertices, - const McUint32* pFaceIndices, - const McUint32* pFaceSizes, - const McUint32 numVertices, - const McUint32 numFaces); - struct Timer { std::string m_name; std::chrono::time_point m_startpoint; @@ -78,41 +73,50 @@ int main() { Timer scoped_timer_main_fn("main-function"); - double* srcMeshVertices = NULL; - McUint32* srcMeshFaceIndices = NULL; - McUint32* srcMeshFaceSizes = NULL; - McUint32 srcMeshNumFaces = 0; - McUint32 srcMeshNumVertices = 0; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; - double* cutMeshVertices = NULL; - McUint32* cutMeshFaceIndices = NULL; - McUint32* cutMeshFaceSizes = NULL; - McUint32 cutMeshNumFaces = 0; - McUint32 cutMeshNumVertices = 0; + MioMesh cutMesh = srcMesh; - McResult api_err = MC_NO_ERROR; + McResult status = MC_NO_ERROR; std::vector contexts_array; { Timer scoped_timer("init-function"); - const char* srcMeshFilePath = DATA_DIR "/source-mesh.off"; - const char* cutMeshFilePath = DATA_DIR "/cut-mesh.off"; - - printf(">> source-mesh file: %s\n", srcMeshFilePath); - printf(">> cut-mesh file: %s\n", cutMeshFilePath); - - // load meshes - // ----------- - - readOFF(srcMeshFilePath, &srcMeshVertices, &srcMeshFaceIndices, &srcMeshFaceSizes, &srcMeshNumVertices, &srcMeshNumFaces); - - printf(">> src-mesh vertices=%u faces=%u\n", srcMeshNumVertices, srcMeshNumFaces); - - readOFF(cutMeshFilePath, &cutMeshVertices, &cutMeshFaceIndices, &cutMeshFaceSizes, &cutMeshNumVertices, &cutMeshNumFaces); - - printf(">> cut-mesh vertices=%u faces=%u\n", cutMeshNumVertices, cutMeshNumFaces); + // + // read-in the source-mesh from file + // + + mioReadOFF(DATA_DIR "/source-mesh.off", + &srcMesh.pVertices, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceSizes, + &srcMesh.numVertices, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF(DATA_DIR "/cut-mesh.off", + &cutMesh.pVertices, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceSizes, + &cutMesh.numVertices, + &cutMesh.numFaces); printf("\n>> Create MCUT contexts\n"); @@ -123,37 +127,38 @@ int main() for (McUint32 i = 0; i < num_contexts_to_create; ++i) { - api_err = mcCreateContext(&contexts_array[i], MC_DEBUG | MC_OUT_OF_ORDER_EXEC_MODE_ENABLE); + status = mcCreateContext(&contexts_array[i], MC_DEBUG | MC_OUT_OF_ORDER_EXEC_MODE_ENABLE); - if (api_err != MC_NO_ERROR) { - printf("mcCreateContext failed (err=%d)", (int)api_err); + if (status != MC_NO_ERROR) { + printf("mcCreateContext failed (err=%d)", (int)status); exit(1); } + // // config debug output - // ------------------------------------------------------------------------- + // McFlags contextFlags = MC_NULL_HANDLE; - api_err = mcGetInfo(contexts_array[i], MC_CONTEXT_FLAGS, sizeof(McFlags), &contextFlags, nullptr); + status = mcGetInfo(contexts_array[i], MC_CONTEXT_FLAGS, sizeof(McFlags), &contextFlags, nullptr); - if (api_err != MC_NO_ERROR) { - printf("1:mcGetInfo(MC_CONTEXT_FLAGS) failed (err=%d)", (int)api_err); + if (status != MC_NO_ERROR) { + printf("1:mcGetInfo(MC_CONTEXT_FLAGS) failed (err=%d)", (int)status); exit(1); } if (contextFlags & MC_DEBUG) { - api_err = mcDebugMessageCallback(contexts_array[i], mcDebugOutputCALLBACK, nullptr); + status = mcDebugMessageCallback(contexts_array[i], mcDebugOutputCALLBACK, nullptr); - if (api_err != MC_NO_ERROR) { - printf("mcDebugMessageCallback failed (err=%d)", (int)api_err); + if (status != MC_NO_ERROR) { + printf("mcDebugMessageCallback failed (err=%d)", (int)status); exit(1); } - api_err = mcDebugMessageControl(contexts_array[i], McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); + status = mcDebugMessageControl(contexts_array[i], McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); - if (api_err != MC_NO_ERROR) { - printf("mcDebugMessageControl failed (err=%d)", (int)api_err); + if (status != MC_NO_ERROR) { + printf("mcDebugMessageControl failed (err=%d)", (int)status); exit(1); } } @@ -164,8 +169,9 @@ int main() const McUint32 num_contexts = (McUint32)contexts_array.size(); + // // do the cutting - // ------------------------------------------------------------------------- + // std::vector> per_context_connected_components(num_contexts); @@ -177,34 +183,34 @@ int main() auto schedule_dispatch_call = [&](McContext context, std::vector& emittedEvents, McUint32& numConnComps) { - api_err = mcEnqueueDispatch( + status = mcEnqueueDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, // source mesh - (const McVoid*)srcMeshVertices, - (const McUint32*)srcMeshFaceIndices, - (const McUint32*)srcMeshFaceSizes, - (McUint32)srcMeshNumVertices, - (McUint32)srcMeshNumFaces, + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, // cut mesh - (const McVoid*)cutMeshVertices, - (const McUint32*)cutMeshFaceIndices, - (const McUint32*)cutMeshFaceSizes, - (McUint32)cutMeshNumVertices, - (McUint32)cutMeshNumFaces, + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces, // events to wait for 0, NULL, // emitted event &emittedEvents[0]); - if (api_err != MC_NO_ERROR) { - printf("mcEnqueueDispatch failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcEnqueueDispatch failed (err=%d)\n", (int)status); + return status; } // query for all available connected components: - api_err = mcEnqueueGetConnectedComponents( + status = mcEnqueueGetConnectedComponents( context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, @@ -213,9 +219,9 @@ int main() &emittedEvents[0], // NOTE: MCUT make an internal copy of this handle (i.e. its value) &emittedEvents[1]); - if (api_err != MC_NO_ERROR) { - printf("mcEnqueueGetConnectedComponents failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcEnqueueGetConnectedComponents failed (err=%d)\n", (int)status); + return status; } return MC_NO_ERROR; @@ -230,10 +236,10 @@ int main() per_context_dispatch_events[i].resize(2); // there are two enqueue commands in "schedule_dispatch_call" - api_err = schedule_dispatch_call(contexts_array[i], per_context_dispatch_events[i], per_context_CC_count_array[i]); + status = schedule_dispatch_call(contexts_array[i], per_context_dispatch_events[i], per_context_CC_count_array[i]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "schedule_dispatch_call failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "schedule_dispatch_call failed (err=%d)\n", (int)status); exit(1); } } @@ -245,6 +251,7 @@ int main() // // **Join** // + { std::vector dispatch_events_array; // collection of all events into one list @@ -256,13 +263,25 @@ int main() per_context_dispatch_events[i].cend()); } - api_err = mcWaitForEvents((McUint32)dispatch_events_array.size(), &dispatch_events_array[0]); + // wait for all events + status = mcWaitForEvents((McUint32)dispatch_events_array.size(), &dispatch_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)status); exit(1); } + // + // We no longer need the mem of input meshes, so we can free it! + // + // CAUTION: Make sure that all dispatch functions that refer + // to user allocated memory (like input-mesh pointers) have completed + // before freeing this memory. Thus, the earliest we can call "mioFreeMesh" + // is after waiting for the dispatch functions to finish with "mcWaitForEvents" + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + // check for any runtime errors and request the connected components for (McUint32 i = 0; i < num_contexts; ++i) { @@ -271,10 +290,10 @@ int main() McResult schedule_dispatch_call_fn_status = MC_NO_ERROR; - api_err = mcGetEventInfo(per_context_dispatch_events[i][j], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &schedule_dispatch_call_fn_status, NULL); + status = mcGetEventInfo(per_context_dispatch_events[i][j], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &schedule_dispatch_call_fn_status, NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)status); exit(1); } @@ -288,35 +307,36 @@ int main() if (num_connected_components == 0) { printf("context %p has no connected components\n", contexts_array[i]); - return api_err; + return status; } per_context_connected_components[i].resize(num_connected_components); - api_err = mcGetConnectedComponents( // NOTE: blocking call because we need the result immediately (see below) + status = mcGetConnectedComponents( // NOTE: blocking call because we need the result immediately (see below) contexts_array[i], MC_CONNECTED_COMPONENT_TYPE_ALL, num_connected_components, &per_context_connected_components[i][0], NULL); - if (api_err != MC_NO_ERROR) { - printf("mcGetConnectedComponents failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcGetConnectedComponents failed (err=%d)\n", (int)status); + return status; } } - api_err = mcReleaseEvents((McUint32)dispatch_events_array.size(), &dispatch_events_array[0]); + status = mcReleaseEvents((McUint32)dispatch_events_array.size(), &dispatch_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)status); exit(1); } } } - // Request connected component data size in bytes - // ------------------------------------------------------------------------- + // + // Request connected component data [size] in bytes so that we can allocate memory + // std::vector< // context std::vector< // cc @@ -338,6 +358,7 @@ int main() std::vector>& per_cc_event_waitlist, std::vector& per_cc_vertices_bytes, std::vector& per_cc_triangles_bytes) { + const McUint32 num_connected_components = (McUint32)context_connected_components.size(); for (McUint32 i = 0; i < num_connected_components; ++i) { @@ -352,7 +373,7 @@ int main() McSize& cc_triangles_bytes = per_cc_triangles_bytes[i]; cc_vertices_bytes = 0; - McResult api_err = mcEnqueueGetConnectedComponentData( + McResult status = mcEnqueueGetConnectedComponentData( context, connCompId, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, @@ -361,13 +382,13 @@ int main() 0, NULL, &cc_events[0]); - if (api_err != MC_NO_ERROR) { - printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (err=%d)\n", (int)status); + return status; } cc_triangles_bytes = 0; - api_err = mcEnqueueGetConnectedComponentData( + status = mcEnqueueGetConnectedComponentData( context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, @@ -375,9 +396,9 @@ int main() &cc_triangles_bytes, 0, NULL, &cc_events[1]); - if (api_err != MC_NO_ERROR) { - printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)status); + return status; } } @@ -401,23 +422,24 @@ int main() per_context_per_cc_vertices_bytes[i].resize(num_connected_components); per_context_per_cc_triangles_bytes[i].resize(num_connected_components); - api_err = schedule_cc_data_bytesize_query( + status = schedule_cc_data_bytesize_query( contexts_array[i], per_context_connected_components[i], per_context_per_cc_event_waitlist[i], per_context_per_cc_vertices_bytes[i], per_context_per_cc_triangles_bytes[i]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "schedule_dispatch_call failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "schedule_dispatch_call failed (err=%d)\n", (int)status); exit(1); } } // ** Can do something else here while events are running + // // wait for events - // ------------------------------------------------------------------------- + // { std::vector bytes_size_query_events_array; // collection of all events into one list @@ -434,10 +456,10 @@ int main() } } - api_err = mcWaitForEvents((McUint32)bytes_size_query_events_array.size(), &bytes_size_query_events_array[0]); + status = mcWaitForEvents((McUint32)bytes_size_query_events_array.size(), &bytes_size_query_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)status); exit(1); } @@ -455,10 +477,10 @@ int main() for (McUint32 k = 0; k < num_events; ++k) { McResult schedule_cc_data_bytesize_query_fn_status = MC_NO_ERROR; - api_err = mcGetEventInfo(per_context_per_cc_event_waitlist[i][j][k], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &schedule_cc_data_bytesize_query_fn_status, NULL); + status = mcGetEventInfo(per_context_per_cc_event_waitlist[i][j][k], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &schedule_cc_data_bytesize_query_fn_status, NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "1:mcGetEventInfo(dispatchEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)status); exit(1); } @@ -470,17 +492,18 @@ int main() } } - api_err = mcReleaseEvents((McUint32)bytes_size_query_events_array.size(), &bytes_size_query_events_array[0]); + status = mcReleaseEvents((McUint32)bytes_size_query_events_array.size(), &bytes_size_query_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)status); exit(1); } } } + // // Query connected component data now we know the amount of bytes to allocate - // ------------------------------------------------------------------------- + // std::vector< // context std::vector< // cc @@ -517,7 +540,7 @@ int main() std::vector& cc_vertices_array = per_cc_vertices_array[i]; std::vector& cc_triangles_array = per_cc_triangles_array[i]; - McResult api_err = mcEnqueueGetConnectedComponentData( + McResult status = mcEnqueueGetConnectedComponentData( context, connCompId, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, @@ -526,12 +549,12 @@ int main() 0, NULL, &cc_events[0]); - if (api_err != MC_NO_ERROR) { - printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (err=%d)\n", (int)status); + return status; } - api_err = mcEnqueueGetConnectedComponentData( + status = mcEnqueueGetConnectedComponentData( context, connCompId, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, @@ -539,9 +562,9 @@ int main() NULL, 0, NULL, &cc_events[1]); - if (api_err != MC_NO_ERROR) { - printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)api_err); - return api_err; + if (status != MC_NO_ERROR) { + printf("mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (err=%d)\n", (int)status); + return status; } } @@ -589,8 +612,9 @@ int main() // ** Can do something else here while events are running + // // wait for events (join) - // ------------------------------------------------------------------------- + // std::vector data_query_events_array; // collection of all events into one list for (McUint32 i = 0; i < num_contexts; ++i) { @@ -604,10 +628,10 @@ int main() } } - api_err = mcWaitForEvents((McUint32)data_query_events_array.size(), &data_query_events_array[0]); + status = mcWaitForEvents((McUint32)data_query_events_array.size(), &data_query_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)status); exit(1); } @@ -625,10 +649,10 @@ int main() for (McUint32 k = 0; k < num_events; ++k) { McResult exec_status = MC_NO_ERROR; - api_err = mcGetEventInfo(per_context_per_cc_event_waitlist[i][j][k], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &exec_status, NULL); + status = mcGetEventInfo(per_context_per_cc_event_waitlist[i][j][k], MC_EVENT_RUNTIME_EXECUTION_STATUS, sizeof(McResult), &exec_status, NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcGetEventInfo(MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcGetEventInfo(MC_EVENT_RUNTIME_EXECUTION_STATUS...) failed (err=%d)\n", (int)status); exit(1); } @@ -640,16 +664,17 @@ int main() } } - api_err = mcReleaseEvents((McUint32)data_query_events_array.size(), &data_query_events_array[0]); + status = mcReleaseEvents((McUint32)data_query_events_array.size(), &data_query_events_array[0]); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)status); exit(1); } } + // // Write the connected components to file - // ------------------------------------------------------------------------- + // { Timer scoped_timer("save-files"); @@ -661,23 +686,36 @@ int main() const std::vector& vertex_array = per_context_per_cc_vertices_array[i][j]; const std::vector& triangles_array = per_context_per_cc_triangles_array[i][j]; - std::vector face_sizes(triangles_array.size() / 3, 3); // required by "writeOFF" + std::vector face_sizes(triangles_array.size() / 3, 3); // required by "mioWriteOBJ" + + // + // save connected component (mesh) to an .obj file + // char fnameBuf[256]; - sprintf(fnameBuf, "ctxt%d-cc%d.obj", i, j); - - writeOFF(fnameBuf, - vertex_array.data(), - (McUint32*)triangles_array.data(), - (McUint32*)face_sizes.data(), - (McUint32)vertex_array.size() / 3, - (McUint32)triangles_array.size() / 3); + sprintf(fnameBuf, "ctxt%d-conncomp%d.obj", i, j); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + mioWriteOBJ( + fpath.c_str(), + (McDouble*)vertex_array.data(), + nullptr, // pNormals + nullptr, // pTexCoords + face_sizes.data(), + (McUint32*)triangles_array.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + vertex_array.size()/3, + 0, // numNormals + 0, // numTexCoords + (McUint32)face_sizes.size()); } } } - + + // // Tear down contexts - // ------------------------------------------------------------------------- + // { Timer scoped_timer("teardown"); @@ -686,19 +724,23 @@ int main() McContext context = contexts_array[i]; + // // destroy internal data associated with each connected component - api_err = mcReleaseConnectedComponents(context, (McUint32)per_context_connected_components[i].size(), per_context_connected_components[i].data()); + // + status = mcReleaseConnectedComponents(context, (McUint32)per_context_connected_components[i].size(), per_context_connected_components[i].data()); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseEvents failed (err=%d)\n", (int)status); exit(1); } + // // destroy context - api_err = mcReleaseContext(context); + // + status = mcReleaseContext(context); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)api_err); + if (status != MC_NO_ERROR) { + fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)status); exit(1); } } @@ -791,258 +833,4 @@ void mcCheckError_(McResult err, const char* file, int line) if (err) { std::cout << error << " | " << file << " (" << line << ")" << std::endl; } -} - -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } - - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** lineBuf, size_t* len) -{ - while (getline(lineBuf, len, file)) { - if (strlen(*lineBuf) > 1 && (*lineBuf)[0] != '#') { - return true; - } - } - return false; -} - -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces) -{ - // using "rb" instead of "r" to prevent linefeed conversion - // See: https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* lineBuf = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(lineBuf, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(lineBuf, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (double*)malloc(sizeof(double) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (double)(*numVertices); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - double x, y, z; - sscanf(lineBuf, "%lf %lf %lf", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - char* lineBufShifted = lineBuf; - int j = 0; - - while (j < n) { // parse remaining numbers on lineBuf - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number - - int val; - sscanf(lineBufShifted, "%d", &val); - - (*pFaceIndices)[indexOffset + j] = val; - j++; - } - - indexOffset += n; - } - - free(lineBuf); - - fclose(file); -} - -void writeOFF( - const char* fpath, - const double* pVertices, - const McUint32* pFaceIndices, - const McUint32* pFaceSizes, - const McUint32 numVertices, - const McUint32 numFaces) -{ - fprintf(stdout, "write: %s\n", fpath); - - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - const double* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } - - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - McUint32 faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - const McUint32* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - fclose(file); } \ No newline at end of file diff --git a/tutorials/PlanarSectioning/CMakeLists.txt b/tutorials/PlanarSectioning/CMakeLists.txt deleted file mode 100644 index 215e164..0000000 --- a/tutorials/PlanarSectioning/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(PlanarSectioning PlanarSectioning.cpp) -target_link_libraries(PlanarSectioning mcut ${extra_libs}) -target_include_directories(PlanarSectioning PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(PlanarSectioning PRIVATE ${compilation_flags}) -target_compile_definitions(PlanarSectioning PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/PlanarSectioning/PlanarSectioning.cpp b/tutorials/PlanarSectioning/PlanarSectioning.cpp index 3dc7cd3..15d863a 100644 --- a/tutorials/PlanarSectioning/PlanarSectioning.cpp +++ b/tutorials/PlanarSectioning/PlanarSectioning.cpp @@ -1,26 +1,35 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * PlanarSectioning.cpp + * + * \brief: + * This tutorial shows how to partition/slice a mesh with a plane using mcut. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include @@ -31,18 +40,9 @@ #define my_assert(cond) \ if (!(cond)) { \ fprintf(stderr, "MCUT error: %s\n", #cond); \ - std::exit(1); \ + std::abort(); \ } -void writeOFF( - const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces); - - void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, unsigned int id, @@ -112,7 +112,7 @@ int main() // the cube // -------- - float cubeVertices[] = { + McFloat cubeVertices[] = { -5, -5, 5, // 0 5, -5, 5, // 1 5, 5, 5, //2 @@ -122,7 +122,7 @@ int main() 5, 5, -5, //6 -5, 5, -5 //7 }; - uint32_t cubeFaces[] = { + McUint32 cubeFaces[] = { 0, 1, 2, 3, //0 7, 6, 5, 4, //1 1, 5, 6, 2, //2 @@ -130,42 +130,52 @@ int main() 3, 2, 6, 7, //4 4, 5, 1, 0 //5 }; - uint32_t cubeFaceSizes[] = { + McUint32 cubeFaceSizes[] = { 4, 4, 4, 4, 4, 4}; - uint32_t numCubeVertices = 8; - uint32_t numCubeFaces = 6; + McUint32 numCubeVertices = 8; + McUint32 numCubeFaces = 6; - // 2. create a context - // ------------------- + // + // create a context + // McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); + McResult status = mcCreateContext(&context, MC_DEBUG); - if (err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // config debug output - // ----------------------- + // + // configure debug output + // McSize numBytes = 0; McFlags contextFlags; - err = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); - - err = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + + status = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); + + my_assert (status == MC_NO_ERROR); + + status = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + + my_assert (status == MC_NO_ERROR); if (contextFlags & MC_DEBUG) { - mcDebugMessageCallback(context, mcDebugOutput, nullptr); - mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); + status = mcDebugMessageCallback(context, mcDebugOutput, nullptr); + + my_assert (status == MC_NO_ERROR); + + status = mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, MC_TRUE); + + my_assert (status == MC_NO_ERROR); } - const McDouble normal[] = {0, 1,1}; // can point in any direction + const McDouble normal[] = {0, 1, 1}; // can point in any direction const McDouble sectionOffset = 0.45; McEvent dispatchEvent = MC_NULL_HANDLE; - - // 3. do the magic! - // ---------------- - err = mcEnqueueDispatchPlanarSection( + + // + // do the magic! + // + status = mcEnqueueDispatchPlanarSection( context, MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_ENFORCE_GENERAL_POSITION, cubeVertices, @@ -180,142 +190,122 @@ int main() &dispatchEvent ); - if (err != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - err = mcWaitForEvents(1,&dispatchEvent ); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcWaitForEvents failed (err=%d)\n", (int)err); - exit(1); - } + status = mcWaitForEvents(1,&dispatchEvent ); - // 4. query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnComps; - std::vector connComps; + my_assert (status == MC_NO_ERROR); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); + // + // query the number of available connected components after the cut + // + McUint32 connectedComponentCount; + std::vector connectedComponents; - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); + + my_assert (status == MC_NO_ERROR); - if (numConnComps == 0) { + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - connComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + for (int i = 0; i < (int)connectedComponents.size(); ++i) { + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id numBytes = 0; - // query the vertices - // ---------------------- + // + // vertices + // - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(float) * 3)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); - std::vector vertices(numberOfVertices * 3u); + std::vector ccVertices(ccVertexCount * 3u); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void*)vertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } - - // query the faces - // ------------------- + my_assert (status == MC_NO_ERROR); + + // + // faces + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - std::vector faceIndices; - faceIndices.resize(numBytes / sizeof(uint32_t)); + std::vector ccFaceIndices; + ccFaceIndices.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, faceIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // query the face sizes - // ------------------------ + // + // face sizes + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + + my_assert (status == MC_NO_ERROR); - std::vector faceSizes; - faceSizes.resize(numBytes / sizeof(uint32_t)); + std::vector ccFaceSizes; + ccFaceSizes.resize(numBytes / sizeof(McUint32)); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); - } - - char fnameBuf[32]; - sprintf(fnameBuf, "conncomp%d.off", i); + my_assert (status == MC_NO_ERROR); + // // save to mesh file (.off) - // ------------------------ - writeOFF(fnameBuf, - (float*)vertices.data(), - (uint32_t*)faceIndices.data(), - (uint32_t*)faceSizes.data(), - (uint32_t)vertices.size() / 3, - (uint32_t)faceSizes.size()); + // + + char fnameBuf[64]; + sprintf(fnameBuf, "OUT_conncomp%d.off", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + mioWriteOFF(fpath.c_str(), + (McDouble*)ccVertices.data(), + (McUint32*)ccFaceIndices.data(), + (McUint32*)ccFaceSizes.data(), + NULL, + (McUint32)ccVertices.size() / 3, + (McUint32)ccFaceSizes.size(), + (McUint32)0); } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (err=%d)\n", (int)err); - exit(1); - } + status = mcReleaseConnectedComponents(context, 0, NULL); - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + my_assert(status == MC_NO_ERROR); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)err); - exit(1); - } + // + // free memory of context + // + + status = mcReleaseContext(context); + + my_assert(status == MC_NO_ERROR); return 0; } @@ -323,11 +313,11 @@ int main() // write mesh to .off file void writeOFF( const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces) + McFloat* pVertices, + McUint32* pFaceIndices, + McUint32* pFaceSizes, + McUint32 numVertices, + McUint32 numFaces) { fprintf(stdout, "write: %s\n", fpath); @@ -342,17 +332,17 @@ void writeOFF( fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); int i; for (i = 0; i < (int)numVertices; ++i) { - float* vptr = pVertices + (i * 3); + McFloat* vptr = pVertices + (i * 3); fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); } int faceBaseOffset = 0; for (i = 0; i < (int)numFaces; ++i) { - uint32_t faceVertexCount = pFaceSizes[i]; + McUint32 faceVertexCount = pFaceSizes[i]; fprintf(file, "%d", (int)faceVertexCount); int j; for (j = 0; j < (int)faceVertexCount; ++j) { - uint32_t* fptr = pFaceIndices + faceBaseOffset + j; + McUint32* fptr = pFaceIndices + faceBaseOffset + j; fprintf(file, " %d", *fptr); } fprintf(file, "\n"); diff --git a/tutorials/QuerySeamVerticesSorted/CMakeLists.txt b/tutorials/QuerySeamVerticesSorted/CMakeLists.txt deleted file mode 100644 index b02f8de..0000000 --- a/tutorials/QuerySeamVerticesSorted/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(QuerySeamVerticesSorted QuerySeamVerticesSorted.cpp) -target_link_libraries(QuerySeamVerticesSorted mcut ${extra_libs}) -target_include_directories(QuerySeamVerticesSorted PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(QuerySeamVerticesSorted PRIVATE ${compilation_flags}) -target_compile_definitions(QuerySeamVerticesSorted PRIVATE ${preprocessor_defs} -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") \ No newline at end of file diff --git a/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp b/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp index ea1b8a5..b58fe55 100644 --- a/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp +++ b/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp @@ -1,26 +1,38 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * QuerySeamVerticesUnsorted.cpp + * + * \brief: + * This tutorial shows how to query 'seam vertices' of an output connected component + * as a sorted array. A seam vertex is one which lies along the intersection + * contour/path as a result of a cut. The code also shows you how to identify individual + * contours/paths. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include @@ -31,6 +43,7 @@ #include #include +#include #define my_assert(cond) \ if (!(cond)) { \ @@ -38,674 +51,146 @@ std::exit(1); \ } -#if defined(_WIN32) - // if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; -ssize_t getline(char** lineptr, size_t * n, FILE * stream); -#endif - -void readOFF(const char* fpath, double** pVertices, unsigned int** pFaceVertexIndices, - unsigned int** pFaceSizes, unsigned int* numVertices, - unsigned int* numFaces); - -void writeOFF(const char* fpath, const double* pVertices, - const uint32_t* pFaceVertexIndices, const uint32_t* pFaceSizes, - const uint32_t* pEdges, const uint32_t numVertices, - const uint32_t numFaces, const uint32_t numEdges); - -void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned int id, McDebugSeverity severity, - size_t length, const char* message, - const void* userParam) -{ - - // printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - // printf("userParam=%p\n", userParam); - - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; - break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - // printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - } - - std::string severity_str; - - switch (severity) { - case MC_DEBUG_SEVERITY_HIGH: - severity_str = "HIGH"; - break; - case MC_DEBUG_SEVERITY_MEDIUM: - severity_str = "MEDIUM"; - break; - case MC_DEBUG_SEVERITY_LOW: - severity_str = "LOW"; - break; - case MC_DEBUG_SEVERITY_NOTIFICATION: - severity_str = "NOTIFICATION"; - break; - case MC_DEBUG_SEVERITY_ALL: - break; - } - - printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), - debug_type.c_str(), severity_str.c_str(), length, message); -} - - -#if 1 -enum ObjFileCmdType { - /* - The v command specifies a vertex by its three cartesian coordinates x, y, and - z. The vertex is automatically assigned a name depending on the order in which - it is found in the file. The first vertex in the file gets the name ‘1’, the - second ‘2’, the third ‘3’, and so on. - */ - VERTEX, - /* - This is the vertex normal command. It specifies the normal vector to the - surface. x, y, and z are the components of the normal vector. Note that this - normal vector is not yet associated with any vertex point. We will have to - associate it with a vertex later with another command called the f command. - - The vertex normal command is typically omitted in files because when we group - vertices into polygonal faces with the f command, it will automatically - determine the normal vector from the vertex coordinates and the order in which - the vertices appear. - */ - NORMAL, - /* - The vertex texture command specifies a point in the texture map, which we - covered in an earlier section. u and v are the x and y coordinates in the - texture map. These will be floating point numbers between 0 and 1. They really - don’t tell you anything by themselves, they must be grouped with a vertex in - an f face command, just like the vertex normals. - */ - TEXCOORD, - /* - The face command is probably the most important command. It specifies a - polygonal face made from the vertices that came before this line. - - To reference a vertex you follow the implicit numbering system of the - vertices. For example’ f 23 24 25 27′ means a polygonal face built from - vertices 23, 24, 25, and 27 in order. - - For each vertex, you may associate a vn command, which then associates that - vertex normal to the corresponding vertex. Similarly, you can associate a vt - command with a vertex, which will determine the texture mapping to use at this - point. - - If you specify a vt or vn for a vertex in a file, you must specify it for all - of them. - */ - FACE, - TOTAL, - UNKNOWN = 0xFFFFFFFF -}; - -#include - -// Funcion to read in a .obj file storing a single 3D mesh object (in ASCII -// format) The double pointers will be allocated inside this function and must -// be freed by caller. Only handles polygonal faces, so "vp" command (which is -// used to specify control points of the surface or curve ) is ignored if -// encountered in file. -void readOBJ( - // path to file - const char* fpath, - // pointer to list of vertex coordinates - double** pVertices, - // pointer to list of vertex normals - double** pNormals, - // pointer to list of texture coordinates list - double** pTexCoords, - // pointer to list of face sizes (number of vertices in each face) - unsigned int** pFaceSizes, - // pointer to list of face-vertex indices - unsigned int** pFaceVertexIndices, - // pointer to list of face-vertex texture-coord indices - unsigned int** pFaceVertexTexCoordIndices, - // pointer to list of face texture coordvertex-normal indices - unsigned int** pFaceVertexNormalIndices, - // number of vertices - unsigned int* numVertices, - // number of vertex normals - unsigned int* numNormals, - // number of texture coordinates - unsigned int* numTexcoords, - // number of faces - unsigned int* numFaces) -{ - - fprintf(stdout, "read .obj file: %s\n", fpath); - - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open file `%s`", fpath); - exit(1); - } - - fpos_t startOfFile; - - if (fgetpos(file, &startOfFile) != 0) /* current position: start of file */ - { - perror("fgetpos()"); - fprintf(stderr, "error fgetpos() failed in file %s at line # %d\n", - __FILE__, __LINE__ - 3); - exit(EXIT_FAILURE); - } - - // buffer used to store the contents of a line read from the file. - char* lineBuf = NULL; - // current length of the line buffer (in characters read) - size_t lineBufLen = 0; - - // counts the number of passes we have made over the file to parse contents. - // this is needed because multiple passes are required e.g. to determine how - // much memory to allocate before actually copying data into pointers. - int passIterator = 0; - - int nFaceIndices = 0; // total number of face indices found in file - - do { // each iteration will parse the full file - - // these variables are defined after having parsed the full file - int nVertices = 0; // number of vertex coordinates found in file - int nNormals = 0; // number of vertex normals found in file - int nTexCoords = 0; // number of vertex vertex texture coordnates found in file - int nFaces = 0; // number of faces found in file - - int faceIndicesCounter = 0; // running offset into pFaceVertexIndices (final value - // will be same as nFaceIndices) - - // number of characters read on a lineBuf - ssize_t nread = 0; - - while ((nread = getline(&lineBuf, &lineBufLen, file)) != (((ssize_t)0) -1 )/*-1*/) { // each iteration will parse a line in the file - - // strip newline and carriage return - lineBuf[strcspn(lineBuf, "\r\n")] = '\0'; - - const size_t lineLen = strlen(lineBuf); - - assert(lineLen <= (size_t)nread); - - const bool lineIsEmpty = (lineLen == 0); - - if (lineIsEmpty) { - continue; // .. to next lineBuf - } - - const bool lineIsComment = lineBuf[0] == '#'; - - if (lineIsComment) { - continue; // ... to next lineBuf - } - - ObjFileCmdType lineCmdType = ObjFileCmdType::UNKNOWN; - - // - // In the following, we determine the type of "command" in the object - // file that is contained on the current lineBuf. - // - - if (lineBuf[0] == 'v' && lineBuf[1] == ' ') { - lineCmdType = ObjFileCmdType::VERTEX; - } else { - - if (lineBuf[0] == 'v' && lineBuf[1] == 'n' && lineBuf[2] == ' ') { - lineCmdType = ObjFileCmdType::NORMAL; - } else { - - if (lineBuf[0] == 'v' && lineBuf[1] == 't' && lineBuf[2] == ' ') { - lineCmdType = ObjFileCmdType::TEXCOORD; - } else { - - if (lineBuf[0] == 'f' && lineBuf[1] == ' ') { - lineCmdType = ObjFileCmdType::FACE; - } - } - } - } - - if (lineCmdType == ObjFileCmdType::UNKNOWN) { - //fprintf(stderr, "warning: unrecognised command in lineBuf '%s'\n", lineBuf); - continue; // ... to next lineBuf - } - - // - // Now that we know the type of command whose data is on the current lineBuf - // we will actually parse the lineBuf in full - // - switch (lineCmdType) { - case ObjFileCmdType::VERTEX: { - const int vertexId = nVertices++; // incremental vertex count in file - - if (passIterator == 1) { - - double x = 0.0; - double y = 0.0; - double z = 0.0; - - nread = sscanf(lineBuf + 2, "%lf %lf %lf", &x, &y, &z); - - (*pVertices)[vertexId * 3 + 0] = x; - (*pVertices)[vertexId * 3 + 1] = y; - (*pVertices)[vertexId * 3 + 2] = z; - - if (nread != 3) { - fprintf(stderr, "error: have %zu components for v%d\n", nread, - vertexId); - std::abort(); - } - } - - } break; - case ObjFileCmdType::NORMAL: { - const int normalId = nNormals++; // incremental vertex-normal count in file - - if (passIterator == 1) { - - double x = 0.0; - double y = 0.0; - double z = 0.0; - - nread = sscanf(lineBuf + 2, "%lf %lf %lf", &x, &y, &z); - - (*pNormals)[normalId * 3 + 0] = x; - (*pNormals)[normalId * 3 + 1] = y; - (*pNormals)[normalId * 3 + 2] = z; - - if (nread != 3) { - fprintf(stderr, "error: have %zu components for vn%d\n", nread, - normalId); - std::abort(); - } - } - } break; - case ObjFileCmdType::TEXCOORD: { - const int texCoordId = nTexCoords++; // incremental vertex-normal count in file - - if (passIterator == 1) { - - double x = 0.0; - double y = 0.0; - nread = sscanf(lineBuf + 2, "%lf %lf", &x, &y); - - (*pTexCoords)[texCoordId * 2 + 0] = x; - (*pTexCoords)[texCoordId * 2 + 1] = y; - - if (nread != 2) { - fprintf(stderr, "error: have %zu components for vt%d\n", nread, - texCoordId); - std::abort(); - } - } - } break; - case ObjFileCmdType::FACE: { - const int faceId = nFaces++; // incremental face count in file - - if (passIterator == 1) { - // - // count the number of vertices in face - // - char* pch = strtok(lineBuf + 2, " "); - uint32_t faceVertexCount = 0; - - while (pch != NULL) { - faceVertexCount++; // track number of vertices found in face - pch = strtok(NULL, " "); - } - - assert(pFaceSizes != NULL); - - (*pFaceSizes)[faceId] = faceVertexCount; - - nFaceIndices += faceVertexCount; - } else if (passIterator == 2) // third pass - { - - // - // allocate mem for the number of vertices in face - // - - assert(pFaceSizes != NULL); - - const uint32_t faceVertexCount = (*pFaceSizes)[faceId]; - //printf("lineBuf = %s\n", lineBuf); - int iter = 0; // incremented per vertex of face - - char* token; - char* tokenElem; - char buf[512]; - - // for each vertex in face - for (token = strtok(lineBuf, " "); token != NULL; - token = strtok(token + strlen(token) + 1, " ")) { - - strncpy(buf, token, sizeof(buf)); - - if (buf[0] == 'f') { - continue; - } - - iter++; - int faceVertexDataIt = 0; - - // printf("Line: %s\n", buf); - - // for each data element of a face-vertex - for (tokenElem = strtok(buf, "/"); tokenElem != NULL; - tokenElem = strtok(tokenElem + strlen(tokenElem) + 1, "/")) { - - // printf("\tToken: %s\n", tokenElem); - - const bool haveTexCoords = (nTexCoords > 0); - - if (faceVertexDataIt == 1 && !haveTexCoords) { - faceVertexDataIt = 2; - } - - int val; - sscanf(token, "%d", &val); // extract face vertex data index - - switch (faceVertexDataIt) { - case 0: // vertex id - (*pFaceVertexIndices)[faceIndicesCounter] = (uint32_t)(val - 1); - break; - case 1: // texcooord id - (*pFaceVertexTexCoordIndices)[faceIndicesCounter] = (uint32_t)(val - 1); - break; - case 2: // normal id - (*pFaceVertexNormalIndices)[faceIndicesCounter] = (uint32_t)(val - 1); - break; - default: - break; - } - - faceVertexDataIt++; - } - faceIndicesCounter += 1; - } - - if (iter != (int)faceVertexCount) { - fprintf(stderr, - "error: have %d vertices when there should be =%d\n", iter, - faceVertexCount); - std::abort(); - } - } - } break; - default: - break; - } // switch (lineCmdType) { - } - - if (passIterator == 0) // first pass - { - - printf("\t%d positions\n", nVertices); - - if (nVertices > 0) { - *pVertices = (double*)malloc(nVertices * sizeof(double) * 3); - } - - printf("\t%d normals\n", nNormals); - - if (nNormals > 0) { - *pNormals = (double*)malloc(nNormals * sizeof(double) * 3); - } - - printf("\t%d texture-coords\n", nTexCoords); - - if (nTexCoords > 0) { - *pTexCoords = (double*)malloc(nTexCoords * sizeof(double) * 2); - } - - printf("\t%d face(s)\n", nFaces); - - if (nFaces > 0) { - *pFaceSizes = (uint32_t*)malloc(nFaces * sizeof(uint32_t)); - } - - *numVertices = nVertices; - *numNormals = nNormals; - *numTexcoords = nTexCoords, - *numFaces = nFaces; - } - - if (passIterator == 1) // second pass - { - printf("\t%d face indices\n", nFaceIndices); - - if (nFaceIndices == 0) { - fprintf(stderr, "error: invalid face index count %d\n", nFaceIndices); - std::abort(); - } - - *pFaceVertexIndices = (uint32_t*)malloc(nFaceIndices * sizeof(uint32_t)); - - if (nTexCoords > 0) { - printf("\t%d tex-coord indices\n", nFaceIndices); - - *pFaceVertexTexCoordIndices = (uint32_t*)malloc(nFaceIndices * sizeof(uint32_t)); - } - - if (nNormals > 0) { - printf("\t%d normal indices\n", nFaceIndices); - - *pFaceVertexNormalIndices = (uint32_t*)malloc(nFaceIndices * sizeof(uint32_t)); - } - } - - if (fsetpos(file, &startOfFile) != 0) /* reset current position to start of file */ - { - if (ferror(file)) { - perror("fsetpos()"); - fprintf(stderr, "fsetpos() failed in file %s at lineBuf # %d\n", __FILE__, - __LINE__ - 5); - exit(EXIT_FAILURE); - } - } - } while (++passIterator < 3); - - // - // finish, and free up memory - // - if (lineBuf != NULL) { - free(lineBuf); - } - - fclose(file); - - printf("done.\n"); -} - -#endif - int main() { - double* srcMeshVertices = NULL; - uint32_t* srcMeshFaceIndices = NULL; - uint32_t* srcMeshFaceSizes = NULL; - uint32_t srcMeshNumFaces = 0; - uint32_t srcMeshNumVertices = 0; - - double* cutMeshVertices = NULL; - uint32_t* cutMeshFaceIndices = NULL; - uint32_t* cutMeshFaceSizes = NULL; - uint32_t cutMeshNumFaces = 0; - uint32_t cutMeshNumVertices = 0; - - McResult api_err = MC_NO_ERROR; - - const char* srcMeshFilePath = DATA_DIR "/source-mesh.off"; - const char* cutMeshFilePath = DATA_DIR "/cut-mesh.off"; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; - printf(">> source-mesh file: %s\n", srcMeshFilePath); - printf(">> cut-mesh file: %s\n", cutMeshFilePath); - - // load meshes - // ----------- - - readOFF(srcMeshFilePath, &srcMeshVertices, &srcMeshFaceIndices, - &srcMeshFaceSizes, &srcMeshNumVertices, &srcMeshNumFaces); - - printf(">> src-mesh vertices=%u faces=%u\n", srcMeshNumVertices, - srcMeshNumFaces); - - readOFF(cutMeshFilePath, &cutMeshVertices, &cutMeshFaceIndices, - &cutMeshFaceSizes, &cutMeshNumVertices, &cutMeshNumFaces); + // + // read-in the source-mesh from file + // + + mioReadOFF(DATA_DIR "/source-mesh.off", + &srcMesh.pVertices, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceSizes, + &srcMesh.numVertices, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF(DATA_DIR "/cut-mesh.off", + &cutMesh.pVertices, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceSizes, + &cutMesh.numVertices, + &cutMesh.numFaces); - printf(">> cut-mesh vertices=%u faces=%u\n", cutMeshNumVertices, - cutMeshNumFaces); + // + // create a context + // - // 2. create a context - // ------------------- McContext context = MC_NULL_HANDLE; - api_err = mcCreateContext(&context, MC_DEBUG); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (api_err=%d)\n", (int)api_err); - exit(1); - } - - // config debug output - // ----------------------- - McSize numBytes = 0; - McFlags contextFlags; - api_err = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - api_err = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + my_assert (status == MC_NO_ERROR); - if (contextFlags & MC_DEBUG) { - mcDebugMessageCallback(context, mcDebugOutput, nullptr); - mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, - McDebugType::MC_DEBUG_TYPE_ALL, - McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); - } - - // 3. do the magic! - // ---------------- - api_err = mcDispatch( + // + // do it + // + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, - srcMeshVertices, srcMeshFaceIndices, srcMeshFaceSizes, srcMeshNumVertices, - srcMeshNumFaces, cutMeshVertices, cutMeshFaceIndices, cutMeshFaceSizes, - cutMeshNumVertices, cutMeshNumFaces); + // source mesh + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + my_assert (status == MC_NO_ERROR); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (api_err=%d)\n", (int)api_err); - exit(1); - } + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); - // 4. query the number of available connected component (only fragments to - // keep things simple) - // ------------------------------------------------------------------------------------------ - uint32_t numConnComps; - std::vector connComps; - - api_err = mcGetConnectedComponents( - context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &numConnComps); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_FRAGMENT) " - "failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + // + // query the number of available connected components after the cut + // + McUint32 connectedComponentCount; + std::vector connectedComponents; - if (numConnComps == 0) { + status = mcGetConnectedComponents( + context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &connectedComponentCount); + + my_assert (status == MC_NO_ERROR); + + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - connComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); - api_err = mcGetConnectedComponents( - context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (uint32_t)connComps.size(), - connComps.data(), NULL); + status = mcGetConnectedComponents( + context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (McUint32)connectedComponents.size(), + connectedComponents.data(), NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_FRAGMENT) " - "failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + for (int i = 0; i < (int)connectedComponents.size(); ++i) { + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id - numBytes = 0; + McSize numBytes = 0; - // query the seam vertices (indices) - // --------------------------------- + // + // Query the seam vertices (indices) + // // The format of this array (of 32-bit unsigned int elements) is as follows: // [ - // , // McIndex/uint32_t - // , // McIndex/uint32_t - // <1st-sequence-is-loop-flag-(McBool)>, // McBool, McIndex/uint32_t + // , // McIndex/McUint32 + // , // McIndex/McUint32 + // <1st-sequence-is-loop-flag>, // McBool/McIndex/McUint32 // , // consecutive elements of McIndex // , - // <2nd-sequence-is-loop-flag-(McBool)>, + // <2nd-sequence-is-loop-flag>, // , // ... and so on, until last sequence // ] - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE, 0, + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE, 0, NULL, &numBytes); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_" - "VERTEX_SEQUENCE) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - std::vector seamVertexSequenceArrayFromMCUT; - seamVertexSequenceArrayFromMCUT.resize(numBytes / sizeof(uint32_t)); + std::vector seamVertexSequenceArrayFromMCUT; + seamVertexSequenceArrayFromMCUT.resize(numBytes / sizeof(McUint32)); - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE, + status = mcGetConnectedComponentData( + context, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE, numBytes, seamVertexSequenceArrayFromMCUT.data(), NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_" - "VERTEX_SEQUENCE) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); // We now put each sorted sequence of seam vertices into its own array. // This serves two purposes: @@ -716,35 +201,33 @@ int main() // list of seam vertex sequences, each with a flag stating whether it is a // loop or not std::vector, McBool>> seamVertexSequences; - uint32_t runningOffset = 0; // a runnning offset that we use to access data + McUint32 runningOffset = 0; // a runnning offset that we use to access data // in "seamVertexSequenceArrayFromMCUT" // number of sequences produced by MCUT - const uint32_t numSeamVertexSequences = seamVertexSequenceArrayFromMCUT[runningOffset++]; // always the first + const McUint32 numSeamVertexSequences = seamVertexSequenceArrayFromMCUT[runningOffset++]; // always the first // element // for each sequence... - for (uint32_t numSeamVertexSequenceIter = 0; + for (McUint32 numSeamVertexSequenceIter = 0; numSeamVertexSequenceIter < numSeamVertexSequences; ++numSeamVertexSequenceIter) { // create entry to store own array and flag - seamVertexSequences.push_back(std::pair, McBool>()); - std::pair, McBool>& currentSeamVertexSequenceData = seamVertexSequences.back(); - - std::vector& currentSeamVertexSequenceIndices = currentSeamVertexSequenceData - .first; // Ordered list of vertex indices in CC defining the seam - // sequence - McBool& isLoop = currentSeamVertexSequenceData - .second; // does it form a loop? (auxilliary piece of - // info that might be useful to users) - - // NOTE: order in which we do things here matter because of how we rely on - // "runningOffset++" So here, for each sequence we have 1) the number of - // vertex indices in that sequence 2) a flag telling us whether the - // sequence is a loop, and 3) the actually consecutive list of sorted - // vertex indices that for the sequence - const uint32_t currentSeamVertexSequenceIndicesArraySize = seamVertexSequenceArrayFromMCUT[runningOffset++]; - currentSeamVertexSequenceIndices.resize( - currentSeamVertexSequenceIndicesArraySize); + seamVertexSequences.push_back(std::pair, McBool>()); + std::pair, McBool>& currentSeamVertexSequenceData = seamVertexSequences.back(); + + // Ordered list of vertex indices in CC defining the seam sequence + std::vector& currentSeamVertexSequenceIndices = currentSeamVertexSequenceData.first; + // does it form a loop? (auxilliary piece of info that might be useful to users) + McBool& isLoop = currentSeamVertexSequenceData.second; + + // NOTE: The order in which we do things here matters because of how we rely on + // "runningOffset++". For each sequence we have + // 1) the number of vertex indices in that sequence + // 2) a flag telling us whether the sequence is a loop, and + // 3) the sorted list of vertex indices that for the sequence + const McUint32 currentSeamVertexSequenceIndicesArraySize = seamVertexSequenceArrayFromMCUT[runningOffset++]; + + currentSeamVertexSequenceIndices.resize(currentSeamVertexSequenceIndicesArraySize); isLoop = seamVertexSequenceArrayFromMCUT[runningOffset++]; @@ -757,392 +240,105 @@ int main() } // - // We are now going to save the sequences to file. To do so, we piggyback - // on the "writeOFF" function and pretend that we are writing a mesh where - // each sequence is a face. + // We are now going to save the sequences to file. // - // stub variables for writing to file - uint32_t numFacesStub = (McUint32)seamVertexSequences.size(); - std::vector faceSizesArrayStub(numFacesStub); - std::vector faceIndicesArrayStub; - - std::string flags_str; + char seamFnameBuf[512]; + sprintf(seamFnameBuf, OUTPUT_DIR "/OUT_conncomp%d-seam-vertices.txt", i); + printf("write: %s\n", seamFnameBuf); + std::ofstream f(seamFnameBuf); // for each sequence - for (uint32_t j = 0; j < (McUint32)seamVertexSequences.size(); ++j) { - faceSizesArrayStub[j] = (McUint32)seamVertexSequences[j].first.size(); - faceIndicesArrayStub.insert(faceIndicesArrayStub.cend(), - seamVertexSequences[j].first.cbegin(), - seamVertexSequences[j].first.cend()); - - flags_str.append( - "-id" + std::to_string(j) + ((seamVertexSequences[j].second == MC_TRUE) ? "_isLOOP" : "_isOPEN")); - } + for (McUint32 j = 0; j < (McUint32)seamVertexSequences.size(); ++j) { + + + f << "sequence = " << j << "\n"; + f << "size = " << (McUint32)seamVertexSequences[j].first.size() << "\n"; + f << "is_loop = " << ((seamVertexSequences[j].second == MC_TRUE) ? "TRUE" : "FALSE") << "\n"; + f << "vertices = "; + + for(McInt32 i = 0; i < (McInt32)seamVertexSequences[j].first.size(); ++i) + { + f << seamVertexSequences[j].first[i] << " "; + } - char seamFnameBuf[1024]; - sprintf(seamFnameBuf, "frag-%d-seam-vertices%s.txt", i, flags_str.c_str()); + f << "\n\n"; + } - // save seam vertices to file (.txt) - // ------------------------ - writeOFF(seamFnameBuf, NULL, - // We pretend that the list of seam indices is a list of face - // indices, when in actual fact we are simply using the output file - // as storage for later inspection - faceIndicesArrayStub.data(), faceSizesArrayStub.data(), NULL, 0, - (uint32_t)faceSizesArrayStub.size(), 0); + // + // vertices + // - // query the vertices (coordinates) - // -------------------------------- numBytes = 0; - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, - &numBytes); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_" - "VERTEX_DOUBLE) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(double) * 3)); + my_assert (status == MC_NO_ERROR); - std::vector vertices(numberOfVertices * 3u); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, - (void*)vertices.data(), NULL); + std::vector ccVertices(ccVertexCount * 3u); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_" - "VERTEX_DOUBLE) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); + + my_assert (status == MC_NO_ERROR); + + // + // (triangulated) faces + // - // query (triangulated) faces - // ----------------------------- numBytes = 0; - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, - NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_" - "TRIANGULATION) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t numberOfTriangles = (uint32_t)(numBytes / (sizeof(McIndex) * 3)); + McUint32 numberOfTriangles = (McUint32)(numBytes / (sizeof(McIndex) * 3)); std::vector triangleIndices(numberOfTriangles * 3u); - api_err = mcGetConnectedComponentData( - context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, - numBytes, (void*)triangleIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, (void*)triangleIndices.data(), NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, - "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_" - "TRIANGULATION) failed (api_err=%d)\n", - (int)api_err); - exit(1); - } - - // save mesh to file (.off) - // ------------------------ - char fnameBuf[32]; - sprintf(fnameBuf, "frag-%d.off", i); + my_assert (status == MC_NO_ERROR); - writeOFF(fnameBuf, vertices.data(), triangleIndices.data(), - NULL, // if null then function treat faceIndices array as made up - // of triangles + // + // save connected component (mesh) to a .off file + // + // NOTE: we save the output file in .off format (rather than .obj) + // because .off uses relative/zero-based indexing of vertices, which + // makes it easier to inspect the dumped seam-vertex text file. + // + + char fnameBuf[64]; + sprintf(fnameBuf, "OUT_conncomp%d.off", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + + mioWriteOFF(fnameBuf, + ccVertices.data(), + triangleIndices.data(), + NULL, // if null then function treats "pFaceVertexIndices" array as made up of triangles NULL, // we don't care about writing edges - numberOfVertices, numberOfTriangles, + ccVertexCount, + numberOfTriangles, 0 // zero edges since we don't care about writing edges ); } - // 6. free connected component data - // -------------------------------- - api_err = mcReleaseConnectedComponents(context, 0, NULL); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (api_err=%d)\n", - (int)api_err); - exit(1); - } - - // 7. destroy context - // ------------------ - api_err = mcReleaseContext(context); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (api_err=%d)\n", (int)api_err); - exit(1); - } - - return 0; -} - -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -//typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } - - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** line, size_t* len) -{ - while (getline(line, len, file)) { - if (strlen(*line) > 1 && (*line)[0] != '#') { - return true; - } - } - return false; -} - -void readOFF(const char* fpath, double** pVertices, unsigned int** pFaceVertexIndices, - unsigned int** pFaceSizes, unsigned int* numVertices, - unsigned int* numFaces) -{ - printf("read OFF file %s: \n", fpath); - - // using "rb" instead of "r" to prevent linefeed conversion - // See: - // https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* line = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &line, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(line, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &line, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(line, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (double*)malloc(sizeof(double) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (double)(*numVertices); ++i) { - lineOk = readLine(file, &line, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - double x, y, z; - sscanf(line, "%lf %lf %lf", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &line, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(line, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceVertexIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int api_err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int api_err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (api_err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &line, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(line, "%d", &n); - - char* lineBufShifted = line; - int j = 0; - - while (j < n) { // parse remaining numbers on line - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // - int val; - sscanf(lineBufShifted, "%d", &val); + status = mcReleaseConnectedComponents(context, 0, NULL); - (*pFaceVertexIndices)[indexOffset + j] = val; - j++; - } + my_assert (status == MC_NO_ERROR); - indexOffset += n; - } + // + // free memory of context + // + + status = mcReleaseContext(context); - free(line); + my_assert (status == MC_NO_ERROR); - fclose(file); + return 0; } -// To ignore edges when writing the output just pass pEdges = NULL and numEdges -// = 0 -void writeOFF(const char* fpath, const double* pVertices, - const uint32_t* pFaceVertexIndices, const uint32_t* pFaceSizes, - const uint32_t* pEdges, const uint32_t numVertices, - const uint32_t numFaces, const uint32_t numEdges) -{ - fprintf(stdout, "write OFF file: %s\n", fpath); - - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, numEdges); - int i; - for (i = 0; i < (int)numVertices; ++i) { - const double* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } - - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - const uint32_t faceVertexCount = (pFaceSizes != NULL) ? pFaceSizes[i] : 3; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - const uint32_t* fptr = pFaceVertexIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - for (i = 0; i < (int)numEdges; ++i) { - const uint32_t* eptr = pEdges + (i * 2); - fprintf(file, "%u %u\n", eptr[0], eptr[1]); - } - - fclose(file); -} diff --git a/tutorials/QuerySeamVerticesUnsorted/CMakeLists.txt b/tutorials/QuerySeamVerticesUnsorted/CMakeLists.txt deleted file mode 100644 index 3dd15dc..0000000 --- a/tutorials/QuerySeamVerticesUnsorted/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(QuerySeamVerticesUnsorted QuerySeamVerticesUnsorted.cpp) -target_link_libraries(QuerySeamVerticesUnsorted mcut ${extra_libs}) -target_include_directories(QuerySeamVerticesUnsorted PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(QuerySeamVerticesUnsorted PRIVATE ${compilation_flags}) -target_compile_definitions(QuerySeamVerticesUnsorted PRIVATE ${preprocessor_defs} -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") \ No newline at end of file diff --git a/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp b/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp index 4779242..32b3041 100644 --- a/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp +++ b/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp @@ -1,32 +1,49 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * QuerySeamVerticesUnsorted.cpp + * + * \brief: + * This tutorial shows how to query 'seam vertices' of an output connected component. + * A seam vertex is one which lies along the intersection contour/path as a result + * of a cut. The example code provide only shows how to query the seam vertices in + * UNSORTED order i.e. MCUT just give you back an array containing all the vertices + * in a connected component that lie on the intersection contour. + * + * For an example of how to request a sorted array of seam vertices (which also + * identifies individual contours/paths) refer to the tutorial file called: + * "QuerySeamVerticesSorted". + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include #include +#include #define my_assert(cond) \ if (!(cond)) { \ @@ -34,572 +51,217 @@ std::exit(1); \ } -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces); - -void writeOFF( - const char* fpath, - const double* pVertices, - const uint32_t* pFaceIndices, - const uint32_t* pFaceSizes, - const uint32_t* pEdges, - const uint32_t numVertices, - const uint32_t numFaces, - const uint32_t numEdges); - -void MCAPI_PTR mcDebugOutput(McDebugSource source, - McDebugType type, - unsigned int id, - McDebugSeverity severity, - size_t length, - const char* message, - const void* userParam) +McInt32 main() { + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; + + // + // read-in the source-mesh from file + // + + mioReadOFF(DATA_DIR "/source-mesh.off", + &srcMesh.pVertices, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceSizes, + &srcMesh.numVertices, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF(DATA_DIR "/cut-mesh.off", + &cutMesh.pVertices, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceSizes, + &cutMesh.numVertices, + &cutMesh.numFaces); + + // + // create a context + // - // printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - // printf("userParam=%p\n", userParam); - - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; - break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - // printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - } - - std::string severity_str; - - switch (severity) { - case MC_DEBUG_SEVERITY_HIGH: - severity_str = "HIGH"; - break; - case MC_DEBUG_SEVERITY_MEDIUM: - severity_str = "MEDIUM"; - break; - case MC_DEBUG_SEVERITY_LOW: - severity_str = "LOW"; - break; - case MC_DEBUG_SEVERITY_NOTIFICATION: - severity_str = "NOTIFICATION"; - break; - case MC_DEBUG_SEVERITY_ALL: - break; - } - - printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(), severity_str.c_str(), length, message); -} - -int main() -{ - double* srcMeshVertices = NULL; - uint32_t* srcMeshFaceIndices = NULL; - uint32_t* srcMeshFaceSizes = NULL; - uint32_t srcMeshNumFaces = 0; - uint32_t srcMeshNumVertices = 0; - - double* cutMeshVertices = NULL; - uint32_t* cutMeshFaceIndices = NULL; - uint32_t* cutMeshFaceSizes = NULL; - uint32_t cutMeshNumFaces = 0; - uint32_t cutMeshNumVertices = 0; - - McResult api_err = MC_NO_ERROR; - - const char* srcMeshFilePath = DATA_DIR "/source-mesh.off"; - const char* cutMeshFilePath = DATA_DIR "/cut-mesh.off"; - - printf(">> source-mesh file: %s\n", srcMeshFilePath); - printf(">> cut-mesh file: %s\n", cutMeshFilePath); - - // load meshes - // ----------- - - readOFF(srcMeshFilePath, &srcMeshVertices, &srcMeshFaceIndices, &srcMeshFaceSizes, &srcMeshNumVertices, &srcMeshNumFaces); - - printf(">> src-mesh vertices=%u faces=%u\n", srcMeshNumVertices, srcMeshNumFaces); - - readOFF(cutMeshFilePath, &cutMeshVertices, &cutMeshFaceIndices, &cutMeshFaceSizes, &cutMeshNumVertices, &cutMeshNumFaces); - - printf(">> cut-mesh vertices=%u faces=%u\n", cutMeshNumVertices, cutMeshNumFaces); - - // 2. create a context - // ------------------- McContext context = MC_NULL_HANDLE; - api_err = mcCreateContext(&context, MC_DEBUG); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (api_err=%d)\n", (int)api_err); - exit(1); - } - - // config debug output - // ----------------------- - McSize numBytes = 0; - McFlags contextFlags; - api_err = mcGetInfo(context, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes); + McResult status = mcCreateContext(&context, MC_DEBUG); - api_err = mcGetInfo(context, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr); + my_assert (status == MC_NO_ERROR); - if (contextFlags & MC_DEBUG) { - mcDebugMessageCallback(context, mcDebugOutput, nullptr); - mcDebugMessageControl(context, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); - } + // + // do the cutting + // - // 3. do the magic! - // ---------------- - api_err = mcDispatch( + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, - srcMeshVertices, - srcMeshFaceIndices, - srcMeshFaceSizes, - srcMeshNumVertices, - srcMeshNumFaces, - cutMeshVertices, - cutMeshFaceIndices, - cutMeshFaceSizes, - cutMeshNumVertices, - cutMeshNumFaces); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (api_err=%d)\n", (int)api_err); - exit(1); + // source mesh + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); + + my_assert(status == MC_NO_ERROR); + + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + + // + // query the number of available connected components after the cut + // + McUint32 connectedComponentCount; + std::vector connectedComponents; + + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &connectedComponentCount); + + my_assert (status == MC_NO_ERROR); + + if (connectedComponentCount == 0) { + fprintf(stdout, "no connected components found\n"); + exit(0); } - // 4. query the number of available connected component (only fragments to keep things simple) - // ------------------------------------------------------------------------------------------ - uint32_t numConnComps; - std::vector connComps; + connectedComponents.resize(connectedComponentCount); - api_err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, 0, NULL, &numConnComps); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_FRAGMENT) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - if (numConnComps == 0) { - fprintf(stdout, "no connected components found\n"); - exit(0); - } + // + // query the data of each connected component + // - connComps.resize(numConnComps); + for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id - api_err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_FRAGMENT, (uint32_t)connComps.size(), connComps.data(), NULL); + McSize numBytes = 0; - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_FRAGMENT) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + // + // query the seam ccVertices (indices) + // + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, 0, NULL, &numBytes); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + my_assert (status == MC_NO_ERROR); - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + std::vector seamVertexIndices; + seamVertexIndices.resize(numBytes / sizeof(McUint32)); - numBytes = 0; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, numBytes, seamVertexIndices.data(), NULL); - // query the seam vertices (indices) - // --------------------------------- + my_assert (status == MC_NO_ERROR); - - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, 0, NULL, &numBytes); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX) failed (api_err=%d)\n", (int)api_err); - exit(1); + { // save the seam vertex indices + char seamFnameBuf[512]; + sprintf(seamFnameBuf, OUTPUT_DIR "/OUT_conncomp%d-seam-vertices.txt", i); + printf("write: %s\n", seamFnameBuf); + std::ofstream f(seamFnameBuf); + f << "total = " << seamVertexIndices.size() << "\n"; + f << "indices = "; + + for(McInt32 i = 0; i < (McInt32)seamVertexIndices.size(); ++i) + { + f << seamVertexIndices[i] << " "; + } + f << "\n"; } - std::vector seamVertexIndices; - seamVertexIndices.resize(numBytes / sizeof(uint32_t)); + // + // vertices + // - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, numBytes, seamVertexIndices.data(), NULL); + numBytes = 0; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t faceSizesStub = (McUint32)seamVertexIndices.size(); - - char seamFnameBuf[40]; - sprintf(seamFnameBuf, "frag-%d-seam-vertices.txt", i); - - // save seam vertices to file (.txt) - // ------------------------ - writeOFF(seamFnameBuf, - NULL, - // We pretend that the list of seam vertices is a face, when in actual - // fact we are simply using the output file as storage for later inspection - seamVertexIndices.data(), - &faceSizesStub, - NULL, - 0, - 1, // one face - 0); - - // query the vertices (coordinates) - // -------------------------------- -numBytes = 0; - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(double) * 3)); + std::vector ccVertices(ccVertexCount * 3u); - std::vector vertices(numberOfVertices * 3u); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)vertices.data(), NULL); + my_assert (status == MC_NO_ERROR); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + // + // (triangulated) faces + // - // query (triangulated) faces - // ----------------------------- numBytes = 0; - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t numberOfTriangles = (uint32_t)(numBytes / (sizeof(McIndex) * 3)); + McUint32 numberOfTriangles = (McUint32)(numBytes / (sizeof(McIndex) * 3)); std::vector triangleIndices(numberOfTriangles * 3u); - api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, (void*)triangleIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, (void*)triangleIndices.data(), NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // save mesh to file (.off) - // ------------------------ - char fnameBuf[32]; - sprintf(fnameBuf, "frag-%d.off", i); + // + // save connected component (mesh) to a .off file + // + // NOTE: we save the output file in .off format (rather than .obj) + // because .off uses relative/zero-based indexing of vertices, which + // makes it easier to inspect the dumped seam-vertex text file. + // + + char fnameBuf[64]; + sprintf(fnameBuf, "OUT_conncomp%d.off", i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); - writeOFF(fnameBuf, - vertices.data(), + + mioWriteOFF(fnameBuf, + ccVertices.data(), triangleIndices.data(), - NULL, // if null then function treat faceIndices array as made up of triangles + NULL, // if null then function treats "pFaceVertexIndices" array as made up of triangles NULL, // we don't care about writing edges - numberOfVertices, + ccVertexCount, numberOfTriangles, 0 // zero edges since we don't care about writing edges ); } - // 6. free connected component data - // -------------------------------- - api_err = mcReleaseConnectedComponents(context, 0, NULL); - - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (api_err=%d)\n", (int)api_err); - exit(1); - } + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // - // 7. destroy context - // ------------------ - api_err = mcReleaseContext(context); + status = mcReleaseConnectedComponents(context, 0, NULL); - if (api_err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (api_err=%d)\n", (int)api_err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - return 0; -} + // + // free memory of context + // + + status = mcReleaseContext(context); -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } + my_assert (status == MC_NO_ERROR); - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** lineBuf, size_t* len) -{ - while (getline(lineBuf, len, file)) { - if (strlen(*lineBuf) > 1 && (*lineBuf)[0] != '#') { - return true; - } - } - return false; -} - -void readOFF( - const char* fpath, - double** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces) -{ - // using "rb" instead of "r" to prevent linefeed conversion - // See: https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* lineBuf = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(lineBuf, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(lineBuf, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (double*)malloc(sizeof(double) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (double)(*numVertices); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - double x, y, z; - sscanf(lineBuf, "%lf %lf %lf", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int api_err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int api_err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (api_err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - char* lineBufShifted = lineBuf; - int j = 0; - - while (j < n) { // parse remaining numbers on lineBuf - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number - - int val; - sscanf(lineBufShifted, "%d", &val); - - (*pFaceIndices)[indexOffset + j] = val; - j++; - } - - indexOffset += n; - } - - free(lineBuf); - - fclose(file); + return 0; } - -// To ignore edges when writing the output just pass pEdges = NULL and numEdges = 0 -void writeOFF( - const char* fpath, - const double* pVertices, - const uint32_t* pFaceIndices, - const uint32_t* pFaceSizes, - const uint32_t* pEdges, - const uint32_t numVertices, - const uint32_t numFaces, - const uint32_t numEdges) -{ - fprintf(stdout, "write: %s\n", fpath); - - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, numEdges); - int i; - for (i = 0; i < (int)numVertices; ++i) { - const double* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } - - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - const uint32_t faceVertexCount = (pFaceSizes != NULL) ? pFaceSizes[i] : 3; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - const uint32_t* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - for (i = 0; i < (int)numEdges; ++i) { - const uint32_t* eptr = pEdges + (i * 2); - fprintf(file, "%u %u\n", eptr[0], eptr[1]); - } - - fclose(file); -} \ No newline at end of file diff --git a/tutorials/ReversedConnectedComponentFaces/CMakeLists.txt b/tutorials/ReversedConnectedComponentFaces/CMakeLists.txt deleted file mode 100644 index bad823c..0000000 --- a/tutorials/ReversedConnectedComponentFaces/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -#get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) -#project(${PROJECT_NAME}) - -add_executable(ReversedConnectedComponentFaces ReversedConnectedComponentFaces.cpp) -target_link_libraries(ReversedConnectedComponentFaces mcut ${extra_libs}) -target_include_directories(ReversedConnectedComponentFaces PRIVATE ${MCUT_INCLUDE_DIR}) -target_compile_options(ReversedConnectedComponentFaces PRIVATE ${compilation_flags}) -target_compile_definitions(ReversedConnectedComponentFaces PRIVATE ${preprocessor_defs}) \ No newline at end of file diff --git a/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp b/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp index 8beddb4..d578751 100644 --- a/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp +++ b/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp @@ -1,47 +1,57 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * License details: + * https://www.gnu.org/licenses/gpl-3.0.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of the License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Author(s) : Floyd M. Chitalu - */ + * ReversedConnectedComponentFaces.cpp + * + * \brief: + * This tutorial shows how to query faces of output connected components + * where the WINDING ORDER IS REVERSED. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include +#include -void writeOFF( - const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces); +#define my_assert(cond) \ + if(!(cond)) \ + { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::abort(); \ + } -int main() +McInt32 main() { - // 1. Create meshes. - // ----------------- + // + // Create meshes to intersect + // - // Shape to Cut: - double cubeVertices[] = { + // the source-mesh (a cube) + McDouble cubeVertices[] = { -1, -1, 1, // 0 1, -1, 1, // 1 -1, 1, 1, // 2 @@ -51,7 +61,7 @@ int main() -1, 1, -1, // 6 1, 1, -1 // 7 }; - uint32_t cubeFaces[] = { + McUint32 cubeFaces[] = { 0, 3, 2, // 0 0, 1, 3, // 1 1, 7, 3, // 2 @@ -66,43 +76,42 @@ int main() 4, 5, 1, // 11 }; - int numCubeVertices = 8; - int numCubeFaces = 12; + McInt32 numCubeVertices = 8; + McInt32 numCubeFaces = 12; - uint32_t cubeFaceSizes[] = { + McUint32 cubeFaceSizes[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; - // Cutting Shape: + // the cut mesh (a quad formed of two triangles) - double cutMeshVertices[] = { + McDouble cutMeshVertices[] = { -1.2, 1.6, 0.994070, 1.4, -1.3, 0.994070, -1.2, 1.6, -1.005929, 1.4, -1.3, -1.005929 }; - uint32_t cutMeshFaces[] = { + McUint32 cutMeshFaces[] = { 1, 2, 0, 1, 3, 2 }; - uint32_t numCutMeshVertices = 4; - uint32_t numCutMeshFaces = 2; + McUint32 numCutMeshVertices = 4; + McUint32 numCutMeshFaces = 2; - // 2. create a context - // ------------------- + // + // create a context + // McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_NULL_HANDLE); + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); - if (err != MC_NO_ERROR) { - fprintf(stderr, "could not create context (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // 3. do the magic! - // ---------------- - err = mcDispatch( + // + // do the cutting + // + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE, cubeVertices, @@ -112,84 +121,70 @@ int main() numCubeFaces, cutMeshVertices, cutMeshFaces, - nullptr, // cutMeshFaceSizes, // no need to give 'faceSizes' parameter since cut-mesh is a triangle mesh + nullptr, // cutMeshFaceSizes, // no need to give 'ccFaceSizes' parameter since cut-mesh is a triangle mesh numCutMeshVertices, numCutMeshFaces); - if (err != MC_NO_ERROR) { - fprintf(stderr, "dispatch call failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // 4. query the number of available connected component (all types) - // ------------------------------------------------------------- - uint32_t numConnComps; - std::vector connComps; + // + // query the number of available connected components after the cut + // + McUint32 connectedComponentCount; + std::vector connectedComponents; - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - if (numConnComps == 0) { + if (connectedComponentCount == 0) { fprintf(stdout, "no connected components found\n"); exit(0); } - connComps.resize(numConnComps); + connectedComponents.resize(connectedComponentCount); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponents(MC_CONNECTED_COMPONENT_TYPE_ALL) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - // 5. query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)connComps.size(); ++i) { - McConnectedComponent connComp = connComps[i]; // connected compoenent id + for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { + McConnectedComponent cc = connectedComponents[i]; // connected compoenent id - // query the vertices - // ---------------------- + // + // vertices + // McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); - uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(float) * 3)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McDouble) * 3)); - std::vector vertices(numberOfVertices * 3u); + std::vector ccVertices(ccVertexCount * 3u); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, numBytes, (void*)vertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (McVoid*)ccVertices.data(), NULL); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); // get connected component type to determine whether we should flip faces // ---------------------------------------------------------------------- - bool flip_faces = true; + McBool flip_faces = MC_TRUE; { - McConnectedComponentType type; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), (void*)&type, NULL); + McConnectedComponentType type = (McConnectedComponentType)0; - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_TYPE) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), (McVoid*)&type, NULL); - // in this example we flip the faces of all fragments + my_assert (status == MC_NO_ERROR); + + // in this tutorial we flip the faces of all fragments flip_faces = (type == McConnectedComponentType::MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); @@ -200,125 +195,81 @@ int main() windingOrder = McConnectedComponentFaceWindingOrder::MC_CONNECTED_COMPONENT_FACE_WINDING_ORDER_REVERSED; } - err = mcBindState(context, MC_CONTEXT_CONNECTED_COMPONENT_FACE_WINDING_ORDER, sizeof(McConnectedComponentFaceWindingOrder), &windingOrder); + status = mcBindState(context, MC_CONTEXT_CONNECTED_COMPONENT_FACE_WINDING_ORDER, sizeof(McConnectedComponentFaceWindingOrder), &windingOrder); - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcBindState(MC_CONTEXT_CONNECTED_COMPONENT_FACE_WINDING_ORDER) failed (err=%d)\n", (int)err); - exit(1); - } + my_assert (status == MC_NO_ERROR); } - // query the faces - // ------------------- + + // + // faces + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &numBytes); - std::vector faceIndices; - faceIndices.resize(numBytes / sizeof(uint32_t)); + my_assert (status == MC_NO_ERROR); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, faceIndices.data(), NULL); + std::vector ccFaceIndices; + ccFaceIndices.resize(numBytes / sizeof(McUint32)); - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE) failed (err=%d)\n", (int)err); - exit(1); - } + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE, numBytes, ccFaceIndices.data(), NULL); + my_assert (status == MC_NO_ERROR); + + // // query the face sizes - // ------------------------ - numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); - if (err != MC_NO_ERROR) { - fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); - } - - std::vector faceSizes; - faceSizes.resize(numBytes / sizeof(uint32_t)); + // - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, faceSizes.data(), NULL); - - if (err != MC_NO_ERROR) { - fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_SIZE) failed (err=%d)\n", (int)err); - exit(1); - } - - char fnameBuf[128]; - sprintf(fnameBuf, "cc%d%s.off", i, (flip_faces ? "-reversed" : "-normal")); - - // save to mesh file (.off) - // ------------------------ - writeOFF(fnameBuf, - (float*)vertices.data(), - (uint32_t*)faceIndices.data(), - (uint32_t*)faceSizes.data(), - (uint32_t)vertices.size() / 3, - (uint32_t)faceSizes.size()); - } - - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); - - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseConnectedComponents failed (err=%d)\n", (int)err); - exit(1); - } - - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); - - if (err != MC_NO_ERROR) { - fprintf(stderr, "mcReleaseContext failed (err=%d)\n", (int)err); - exit(1); + numBytes = 0; + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes); + + my_assert (status == MC_NO_ERROR); + + std::vector ccFaceSizes; + ccFaceSizes.resize(numBytes / sizeof(McUint32)); + + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, numBytes, ccFaceSizes.data(), NULL); + + my_assert (status == MC_NO_ERROR); + + // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, "OUT_conncomp%d-%s.obj", i, (flip_faces ? "reversed" : "as-given")); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + mioWriteOBJ( + fpath.c_str(), + ccVertices.data(), + nullptr, // pNormals + nullptr, // pTexCoords + ccFaceSizes.data(), + ccFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + ccVertexCount, + 0, //numNormals + 0, // numTexCoords + (McUint32)ccFaceSizes.size()); } - return 0; -} - -// write mesh to .off file -void writeOFF( - const char* fpath, - float* pVertices, - uint32_t* pFaceIndices, - uint32_t* pFaceSizes, - uint32_t numVertices, - uint32_t numFaces) -{ - fprintf(stdout, "write: %s\n", fpath); + // + // free memory of _all_ connected components (could also free them individually inside above for-loop) + // - FILE* file = fopen(fpath, "w"); + status = mcReleaseConnectedComponents(context, 0, NULL); - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } + my_assert (status == MC_NO_ERROR); - fprintf(file, "OFF\n"); - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - float* vptr = pVertices + (i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } + // + // free memory of context + // + + status = mcReleaseContext(context); - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - uint32_t faceVertexCount = pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - int j; - for (j = 0; j < (int)faceVertexCount; ++j) { - uint32_t* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } + my_assert (status == MC_NO_ERROR); - fclose(file); + return 0; } diff --git a/tutorials/TriangulatedFaceMaps/CMakeLists.txt b/tutorials/TriangulatedFaceMaps/CMakeLists.txt deleted file mode 100644 index 97fff5e..0000000 --- a/tutorials/TriangulatedFaceMaps/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -add_executable(TriangulatedFaceMaps TriangulatedFaceMaps.cpp) -target_link_libraries(TriangulatedFaceMaps mcut ${extra_libs}) -target_include_directories(TriangulatedFaceMaps PRIVATE ${MCUT_INCLUDE_DIR} ${libigl_include_dir} ${eigen_include_dir})# -target_compile_definitions(TriangulatedFaceMaps PRIVATE -DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data" -DOUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}" ${preprocessor_defs}) -target_compile_options(TriangulatedFaceMaps PRIVATE ${compilation_flags}) \ No newline at end of file diff --git a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp index 9e06d24..8d69bc1 100644 --- a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp +++ b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp @@ -1,170 +1,262 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -/* -This tutorial shows how to propagate per-triangulated0face normals (flat shading) from input meshes and onto the output -triangulated connected components after cutting. -*/ +/*************************************************************************** + * + * Copyright (C) 2023 CutDigital Enterprise Ltd + * Licensed under the GNU GPL License, Version 3.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/gpl-3.0.html. + * + * For your convenience, a copy of the License has been included in this + * repository. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * FaceNormals.cpp + * + * \brief: + * This tutorial shows how to propagate per-triangulated-face normals (flat + * shading) from input meshes and onto the output connected component(s) after + * cutting. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include #include -// libigl dependencies -#include -#include -#include -#include -#include - -#define my_assert(cond) if(!(cond)){fprintf(stderr, "MCUT error: %s\n", #cond );std::exit(1);} - -struct InputMesh { - // variables for reading .obj file data with libigl - std::vector> V, TC, N; - std::vector> F, FTC, FN; - std::vector> FM; - - // variables for mesh data in a format suited for MCUT - std::string fpath; // path to mesh file - std::vector faceSizesArray; // vertices per face - std::vector faceIndicesArray; // face indices - std::vector vertexCoordsArray; // vertex coords -}; - -// basic comparison of doubles -bool compare(double x, double y) -{ - return std::fabs(x - y) < 1e-6; -} +#include -int main() -{ - // load meshes. - // ----------------- - InputMesh srcMesh; +#define my_assert(cond) \ + if(!(cond)) \ + { \ + fprintf(stderr, "MCUT error: %s\n", #cond); \ + std::abort(); \ + } - // read file - srcMesh.fpath = DATA_DIR "/cube.obj"; - bool srcMeshLoaded = igl::readOBJ(srcMesh.fpath, srcMesh.V, srcMesh.TC, srcMesh.N, srcMesh.F, srcMesh.FTC, srcMesh.FN); - if (!srcMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", srcMesh.fpath.c_str()); - std::exit(1); - } - - // copy vertices - for (int i = 0; i < (int)srcMesh.V.size(); ++i) { - const std::vector& v = srcMesh.V[i]; - my_assert(v.size() == 3); - srcMesh.vertexCoordsArray.push_back(v[0]); - srcMesh.vertexCoordsArray.push_back(v[1]); - srcMesh.vertexCoordsArray.push_back(v[2]); +// simple structure representing a 3d vector and the operations we will perform with it +struct vec3 +{ + union + { + struct + { + McDouble x, y, z; + }; + struct + { + McDouble u, v, w; + }; + }; + + vec3 operator*(const McDouble c) const { + vec3 result = {}; + result.x = x * c; + result.y = y * c; + result.z = z * c; + return result; } - // copy faces - for (int i = 0; i < (int)srcMesh.F.size(); ++i) { - const std::vector& f = srcMesh.F[i]; - my_assert(f.size() == 3); // we assume triangle meshes for simplicity - for (int j = 0; j < (int)f.size(); ++j) { - srcMesh.faceIndicesArray.push_back(f[j]); - } - - srcMesh.faceSizesArray.push_back((uint32_t)f.size()); + vec3 operator+(const vec3& rhs) const { + vec3 result = {}; + result.x = x + rhs.x; + result.y = y + rhs.y; + result.z = z + rhs.z; + return result; } - printf("source mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)srcMesh.V.size(), (int)srcMesh.F.size()); + vec3 operator-(const vec3& rhs) const + { + vec3 result = {}; + result.x = x - rhs.x; + result.y = y - rhs.y; + result.z = z - rhs.z; + return result; + } +}; - InputMesh cutMesh; +inline McDouble +getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x3, McDouble y3) +{ + return (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2); +} - // read file - cutMesh.fpath = DATA_DIR "/plane.obj"; - bool cutMeshLoaded = igl::readOBJ(cutMesh.fpath, cutMesh.V, cutMesh.TC, cutMesh.N, cutMesh.F, cutMesh.FTC, cutMesh.FN); +vec3 crossProduct(const vec3& u, const vec3& v) +{ + vec3 out = {}; + out.x = u.y * v.z - u.z * v.y; + out.y = u.z * v.x - u.x * v.z; + out.z = u.x * v.y - u.y * v.x; + return out; +} - if (!cutMeshLoaded) { - std::fprintf(stderr, "error: could not load source mesh --> %s\n", cutMesh.fpath.c_str()); - std::exit(1); - } +// Compute barycentric coordinates (u, v, w) for point p with respect to triangle (a, b, c) +vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec3& c) +{ + // Unnormalized triangle normal + const vec3 m = crossProduct(b - a, c - a); + // Nominators and one-over-denominator for u and v ratios + McDouble nu = 0.0, nv = 0.0, ood = 0.0; + // Absolute components for determining projection plane + const McDouble x = std::abs(m.x), y = std::abs(m.y), z = std::abs(m.z); + + // Compute areas in plane of largest projection + if(x >= y && x >= z) + { + // x is largest, project to the yz plane + nu = getTriangleArea2D(p.y, p.z, b.y, b.z, c.y, c.z); + // Area of PBC in yz plane + nv = getTriangleArea2D(p.y, p.z, c.y, c.z, a.y, a.z); + // Area of PCA in yz plane + ood = 1.0f / m.x; // 1/(2*area of ABC in yz plane + } + else if(y >= x && y >= z) + { + // y is largest, project to the xz plane + nu = getTriangleArea2D(p.x, p.z, b.x, b.z, c.x, c.z); + nv = getTriangleArea2D(p.x, p.z, c.x, c.z, a.x, a.z); + ood = 1.0f / -m.y; + } + else + { + // z is largest, project to the xy plane + nu = getTriangleArea2D(p.x, p.y, b.x, b.y, c.x, c.y); + nv = getTriangleArea2D(p.x, p.y, c.x, c.y, a.x, a.y); + ood = 1.0f / m.z; + } + + vec3 result = {}; + result.u = nu * ood; + result.v = nv * ood; + result.w = 1.0f - result.u - result.v; + return result; +} - // copy vertices - for (int i = 0; i < (int)cutMesh.V.size(); ++i) { - const std::vector& v = cutMesh.V[i]; - my_assert(v.size() == 3); - cutMesh.vertexCoordsArray.push_back(v[0]); - cutMesh.vertexCoordsArray.push_back(v[1]); - cutMesh.vertexCoordsArray.push_back(v[2]); - } - // copy faces - for (int i = 0; i < (int)cutMesh.F.size(); ++i) { - const std::vector& f = cutMesh.F[i]; - my_assert(f.size() == 3); - for (int j = 0; j < (int)f.size(); ++j) { - cutMesh.faceIndicesArray.push_back(f[j]); - } +// basic comparison of doubles +bool are_equal(const McDouble& x, const McDouble &y) +{ + const McDouble eps = 1e-6; + const McDouble diff = (x > y) ? (x - y) : (y - x); - cutMesh.faceSizesArray.push_back((uint32_t)f.size()); - } + return diff < eps; +} - printf("cut mesh:\n\tvertices=%d\n\tfaces=%d\n", (int)cutMesh.V.size(), (int)cutMesh.F.size()); +// assigns a string name to a connected component based on it unique properties +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation, + McBool& isDerivedFromSrcMesh); - // create an MCUT context - // ------------------------- - McContext context = MC_NULL_HANDLE; - McResult err = mcCreateContext(&context, MC_DEBUG); - my_assert(err == MC_NO_ERROR); - // do the cutting - // ----------------- - err = mcDispatch( +int main() +{ + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = srcMesh; + + // + // read-in the source-mesh from file + // + mioReadOBJ(DATA_DIR "/cube.obj", + &srcMesh.pVertices, + &srcMesh.pNormals, + &srcMesh.pTexCoords, + &srcMesh.pFaceSizes, + &srcMesh.pFaceVertexIndices, + &srcMesh.pFaceVertexTexCoordIndices, + &srcMesh.pFaceVertexNormalIndices, + &srcMesh.numVertices, + &srcMesh.numNormals, + &srcMesh.numTexCoords, + &srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOBJ(DATA_DIR "/plane.obj", + &cutMesh.pVertices, + &cutMesh.pNormals, + &cutMesh.pTexCoords, + &cutMesh.pFaceSizes, + &cutMesh.pFaceVertexIndices, + &cutMesh.pFaceVertexTexCoordIndices, + &cutMesh.pFaceVertexNormalIndices, + &cutMesh.numVertices, + &cutMesh.numNormals, + &cutMesh.numTexCoords, + &cutMesh.numFaces); + + + // + // create a context + // + + McContext context = MC_NULL_HANDLE; + + McResult status = mcCreateContext(&context, MC_NULL_HANDLE); + + my_assert(status == MC_NO_ERROR); + + // + // do the cutting + // + + status = mcDispatch( context, MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_INCLUDE_VERTEX_MAP | MC_DISPATCH_INCLUDE_FACE_MAP, // We need vertex and face maps to propagate normals // source mesh - reinterpret_cast(srcMesh.vertexCoordsArray.data()), - reinterpret_cast(srcMesh.faceIndicesArray.data()), - srcMesh.faceSizesArray.data(), - static_cast(srcMesh.vertexCoordsArray.size() / 3), - static_cast(srcMesh.faceSizesArray.size()), - // cut mesh - reinterpret_cast(cutMesh.vertexCoordsArray.data()), - cutMesh.faceIndicesArray.data(), - cutMesh.faceSizesArray.data(), - static_cast(cutMesh.vertexCoordsArray.size() / 3), - static_cast(cutMesh.faceSizesArray.size())); + srcMesh.pVertices, + srcMesh.pFaceVertexIndices, + srcMesh.pFaceSizes, + srcMesh.numVertices, + srcMesh.numFaces, + // cut mesh + cutMesh.pVertices, + cutMesh.pFaceVertexIndices, + cutMesh.pFaceSizes, + cutMesh.numVertices, + cutMesh.numFaces); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); - // query the number of available connected component (all types) - // ---------------------------------------------------------------- + // + // query the number of available connected components + // - uint32_t numConnectedComponents; + McUint32 numConnectedComponents; - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents); + my_assert(status == MC_NO_ERROR); - printf("connected components: %d\n", (int)numConnectedComponents); + printf("connected components: %d\n", (McInt32)numConnectedComponents); if (numConnectedComponents == 0) { fprintf(stdout, "no connected components found\n"); @@ -172,337 +264,459 @@ int main() } std::vector connectedComponents(numConnectedComponents, 0); - err = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connectedComponents.size(), connectedComponents.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponents(context, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL); + my_assert(status == MC_NO_ERROR); - // query the data of each connected component from MCUT - // ------------------------------------------------------- + // + // query the data of each connected component + // - for (int i = 0; i < (int)connectedComponents.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { McConnectedComponent connComp = connectedComponents[i]; // connected compoene - // query the vertices - // ---------------------- + // + // vertices + // McSize numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + my_assert(status == MC_NO_ERROR); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(double) * 3)); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(double) * 3)); std::vector ccVertices((size_t)ccVertexCount * 3u, 0.0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); - my_assert(err == MC_NO_ERROR); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); + my_assert(status == MC_NO_ERROR); - // query the [triangulated] faces - // ------------------- + // + // [triangulated] faces + // numBytes = 0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccTriangulatedFaceIndices(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccTriangulatedFaceIndices.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the vertex map - // ------------------------ - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccVertexMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // query the triangulated face map - // ----------------------- - const uint32_t ccTriangulatedFaceCount = static_cast(ccTriangulatedFaceIndices.size()/3); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, 0, NULL, &numBytes); - my_assert(err == MC_NO_ERROR); - std::vector ccFaceMap(numBytes / sizeof(uint32_t), 0); - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, numBytes, ccFaceMap.data(), NULL); - my_assert(err == MC_NO_ERROR); - - // resolve fragment name - // ------------------------- - - // Here we create and name the connected component based on its properties - - // get type - McConnectedComponentType ccType; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_TYPE, sizeof(McConnectedComponentType), &ccType, NULL); - my_assert(err == MC_NO_ERROR); - - std::string name; - McFragmentLocation fragmentLocation = (McFragmentLocation)0; - McPatchLocation patchLocation = (McPatchLocation)0; - bool isFragment = false; - - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) { - name += "seam"; - } else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - name += "input"; - } else { - isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - name += isFragment ? "frag" : "patch"; - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, sizeof(McPatchLocation), &patchLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += patchLocation == MC_PATCH_LOCATION_INSIDE ? ".inside" : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".outside" : ".undefined"); - - if (isFragment) { - - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, sizeof(McFragmentLocation), &fragmentLocation, NULL); - my_assert(err == MC_NO_ERROR); - name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE ? ".above" : ".below"; // missing loc="undefined" case - - McFragmentSealType sType = (McFragmentSealType)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, sizeof(McFragmentSealType), &sType, NULL); - my_assert(err == MC_NO_ERROR); - name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".sealed" : ".unsealed"; - } - } - - bool ccIsFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); - - // connected-component is not a fragment && it is a seam - if (!ccIsFromSrcMesh) { - if (ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) { - // get origin - McSeamOrigin ccOrig = (McSeamOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McSeamOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - - ccIsFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } else if (ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) { - McInputOrigin ccOrig = (McInputOrigin)0; - err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, sizeof(McInputOrigin), &ccOrig, NULL); - my_assert(err == MC_NO_ERROR); - ccIsFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); - name += ccIsFromSrcMesh ? ".sm" : ".cm"; - } - } - - int faceVertexOffsetBase = 0; - - std::vector ccNormals; // our normals (what we want) - - // CC-vertex-index-to-normal-indices. - // Its possible to map to more than one normal since such coordinates are specified to per-face. - std::map> ccVertexIndexToNormalIndices; - std::vector ccTriangleVertexNormalIndices; // normal indices reference by each triangle + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); + my_assert(status == MC_NO_ERROR); + std::vector ccTriangulatedFaceIndices(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccTriangulatedFaceIndices.data(), NULL); + my_assert(status == MC_NO_ERROR); + + // + // vertex map + // + + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); + my_assert(status == MC_NO_ERROR); + std::vector ccVertexMap(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); + my_assert(status == MC_NO_ERROR); + + // + // triangulated face map + // + + const McUint32 ccTriangulatedFaceCount = static_cast(ccTriangulatedFaceIndices.size()/3); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, 0, NULL, &numBytes); + + my_assert(status == MC_NO_ERROR); + + std::vector ccTriangleFaceMap(numBytes / sizeof(McUint32), 0); + status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, numBytes, ccTriangleFaceMap.data(), NULL); + + my_assert(status == MC_NO_ERROR); + + // + // Here we create a name for the connected component based on its properties + // and save whether its a fragment, and if so the location of this fragment + // + + McBool isFragment = MC_FALSE; + McBool isDerivedFromSrcMesh = MC_FALSE; + McFragmentLocation fragmentLocation = (McFragmentLocation)0; + const std::string name = + resolve_cc_name_string(context, cc, isFragment, fragmentLocation, isDerivedFromSrcMesh); + + McUint32 faceVertexOffsetBase = 0; // offset of vertex in face + // our array normals (what we want). This is the list that will be referred to by + // the face-vertices of the cc (each face will have vertex indices and normal indices) + std::vector ccNormals; + + std::vector ccFaceVertexNormalIndices; // normal indices reference by each face of cc // for each triangle in cc - for (int t = 0; t < (int)ccTriangulatedFaceCount; ++t) { + for (McInt32 t = 0; t < (McInt32)ccTriangulatedFaceCount; ++t) { // get the [origin] input-mesh face index (Note: this index may be offsetted // to distinguish between source-mesh and cut-mesh faces). - const uint32_t imFaceIdxRaw = ccFaceMap.at(t); // source- or cut-mesh face index (we don't know yet) - // ** This is how we infer which mapped indices belong to the source-mesh or the cut-mesh. - // NOTE: it is generally advisable to use the number of face of the internal source-mesh since MCUT might modify - // the user-provided source mesh. Keeping things simple for now - const bool faceIsFromSrcMesh = (imFaceIdxRaw < (uint32_t)srcMesh.F.size()); - bool flipNormalsOnFace = false; - // Now compute the actual input mesh face index (accounting for offset) - uint32_t imFaceIdx = imFaceIdxRaw; - - if (!faceIsFromSrcMesh) { // if the current face is from the cut-mesh - imFaceIdx = (imFaceIdxRaw - (uint32_t)srcMesh.F.size()); // accounting for offset - // check if we need to flip normals on the face - flipNormalsOnFace = (isFragment && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); - } - - int faceSize = 3; /// number of vertices in face - - // for each vertex in face - for (int v = 0; v < faceSize; ++v) { - - const int ccVertexIdx = ccTriangulatedFaceIndices.at((McSize)faceVertexOffsetBase + v); - const uint32_t imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); - // NOTE: it is generally advisable to use the number of vertices of the internal source-mesh since MCUT might modify - // the user-provided source mesh. Keeping things simple for now - bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.V.size()); - const bool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); // i.e. a vertex along the cut-path (an intersection point) - uint32_t imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset - - if (!vertexIsFromSrcMesh) { - imVertexIdx = (imVertexIdxRaw - (std::uint32_t)srcMesh.V.size()); // account for offset - } - - const InputMesh* inputMeshPtr = faceIsFromSrcMesh ? &srcMesh : &cutMesh; - - // the face from which the current cc face came ("birth face") - const std::vector& imFace = inputMeshPtr->F[imFaceIdx]; - - Eigen::Vector3d normal; // the normal of the current vertex - - if (isSeamVertex) { // normal completely unknown and must be inferred/computed - - // interpolate texture coords from input-mesh values - // -------------------------------------------------- - - // coordinates of current point - double x(ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); - double y(ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); - double z(ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); - - // vertices of the origin face (i.e. the face from which the current face came from). - // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation - // will be more complex, which is unnecessary for now. - const std::vector& a = inputMeshPtr->V[imFace[0]]; - const std::vector& b = inputMeshPtr->V[imFace[1]]; - const std::vector& c = inputMeshPtr->V[imFace[2]]; - - // compute the barycentric coords of our seam vertex on the origin face - Eigen::MatrixXd P; // our vertex - P.resize(1, 3); - P << x, y, z; - // the origin face vertices added into Eigen matrices for libIGL - Eigen::MatrixXd A; - A.resize(1, 3); - A << a[0], a[1], a[2]; - Eigen::MatrixXd B; - B.resize(1, 3); - B << b[0], b[1], b[2]; - Eigen::MatrixXd C; - C.resize(1, 3); - C << c[0], c[1], c[2]; - - // our barycentric coords - Eigen::MatrixXd L; - - igl::barycentric_coordinates(P, A, B, C, L); - - // compute the normal of our vertex by interpolation - // ------------------------------------------------- - - // indices of the normals that are used by the origin face "imFaceIdx" - const std::vector& imFaceNormalIndices = inputMeshPtr->FN[imFaceIdx]; - my_assert(imFaceNormalIndices.size() == 3); - - // normals of vertices in the origin face - const std::vector& Na_ = inputMeshPtr->N[imFaceNormalIndices[0]]; - const std::vector& Nb_ = inputMeshPtr->N[imFaceNormalIndices[1]]; - const std::vector& Nc_ = inputMeshPtr->N[imFaceNormalIndices[2]]; - // simple conversion to Eigen's Vector3d type - const Eigen::Vector3d Na(Na_[0], Na_[1], Na_[2]); - const Eigen::Vector3d Nb(Nb_[0], Nb_[1], Nb_[2]); - const Eigen::Vector3d Nc(Nc_[0], Nc_[1], Nc_[2]); - const Eigen::Vector3d baryCoords = L.row(0); - - // interpolate using barycentric coords - normal = (Na * baryCoords.x()) + (Nb * baryCoords.y()) + (Nc * baryCoords.z()); - - // NOTE: if all three vertices have the same normal (index) then there is no need for interpolation - // we'd just copy that value from the respective input mesh. - - } else { // the normal is known must be inferred from input mesh - - // the index of the mapped-to index in the input mesh - int imFaceVertexOffset = -1; - for (int p = 0; p < (int)imFace.size(); ++p) { - if (imFace[p] == (int)imVertexIdx) { - imFaceVertexOffset = p; - break; - } + const McUint32 imFaceIdxRaw = ccTriangleFaceMap.at(t); // source- or cut-mesh face index (we don't know yet) + // This is how we infer which mapped indices belong to the source-mesh or the cut-mesh. + const bool faceIsFromSrcMesh = (imFaceIdxRaw < (McUint32)srcMesh.numFaces); + bool flipNormalsOnFace = false; + // Now compute the actual input mesh face index (accounting for offset) + McUint32 imFaceIdx = imFaceIdxRaw; + + if(!faceIsFromSrcMesh) + { // if the current face is from the cut-mesh + imFaceIdx = (imFaceIdxRaw - (McUint32)srcMesh.numFaces); // accounting for offset + // check if we need to flip normals on the face + flipNormalsOnFace = (isFragment && fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE); + } + + McUint32 faceSize = 3; /// number of vertices in face + + // for each vertex in face + for(McUint32 v = 0; v < faceSize; ++v) + { + const McUint32 ccVertexIdx = ccTriangulatedFaceIndices.at((McSize)faceVertexOffsetBase + v); + const McUint32 imVertexIdxRaw = ccVertexMap.at(ccVertexIdx); + bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMesh.numVertices); + // i.e. a vertex along the cut-path (an intersection point) + const bool isSeamVertex = (imVertexIdxRaw == MC_UNDEFINED_VALUE); + McUint32 imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset + + if(!vertexIsFromSrcMesh) + { + // account for offset + imVertexIdx = (imVertexIdxRaw - (McUint32)srcMesh.numVertices); + } + + const MioMesh* inputMeshPtr = faceIsFromSrcMesh ? &srcMesh : &cutMesh; + + // the face from which the current cc face came ("birth face") + //const std::vector& imFace = inputMeshPtr->F[imFaceIdx]; + // NOTE: there is a presumption here that the input mesh is a triangle-mesh! + const McUint32* imFace = inputMeshPtr->pFaceVertexIndices + (imFaceIdx * 3); + + vec3 normal; // the normal of the current vertex + + if(isSeamVertex) + { // normal completely unknown and must be inferred + + // + // interpolate from input-mesh values + // + + // coordinates of current point (whose barycentric coords we want) + vec3 p = {0.0, 0.0,0.0}; + p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); + p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); + p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); + + // vertices of the origin face (i.e. the face from which the current face came from). + // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation + // will be more complex, which is unnecessary for now. + vec3 a = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[0]*3; + a.x = ptr[0]; + a.y = ptr[1]; + a.z = ptr[2]; + } + vec3 b = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[1]*3; + b.x = ptr[0]; + b.y = ptr[1]; + b.z = ptr[2]; } - my_assert(imFaceVertexOffset != -1); - - // get the normal index of the vertex - int imNormalIdx = inputMeshPtr->FN[imFaceIdx][imFaceVertexOffset]; - // copy the normal value from the input mesh - const std::vector& n = inputMeshPtr->N[imNormalIdx]; - my_assert(n.size() == 3); - normal = Eigen::Vector3d(n[0], n[1], n[2]); - } - - // When MCUT seal's holes, it uses polygons directly from the cut mesh. These polygons - // may require to be flipped sometimes when holes are filled (e.g. when a fragment is - // "above"). Thus, we cannot just copy/interpolate the normal from the origin mesh in - // such cases, we must also flip (negate) it. - if (flipNormalsOnFace) { - normal *= -1.0; - } - - // Do some book-keeping to prevent us from duplicate the normals that we write to file. - int normalIndex = -1; - - // has a normal with the same value already been computed? - std::vector::const_iterator fiter = std::find_if( - ccNormals.cbegin(), ccNormals.cend(), - [&](const Eigen::Vector3d& e) { return compare(e.x(), normal.x()) && compare(e.y(), normal.y()) && compare(e.z(), normal.z()); }); - - if (fiter != ccNormals.cend()) { - normalIndex = (int)std::distance(ccNormals.cbegin(), fiter); - } + vec3 c = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pVertices + imFace[2]*3; + c.x = ptr[0]; + c.y = ptr[1]; + c.z = ptr[2]; + } + + const vec3 bary = getBarycentricCoords(p, a, b, c); + + // + // compute the normal of our vertex by interpolation + // + + // indices of the normals that are used by the vertices defining the origin face "imFaceIdx" + const McUint32* imFaceNormalIndices = inputMeshPtr->pFaceVertexNormalIndices + (imFaceIdx*3); //inputMeshPtr->FN[imFaceIdx]; + + // normal coordinates of vertices in the origin face + + vec3 normalA = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0]*3); + normalA.x = ptr[0]; + normalA.y = ptr[1]; + normalA.z = ptr[2]; + } + vec3 normalB = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1]*3); + normalB.x = ptr[0]; + normalB.y = ptr[1]; + normalB.z = ptr[2]; + } + vec3 normalC = {0.0, 0.0, 0.0}; + { + const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2]*3); + normalC.x = ptr[0]; + normalC.y = ptr[1]; + normalC.z = ptr[2]; + } - if (normalIndex == -1) { // normal not yet stored for CC vertex in face - normalIndex = (int)ccNormals.size(); - ccNormals.push_back(normal); + // interpolate at point "p" using barycentric coords + normal = (normalA * bary.u) + (normalB * bary.v ) + (normalC * bary.w); + + // NOTE: if all three vertices have the same normal (index) then there is no need for interpolation + // we'd just copy that value from the respective input mesh. + } + else + { // the normal is known and can therefore be inferred from the input mesh + + // the index of the mapped-to index in the input mesh + McIndex imFaceVertexOffset = MC_UNDEFINED_VALUE; + + // for each vertex in face + for(McUint32 p = 0; p < inputMeshPtr->pFaceSizes[imFaceIdx]; ++p) + { + if(imFace[p] == imVertexIdx) + { + imFaceVertexOffset = p; + break; + } + } + + my_assert(imFaceVertexOffset != MC_UNDEFINED_VALUE); + + // get the normal index of the vertex + McUint32 imNormalIdx = inputMeshPtr->pFaceVertexNormalIndices[imFaceIdx*3 + imFaceVertexOffset]; + // copy the normal value from the input mesh + const McDouble* ptr = inputMeshPtr->pNormals + (imNormalIdx * 3); + + normal.x = ptr[0]; + normal.y = ptr[1]; + normal.z = ptr[2]; + } + + // When MCUT seal's holes, it uses polygons directly from the cut mesh. These polygons + // may require to be flipped sometimes when holes are filled (e.g. when a fragment is + // "above"). Thus, we cannot just copy/interpolate the normal from the origin mesh in + // such cases, we must also flip (negate) it. + + if(flipNormalsOnFace) + { + normal = normal * -1.0; + } + + // + // Do some book-keeping to prevent us from duplicating the normals that we write to file. + // + + // has a normal with the same value already been computed? + // pointer to the location of the existing (i.e. already computed) normal, which matches "normal" + const McDouble* pNormalIter = nullptr; + + // for each normal vector (in the list that we have so far) + for(McUint32 n = 0; n < ccNormals.size() / 3; ++n) + { + const McDouble* pNormal = ccNormals.data() + (n * 3); + const bool haveMatch = are_equal(normal.x, pNormal[0]) && + are_equal(normal.y, pNormal[1]) && + are_equal(normal.z, pNormal[2]); + if(haveMatch) + { + pNormalIter = pNormal; + break; + } + } + + std::ptrdiff_t normalIndex = -1; + + if(pNormalIter != nullptr) + { + normalIndex = (pNormalIter - ccNormals.data()) / 3; + + my_assert(normalIndex >=0); + } + else{ + normalIndex = ccNormals.size()/3; + + ccNormals.push_back(normal.x); + ccNormals.push_back(normal.y); + ccNormals.push_back(normal.z); } - ccTriangleVertexNormalIndices.push_back(normalIndex); - } // for (int v = 0; v < faceSize; ++v) { - - faceVertexOffsetBase += faceSize; - } // for (int f = 0; f < ccTriangulatedFaceCount; ++f) { - - // save connected component (mesh) to an .obj file - // ----------------------------------------------- - - char fnameBuf[64]; - sprintf(fnameBuf, ("OUT_" + name + ".obj").c_str(), i); - std::string fpath(DATA_DIR "/" + std::string(fnameBuf)); - - printf("write file: %s\n", fpath.c_str()); - - std::ofstream file(fpath); - - // write vertices - - for (int p = 0; p < (int)ccVertexCount; ++p) { - double x = ccVertices[(McSize)p * 3 + 0]; - double y = ccVertices[(McSize)p * 3 + 1]; - double z = ccVertices[(McSize)p * 3 + 2]; - file << std::setprecision(std::numeric_limits::digits10 + 1) << "v " << x << " " << y << " " << z << std::endl; - } - - // write normals - - for (int p = 0; p < (int)ccNormals.size(); ++p) { - Eigen::Vector3d n = ccNormals[p]; - file << "vn " << std::setprecision(std::numeric_limits::digits10 + 1) << n.x() << " " << n.y() << " " << n.z() << std::endl; - } - - // write faces (with normal indices) - - faceVertexOffsetBase = 0; - for (int k = 0; k < (int)ccTriangulatedFaceCount; ++k) { - int faceSize = 3; - - file << "f "; - for (int j = 0; j < faceSize; ++j) { - const int idx = faceVertexOffsetBase + j; - const int ccVertexIdx = ccTriangulatedFaceIndices.at(static_cast(idx)); - file << (ccVertexIdx + 1) << "//" << ccTriangleVertexNormalIndices[idx] + 1 << " "; - } - file << std::endl; - - faceVertexOffsetBase += faceSize; - } + ccFaceVertexNormalIndices.push_back(normalIndex); + } // for (int v = 0; v < faceSize; ++v) { + + faceVertexOffsetBase += faceSize; + + } // for (McInt32 f = 0; f < ccTriangulatedFaceCount; ++f) { + + // + // save connected component (mesh) to an .obj file + // + + char fnameBuf[64]; + sprintf(fnameBuf, ("OUT_" + name + "-%d.obj").c_str(), i); + std::string fpath(OUTPUT_DIR "/" + std::string(fnameBuf)); + + // each face has 3 vertices + std::vector ccFaceSizes((McUint32)ccTriangulatedFaceIndices.size()/3, 3); + + mioWriteOBJ( + fpath.c_str(), + ccVertices.data(), + ccNormals.data(), + nullptr, // pTexCoords + ccFaceSizes.data(), + ccTriangulatedFaceIndices.data(), + nullptr, // pFaceVertexTexCoordIndices + ccFaceVertexNormalIndices.data(), + ccVertexCount, + ccNormals.size()/3, + 0, // numTexCoords + ccTriangulatedFaceCount); } - // 6. free connected component data - // -------------------------------- - err = mcReleaseConnectedComponents(context, 0, NULL); + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); + + // + // free connected component data + // + status = mcReleaseConnectedComponents(context, 0, NULL); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); - // 7. destroy context - // ------------------ - err = mcReleaseContext(context); + // + // destroy context + // + status = mcReleaseContext(context); - my_assert(err == MC_NO_ERROR); + my_assert(status == MC_NO_ERROR); return 0; } + + +std::string resolve_cc_name_string(McContext context, + McConnectedComponent cc, + McBool& isFragment, + McFragmentLocation& fragmentLocation, + McBool& isDerivedFromSrcMesh) +{ + isDerivedFromSrcMesh = MC_FALSE; + + // get type + McConnectedComponentType ccType = (McConnectedComponentType)0; + + McResult status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_TYPE, + sizeof(McConnectedComponentType), + &ccType, + NULL); + + my_assert(status == MC_NO_ERROR); + + std::string name; + McPatchLocation patchLocation = (McPatchLocation)0; + + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + name += "seam"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + name += "input"; + } + else + { + isFragment = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + name += isFragment ? "frag" : "patch"; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_PATCH_LOCATION, + sizeof(McPatchLocation), + &patchLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += patchLocation == MC_PATCH_LOCATION_INSIDE + ? ".ploc=in" + : (patchLocation == MC_PATCH_LOCATION_OUTSIDE ? ".ploc=out" : ".ploc=undef"); + + if(isFragment) + { + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_LOCATION, + sizeof(McFragmentLocation), + &fragmentLocation, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += fragmentLocation == MC_FRAGMENT_LOCATION_ABOVE + ? ".floc=abv" + : ".floc=blw"; // missing loc="undefined" case + + McFragmentSealType sType = (McFragmentSealType)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_FRAGMENT_SEAL_TYPE, + sizeof(McFragmentSealType), + &sType, + NULL); + + my_assert(status == MC_NO_ERROR); + + name += sType == MC_FRAGMENT_SEAL_TYPE_COMPLETE ? ".seal=yes" : ".seal=no"; + } + } + + isDerivedFromSrcMesh = (ccType == MC_CONNECTED_COMPONENT_TYPE_FRAGMENT); + + // connected-components is not a fragment && it is a seam + if(!isDerivedFromSrcMesh) + { + if(ccType == MC_CONNECTED_COMPONENT_TYPE_SEAM) + { + // get origin + McSeamOrigin ccOrig = (McSeamOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McSeamOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + isDerivedFromSrcMesh = (ccOrig == McSeamOrigin::MC_SEAM_ORIGIN_SRCMESH); + name += isDerivedFromSrcMesh ? ".orig=s" : ".orig=c"; + } + else if(ccType == MC_CONNECTED_COMPONENT_TYPE_INPUT) + { + McInputOrigin ccOrig = (McInputOrigin)0; + + status = mcGetConnectedComponentData(context, + cc, + MC_CONNECTED_COMPONENT_DATA_ORIGIN, + sizeof(McInputOrigin), + &ccOrig, + NULL); + + my_assert(status == MC_NO_ERROR); + + isDerivedFromSrcMesh = (ccOrig == McInputOrigin::MC_INPUT_ORIGIN_SRCMESH); + name += isDerivedFromSrcMesh ? ".orig=s" : ".orig=c"; + } + } + + return name; +} \ No newline at end of file From 43f147d302a1ee3d8d22418afbf3910dbd5676f9 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Fri, 19 Jan 2024 12:05:21 +0000 Subject: [PATCH 10/23] update lecensing terms and readme file --- LICENSE.GPL.txt | 674 ------------------ LICENSE.txt | 16 - README.md | 26 +- include/mcut/internal/bvh.h | 46 +- include/mcut/internal/frontend.h | 45 +- include/mcut/internal/hmesh.h | 45 +- include/mcut/internal/kernel.h | 45 +- include/mcut/internal/math.h | 45 +- include/mcut/internal/preproc.h | 45 +- include/mcut/internal/timer.h | 46 +- include/mcut/internal/tpool.h | 45 +- include/mcut/internal/utils.h | 45 +- include/mcut/mcut.h | 45 +- include/mcut/platform.h | 51 +- source/bvh.cpp | 45 +- source/frontend.cpp | 35 + source/hmesh.cpp | 45 +- source/math.cpp | 45 +- source/mcut.cpp | 45 +- source/preproc.cpp | 35 + tests/include/off.h | 62 -- tests/source/benchmark.cpp | 247 ++++--- tests/source/booleanOperation.cpp | 163 +++-- tests/source/computeSeams.cpp | 149 ++-- .../source/concurrentSynchronizedContexts.cpp | 75 +- tests/source/createContext.cpp | 51 +- tests/source/debugCallback.cpp | 65 +- tests/source/debugVerboseLog.cpp | 65 +- tests/source/degenerateInput.cpp | 87 ++- tests/source/dispatchFilterFlags.cpp | 217 +++--- tests/source/getContextInfo.cpp | 51 +- tests/source/getDataMaps.cpp | 193 ++--- tests/source/getEventInfo.cpp | 63 +- tests/source/intersectionType.cpp | 63 +- tests/source/main.cpp | 315 +------- tests/source/off.cpp | 86 --- tests/source/perturbationState.cpp | 73 +- tests/source/polygonWithHoles.cpp | 81 ++- tests/source/triangulation.cpp | 165 +++-- tests/source/userEvents.cpp | 71 +- tutorials/AdjacentFaces/AdjacentFaces.cpp | 36 +- tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp | 33 +- tutorials/CSGBoolean/CSGBoolean.cpp | 33 +- tutorials/EventCallback/EventCallback.cpp | 35 +- tutorials/FaceNormals/FaceNormals.cpp | 33 +- tutorials/HelloWorld/HelloWorld.cpp | 41 +- tutorials/InOutQuery/InOutQuery.cpp | 42 +- .../MultipleContextsInParallel.cpp | 34 +- .../PlanarSectioning/PlanarSectioning.cpp | 34 +- .../QuerySeamVerticesSorted.cpp | 34 +- .../QuerySeamVerticesUnsorted.cpp | 33 +- .../ReversedConnectedComponentFaces.cpp | 33 +- tutorials/TextureCoordinates/README.txt | 10 - .../TextureCoordinates/TextureCoordinates.cpp | 33 +- .../TriangulatedFaceMaps.cpp | 42 +- tutorials/Triangulation/Triangulation.cpp | 35 +- tutorials/VertexNormals/VertexNormals.cpp | 33 +- 57 files changed, 1978 insertions(+), 2407 deletions(-) delete mode 100644 LICENSE.GPL.txt delete mode 100644 LICENSE.txt delete mode 100644 tests/include/off.h delete mode 100644 tests/source/off.cpp delete mode 100644 tutorials/TextureCoordinates/README.txt diff --git a/LICENSE.GPL.txt b/LICENSE.GPL.txt deleted file mode 100644 index 94a9ed0..0000000 --- a/LICENSE.GPL.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index aac9c02..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,16 +0,0 @@ -Permission to use this software is governed by two licensing options which are mutually exclusive: - -(A) Open source GNU General Public License ("GPL"); a copy of which you should have recieved. - - see also: - -(B) Commercial license, which can be purchased from the owner. - - The commercial license option is for users that wish to use MCUT in - their products for comercial purposes but do not wish to release their - software under the GPL. - - For more information, email "floyd.m.chitalu@gmail.com". - -These options protect the project's commercial value and thus make it possible for the -author(s) to guarantee long term support, maintenance and further development of the -code for the benefit of the project and its users. \ No newline at end of file diff --git a/README.md b/README.md index 3f37efb..fc703bd 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,22 @@ # MCUT Overview -Gist: _A simple and fast C++ library for mesh booleans and more..._ +Gist: _A robust library for detecting and resolving surface intersections between two objects._ [![Windows](https://github.com/cutdigital/mcut/actions/workflows/windows.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/windows.yml) [![MacOS](https://github.com/cutdigital/mcut/actions/workflows/macos.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/macos.yml) [![Linux](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml) -This is a software project designed for a broad range of real-world problems relating to 3D modelling and design tasks. Application areas include computer animation, aerospace and automotive engineering, mining, civil and mechanical engineering amongst others. - -The project is called "MCUT" (short for 'mesh cutting'), and it provides functionality to perform fast and robust geometry operations, as shown below: +This project is called "MCUT" (short for 'mesh cutting'), and it provides functionality to perform robust geometry operations between surfaces, as shown below:

Figure 1: Generate, slice and perform Booleans without errors.

- -The codebase provides a comprehensive tool for ensuring that computer-aided planning tasks for e.g. mine-design, rock strata boring (e.g. underground-tunnel excavations), oil-well drilling and general 3D modelling for animation are achievable with robustness. The tool is developed to take advantage of modern high-performance parallel computing hardware for you, and is demonstrably robust by using precise geometric algorithms that are implemented in C++ and accessed through an intuitive API that resembles the all-familiar C programming language. - -Importantly, MCUT is designed with the philosophy that users don't know or don't care about esoteric problems with floating point arithmetic. +The project is designed for a broad range of real-world problems relating to 3D modelling and design tasks. Application areas include computer animation, aerospace and automotive engineering, mining, civil and mechanical engineering amongst others. # Capabilities -MCUT is a tool for partitioning meshes that represent solids or open surfaces: It is a code library for cutting 3D mesh objects using their geometry to produce crisp fragments at fine scale, which is useful for operations like slicing and boolean operations (union, subtraction and intersection). Supported features include (see images below): +MCUT is a tool for partitioning objects represented as meshes that model solids or open surfaces: It is a code library for cutting 3D mesh objects using their geometry to produce crisp fragments at fine scale, which is useful for operations like slicing and boolean operations (union, subtraction and intersection). Supported features include (see images below): * **Stencilling**: exact cut-outs of the cutting surface * **Intersection curve access**: geometry representing lines of intersection-contour points @@ -45,7 +40,7 @@ What is being offered is a general solution to the problem of resolving solid- a The expert capabilities of MCUT will allow companies, individuals and researchers-alike to develop robust (and fast) Computer-Aided Design (CAD) and Manufacturing (CAM) tools. For example, these tools could cater to the design of industry-specific structural models like tunnels, drill holes, mechanical instruments and rock-block models. All this alongside the ability to handle general 3D modelling tasks that are typical in industry and academic-fields related to computer graphics (e.g. game-engine level design) and mechanical engineering (e.g. fracture simulation). In essence, users of MCUT are provided with the capability to create robust derivative products and tools for generating (and testing) structural designs in a virtual setting for short- and long-term production operations and feasibility tests/studies. -The following images show more examples of what users can achieve with MCUT: +The following images show more examples of what users can do with MCUT:

@@ -101,12 +96,15 @@ Next, try out one of the tutorials! # Licensing -MCUT is available under an Open Source license as well as a commercial license. Users choosing to use MCUT under the free-of-charge Open Source license (e.g. for academic purposes) simply need to comply to its terms, otherwise a commercial license is required. The Open Source license is the "GNU General Public License" (GPL). In cases where the constraints of the Open source license prevent you from using MCUT, a commercial license can be purchased. The library is licensed with an attractively low price which is a one-off sum, requiring no further loyalty fees with guarranteed future updates for free. +MCUT is available under an Open Source license as well as a commercial license. Users choosing to use MCUT under the free-of-charge Open Source license (e.g. for academic purposes) simply need to comply to its terms, otherwise a commercial license is required. + +* The Open Source license is the GNU [Lesser General Public License (v3+)](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. +* The commercial license option is for users that wish to use MCUT in their products for commercial purposes but do not wish to release their software under the LGPL. You can buy a commercial license from [CutDigital Enterprise](contact@cut-digital.com). The commercial offer is adapted based on company size (number of employees). -These options protect the project's commercial value and thus make it possible for the author to guarantee long term support, maintenance and further development of the code for the benefit of the project and its users. +These options facilitate the adoption of MCUT in other [Open Source](https://opensource.org/) projects, while protecting its commercial value and thus make it possible to guarantee long term support, maintenance and further development of the code for the benefit of its users. --- -If MCUT helped you please consider adding a star here on GitHub. This means a lot to the author. +Consider adding a Star here on GitHub if MCUT has helped you in anyway. -_You can also send an [email](floyd.m.chitalu@gmail.com) to the author if you have questions about MCUT_. +_You may also send an [email](floyd.m.chitalu@gmail.com) to the original author if you have questions about MCUT_. diff --git a/include/mcut/internal/bvh.h b/include/mcut/internal/bvh.h index cb040ac..a33c37b 100644 --- a/include/mcut/internal/bvh.h +++ b/include/mcut/internal/bvh.h @@ -1,24 +1,38 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + #ifndef MCUT_BVH_H_ #define MCUT_BVH_H_ diff --git a/include/mcut/internal/frontend.h b/include/mcut/internal/frontend.h index 16f808f..3f9e5ed 100644 --- a/include/mcut/internal/frontend.h +++ b/include/mcut/internal/frontend.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /** * @file mcut.h diff --git a/include/mcut/internal/hmesh.h b/include/mcut/internal/hmesh.h index 24c742c..73a58c3 100644 --- a/include/mcut/internal/hmesh.h +++ b/include/mcut/internal/hmesh.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #ifndef MCUT_HALFEDGE_MESH_H_ #define MCUT_HALFEDGE_MESH_H_ diff --git a/include/mcut/internal/kernel.h b/include/mcut/internal/kernel.h index caed4e1..3a5fdfe 100644 --- a/include/mcut/internal/kernel.h +++ b/include/mcut/internal/kernel.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #ifndef MCUT_KERNEL_H #define MCUT_KERNEL_H diff --git a/include/mcut/internal/math.h b/include/mcut/internal/math.h index 8a00e63..cf77d6c 100644 --- a/include/mcut/internal/math.h +++ b/include/mcut/internal/math.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #ifndef MCUT_MATH_H_ #define MCUT_MATH_H_ diff --git a/include/mcut/internal/preproc.h b/include/mcut/internal/preproc.h index b7129aa..bb712c6 100644 --- a/include/mcut/internal/preproc.h +++ b/include/mcut/internal/preproc.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /** * @file mcut.h diff --git a/include/mcut/internal/timer.h b/include/mcut/internal/timer.h index b26289f..cd65432 100644 --- a/include/mcut/internal/timer.h +++ b/include/mcut/internal/timer.h @@ -1,24 +1,38 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + #ifndef MCUT_TIMER_H_ #define MCUT_TIMER_H_ diff --git a/include/mcut/internal/tpool.h b/include/mcut/internal/tpool.h index 5e36cdb..56d5833 100644 --- a/include/mcut/internal/tpool.h +++ b/include/mcut/internal/tpool.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #ifndef MCUT_SCHEDULER_H_ #define MCUT_SCHEDULER_H_ diff --git a/include/mcut/internal/utils.h b/include/mcut/internal/utils.h index e9ad76d..004b11e 100644 --- a/include/mcut/internal/utils.h +++ b/include/mcut/internal/utils.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #ifndef MCUT_UTILS_H_ #define MCUT_UTILS_H_ diff --git a/include/mcut/mcut.h b/include/mcut/mcut.h index e6fbf4d..63676c0 100644 --- a/include/mcut/mcut.h +++ b/include/mcut/mcut.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /** * @file mcut.h diff --git a/include/mcut/platform.h b/include/mcut/platform.h index 8485b3c..372bd8d 100644 --- a/include/mcut/platform.h +++ b/include/mcut/platform.h @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /** * @file platform.h diff --git a/source/bvh.cpp b/source/bvh.cpp index e23025d..83e71f5 100644 --- a/source/bvh.cpp +++ b/source/bvh.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include #include diff --git a/source/frontend.cpp b/source/frontend.cpp index ab74f9a..6f6c173 100644 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -1,3 +1,38 @@ +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + #include "mcut/internal/frontend.h" #include "mcut/internal/preproc.h" diff --git a/source/hmesh.cpp b/source/hmesh.cpp index e74e8fb..90d9ba0 100644 --- a/source/hmesh.cpp +++ b/source/hmesh.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/internal/hmesh.h" diff --git a/source/math.cpp b/source/math.cpp index 72639ee..50c67c5 100644 --- a/source/math.cpp +++ b/source/math.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/internal/math.h" #include // std::sort diff --git a/source/mcut.cpp b/source/mcut.cpp index b595654..c12e4e9 100644 --- a/source/mcut.cpp +++ b/source/mcut.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "mcut/mcut.h" diff --git a/source/preproc.cpp b/source/preproc.cpp index bfc058a..467f4ca 100644 --- a/source/preproc.cpp +++ b/source/preproc.cpp @@ -1,3 +1,38 @@ +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + #include "mcut/internal/frontend.h" #include "mcut/internal/bvh.h" diff --git a/tests/include/off.h b/tests/include/off.h deleted file mode 100644 index 714d577..0000000 --- a/tests/include/off.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. - * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. - * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ - -#ifndef OFF_FILE_H_ -#define OFF_FILE_H_ - -#include -#include -#include - -#if defined(_WIN32) -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -extern "C" void readOFF( - const char* fpath, - float** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces); - -extern "C" void writeOFF( - const char* fpath, - float* pVertices, - unsigned int* pFaceIndices, - unsigned int* pFaceSizes, - unsigned int* pEdgeIndices, - unsigned int numVertices, - unsigned int numFaces, - unsigned int numEdges); - -void writeOBJ(const std::string& fname, const std::vector& vertices, const std::vector& triangles); - -extern "C" void MCAPI_PTR mcDebugOutput(McDebugSource source, - McDebugType type, - unsigned int id, - McDebugSeverity severity, - size_t length, - const char* message, - const void* userParam); - -#endif diff --git a/tests/source/benchmark.cpp b/tests/source/benchmark.cpp index 149fc3b..b4b6b2b 100644 --- a/tests/source/benchmark.cpp +++ b/tests/source/benchmark.cpp @@ -1,56 +1,84 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #if defined(_WIN32) #define _CRT_SECURE_NO_WARNINGS 1 #endif #include "utest.h" -#include +#include "mcut/mcut.h" +#include "mio/mio.h" #include #include #include #include -#include "off.h" - #define NUMBER_OF_BENCHMARKS 61 // struct Benchmark { McContext myContext = MC_NULL_HANDLE; - int benchmarkIndex = 0; - - float* pSrcMeshVertices = NULL; - uint32_t* pSrcMeshFaceIndices = NULL; - uint32_t* pSrcMeshFaceSizes = NULL; - uint32_t numSrcMeshVertices = 0; - uint32_t numSrcMeshFaces = 0; - - float* pCutMeshVertices = NULL; - uint32_t* pCutMeshFaceIndices = NULL; - uint32_t* pCutMeshFaceSizes = NULL; - uint32_t numCutMeshVertices = 0; - uint32_t numCutMeshFaces = 0; + McInt32 benchmarkIndex = 0; + + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; }; UTEST_I_SETUP(Benchmark) @@ -59,19 +87,7 @@ UTEST_I_SETUP(Benchmark) // create with no flags (default) EXPECT_EQ(mcCreateContext(&utest_fixture->myContext, MC_NULL_HANDLE), MC_NO_ERROR); EXPECT_TRUE(utest_fixture->myContext != nullptr); - utest_fixture->benchmarkIndex = (int)utest_index; - - utest_fixture->pSrcMeshVertices = nullptr; - utest_fixture->pSrcMeshFaceIndices = nullptr; - utest_fixture->pSrcMeshFaceSizes = nullptr; - utest_fixture->numSrcMeshVertices = 0; - utest_fixture->numSrcMeshFaces = 0; - - utest_fixture->pCutMeshVertices = nullptr; - utest_fixture->pCutMeshFaceIndices = nullptr; - utest_fixture->pCutMeshFaceSizes = nullptr; - utest_fixture->numCutMeshVertices = 0; - utest_fixture->numCutMeshFaces = 0; + utest_fixture->benchmarkIndex = (McInt32)utest_index; } } @@ -95,118 +111,125 @@ UTEST_I(Benchmark, inputID, NUMBER_OF_BENCHMARKS) const std::string srcMeshName = i.first; const std::string cutMeshName = i.second; - // do the cutting - // -------------- - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/" + srcMeshName; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); + // + // read-in the source-mesh from file + // - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/" + srcMeshName).c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/" + cutMeshName; + + // + // read-in the cut-mesh from file + // NOTE: the icosphere (cut-mesh) provided lies inside the cube (source-mesh) + // - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/" + cutMeshName).c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); + // + // do the cutting + // ASSERT_EQ(mcDispatch( - utest_fixture->myContext, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_ENFORCE_GENERAL_POSITION, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->myContext, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_ENFORCE_GENERAL_POSITION, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); - free(utest_fixture->pSrcMeshVertices); - free(utest_fixture->pSrcMeshFaceIndices); - free(utest_fixture->pSrcMeshFaceSizes); - - free(utest_fixture->pCutMeshVertices); - free(utest_fixture->pCutMeshFaceIndices); - free(utest_fixture->pCutMeshFaceSizes); + // + // We no longer need the mem of input meshes, so we can free it! + // + mioFreeMesh(&srcMesh); + mioFreeMesh(&cutMesh); - uint32_t numConnComps = 0; + McUint32 connectedComponentCount = 0; - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &connectedComponentCount), MC_NO_ERROR); - if (numConnComps == 0) { + if (connectedComponentCount == 0) { printf("no connected component found\n"); } - std::vector connComps; - connComps.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); + std::vector connectedComponents; + connectedComponents.resize(connectedComponentCount); + + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connectedComponents.size(), connectedComponents.data(), NULL), MC_NO_ERROR); // // query connected component data // - for (int c = 0; c < (int)connComps.size(); ++c) { - McConnectedComponent cc = connComps[c]; // connected compoenent id + for (McInt32 c = 0; c < (McInt32)connectedComponents.size(); ++c) { + McConnectedComponent cc = connectedComponents[c]; // connected compoenent id // vertex array McSize connCompVerticesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &connCompVerticesBytes), MC_NO_ERROR); ASSERT_GT(connCompVerticesBytes, McSize(0)); - ASSERT_GE(connCompVerticesBytes, McSize(sizeof(float) * 9)); // triangle - const uint32_t numberOfVertices = (uint32_t)(connCompVerticesBytes / (sizeof(float) * 3)); + ASSERT_GE(connCompVerticesBytes, McSize(sizeof(McFloat) * 9)); // triangle + const McUint32 numberOfVertices = (McUint32)(connCompVerticesBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices*3); + std::vector vertices(numberOfVertices*3); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, connCompVerticesBytes, (void*)vertices.data(), NULL), MC_NO_ERROR); // face indices McSize connCompFaceIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE, 0, NULL, &connCompFaceIndicesBytes), MC_NO_ERROR); ASSERT_GT(connCompFaceIndicesBytes, McSize(0)); - ASSERT_GE(connCompFaceIndicesBytes, McSize(sizeof(uint32_t) * 3)); // triangle - std::vector faceIndices; - faceIndices.resize(connCompFaceIndicesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompFaceIndicesBytes, McSize(sizeof(McUint32) * 3)); // triangle + std::vector faceIndices; + faceIndices.resize(connCompFaceIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE, connCompFaceIndicesBytes, faceIndices.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)faceIndices.size(); ++v) { - ASSERT_GE((uint32_t)faceIndices[v], (uint32_t)0); - ASSERT_LT((uint32_t)faceIndices[v], numberOfVertices); // "out of bounds vertex index" + for (McInt32 v = 0; v < (McInt32)faceIndices.size(); ++v) { + ASSERT_GE((McUint32)faceIndices[v], (McUint32)0); + ASSERT_LT((McUint32)faceIndices[v], numberOfVertices); // "out of bounds vertex index" } // face sizes McSize connCompFaceSizesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &connCompFaceSizesBytes), MC_NO_ERROR); - ASSERT_GE(connCompFaceIndicesBytes, sizeof(uint32_t)); - std::vector faceSizes; - faceSizes.resize(connCompFaceSizesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompFaceIndicesBytes, sizeof(McUint32)); + std::vector faceSizes; + faceSizes.resize(connCompFaceSizesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, connCompFaceSizesBytes, faceSizes.data(), NULL), MC_NO_ERROR); ASSERT_GT(faceSizes.size(), std::size_t(0)); // "there has to be at least one face in a connected component" - for (int v = 0; v < (int)faceSizes.size(); ++v) { - ASSERT_GE(faceSizes[v], (uint32_t)3); // "3 is the minimum possible number of vertices in a polygon, which is a triangle" + for (McInt32 v = 0; v < (McInt32)faceSizes.size(); ++v) { + ASSERT_GE(faceSizes[v], (McUint32)3); // "3 is the minimum possible number of vertices in a polygon, which is a triangle" } // edge indices McSize connCompEdgesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_EDGE, 0, NULL, &connCompEdgesBytes), MC_NO_ERROR); - ASSERT_GE(connCompEdgesBytes, McSize(sizeof(uint32_t) * 6)); // triangle + ASSERT_GE(connCompEdgesBytes, McSize(sizeof(McUint32) * 6)); // triangle - std::vector edgeIndices; - edgeIndices.resize(connCompEdgesBytes / sizeof(uint32_t)); + std::vector edgeIndices; + edgeIndices.resize(connCompEdgesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_EDGE, connCompEdgesBytes, edgeIndices.data(), NULL), MC_NO_ERROR); - ASSERT_GE((uint32_t)edgeIndices.size(), (uint32_t)6); // "6 is the minimum number of indices in a triangle, which is the simplest polygon" + ASSERT_GE((McUint32)edgeIndices.size(), (McUint32)6); // "6 is the minimum number of indices in a triangle, which is the simplest polygon" - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (uint32_t)connComps.size(), connComps.data()), MC_NO_ERROR); - connComps.clear(); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (McUint32)connectedComponents.size(), connectedComponents.data()), MC_NO_ERROR); + connectedComponents.clear(); } } } diff --git a/tests/source/booleanOperation.cpp b/tests/source/booleanOperation.cpp index e7ebe20..88b8496 100644 --- a/tests/source/booleanOperation.cpp +++ b/tests/source/booleanOperation.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -29,14 +42,14 @@ struct BooleanOperation { McContext myContext = MC_NULL_HANDLE; std::vector pConnComps_; - std::vector srcMeshVertices; - std::vector meshFaceIndices; - std::vector meshFaceSizes; + std::vector srcMeshVertices; + std::vector meshFaceIndices; + std::vector meshFaceSizes; }; static void MCAPI_PTR mcDebugOutput_(McDebugSource source, McDebugType type, - unsigned int id, + unsigned McInt32 id, McDebugSeverity severity, size_t length, const char* message, @@ -144,7 +157,7 @@ UTEST_F_SETUP(BooleanOperation) UTEST_F_TEARDOWN(BooleanOperation) { - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (uint32_t)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (McUint32)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); EXPECT_EQ(mcReleaseContext(utest_fixture->myContext), MC_NO_ERROR); } @@ -152,16 +165,16 @@ UTEST_F_TEARDOWN(BooleanOperation) // pass the appropriate MC_DISPATCH_ENFORCE_GENERAL_POSITION flag. UTEST_F(BooleanOperation, selfUnionWithoutGeneralPositionEnforcement) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; const McFlags booleanUnionFlags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE; ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanUnionFlags, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_INVALID_OPERATION); } @@ -169,16 +182,16 @@ UTEST_F(BooleanOperation, selfUnionWithoutGeneralPositionEnforcement) // position enforcement. UTEST_F(BooleanOperation, selfUnionWithGeneralPositionEnforcement) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; const McFlags booleanUnionFlags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE; ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanUnionFlags | MC_DISPATCH_ENFORCE_GENERAL_POSITION, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); } @@ -186,29 +199,29 @@ UTEST_F(BooleanOperation, selfUnionWithGeneralPositionEnforcement) // position enforcement (with MC_DISPATCH_ENFORCE_GENERAL_POSITION_ABSOLUTE). UTEST_F(BooleanOperation, selfUnionWithGeneralPositionEnforcement_abs) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; const McFlags booleanUnionFlags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE; ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanUnionFlags | MC_DISPATCH_ENFORCE_GENERAL_POSITION_ABSOLUTE, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); } // Performing a Boolean "diff(A,B)" operation. UTEST_F(BooleanOperation, differenceA_Not_B) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; - std::vector cutMeshVertices = srcMeshVertices; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + std::vector cutMeshVertices = srcMeshVertices; // shifted so that the front-bottom-left vertex is located at (0,0,0) and the centre is at (1,1,1) - for (int i = 0; i < (int)cutMeshVertices.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)cutMeshVertices.size(); ++i) { cutMeshVertices[i] += 1.f; } @@ -216,25 +229,25 @@ UTEST_F(BooleanOperation, differenceA_Not_B) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanA_Not_BFlags, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(cutMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(cutMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps; + McUint32 numConnComps; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); - ASSERT_EQ(uint32_t(3), numConnComps); + ASSERT_EQ(McUint32(3), numConnComps); } UTEST_F(BooleanOperation, differenceB_Not_A) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; - std::vector cutMeshVertices = srcMeshVertices; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + std::vector cutMeshVertices = srcMeshVertices; // shifted so that the front-bottom-left vertex is located at (0,0,0) and the centre is at (1,1,1) - for (int i = 0; i < (int)cutMeshVertices.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)cutMeshVertices.size(); ++i) { cutMeshVertices[i] += 1.f; } @@ -242,25 +255,25 @@ UTEST_F(BooleanOperation, differenceB_Not_A) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanB_Not_AFlags, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(cutMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(cutMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps; + McUint32 numConnComps; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); - ASSERT_EQ(numConnComps, uint32_t(3)); + ASSERT_EQ(numConnComps, McUint32(3)); } UTEST_F(BooleanOperation, unionOp) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; - std::vector cutMeshVertices = srcMeshVertices; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + std::vector cutMeshVertices = srcMeshVertices; // shifted so that the front-bottom-left vertex is located at (0,0,0) and the centre is at (1,1,1) - for (int i = 0; i < (int)cutMeshVertices.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)cutMeshVertices.size(); ++i) { cutMeshVertices[i] += 1.f; } @@ -268,25 +281,25 @@ UTEST_F(BooleanOperation, unionOp) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanB_Not_AFlags, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(cutMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(cutMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps; + McUint32 numConnComps; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); - ASSERT_EQ(uint32_t(3), numConnComps); + ASSERT_EQ(McUint32(3), numConnComps); } UTEST_F(BooleanOperation, intersectionOp) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; - std::vector cutMeshVertices = srcMeshVertices; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + std::vector cutMeshVertices = srcMeshVertices; // shifted so that the front-bottom-left vertex is located at (0,0,0) and the centre is at (1,1,1) - for (int i = 0; i < (int)cutMeshVertices.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)cutMeshVertices.size(); ++i) { cutMeshVertices[i] += 1.f; } @@ -294,12 +307,12 @@ UTEST_F(BooleanOperation, intersectionOp) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanB_Not_AFlags, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(cutMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &cutMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(cutMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps; + McUint32 numConnComps; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); - ASSERT_EQ(numConnComps, uint32_t(3)); + ASSERT_EQ(numConnComps, McUint32(3)); } diff --git a/tests/source/computeSeams.cpp b/tests/source/computeSeams.cpp index 331c6b9..8904c56 100644 --- a/tests/source/computeSeams.cpp +++ b/tests/source/computeSeams.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -35,17 +48,17 @@ struct SeamConnectedComponent { std::vector connComps_ = {}; McContext context_ = MC_NULL_HANDLE; - float* pSrcMeshVertices = NULL; - uint32_t* pSrcMeshFaceIndices = NULL; - uint32_t* pSrcMeshFaceSizes = NULL; - uint32_t numSrcMeshVertices = 0; - uint32_t numSrcMeshFaces = 0; - - float* pCutMeshVertices = NULL; - uint32_t* pCutMeshFaceIndices = NULL; - uint32_t* pCutMeshFaceSizes = NULL; - uint32_t numCutMeshVertices = 0; - uint32_t numCutMeshFaces = 0; + McFloat* pSrcMeshVertices = NULL; + McUint32* pSrcMeshFaceIndices = NULL; + McUint32* pSrcMeshFaceSizes = NULL; + McUint32 numSrcMeshVertices = 0; + McUint32 numSrcMeshFaces = 0; + + McFloat* pCutMeshVertices = NULL; + McUint32* pCutMeshFaceIndices = NULL; + McUint32* pCutMeshFaceSizes = NULL; + McUint32 numCutMeshVertices = 0; + McUint32 numCutMeshFaces = 0; }; UTEST_F_SETUP(SeamConnectedComponent) @@ -72,7 +85,7 @@ UTEST_F_TEARDOWN(SeamConnectedComponent) if (utest_fixture->connComps_.size() > 0) { EXPECT_EQ(mcReleaseConnectedComponents( utest_fixture->context_, - (uint32_t)utest_fixture->connComps_.size(), + (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); } @@ -109,8 +122,8 @@ UTEST_F(SeamConnectedComponent, queryVertices) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; @@ -118,8 +131,8 @@ UTEST_F(SeamConnectedComponent, queryVertices) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -136,35 +149,35 @@ UTEST_F(SeamConnectedComponent, queryVertices) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, 0, NULL, &numConnComps), MC_NO_ERROR); // NOTE: there can only be a seamed mesh whose origin/parent is the cut-mesh in this test // a seam conn-comp whose origin is the cut-mesh is guarranteed to exist if the src-mesh is water-tight. // More generally, a seamed mesh is guarranteed to exist if and only if discovered seams/cut-paths are either 1) "circular" (loop) or 2) "linear" // which means that they sever/partition the respective origin (src-mesh or cut-mesh) - ASSERT_EQ(numConnComps, uint32_t(1)); + ASSERT_EQ(numConnComps, McUint32(1)); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); - for (int c = 0; c < (int)utest_fixture->connComps_.size(); ++c) { + for (McInt32 c = 0; c < (McInt32)utest_fixture->connComps_.size(); ++c) { McConnectedComponent cc = utest_fixture->connComps_[c]; // connected compoenent id // indices of the vertices which define the seam McSize connCompSeamVertexIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, 0, NULL, &connCompSeamVertexIndicesBytes), MC_NO_ERROR); - std::vector seamVertexIndices; - seamVertexIndices.resize(connCompSeamVertexIndicesBytes / sizeof(uint32_t)); + std::vector seamVertexIndices; + seamVertexIndices.resize(connCompSeamVertexIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, connCompSeamVertexIndicesBytes, seamVertexIndices.data(), NULL), MC_NO_ERROR); - for (int i = 0; i < (int)seamVertexIndices.size(); ++i) { - ASSERT_GE((uint32_t)seamVertexIndices[i], (uint32_t)0); + for (McInt32 i = 0; i < (McInt32)seamVertexIndices.size(); ++i) { + ASSERT_GE((McUint32)seamVertexIndices[i], (McUint32)0); } - ASSERT_EQ((uint32_t)seamVertexIndices.size(), 4u); // specifc to benchmark meshes used (see setup function). + ASSERT_EQ((McUint32)seamVertexIndices.size(), 4u); // specifc to benchmark meshes used (see setup function). } } @@ -177,8 +190,8 @@ UTEST_F(SeamConnectedComponent, queryOriginPartialCut) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; @@ -187,8 +200,8 @@ UTEST_F(SeamConnectedComponent, queryOriginPartialCut) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -205,14 +218,14 @@ UTEST_F(SeamConnectedComponent, queryOriginPartialCut) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, 0, NULL, &numConnComps), MC_NO_ERROR); - ASSERT_EQ(uint32_t(1), numConnComps); + ASSERT_EQ(McUint32(1), numConnComps); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); McConnectedComponent cc = utest_fixture->connComps_[0]; // connected compoenent id @@ -234,8 +247,8 @@ UTEST_F(SeamConnectedComponent, queryConnectedComponentType_CompleteCut) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -244,8 +257,8 @@ UTEST_F(SeamConnectedComponent, queryConnectedComponentType_CompleteCut) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -262,18 +275,18 @@ UTEST_F(SeamConnectedComponent, queryConnectedComponentType_CompleteCut) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, 0, NULL, &numConnComps), MC_NO_ERROR); ASSERT_EQ(numConnComps, 2u); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); bool foundSeamedMeshFromSrcMesh = false; bool foundSeamedMeshFromCutMesh = false; - for (int i = 0; i < (int)utest_fixture->connComps_.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->connComps_.size(); ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; // connected compoenent id McSeamOrigin orig = McSeamOrigin::MC_SEAM_ORIGIN_ALL; @@ -303,8 +316,8 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_CompleteCut) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -313,8 +326,8 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_CompleteCut) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -331,7 +344,7 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_CompleteCut) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_SEAM, 0, NULL, &numConnComps), MC_NO_ERROR); ASSERT_EQ(numConnComps, 2u); @@ -348,8 +361,8 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_PartialCut) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; @@ -358,8 +371,8 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_PartialCut) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -376,7 +389,7 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_PartialCut) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); ASSERT_EQ(numConnComps, 2u); // there should be no connected components besides inputs diff --git a/tests/source/concurrentSynchronizedContexts.cpp b/tests/source/concurrentSynchronizedContexts.cpp index f14a9ac..b4fbba1 100644 --- a/tests/source/concurrentSynchronizedContexts.cpp +++ b/tests/source/concurrentSynchronizedContexts.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /* This test creates multiple contexts that run in parallel. @@ -40,21 +53,21 @@ struct ConcurrentSynchronizedContexts { // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - int numCubeVertices; - int numCubeFaces; + std::vector cubeVertices; + std::vector cubeFaces; + McInt32 numCubeVertices; + McInt32 numCubeFaces; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices; - std::vector cutMeshFaces; + std::vector cutMeshFaces; - uint32_t numCutMeshVertices; - uint32_t numCutMeshFaces; + McUint32 numCutMeshVertices; + McUint32 numCutMeshFaces; }; UTEST_F_SETUP(ConcurrentSynchronizedContexts) @@ -62,9 +75,9 @@ UTEST_F_SETUP(ConcurrentSynchronizedContexts) utest_fixture->contexts.resize(std::thread::hardware_concurrency() / 2); // create the context objects - for (int i = 0; i < (int)utest_fixture->contexts.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->contexts.size(); ++i) { utest_fixture->contexts[i] = MC_NULL_HANDLE; - uint32_t helpers = ((i % 2 == 0) ? 1 : 0); + McUint32 helpers = ((i % 2 == 0) ? 1 : 0); ASSERT_EQ(mcCreateContextWithHelpers(&utest_fixture->contexts[i], MC_OUT_OF_ORDER_EXEC_MODE_ENABLE, helpers), MC_NO_ERROR); ASSERT_TRUE(utest_fixture->contexts[i] != nullptr); } @@ -121,14 +134,14 @@ UTEST_F_SETUP(ConcurrentSynchronizedContexts) UTEST_F_TEARDOWN(ConcurrentSynchronizedContexts) { - for (int i = 0; i < (int)utest_fixture->contexts.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->contexts.size(); ++i) { EXPECT_EQ(mcReleaseContext(utest_fixture->contexts[i]), MC_NO_ERROR); } } UTEST_F(ConcurrentSynchronizedContexts, sequentialDispatchCalls) { - for (int i = 0; i < (int)utest_fixture->contexts.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->contexts.size(); ++i) { McEvent dispatchEvent = MC_NULL_HANDLE; ASSERT_EQ(mcEnqueueDispatch( utest_fixture->contexts[i], @@ -217,12 +230,12 @@ UTEST_F(ConcurrentSynchronizedContexts, parallelButUnsynchronisedDispatchCalls) std::vector> futures(utest_fixture->contexts.size()); // run multiple dispatch calls in parallel! - for (int i = 0; i < (int)utest_fixture->contexts.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->contexts.size(); ++i) { futures[i] = std::async(std::launch::async, myDispatchWrapperFunc, utest_fixture->contexts[i]); } // wait for our dispatch call to finish - for (int i = 0; i < (int)utest_fixture->contexts.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->contexts.size(); ++i) { futures[i].wait(); } } \ No newline at end of file diff --git a/tests/source/createContext.cpp b/tests/source/createContext.cpp index f9e4d5f..d7b6878 100644 --- a/tests/source/createContext.cpp +++ b/tests/source/createContext.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include diff --git a/tests/source/debugCallback.cpp b/tests/source/debugCallback.cpp index 151f281..de2565a 100644 --- a/tests/source/debugCallback.cpp +++ b/tests/source/debugCallback.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -27,7 +40,7 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned int id, + unsigned McInt32 id, McDebugSeverity severity, size_t length, const char* message, @@ -91,20 +104,20 @@ struct DebugCallback { // 1. Create meshes. // ----------------- // Shape to Cut: - std::vector cubeVertices; - std::vector cubeFaces; - int numCubeVertices; - int numCubeFaces; + std::vector cubeVertices; + std::vector cubeFaces; + McInt32 numCubeVertices; + McInt32 numCubeFaces; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices; - std::vector cutMeshFaces; - uint32_t numCutMeshVertices; - uint32_t numCutMeshFaces; + std::vector cutMeshFaces; + McUint32 numCutMeshVertices; + McUint32 numCutMeshFaces; }; UTEST_F_SETUP(DebugCallback) diff --git a/tests/source/debugVerboseLog.cpp b/tests/source/debugVerboseLog.cpp index a97e244..164c871 100644 --- a/tests/source/debugVerboseLog.cpp +++ b/tests/source/debugVerboseLog.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -28,7 +41,7 @@ #if 0 static void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned int id, + unsigned McInt32 id, McDebugSeverity severity, size_t length, const char* message, @@ -93,20 +106,20 @@ struct DebugLog { // 1. Create meshes. // ----------------- // Shape to Cut: - std::vector cubeVertices; - std::vector cubeFaces; - int numCubeVertices; - int numCubeFaces; + std::vector cubeVertices; + std::vector cubeFaces; + McInt32 numCubeVertices; + McInt32 numCubeFaces; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices; - std::vector cutMeshFaces; - uint32_t numCutMeshVertices; - uint32_t numCutMeshFaces; + std::vector cutMeshFaces; + McUint32 numCutMeshVertices; + McUint32 numCutMeshFaces; }; UTEST_F_SETUP(DebugLog) diff --git a/tests/source/degenerateInput.cpp b/tests/source/degenerateInput.cpp index fb8bb8a..9aa3167 100644 --- a/tests/source/degenerateInput.cpp +++ b/tests/source/degenerateInput.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -44,23 +57,23 @@ UTEST_F_TEARDOWN(DegenerateInput) // two edges intersecting, which is not allowed (if perturbation is disabled). UTEST_F(DegenerateInput, edgeEdgeIntersection) { - std::vector srcMeshVertices = { + std::vector srcMeshVertices = { 0.f, 0.f, 0.f, 3.f, 0.f, 0.f, 0.f, 3.f, 0.f }; - std::vector srcMeshFaceIndices = { 0, 1, 2 }; - uint32_t srcMeshFaceSizes = 3; // array of one + std::vector srcMeshFaceIndices = { 0, 1, 2 }; + McUint32 srcMeshFaceSizes = 3; // array of one - std::vector cutMeshVertices = { + std::vector cutMeshVertices = { 0.f, 2.f, -1.f, 3.f, 2.f, -1.f, 0.f, 2.f, 2.f }; - std::vector cutMeshFaceIndices = { 0, 1, 2 }; - uint32_t cutMeshFaceSizes = 3; // array of one + std::vector cutMeshFaceIndices = { 0, 1, 2 }; + McUint32 cutMeshFaceSizes = 3; // array of one ASSERT_EQ(mcDispatch(utest_fixture->myContext, MC_DISPATCH_VERTEX_ARRAY_FLOAT, // &srcMeshVertices[0], &srcMeshFaceIndices[0], &srcMeshFaceSizes, 3, 1, // @@ -73,23 +86,23 @@ UTEST_F(DegenerateInput, edgeEdgeIntersection) // lies on the src-mesh triangle. (This will only work with exact arith) UTEST_F(DegenerateInput, faceVertexIntersection) { - std::vector srcMeshVertices = { + std::vector srcMeshVertices = { 0.f, 0.f, 0.f, 3.f, 0.f, 0.f, 0.f, 3.f, 0.f }; - std::vector srcMeshFaceIndices = { 0, 1, 2 }; - uint32_t srcMeshFaceSizes = 3; // array of one + std::vector srcMeshFaceIndices = { 0, 1, 2 }; + McUint32 srcMeshFaceSizes = 3; // array of one - std::vector cutMeshVertices = { + std::vector cutMeshVertices = { 1.f, 1.f, -3.f, 3.f, 1.f, -3.f, 1.f, 1.f, 0.f }; - std::vector cutMeshFaceIndices = { 0, 1, 2 }; - uint32_t cutMeshFaceSizes = 3; // array of one + std::vector cutMeshFaceIndices = { 0, 1, 2 }; + McUint32 cutMeshFaceSizes = 3; // array of one // NOTE: this test will fail due to limitations in floating point precisions // It should pass for exact numbers build @@ -104,25 +117,25 @@ UTEST_F(DegenerateInput, faceVertexIntersection) UTEST_F(DegenerateInput, faceWithZeroArea) { - std::vector srcMeshVertices = { + std::vector srcMeshVertices = { -1., -1., 0.,// 1., -1., 0.,// 1., 1., 0.,// -1., -1., 0.// }; - std::vector srcMeshFaceIndices = { 0, 1, 2, 0, 2, 3 }; - std::vector srcMeshFaceSizes = {3, 3}; + std::vector srcMeshFaceIndices = { 0, 1, 2, 0, 2, 3 }; + std::vector srcMeshFaceSizes = {3, 3}; - std::vector cutMeshVertices = { + std::vector cutMeshVertices = { -1., 0., 1.,// 2., 0., 1.,// 2., 0., -1.,// -1., 0., -1.,// }; - std::vector cutMeshFaceIndices = { 0, 1, 2 , 3}; - uint32_t cutMeshFaceSizes = 4; // array of one + std::vector cutMeshFaceIndices = { 0, 1, 2 , 3}; + McUint32 cutMeshFaceSizes = 4; // array of one ASSERT_EQ(mcDispatch(utest_fixture->myContext, MC_DISPATCH_VERTEX_ARRAY_FLOAT, // &srcMeshVertices[0], &srcMeshFaceIndices[0], &srcMeshFaceSizes[0], 4, 2, // diff --git a/tests/source/dispatchFilterFlags.cpp b/tests/source/dispatchFilterFlags.cpp index 38074fc..913d955 100644 --- a/tests/source/dispatchFilterFlags.cpp +++ b/tests/source/dispatchFilterFlags.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -35,17 +48,17 @@ struct DispatchFilterFlags { std::vector connComps_ = {}; McContext context_ = MC_NULL_HANDLE; - float* pSrcMeshVertices = NULL; - uint32_t* pSrcMeshFaceIndices = NULL; - uint32_t* pSrcMeshFaceSizes = NULL; - uint32_t numSrcMeshVertices = 0; - uint32_t numSrcMeshFaces = 0; - - float* pCutMeshVertices = NULL; - uint32_t* pCutMeshFaceIndices = NULL; - uint32_t* pCutMeshFaceSizes = NULL; - uint32_t numCutMeshVertices = 0; - uint32_t numCutMeshFaces = 0; + McFloat* pSrcMeshVertices = NULL; + McUint32* pSrcMeshFaceIndices = NULL; + McUint32* pSrcMeshFaceSizes = NULL; + McUint32 numSrcMeshVertices = 0; + McUint32 numSrcMeshFaces = 0; + + McFloat* pCutMeshVertices = NULL; + McUint32* pCutMeshFaceIndices = NULL; + McUint32* pCutMeshFaceSizes = NULL; + McUint32 numCutMeshVertices = 0; + McUint32 numCutMeshFaces = 0; }; UTEST_F_SETUP(DispatchFilterFlags) @@ -72,7 +85,7 @@ UTEST_F_TEARDOWN(DispatchFilterFlags) if (utest_fixture->connComps_.size() > 0) { EXPECT_EQ(mcReleaseConnectedComponents( utest_fixture->context_, - (int)utest_fixture->connComps_.size(), + (McInt32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); } @@ -107,8 +120,8 @@ UTEST_F(DispatchFilterFlags, noFiltering) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -117,8 +130,8 @@ UTEST_F(DispatchFilterFlags, noFiltering) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -135,13 +148,13 @@ UTEST_F(DispatchFilterFlags, noFiltering) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(uint32_t(12), numConnectedComponents); // including sealed, partially, unsealed, above, below, patches & seams + ASSERT_EQ(McUint32(12), numConnectedComponents); // including sealed, partially, unsealed, above, below, patches & seams utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (uint32_t i = 0; i < numConnectedComponents; ++i) { + for (McUint32 i = 0; i < numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); } @@ -156,8 +169,8 @@ UTEST_F(DispatchFilterFlags, partialCutWithInsideSealing) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/bunnyCuttingPlanePartial.off"; @@ -166,8 +179,8 @@ UTEST_F(DispatchFilterFlags, partialCutWithInsideSealing) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -184,13 +197,13 @@ UTEST_F(DispatchFilterFlags, partialCutWithInsideSealing) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(4)); // one completely filled (from the inside) fragment plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(4)); // one completely filled (from the inside) fragment plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (uint32_t i = 0; i < numConnectedComponents; ++i) { + for (McUint32 i = 0; i < numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -226,8 +239,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowInside) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -236,8 +249,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowInside) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -254,13 +267,13 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowInside) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one completely filled (from the inside) fragment plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one completely filled (from the inside) fragment plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (uint32_t i = 0; i < numConnectedComponents; ++i) { + for (McUint32 i = 0; i < numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -296,8 +309,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowOutside) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -306,8 +319,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowOutside) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -324,13 +337,13 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowOutside) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one completely filled (from the outside) fragment plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one completely filled (from the outside) fragment plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (uint32_t i = 0; i < numConnectedComponents; ++i) { + for (McUint32 i = 0; i < numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -363,8 +376,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowUnsealed) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -373,8 +386,8 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowUnsealed) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -391,11 +404,11 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowUnsealed) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one unsealed fragment plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one unsealed fragment plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); McConnectedComponent cc = utest_fixture->connComps_[0]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -429,8 +442,8 @@ UTEST_F(DispatchFilterFlags, patchInside) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -439,8 +452,8 @@ UTEST_F(DispatchFilterFlags, patchInside) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -457,13 +470,13 @@ UTEST_F(DispatchFilterFlags, patchInside) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one interior patch plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one interior patch plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (int i = 0; i < (int)numConnectedComponents; ++i) { + for (McInt32 i = 0; i < (McInt32)numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[0]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -487,8 +500,8 @@ UTEST_F(DispatchFilterFlags, patchOutside) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -497,8 +510,8 @@ UTEST_F(DispatchFilterFlags, patchOutside) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -515,13 +528,13 @@ UTEST_F(DispatchFilterFlags, patchOutside) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one interior patch plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one interior patch plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (int i = 0; i < (int)numConnectedComponents; ++i) { + for (McInt32 i = 0; i < (McInt32)numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -547,8 +560,8 @@ UTEST_F(DispatchFilterFlags, seamFromSrcMesh) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -557,8 +570,8 @@ UTEST_F(DispatchFilterFlags, seamFromSrcMesh) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -575,13 +588,13 @@ UTEST_F(DispatchFilterFlags, seamFromSrcMesh) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one interior patch plus input + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one interior patch plus input utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (int i = 0; i < (int)numConnectedComponents; ++i) { + for (McInt32 i = 0; i < (McInt32)numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); @@ -606,8 +619,8 @@ UTEST_F(DispatchFilterFlags, seamFromCutMesh) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; @@ -616,8 +629,8 @@ UTEST_F(DispatchFilterFlags, seamFromCutMesh) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -634,13 +647,13 @@ UTEST_F(DispatchFilterFlags, seamFromCutMesh) utest_fixture->numCutMeshFaces), MC_NO_ERROR); - uint32_t numConnectedComponents = 0; + McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); - ASSERT_EQ(numConnectedComponents, uint32_t(3)); // one interior patch plus inputs + ASSERT_EQ(numConnectedComponents, McUint32(3)); // one interior patch plus inputs utest_fixture->connComps_.resize(numConnectedComponents); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), &utest_fixture->connComps_[0], NULL), MC_NO_ERROR); - for (int i = 0; i < (int)numConnectedComponents; ++i) { + for (McInt32 i = 0; i < (McInt32)numConnectedComponents; ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; ASSERT_TRUE(cc != MC_NULL_HANDLE); diff --git a/tests/source/getContextInfo.cpp b/tests/source/getContextInfo.cpp index b296c6f..2c9bab2 100644 --- a/tests/source/getContextInfo.cpp +++ b/tests/source/getContextInfo.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include diff --git a/tests/source/getDataMaps.cpp b/tests/source/getDataMaps.cpp index ba54ef6..9aa9dcf 100644 --- a/tests/source/getDataMaps.cpp +++ b/tests/source/getDataMaps.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -39,12 +52,12 @@ struct TestConfig { struct DataMapsQueryTest { McContext context_ = MC_NULL_HANDLE; std::vector connComps_; - std::vector pSrcMeshVertices; - std::vector pSrcMeshFaceIndices; - std::vector pSrcMeshFaceSizes; - std::vector pCutMeshVertices; - std::vector pCutMeshFaceIndices; - std::vector pCutMeshFaceSizes; + std::vector pSrcMeshVertices; + std::vector pSrcMeshFaceIndices; + std::vector pSrcMeshFaceSizes; + std::vector pCutMeshVertices; + std::vector pCutMeshFaceIndices; + std::vector pCutMeshFaceSizes; McFlags dispatchflags = 0; }; @@ -72,12 +85,12 @@ TestConfig testConfigs[] = { }; void createCubeSMAndtwoTriCM( - std::vector& pSrcMeshVertices, - std::vector& pSrcMeshFaceIndices, - std::vector& pSrcMeshFaceSizes, - std::vector& pCutMeshVertices, - std::vector& pCutMeshFaceIndices, - std::vector& pCutMeshFaceSizes) + std::vector& pSrcMeshVertices, + std::vector& pSrcMeshFaceIndices, + std::vector& pSrcMeshFaceSizes, + std::vector& pCutMeshVertices, + std::vector& pCutMeshFaceIndices, + std::vector& pCutMeshFaceSizes) { // NOTE: same mesh as hello world pSrcMeshVertices = { @@ -123,12 +136,12 @@ void createCubeSMAndtwoTriCM( }; } -void CreateInputsRequiringFacePartitioning(std::vector& pSrcMeshVertices, - std::vector& pSrcMeshFaceIndices, - std::vector& pSrcMeshFaceSizes, - std::vector& pCutMeshVertices, - std::vector& pCutMeshFaceIndices, - std::vector& pCutMeshFaceSizes) +void CreateInputsRequiringFacePartitioning(std::vector& pSrcMeshVertices, + std::vector& pSrcMeshFaceIndices, + std::vector& pSrcMeshFaceSizes, + std::vector& pCutMeshVertices, + std::vector& pCutMeshFaceIndices, + std::vector& pCutMeshFaceSizes) { // NOTE: same mesh as benchmark 8 pSrcMeshVertices = { @@ -225,7 +238,7 @@ UTEST_I_TEARDOWN(DataMapsQueryTest) utest_fixture->pCutMeshVertices.clear(); utest_fixture->pCutMeshFaceIndices.clear(); utest_fixture->pCutMeshFaceSizes.clear(); - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->context_, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->context_, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); utest_fixture->connComps_.clear(); EXPECT_EQ(mcReleaseContext(utest_fixture->context_), MC_NO_ERROR); } @@ -233,10 +246,10 @@ UTEST_I_TEARDOWN(DataMapsQueryTest) UTEST_I(DataMapsQueryTest, testConfigID, NUM_TEST_CONFIGS) { - uint32_t srcMeshVertexCount = (uint32_t)utest_fixture->pSrcMeshVertices.size() / 3; - uint32_t srcMeshFaceCount = (uint32_t)utest_fixture->pSrcMeshFaceSizes.size(); - uint32_t cutMeshVertexCount = (uint32_t)utest_fixture->pCutMeshVertices.size() / 3; - uint32_t cutMeshFaceCount = (uint32_t)utest_fixture->pCutMeshFaceSizes.size(); + McUint32 srcMeshVertexCount = (McUint32)utest_fixture->pSrcMeshVertices.size() / 3; + McUint32 srcMeshFaceCount = (McUint32)utest_fixture->pSrcMeshFaceSizes.size(); + McUint32 cutMeshVertexCount = (McUint32)utest_fixture->pCutMeshVertices.size() / 3; + McUint32 cutMeshFaceCount = (McUint32)utest_fixture->pCutMeshFaceSizes.size(); ASSERT_EQ(mcDispatch( utest_fixture->context_, @@ -257,14 +270,14 @@ UTEST_I(DataMapsQueryTest, testConfigID, NUM_TEST_CONFIGS) // Now we query [all] connected components, including the input CCs // We want to ensure that we can query vertex- and face-data map for all each of them - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); - for (int i = 0; i < (int)utest_fixture->connComps_.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->connComps_.size(); ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; // connected compoenent id McConnectedComponentType type = McConnectedComponentType::MC_CONNECTED_COMPONENT_TYPE_ALL; @@ -274,47 +287,47 @@ UTEST_I(DataMapsQueryTest, testConfigID, NUM_TEST_CONFIGS) McSize numBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &numBytes), MC_NO_ERROR); - ASSERT_GT((int)numBytes, 0); - uint32_t ccVertexCount = (uint32_t)(numBytes / (sizeof(float)*3)); + ASSERT_GT((McInt32)numBytes, 0); + McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(McFloat)*3)); numBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes), MC_NO_ERROR); - ASSERT_EQ(numBytes / sizeof(uint32_t), ccVertexCount); + ASSERT_EQ(numBytes / sizeof(McUint32), ccVertexCount); - std::vector vertexMap; + std::vector vertexMap; vertexMap.resize(ccVertexCount); - ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, vertexMap.size() * sizeof(uint32_t), vertexMap.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, vertexMap.size() * sizeof(McUint32), vertexMap.data(), NULL), MC_NO_ERROR); auto testSrcMeshCC = [&]() { - for (int i = 0; i < (int)ccVertexCount; i++) { + for (McInt32 i = 0; i < (McInt32)ccVertexCount; i++) { - const uint32_t imVertexIdxRaw = vertexMap[i]; + const McUint32 imVertexIdxRaw = vertexMap[i]; bool vertexIsFromSrcMesh = (imVertexIdxRaw < srcMeshVertexCount); const bool isIntersectionPoint = (imVertexIdxRaw == MC_UNDEFINED_VALUE); if (!isIntersectionPoint) { - uint32_t imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset + McUint32 imVertexIdx = imVertexIdxRaw; // actual index value, accounting for offset if (!vertexIsFromSrcMesh) { imVertexIdx = (imVertexIdxRaw - srcMeshVertexCount); // account for offset (i.e. where the input msh is the cutmesh) - ASSERT_LT((int)imVertexIdx, (int)cutMeshVertexCount); + ASSERT_LT((McInt32)imVertexIdx, (McInt32)cutMeshVertexCount); } else { - ASSERT_LT((int)imVertexIdx, (int)srcMeshVertexCount); + ASSERT_LT((McInt32)imVertexIdx, (McInt32)srcMeshVertexCount); } } } }; auto testPatchCC = [&]() { - for (int i = 0; i < (int)ccVertexCount; i++) { - uint32_t correspondingCutMeshVertex = vertexMap[i]; + for (McInt32 i = 0; i < (McInt32)ccVertexCount; i++) { + McUint32 correspondingCutMeshVertex = vertexMap[i]; const bool isIntersectionPoint = (correspondingCutMeshVertex == MC_UNDEFINED_VALUE); if (!isIntersectionPoint) { correspondingCutMeshVertex -= srcMeshVertexCount; // account for offset - ASSERT_GE((int)correspondingCutMeshVertex, (int)0); - ASSERT_LT((int)correspondingCutMeshVertex, (int)cutMeshVertexCount); + ASSERT_GE((McInt32)correspondingCutMeshVertex, (McInt32)0); + ASSERT_LT((McInt32)correspondingCutMeshVertex, (McInt32)cutMeshVertexCount); } } }; @@ -360,31 +373,31 @@ UTEST_I(DataMapsQueryTest, testConfigID, NUM_TEST_CONFIGS) if (utest_fixture->dispatchflags & MC_DISPATCH_INCLUDE_FACE_MAP) { McSize numBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_FACE_SIZE, 0, NULL, &numBytes), MC_NO_ERROR); - uint32_t ccFaceCount = (uint32_t)(numBytes / sizeof(uint32_t)); - ASSERT_GT((int)ccFaceCount, (int)0); + McUint32 ccFaceCount = (McUint32)(numBytes / sizeof(McUint32)); + ASSERT_GT((McInt32)ccFaceCount, (McInt32)0); numBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, 0, NULL, &numBytes), MC_NO_ERROR); - ASSERT_EQ(numBytes / sizeof(uint32_t), ccFaceCount); + ASSERT_EQ(numBytes / sizeof(McUint32), ccFaceCount); - std::vector faceMap; + std::vector faceMap; faceMap.resize(ccFaceCount); - ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, faceMap.size() * sizeof(uint32_t), faceMap.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->context_, cc, MC_CONNECTED_COMPONENT_DATA_FACE_MAP, faceMap.size() * sizeof(McUint32), faceMap.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)ccFaceCount; v++) { - const uint32_t imFaceIdxRaw = faceMap[v]; + for (McInt32 v = 0; v < (McInt32)ccFaceCount; v++) { + const McUint32 imFaceIdxRaw = faceMap[v]; bool faceIsFromSrcMesh = (imFaceIdxRaw < srcMeshFaceCount); ASSERT_TRUE(imFaceIdxRaw != MC_UNDEFINED_VALUE); // all face indices are mapped! - uint32_t imFaceIdx = imFaceIdxRaw; // actual index value, accounting for offset + McUint32 imFaceIdx = imFaceIdxRaw; // actual index value, accounting for offset if (!faceIsFromSrcMesh) { imFaceIdx = (imFaceIdxRaw - srcMeshFaceCount); // account for offset - ASSERT_LT((int)imFaceIdx, (int)cutMeshFaceCount); + ASSERT_LT((McInt32)imFaceIdx, (McInt32)cutMeshFaceCount); } else { - ASSERT_LT((int)imFaceIdx, (int)srcMeshFaceCount); + ASSERT_LT((McInt32)imFaceIdx, (McInt32)srcMeshFaceCount); } } } @@ -394,12 +407,12 @@ UTEST_I(DataMapsQueryTest, testConfigID, NUM_TEST_CONFIGS) struct FaceAndVertexDataMapsQueryMissingFlagTest { McContext context_ = MC_NULL_HANDLE; std::vector connComps_; - std::vector pSrcMeshVertices; - std::vector pSrcMeshFaceIndices; - std::vector pSrcMeshFaceSizes; - std::vector pCutMeshVertices; - std::vector pCutMeshFaceIndices; - std::vector pCutMeshFaceSizes; + std::vector pSrcMeshVertices; + std::vector pSrcMeshFaceIndices; + std::vector pSrcMeshFaceSizes; + std::vector pCutMeshVertices; + std::vector pCutMeshFaceIndices; + std::vector pCutMeshFaceSizes; }; UTEST_F_SETUP(FaceAndVertexDataMapsQueryMissingFlagTest) @@ -426,7 +439,7 @@ UTEST_F_TEARDOWN(FaceAndVertexDataMapsQueryMissingFlagTest) utest_fixture->pCutMeshVertices.clear(); utest_fixture->pCutMeshFaceIndices.clear(); utest_fixture->pCutMeshFaceSizes.clear(); - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->context_, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->context_, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data()), MC_NO_ERROR); utest_fixture->connComps_.clear(); EXPECT_EQ(mcReleaseContext(utest_fixture->context_), MC_NO_ERROR); } @@ -439,24 +452,24 @@ UTEST_F(FaceAndVertexDataMapsQueryMissingFlagTest, vertexMapFlag) utest_fixture->pSrcMeshVertices.data(), utest_fixture->pSrcMeshFaceIndices.data(), utest_fixture->pSrcMeshFaceSizes.data(), - (uint32_t)utest_fixture->pSrcMeshVertices.size() / 3, - (uint32_t)utest_fixture->pSrcMeshFaceIndices.size() / 4, + (McUint32)utest_fixture->pSrcMeshVertices.size() / 3, + (McUint32)utest_fixture->pSrcMeshFaceIndices.size() / 4, utest_fixture->pCutMeshVertices.data(), utest_fixture->pCutMeshFaceIndices.data(), utest_fixture->pCutMeshFaceSizes.data(), - (uint32_t)utest_fixture->pCutMeshVertices.size() / 3, - (uint32_t)utest_fixture->pCutMeshFaceIndices.size() / 3), + (McUint32)utest_fixture->pCutMeshVertices.size() / 3, + (McUint32)utest_fixture->pCutMeshFaceIndices.size() / 3), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); - for (int i = 0; i < (int)utest_fixture->connComps_.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->connComps_.size(); ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; // connected compoenent id McSize numBytes = 0; @@ -472,24 +485,24 @@ UTEST_F(FaceAndVertexDataMapsQueryMissingFlagTest, faceMapFlag) utest_fixture->pSrcMeshVertices.data(), utest_fixture->pSrcMeshFaceIndices.data(), utest_fixture->pSrcMeshFaceSizes.data(), - (uint32_t)utest_fixture->pSrcMeshVertices.size() / 3, - (uint32_t)utest_fixture->pSrcMeshFaceIndices.size() / 4, + (McUint32)utest_fixture->pSrcMeshVertices.size() / 3, + (McUint32)utest_fixture->pSrcMeshFaceIndices.size() / 4, utest_fixture->pCutMeshVertices.data(), utest_fixture->pCutMeshFaceIndices.data(), utest_fixture->pCutMeshFaceSizes.data(), - (uint32_t)utest_fixture->pCutMeshVertices.size() / 3, - (uint32_t)utest_fixture->pCutMeshFaceIndices.size() / 3), + (McUint32)utest_fixture->pCutMeshVertices.size() / 3, + (McUint32)utest_fixture->pCutMeshFaceIndices.size() / 3), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); utest_fixture->connComps_.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)utest_fixture->connComps_.size(), utest_fixture->connComps_.data(), NULL), MC_NO_ERROR); - for (int i = 0; i < (int)utest_fixture->connComps_.size(); ++i) { + for (McInt32 i = 0; i < (McInt32)utest_fixture->connComps_.size(); ++i) { McConnectedComponent cc = utest_fixture->connComps_[i]; // connected compoenent id McSize numBytes = 0; diff --git a/tests/source/getEventInfo.cpp b/tests/source/getEventInfo.cpp index 0367c9f..76ecdf0 100644 --- a/tests/source/getEventInfo.cpp +++ b/tests/source/getEventInfo.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -31,21 +44,21 @@ struct GetEventInfo { // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - int numCubeVertices; - int numCubeFaces; + std::vector cubeVertices; + std::vector cubeFaces; + McInt32 numCubeVertices; + McInt32 numCubeFaces; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices; - std::vector cutMeshFaces; + std::vector cutMeshFaces; - uint32_t numCutMeshVertices; - uint32_t numCutMeshFaces; + McUint32 numCutMeshVertices; + McUint32 numCutMeshFaces; }; UTEST_F_SETUP(GetEventInfo) diff --git a/tests/source/intersectionType.cpp b/tests/source/intersectionType.cpp index 988b2f4..a7794c7 100644 --- a/tests/source/intersectionType.cpp +++ b/tests/source/intersectionType.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /* This test creates multiple contexts that run in parallel. @@ -88,7 +101,7 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble // front - int i = 0; + McInt32 i = 0; // v0 - bottom left verts[i++] = -h; // x verts[i++] = -h; // y @@ -131,7 +144,7 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble verts[i++] = h; // y verts[i++] = -h; // z - for (int j = 0; j < 8; ++j) + for (McInt32 j = 0; j < 8; ++j) { verts[j * 3 + 0] += translX; verts[j * 3 + 1] += translY; @@ -179,7 +192,7 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble faces[i++] = 1; m.faceSizes.resize(m.numFaces); - for (int j = 0; j < m.numFaces; ++j) + for (McInt32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } @@ -198,7 +211,7 @@ Mesh makeQuad_xz( verts.resize(m.numVertices * 3); - int i = 0; + McInt32 i = 0; verts[i++] = -h; // x verts[i++] = 0; // y @@ -216,7 +229,7 @@ Mesh makeQuad_xz( verts[i++] = 0; // y verts[i++] = -h; // z - for (int j = 0; j < 4; ++j) + for (McInt32 j = 0; j < 4; ++j) { verts[j * 3 + 0] += translX; verts[j * 3 + 1] += translY; @@ -234,7 +247,7 @@ Mesh makeQuad_xz( faces[i++] = 3; m.faceSizes.resize(m.numFaces); - for (int j = 0; j < m.numFaces; ++j) + for (McInt32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } @@ -253,7 +266,7 @@ Mesh makeQuad_xy( verts.resize(m.numVertices * 3); - int i = 0; + McInt32 i = 0; verts[i++] = -h; // x verts[i++] = h; // y @@ -271,7 +284,7 @@ Mesh makeQuad_xy( verts[i++] = -h; // y verts[i++] = 0; // z - for (int j = 0; j < 4; ++j) + for (McInt32 j = 0; j < 4; ++j) { verts[j * 3 + 0] += translX; verts[j * 3 + 1] += translY; @@ -289,7 +302,7 @@ Mesh makeQuad_xy( faces[i++] = 3; m.faceSizes.resize(m.numFaces); - for (int j = 0; j < m.numFaces; ++j) + for (McInt32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } diff --git a/tests/source/main.cpp b/tests/source/main.cpp index 6bc6535..a681d05 100644 --- a/tests/source/main.cpp +++ b/tests/source/main.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #if defined(_WIN32) #define _CRT_SECURE_NO_WARNINGS 1 @@ -26,268 +39,4 @@ #include "utest.h" -#include -#include -#include - -#if defined(_WIN32) - -// https://stackoverflow.com/questions/735126/are-there-alternate-implementations-of-gnu-getline-interface/735472#735472 -/* Modifications, public domain as well, by Antti Haapala, 11/10/17 -- Switched to getc on 5/23/19 */ -#include -#include - -// if typedef doesn't exist (msvc, blah) -typedef intptr_t ssize_t; - -ssize_t getline(char** lineptr, size_t* n, FILE* stream) -{ - size_t pos; - int c; - - if (lineptr == NULL || stream == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - c = getc(stream); - if (c == EOF) { - return -1; - } - - if (*lineptr == NULL) { - *lineptr = (char*)malloc(128); - if (*lineptr == NULL) { - return -1; - } - *n = 128; - } - - pos = 0; - while (c != EOF) { - if (pos + 1 >= *n) { - size_t new_size = *n + (*n >> 2); - if (new_size < 128) { - new_size = 128; - } - char* new_ptr = (char*)realloc(*lineptr, new_size); - if (new_ptr == NULL) { - return -1; - } - *n = new_size; - *lineptr = new_ptr; - } - - ((unsigned char*)(*lineptr))[pos++] = (unsigned char)c; - if (c == '\n') { - break; - } - c = getc(stream); - } - - (*lineptr)[pos] = '\0'; - return pos; -} -#endif // #if defined (_WIN32) - -bool readLine(FILE* file, char** lineBuf, size_t* len) -{ - while (getline(lineBuf, len, file)) { - if (strlen(*lineBuf) > 1 && (*lineBuf)[0] != '#') { - return true; - } - } - return false; -} - -extern "C" void readOFF( - const char* fpath, - float** pVertices, - unsigned int** pFaceIndices, - unsigned int** pFaceSizes, - unsigned int* numVertices, - unsigned int* numFaces) -{ - // using "rb" instead of "r" to prevent linefeed conversion - // See: https://stackoverflow.com/questions/27530636/read-text-file-in-c-with-fopen-without-linefeed-conversion - FILE* file = fopen(fpath, "rb"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - char* lineBuf = NULL; - size_t lineBufLen = 0; - bool lineOk = true; - int i = 0; - - // file header - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file header not found\n"); - exit(1); - } - - if (strstr(lineBuf, "OFF") == NULL) { - fprintf(stderr, "error: unrecognised .off file header\n"); - exit(1); - } - - // #vertices, #faces, #edges - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off element count not found\n"); - exit(1); - } - - int nedges = 0; - sscanf(lineBuf, "%d %d %d", numVertices, numFaces, &nedges); - *pVertices = (float*)malloc(sizeof(float) * (*numVertices) * 3); - *pFaceSizes = (unsigned int*)malloc(sizeof(unsigned int) * (*numFaces)); - - // vertices - for (i = 0; i < (float)(*numVertices); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off vertex not found\n"); - exit(1); - } - - float x, y, z; - sscanf(lineBuf, "%f %f %f", &x, &y, &z); - - (*pVertices)[(i * 3) + 0] = x; - (*pVertices)[(i * 3) + 1] = y; - (*pVertices)[(i * 3) + 2] = z; - } -#if _WIN64 - __int64 facesStartOffset = _ftelli64(file); -#else - long int facesStartOffset = ftell(file); -#endif - int numFaceIndices = 0; - - // faces - for (i = 0; i < (int)(*numFaces); ++i) { - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - if (n < 3) { - fprintf(stderr, "error: invalid vertex count in file %d\n", n); - exit(1); - } - - (*pFaceSizes)[i] = n; - numFaceIndices += n; - } - - (*pFaceIndices) = (unsigned int*)malloc(sizeof(unsigned int) * numFaceIndices); - -#if _WIN64 - int err = _fseeki64(file, facesStartOffset, SEEK_SET); -#else - int err = fseek(file, facesStartOffset, SEEK_SET); -#endif - if (err != 0) { - fprintf(stderr, "error: fseek failed\n"); - exit(1); - } - - int indexOffset = 0; - for (i = 0; i < (int)(*numFaces); ++i) { - - lineOk = readLine(file, &lineBuf, &lineBufLen); - - if (!lineOk) { - fprintf(stderr, "error: .off file face not found\n"); - exit(1); - } - - int n; // number of vertices in face - sscanf(lineBuf, "%d", &n); - - char* lineBufShifted = lineBuf; - int j = 0; - - while (j < n) { // parse remaining numbers on lineBuf - lineBufShifted = strstr(lineBufShifted, " ") + 1; // start of next number - - int val; - sscanf(lineBufShifted, "%d", &val); - - (*pFaceIndices)[indexOffset + j] = val; - j++; - } - - indexOffset += n; - } - - free(lineBuf); - - fclose(file); -} - -extern "C" void writeOFF( - const char* fpath, - float* pVertices, - unsigned int* pFaceIndices, - unsigned int* pFaceSizes, - unsigned int* pEdgeIndices, - unsigned int numVertices, - unsigned int numFaces, - unsigned int numEdges) -{ - FILE* file = fopen(fpath, "w"); - - if (file == NULL) { - fprintf(stderr, "error: failed to open `%s`", fpath); - exit(1); - } - - fprintf(file, "OFF\n"); - printf("skipped .off file edges %d, %p\n", numEdges, pEdgeIndices); - //numEdges; - //pEdgeIndices; - fprintf(file, "%d %d %d\n", numVertices, numFaces, 0 /*numEdges*/); - int i; - for (i = 0; i < (int)numVertices; ++i) { - float* vptr = pVertices + ((size_t)i * 3); - fprintf(file, "%f %f %f\n", vptr[0], vptr[1], vptr[2]); - } -#if 0 - for (i = 0; i < numEdges; ++i) { - unsigned int* iptr = pEdgeIndices + (i * 2); - fprintf(file, "%u %u\n", iptr[0], iptr[1]); - } -#endif - bool isTriangleMesh = (pFaceSizes == NULL); - - int faceBaseOffset = 0; - for (i = 0; i < (int)numFaces; ++i) { - unsigned int faceVertexCount = isTriangleMesh ? 3 : pFaceSizes[i]; - fprintf(file, "%d", (int)faceVertexCount); - unsigned int j; - for (j = 0; j < faceVertexCount; ++j) { - unsigned int* fptr = pFaceIndices + faceBaseOffset + j; - fprintf(file, " %d", *fptr); - } - fprintf(file, "\n"); - faceBaseOffset += faceVertexCount; - } - - fclose(file); -} - UTEST_MAIN(); diff --git a/tests/source/off.cpp b/tests/source/off.cpp deleted file mode 100644 index 6e47102..0000000 --- a/tests/source/off.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "off.h" -#include -#include -#include - -void writeOBJ(const std::string& fname, const std::vector& vertices, const std::vector& triangles) -{ - printf("writeOBJ: %s\n", fname.c_str()); - - std::ofstream file(fname); - - for(uint32_t i =0; i < (uint32_t)vertices.size(); i+=3) - { - file << "v " << vertices[i+0]<< " " << vertices[i+1] << " " << vertices[i+2]<< "\n"; - } - - for(uint32_t i =0; i < (uint32_t)triangles.size(); i+=3) - { - file << "f " << triangles[i+0]+1<< " " << triangles[i+1]+1 << " " << triangles[i+2]+1<< "\n"; - } - - file.close(); -} - - -void MCAPI_PTR mcDebugOutput(McDebugSource source, - McDebugType type, - unsigned int id, - McDebugSeverity severity, - size_t length, - const char* message, - const void* userParam) -{ - - //printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - //printf("userParam=%p\n", userParam); - - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; - break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - //printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - - } - - std::string severity_str; - - switch (severity) { - case MC_DEBUG_SEVERITY_HIGH: - severity_str = "HIGH"; - break; - case MC_DEBUG_SEVERITY_MEDIUM: - severity_str = "MEDIUM"; - break; - case MC_DEBUG_SEVERITY_LOW: - severity_str = "LOW"; - break; - case MC_DEBUG_SEVERITY_NOTIFICATION: - severity_str = "NOTIFICATION"; - break; - case MC_DEBUG_SEVERITY_ALL: - break; - } - - printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(),severity_str.c_str(), length, message); -} \ No newline at end of file diff --git a/tests/source/perturbationState.cpp b/tests/source/perturbationState.cpp index c4b3061..88b309f 100644 --- a/tests/source/perturbationState.cpp +++ b/tests/source/perturbationState.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -29,9 +42,9 @@ struct PerturbationState { McContext myContext = MC_NULL_HANDLE; std::vector pConnComps_; - std::vector srcMeshVertices; - std::vector meshFaceIndices; - std::vector meshFaceSizes; + std::vector srcMeshVertices; + std::vector meshFaceIndices; + std::vector meshFaceSizes; }; UTEST_F_SETUP(PerturbationState) @@ -65,7 +78,7 @@ UTEST_F_SETUP(PerturbationState) UTEST_F_TEARDOWN(PerturbationState) { - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (uint32_t)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (McUint32)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); EXPECT_EQ(mcReleaseContext(utest_fixture->myContext), MC_NO_ERROR); } @@ -73,16 +86,16 @@ UTEST_F_TEARDOWN(PerturbationState) // position enforcement (with MC_DISPATCH_ENFORCE_GENERAL_POSITION). UTEST_F(PerturbationState, getCCPerturbationVector) { - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; const McFlags booleanUnionFlags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE; ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanUnionFlags | MC_DISPATCH_ENFORCE_GENERAL_POSITION, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); McUint32 numCCs = 0; @@ -120,16 +133,16 @@ UTEST_F(PerturbationState, setPerturbationConstant) McDouble eps = 1.5e-5; ASSERT_EQ(mcBindState(utest_fixture->myContext, MC_CONTEXT_GENERAL_POSITION_ENFORCEMENT_CONSTANT, sizeof(McDouble), (void*)&eps), MC_NO_ERROR); - const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; - const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; - const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; + const std::vector& srcMeshVertices = utest_fixture->srcMeshVertices; + const std::vector& meshFaceIndices = utest_fixture->meshFaceIndices; + const std::vector& meshFaceSizes = utest_fixture->meshFaceSizes; const McFlags booleanUnionFlags = MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_ABOVE; ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT | booleanUnionFlags | MC_DISPATCH_ENFORCE_GENERAL_POSITION_ABSOLUTE, - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size(), // - &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (uint32_t)(srcMeshVertices.size() / 3), (uint32_t)meshFaceSizes.size()), + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size(), // + &srcMeshVertices[0], &meshFaceIndices[0], &meshFaceSizes[0], (McUint32)(srcMeshVertices.size() / 3), (McUint32)meshFaceSizes.size()), MC_NO_ERROR); McUint32 numCCs = 0; diff --git a/tests/source/polygonWithHoles.cpp b/tests/source/polygonWithHoles.cpp index e54187d..2f2334d 100644 --- a/tests/source/polygonWithHoles.cpp +++ b/tests/source/polygonWithHoles.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * Copyright (C) 2024 CutDigital Enterprise Ltd * - * License details: - * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com - * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. - * - * Author(s) : Floyd M. Chitalu - */ + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from + * + * https://www.gnu.org/licenses/lgpl-3.0.en.html. + * + * For your convenience, a copy of this License has been included in this + * repository. + * + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include @@ -34,17 +47,17 @@ struct PolygonsWithHoles { McContext context_ {}; - float* pSrcMeshVertices {}; - uint32_t* pSrcMeshFaceIndices {}; - uint32_t* pSrcMeshFaceSizes {}; - uint32_t numSrcMeshVertices{}; - uint32_t numSrcMeshFaces {}; - - float* pCutMeshVertices {}; - uint32_t* pCutMeshFaceIndices {}; - uint32_t* pCutMeshFaceSizes {}; - uint32_t numCutMeshVertices {}; - uint32_t numCutMeshFaces {}; + McFloat* pSrcMeshVertices {}; + McUint32* pSrcMeshFaceIndices {}; + McUint32* pSrcMeshFaceSizes {}; + McUint32 numSrcMeshVertices{}; + McUint32 numSrcMeshFaces {}; + + McFloat* pCutMeshVertices {}; + McUint32* pCutMeshFaceIndices {}; + McUint32* pCutMeshFaceSizes {}; + McUint32 numCutMeshVertices {}; + McUint32 numCutMeshFaces {}; }; UTEST_F_SETUP(PolygonsWithHoles) @@ -100,8 +113,8 @@ UTEST_F(PolygonsWithHoles, outputWillHaveHoles) ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((int)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numSrcMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); const std::string cutMeshPath = std::string(MESHES_DIR) + "/cube-flattened-with-holes.off"; @@ -109,8 +122,8 @@ UTEST_F(PolygonsWithHoles, outputWillHaveHoles) ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((int)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((int)utest_fixture->numCutMeshFaces, 0); + ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); + ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( utest_fixture->context_, diff --git a/tests/source/triangulation.cpp b/tests/source/triangulation.cpp index 8b8439c..bc845c8 100644 --- a/tests/source/triangulation.cpp +++ b/tests/source/triangulation.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ #include "utest.h" #include "off.h" @@ -29,9 +42,9 @@ struct Triangulation { McContext myContext = MC_NULL_HANDLE; std::vector pConnComps_; struct { - std::vector vertices; - std::vector faceIndices; - std::vector faceSizes; + std::vector vertices; + std::vector faceIndices; + std::vector faceSizes; } srcMesh, cutMesh; }; @@ -60,7 +73,7 @@ UTEST_F_SETUP(Triangulation) UTEST_F_TEARDOWN(Triangulation) { - EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (uint32_t)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); + EXPECT_EQ(mcReleaseConnectedComponents(utest_fixture->myContext, (McUint32)utest_fixture->pConnComps_.size(), utest_fixture->pConnComps_.data()), MC_NO_ERROR); EXPECT_EQ(mcReleaseContext(utest_fixture->myContext), MC_NO_ERROR); } @@ -90,11 +103,11 @@ UTEST_F(Triangulation, oneEdgePartialCut) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT, - &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (uint32_t)(utest_fixture->srcMesh.vertices.size() / 3), (uint32_t)utest_fixture->srcMesh.faceSizes.size(), // - &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (uint32_t)(utest_fixture->cutMesh.vertices.size() / 3), (uint32_t)utest_fixture->cutMesh.faceSizes.size()), + &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (McUint32)(utest_fixture->srcMesh.vertices.size() / 3), (McUint32)utest_fixture->srcMesh.faceSizes.size(), // + &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (McUint32)(utest_fixture->cutMesh.vertices.size() / 3), (McUint32)utest_fixture->cutMesh.faceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); @@ -104,36 +117,36 @@ UTEST_F(Triangulation, oneEdgePartialCut) std::vector connComps; connComps.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); // // query connected component data // - for (int c = 0; c < (int)connComps.size(); ++c) { + for (McInt32 c = 0; c < (McInt32)connComps.size(); ++c) { McConnectedComponent cc = connComps[c]; // connected compoenent id // vertex array McSize connCompVerticesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &connCompVerticesBytes), MC_NO_ERROR); ASSERT_GT(connCompVerticesBytes, McSize(0)); - ASSERT_GE(connCompVerticesBytes, McSize(sizeof(float) * 9)); // triangle - const uint32_t numberOfVertices = (uint32_t)(connCompVerticesBytes / (sizeof(float) * 3)); + ASSERT_GE(connCompVerticesBytes, McSize(sizeof(McFloat) * 9)); // triangle + const McUint32 numberOfVertices = (McUint32)(connCompVerticesBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices * 3); + std::vector vertices(numberOfVertices * 3); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, connCompVerticesBytes, (void*)vertices.data(), NULL), MC_NO_ERROR); // triangle indices McSize connCompTriIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &connCompTriIndicesBytes), MC_NO_ERROR); ASSERT_GT(connCompTriIndicesBytes, McSize(0)); - ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(uint32_t) * 3)); // triangle - std::vector triangleIndices; - triangleIndices.resize(connCompTriIndicesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(McUint32) * 3)); // triangle + std::vector triangleIndices; + triangleIndices.resize(connCompTriIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, connCompTriIndicesBytes, triangleIndices.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)triangleIndices.size(); ++v) { - ASSERT_GE((uint32_t)triangleIndices[v], (uint32_t)0); - ASSERT_LT((uint32_t)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" + for (McInt32 v = 0; v < (McInt32)triangleIndices.size(); ++v) { + ASSERT_GE((McUint32)triangleIndices[v], (McUint32)0); + ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); @@ -169,11 +182,11 @@ UTEST_F(Triangulation, twoEdgePartialCut) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT, - &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (uint32_t)(utest_fixture->srcMesh.vertices.size() / 3), (uint32_t)utest_fixture->srcMesh.faceSizes.size(), // - &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (uint32_t)(utest_fixture->cutMesh.vertices.size() / 3), (uint32_t)utest_fixture->cutMesh.faceSizes.size()), + &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (McUint32)(utest_fixture->srcMesh.vertices.size() / 3), (McUint32)utest_fixture->srcMesh.faceSizes.size(), // + &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (McUint32)(utest_fixture->cutMesh.vertices.size() / 3), (McUint32)utest_fixture->cutMesh.faceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); @@ -183,36 +196,36 @@ UTEST_F(Triangulation, twoEdgePartialCut) std::vector connComps; connComps.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); // // query connected component data // - for (int c = 0; c < (int)connComps.size(); ++c) { + for (McInt32 c = 0; c < (McInt32)connComps.size(); ++c) { McConnectedComponent cc = connComps[c]; // connected compoenent id // vertex array McSize connCompVerticesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &connCompVerticesBytes), MC_NO_ERROR); ASSERT_GT(connCompVerticesBytes, McSize(0)); - ASSERT_GE(connCompVerticesBytes, McSize(sizeof(float) * 9)); // triangle - const uint32_t numberOfVertices = (uint32_t)(connCompVerticesBytes / (sizeof(float) * 3)); + ASSERT_GE(connCompVerticesBytes, McSize(sizeof(McFloat) * 9)); // triangle + const McUint32 numberOfVertices = (McUint32)(connCompVerticesBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices * 3); + std::vector vertices(numberOfVertices * 3); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, connCompVerticesBytes, (void*)vertices.data(), NULL), MC_NO_ERROR); // triangle indices McSize connCompTriIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &connCompTriIndicesBytes), MC_NO_ERROR); ASSERT_GT(connCompTriIndicesBytes, McSize(0)); - ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(uint32_t) * 3)); // triangle - std::vector triangleIndices; - triangleIndices.resize(connCompTriIndicesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(McUint32) * 3)); // triangle + std::vector triangleIndices; + triangleIndices.resize(connCompTriIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, connCompTriIndicesBytes, triangleIndices.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)triangleIndices.size(); ++v) { - ASSERT_GE((uint32_t)triangleIndices[v], (uint32_t)0); - ASSERT_LT((uint32_t)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" + for (McInt32 v = 0; v < (McInt32)triangleIndices.size(); ++v) { + ASSERT_GE((McUint32)triangleIndices[v], (McUint32)0); + ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); @@ -255,11 +268,11 @@ UTEST_F(Triangulation, threeEdgePartialCut) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT, - &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (uint32_t)(utest_fixture->srcMesh.vertices.size() / 3), (uint32_t)utest_fixture->srcMesh.faceSizes.size(), // - &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (uint32_t)(utest_fixture->cutMesh.vertices.size() / 3), (uint32_t)utest_fixture->cutMesh.faceSizes.size()), + &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (McUint32)(utest_fixture->srcMesh.vertices.size() / 3), (McUint32)utest_fixture->srcMesh.faceSizes.size(), // + &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (McUint32)(utest_fixture->cutMesh.vertices.size() / 3), (McUint32)utest_fixture->cutMesh.faceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); @@ -269,36 +282,36 @@ UTEST_F(Triangulation, threeEdgePartialCut) std::vector connComps; connComps.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); // // query connected component data // - for (int c = 0; c < (int)connComps.size(); ++c) { + for (McInt32 c = 0; c < (McInt32)connComps.size(); ++c) { McConnectedComponent cc = connComps[c]; // connected compoenent id // vertex array McSize connCompVerticesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &connCompVerticesBytes), MC_NO_ERROR); ASSERT_GT(connCompVerticesBytes, McSize(0)); - ASSERT_GE(connCompVerticesBytes, McSize(sizeof(float) * 9)); // triangle - const uint32_t numberOfVertices = (uint32_t)(connCompVerticesBytes / (sizeof(float) * 3)); + ASSERT_GE(connCompVerticesBytes, McSize(sizeof(McFloat) * 9)); // triangle + const McUint32 numberOfVertices = (McUint32)(connCompVerticesBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices * 3); + std::vector vertices(numberOfVertices * 3); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, connCompVerticesBytes, (void*)vertices.data(), NULL), MC_NO_ERROR); // triangle indices McSize connCompTriIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &connCompTriIndicesBytes), MC_NO_ERROR); ASSERT_GT(connCompTriIndicesBytes, McSize(0)); - ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(uint32_t) * 3)); // triangle - std::vector triangleIndices; - triangleIndices.resize(connCompTriIndicesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(McUint32) * 3)); // triangle + std::vector triangleIndices; + triangleIndices.resize(connCompTriIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, connCompTriIndicesBytes, triangleIndices.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)triangleIndices.size(); ++v) { - ASSERT_GE((uint32_t)triangleIndices[v], (uint32_t)0); - ASSERT_LT((uint32_t)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" + for (McInt32 v = 0; v < (McInt32)triangleIndices.size(); ++v) { + ASSERT_GE((McUint32)triangleIndices[v], (McUint32)0); + ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); @@ -341,11 +354,11 @@ UTEST_F(Triangulation, threeEdgeVerticalPartialCut) ASSERT_EQ(mcDispatch(utest_fixture->myContext, // MC_DISPATCH_VERTEX_ARRAY_FLOAT, - &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (uint32_t)(utest_fixture->srcMesh.vertices.size() / 3), (uint32_t)utest_fixture->srcMesh.faceSizes.size(), // - &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (uint32_t)(utest_fixture->cutMesh.vertices.size() / 3), (uint32_t)utest_fixture->cutMesh.faceSizes.size()), + &utest_fixture->srcMesh.vertices[0], &utest_fixture->srcMesh.faceIndices[0], &utest_fixture->srcMesh.faceSizes[0], (McUint32)(utest_fixture->srcMesh.vertices.size() / 3), (McUint32)utest_fixture->srcMesh.faceSizes.size(), // + &utest_fixture->cutMesh.vertices[0], &utest_fixture->cutMesh.faceIndices[0], &utest_fixture->cutMesh.faceSizes[0], (McUint32)(utest_fixture->cutMesh.vertices.size() / 3), (McUint32)utest_fixture->cutMesh.faceSizes.size()), MC_NO_ERROR); - uint32_t numConnComps = 0; + McUint32 numConnComps = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnComps), MC_NO_ERROR); @@ -355,36 +368,36 @@ UTEST_F(Triangulation, threeEdgeVerticalPartialCut) std::vector connComps; connComps.resize(numConnComps); - ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (uint32_t)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); + ASSERT_EQ(mcGetConnectedComponents(utest_fixture->myContext, MC_CONNECTED_COMPONENT_TYPE_ALL, (McUint32)connComps.size(), connComps.data(), NULL), MC_NO_ERROR); // // query connected component data // - for (int c = 0; c < (int)connComps.size(); ++c) { + for (McInt32 c = 0; c < (McInt32)connComps.size(); ++c) { McConnectedComponent cc = connComps[c]; // connected compoenent id // vertex array McSize connCompVerticesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, 0, NULL, &connCompVerticesBytes), MC_NO_ERROR); ASSERT_GT(connCompVerticesBytes, McSize(0)); - ASSERT_GE(connCompVerticesBytes, McSize(sizeof(float) * 9)); // triangle - const uint32_t numberOfVertices = (uint32_t)(connCompVerticesBytes / (sizeof(float) * 3)); + ASSERT_GE(connCompVerticesBytes, McSize(sizeof(McFloat) * 9)); // triangle + const McUint32 numberOfVertices = (McUint32)(connCompVerticesBytes / (sizeof(McFloat) * 3)); - std::vector vertices(numberOfVertices * 3); + std::vector vertices(numberOfVertices * 3); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_FLOAT, connCompVerticesBytes, (void*)vertices.data(), NULL), MC_NO_ERROR); // triangle indices McSize connCompTriIndicesBytes = 0; ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &connCompTriIndicesBytes), MC_NO_ERROR); ASSERT_GT(connCompTriIndicesBytes, McSize(0)); - ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(uint32_t) * 3)); // triangle - std::vector triangleIndices; - triangleIndices.resize(connCompTriIndicesBytes / sizeof(uint32_t)); + ASSERT_GE(connCompTriIndicesBytes, McSize(sizeof(McUint32) * 3)); // triangle + std::vector triangleIndices; + triangleIndices.resize(connCompTriIndicesBytes / sizeof(McUint32)); ASSERT_EQ(mcGetConnectedComponentData(utest_fixture->myContext, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, connCompTriIndicesBytes, triangleIndices.data(), NULL), MC_NO_ERROR); - for (int v = 0; v < (int)triangleIndices.size(); ++v) { - ASSERT_GE((uint32_t)triangleIndices[v], (uint32_t)0); - ASSERT_LT((uint32_t)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" + for (McInt32 v = 0; v < (McInt32)triangleIndices.size(); ++v) { + ASSERT_GE((McUint32)triangleIndices[v], (McUint32)0); + ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); diff --git a/tests/source/userEvents.cpp b/tests/source/userEvents.cpp index 1a2e5a6..804fcab 100644 --- a/tests/source/userEvents.cpp +++ b/tests/source/userEvents.cpp @@ -1,24 +1,37 @@ -/** - * Copyright (c) 2021-2023 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ /* This test creates multiple contexts that run in parallel. @@ -41,21 +54,21 @@ struct UserEvents { // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - int numCubeVertices; - int numCubeFaces; + std::vector cubeVertices; + std::vector cubeFaces; + McInt32 numCubeVertices; + McInt32 numCubeFaces; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices; - std::vector cutMeshFaces; + std::vector cutMeshFaces; - uint32_t numCutMeshVertices; - uint32_t numCutMeshFaces; + McUint32 numCutMeshVertices; + McUint32 numCutMeshFaces; }; UTEST_F_SETUP(UserEvents) @@ -159,7 +172,7 @@ UTEST_F(UserEvents, getContext) void myCallback(McEvent event, void* data) { (void)event; - int* var = (int*)data; + McInt32* var = (McInt32*)data; *var = 42; } @@ -168,7 +181,7 @@ UTEST_F(UserEvents, setCallbackAndInvokeOnRelease) ASSERT_EQ(mcCreateUserEvent(&utest_fixture->userEvent, utest_fixture->context), McResult::MC_NO_ERROR); ASSERT_TRUE(utest_fixture->userEvent != MC_NULL_HANDLE); - int myInt(0); + McInt32 myInt(0); ASSERT_EQ(mcSetEventCallback(utest_fixture->userEvent, myCallback, (void*)&myInt), McResult::MC_NO_ERROR); ; @@ -189,7 +202,7 @@ UTEST_F(UserEvents, dependOn) auto someUserEventFunction = [](McEvent userEvent_) { // do stuff that uses use some 100ms - for (int i = 0; i < 20; ++i) { + for (McInt32 i = 0; i < 20; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } @@ -254,7 +267,7 @@ UTEST_F(UserEvents, dependOnWithError) auto someUserEventFunction = [](McEvent userEvent_) { // do stuff that uses use some 100ms - for (int i = 0; i < 10; ++i) { + for (McInt32 i = 0; i < 10; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } diff --git a/tutorials/AdjacentFaces/AdjacentFaces.cpp b/tutorials/AdjacentFaces/AdjacentFaces.cpp index 438b939..5b67312 100644 --- a/tutorials/AdjacentFaces/AdjacentFaces.cpp +++ b/tutorials/AdjacentFaces/AdjacentFaces.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * AdjacentFaces.cpp * @@ -33,10 +44,11 @@ * * Author(s): * - * Floyd M. Chitalu CutDigital Enterprise Ltd. + * Floyd M. Chitalu CutDigital Efnterprise Ltd. * **************************************************************************/ + #include "mcut/mcut.h" #include "mio/mio.h" diff --git a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp index b1e8d8b..b0a39a9 100644 --- a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp +++ b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * BasicCmdLineApp.cpp * diff --git a/tutorials/CSGBoolean/CSGBoolean.cpp b/tutorials/CSGBoolean/CSGBoolean.cpp index a702d58..d7bfe2c 100644 --- a/tutorials/CSGBoolean/CSGBoolean.cpp +++ b/tutorials/CSGBoolean/CSGBoolean.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * CSGBoolean.cpp * diff --git a/tutorials/EventCallback/EventCallback.cpp b/tutorials/EventCallback/EventCallback.cpp index 479f5f3..fb05891 100644 --- a/tutorials/EventCallback/EventCallback.cpp +++ b/tutorials/EventCallback/EventCallback.cpp @@ -1,22 +1,33 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * FaceNormals.cpp + * EventCallback.cpp * * \brief: * This tutorial shows how to call the asynchronious mcDisptach function and diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 2f18939..0275c75 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * FaceNormals.cpp * diff --git a/tutorials/HelloWorld/HelloWorld.cpp b/tutorials/HelloWorld/HelloWorld.cpp index 425a653..f536866 100644 --- a/tutorials/HelloWorld/HelloWorld.cpp +++ b/tutorials/HelloWorld/HelloWorld.cpp @@ -1,27 +1,38 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * HelloWorld.cpp + * HelloWorld.cpp * - * \brief: - * Simple "hello world" program using MCUT. + * \brief: + * Simple "hello world" program using MCUT. * - * Author(s): + * Author(s): * * Floyd M. Chitalu CutDigital Enterprise Ltd. * diff --git a/tutorials/InOutQuery/InOutQuery.cpp b/tutorials/InOutQuery/InOutQuery.cpp index 2aeadb3..18af7fa 100644 --- a/tutorials/InOutQuery/InOutQuery.cpp +++ b/tutorials/InOutQuery/InOutQuery.cpp @@ -1,23 +1,33 @@ /*************************************************************************** - * - * Copyright (C) 2023 CutDigital Enterprise Ltd + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * PlanarSectioning.cpp + * InOutQuery.cpp * * \brief: * This tutorial shows how to determine the spatial configuration that @@ -161,7 +171,7 @@ int main() mioFreeMesh(&srcMesh); mioFreeMesh(&cutMesh); - McUint32 numConnComps = 0; + McUint32 connectedComponentCount = 0; // // Query for all available connected components. @@ -172,11 +182,11 @@ int main() context, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, - &numConnComps); + &connectedComponentCount); my_assert (status == MC_NO_ERROR); - printf("have %u connected components\n", numConnComps); + printf("have %u connected components\n", connectedComponentCount); McSize bytes = 0; diff --git a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp index f35d670..5f8d1e1 100644 --- a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp +++ b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp @@ -1,21 +1,31 @@ /*************************************************************************** - * - * Copyright (C) 2023 CutDigital Enterprise Ltd + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * MultipleContextsInParallel.cpp * diff --git a/tutorials/PlanarSectioning/PlanarSectioning.cpp b/tutorials/PlanarSectioning/PlanarSectioning.cpp index 15d863a..8795be9 100644 --- a/tutorials/PlanarSectioning/PlanarSectioning.cpp +++ b/tutorials/PlanarSectioning/PlanarSectioning.cpp @@ -1,21 +1,31 @@ /*************************************************************************** - * - * Copyright (C) 2023 CutDigital Enterprise Ltd + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * PlanarSectioning.cpp * diff --git a/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp b/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp index b58fe55..b1afd59 100644 --- a/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp +++ b/tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp @@ -1,21 +1,31 @@ /*************************************************************************** - * - * Copyright (C) 2023 CutDigital Enterprise Ltd + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. * - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. + * + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * QuerySeamVerticesUnsorted.cpp * diff --git a/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp b/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp index 32b3041..27d8961 100644 --- a/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp +++ b/tutorials/QuerySeamVerticesUnsorted/QuerySeamVerticesUnsorted.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * QuerySeamVerticesUnsorted.cpp * diff --git a/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp b/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp index d578751..9b4e57a 100644 --- a/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp +++ b/tutorials/ReversedConnectedComponentFaces/ReversedConnectedComponentFaces.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * ReversedConnectedComponentFaces.cpp * diff --git a/tutorials/TextureCoordinates/README.txt b/tutorials/TextureCoordinates/README.txt deleted file mode 100644 index 1ec94c7..0000000 --- a/tutorials/TextureCoordinates/README.txt +++ /dev/null @@ -1,10 +0,0 @@ -This tutorial loads two meshes with texture coordinates and cuts them, propagating the texture coordinates to the output fragments. - -"a.obj" is the source mesh -"b.obj" is the cut mesh - -Simply compile and run - -The output will be written into the data/ folder because that is where the textures are located. - -You can view the meshes using Meshlab (https://www.meshlab.net/) or any tool that can visualise .obj files that have textures. \ No newline at end of file diff --git a/tutorials/TextureCoordinates/TextureCoordinates.cpp b/tutorials/TextureCoordinates/TextureCoordinates.cpp index 0839c16..dd514ba 100644 --- a/tutorials/TextureCoordinates/TextureCoordinates.cpp +++ b/tutorials/TextureCoordinates/TextureCoordinates.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * TextureCoordinates.cpp * diff --git a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp index 8d69bc1..e87428c 100644 --- a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp +++ b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp @@ -1,27 +1,39 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * FaceNormals.cpp + * TriangulatedFaceMaps.cpp * * \brief: - * This tutorial shows how to propagate per-triangulated-face normals (flat - * shading) from input meshes and onto the output connected component(s) after - * cutting. + * This tutorial shows how to propagate per-triangulated-face normals (flat shading) + * from input meshes and onto the output triangulated connected components after cutting. + * It essentially shows you how to query the mapping between the triangulated faces of + * an output connected component and the original/proginator face of an input mesh * * Author(s): * diff --git a/tutorials/Triangulation/Triangulation.cpp b/tutorials/Triangulation/Triangulation.cpp index f788679..be2fba8 100644 --- a/tutorials/Triangulation/Triangulation.cpp +++ b/tutorials/Triangulation/Triangulation.cpp @@ -1,22 +1,33 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * VertexNormals.cpp + * Triangulation.cpp * * \brief: * This tutorial shows how to query faces of output connected components diff --git a/tutorials/VertexNormals/VertexNormals.cpp b/tutorials/VertexNormals/VertexNormals.cpp index be7f73a..8a6a3cb 100644 --- a/tutorials/VertexNormals/VertexNormals.cpp +++ b/tutorials/VertexNormals/VertexNormals.cpp @@ -1,20 +1,31 @@ /*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * Copyright (C) 2023 CutDigital Enterprise Ltd - * Licensed under the GNU GPL License, Version 3.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * https://www.gnu.org/licenses/gpl-3.0.html. + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * For your convenience, a copy of the License has been included in this + * For your convenience, a copy of this License has been included in this * repository. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * VertexNormals.cpp * From 46f10a32e55c045b159a62cfda7a8bd96115ee0e Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Fri, 19 Jan 2024 12:06:09 +0000 Subject: [PATCH 11/23] add updated license files --- CLA | 87 +++++++ CONTRIBUTORS | 17 ++ COPYING | 674 +++++++++++++++++++++++++++++++++++++++++++++++++ COPYING.LESSER | 165 ++++++++++++ LICENSE | 28 ++ 5 files changed, 971 insertions(+) create mode 100644 CLA create mode 100644 CONTRIBUTORS create mode 100644 COPYING create mode 100644 COPYING.LESSER create mode 100644 LICENSE diff --git a/CLA b/CLA new file mode 100644 index 0000000..ca1235f --- /dev/null +++ b/CLA @@ -0,0 +1,87 @@ +# MCUT CONTRIBUTOR AGREEMENTS + +The MCUT project follows the Apache Software Foundation [model](https://apache.org/licenses/contributor-agreements.html) when handling contribution. The project relies on two agreements to accept contributions of software code and documentation from individuals and corporations, respectively. + +These agreements help achieve the goal of providing a reliable and long-lived software product through collaborative, open-source software development. In all cases, contributors retain full rights to use their original contributions for any other purpose outside of MCUT, while providing CutDigital Enterprise Ltd (copyright owner) the right to distribute and build upon their work. + +# CONTRIBUTOR LICENSE AGREEMENTS (CLA) + +## Overview + +The Individual Contributor License Agreement (ICLA) is provided below. The purpose of this agreement is to clearly define the terms under which intellectual property has been contributed to the MCUT project and thereby allow the copyright holder of the MCUT project to defend it should there be a legal dispute regarding the software. By contribution of ideas, code, or documentation to the MCUT project, a contributor acknowledges that they are bound by the terms laid out herein. The ICLA an individual signs is not tied to any employer they may have. + +The Corporate Contributor License Agreement (CCLA) is also provided below. The CCLA is available to cover contributing intellectual property via a corporation that may have been assigned as part of an employment agreement. Note that a Corporate CLA does not remove the need for every developer to acknowledge their own ICLA as an individual, which covers both contributions the corporation owns, and those it does not own. The CCLA legally binds the corporation, so a person with authority to enter into legal contracts on behalf of the corporation must acknowledge it. + +CutDigital Enterprise will not publish your personal details as a contributor in any form except possibly via the revision history in source control. + +## Individual Contributor License Agreement + +This agreement is for your protection as a Contributor as well as the protection of CutDigital Enterprise, the MCUT project and its users. It does not change your rights to use your own Contributions for any other purpose. + +Read this text carefully before making a contribution and keep a copy for your records. + +You accept and agree to the following terms and conditions for Your Contributions (present and future) that you submit to the MCUT project. In return, CutDigital Enterprise shall not use Your Contributions in a way that is contrary to the public benefit and bylaws in effect at the time of the Contribution. Except for the license granted herein to CutDigital Enterprise, You reserve all right, title, and interest in and to Your Contributions. + +1. Definitions. + +"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with CutDigital Enterprise. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to CutDigital Enterprise for inclusion in, or documentation of, any of the products owned or managed by CutDigital Enterprise (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to CutDigital Enterprise or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, CutDigital Enterprise for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." + +2. Grant of Copyright License. + +Subject to the terms and conditions of this Agreement, You hereby grant to CutDigital Enterprise a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. + +3. Grant of Patent License. + +Subject to the terms and conditions of this Agreement, You hereby grant to CutDigital Enterprise a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement forthat Contribution or Work shall terminate as of the date such litigation is filed. + +4. You represent that you are legally entitled to grant the above license. + +If your employer(s) has rights to intellectual propertythat you create that includes your Contributions, you representthat you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to CutDigital Enterprise, or that your employer has executed a separate Corporate CLA with CutDigital Enterprise. + +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). + +You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of YourContributions. + +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. + +You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + +7. Should You wish to submit work that is not Your original creation, You may submit it to CutDigital Enterprise separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". + +8. You agree to notify CutDigital Enterprise of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect. + +## Corporate Contributor License Agreement + +This version of the Agreement allows an entity (the "Corporation") to submit Contributions to the MCUT project, to authorize Contributions submitted by its designated employees, and to grant copyright and patent licenses. + +You accept and agree to the following terms and conditions for Your present and future Contributions submitted to the MCUT project. In return, the CutDigital Enterprise shall not use Your Contributions in a way that is contrary to the public benefit and bylaws in effect at the time of the Contribution. Except for the license granted herein to the CutDigital Enterprise, You reserve all right, title, and interest in and to Your Contributions. + +1. Definitions. + +"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with the CutDigital Enterprise. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"Contribution" shall mean the code, documentation or other original works of authorship expressly identified, as well as any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to the CutDigital Enterprise for inclusion in, or documentation of, any of the products owned or managed by the CutDigital Enterprise (the "Work"). For the purposes of this definition, "identified" and "submitted" mean any form of electronic, verbal, or written communication sent to the CutDigital Enterprise or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the CutDigital Enterprise for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." + +2. Grant of Copyright License. + +Subject to the terms and conditions of this Agreement, You hereby grant to the CutDigital Enterprise a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. + +3. Grant of Patent License. + +Subject to the terms and conditions of this Agreement, You hereby grant to the CutDigital Enterprise a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) were submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. + +4. You represent that You are legally entitled to grant the above license. + +You represent further that each designated employee of the Corporation is authorized to submit Contributions on behalf of the Corporation. + +5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). + +6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. + +You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, ON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + +7. Should You wish to submit work that is not Your original creation, You may submit it to CutDigital Enterprise separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limitedto, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [named here]". + +8. It is your responsibility to notify the CutDigital Enterprise when any change is required to the list of designated employees authorized to submit Contributions on behalf of the Corporation, or to the Corporation's Point of Contact with the CutDigital Enterprise. diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..e8adf65 --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,17 @@ +# CONTRIBUTORS + +This file provides the list of MCUT authors/contributors for legal purposes. +The file does not necessarily list everyone who has contributed, since in some +cases, their employer may be the copyright holder. To see the full list of +contributors, see the revision history in source control. + +## LIST + +* Floyd M. Chitalu + +# CONTRIBUTOR LICENSE AGREEMENT (CLA) + +The terms and conditions that apply to contributor of the MCUT project can be +found in the file called "CLA". By making a contribution, a contributor +acknowledges that they have read and accepted the terms and conditions therein. + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/COPYING.LESSER b/COPYING.LESSER new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/COPYING.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a3cbd7e --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +# LICENSING + +MCUT is available under an [Open Source](https://opensource.org/) license as well as a commercial license. If you want to use MCUT under the free-of-charge Open Source license then you simply have to comply to its terms. Otherwise you will need to buy a commercial license. These options protect the project's commercial value and thus make it possible for the author(s) to guarantee long term support, maintenance and further development of the code for the benefit of the project and its users. + +## Open Source License + +The Open Source license is the GNU [Lesser General Public License (v3+)](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. + +Users of code licensed under LGPL must: + +* Include a copy of the full license text and the original copyright notice +* Make available the source updates when you distribute a derivative work based on the licensed library +* License any derivative works of the library under the same or later version of the LGPL or GPL as described above + +In sum, the LGPL license gives you the right to use and copy the source code of MCUT freely. It is also possible to modify the MCUT code under the condition that the resulting modifications are released as source code under LGPL with any binary distribution of your software that uses these LGPL parts. + +## Commercial License + +The commercial license option is for users that wish to use MCUT in their products for commercial purposes but do not wish to release their software under the LGPL. You can buy a commercial license from [CutDigital Enterprise](contact@cut-digital.com). The commercial offer is adapted based on company size (number of employees). + +## Third-party attributions + +MCUT is based part on CDT (a C++ library for constrained Delaunay triangulation): +* Copyright © 2019 Leica Geosystems Technology AB +* Copyright © The CDT Contributors +* Licensed under the MPL-2.0 license. +* https://github.com/artem-ogre/CDT +* https://www.mozilla.org/en-US/MPL/2.0/FAQ/ From ad7a72325840650a4e6472d6eafe4d1d4fd50c64 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Fri, 19 Jan 2024 20:36:41 +0000 Subject: [PATCH 12/23] update test files --- CMakeLists.txt | 2 +- LICENSE => LICENSE.txt | 0 include/mcut/internal/tpool.h | 10 +- source/kernel.cpp | 76 +- tests/CMakeLists.txt | 40 +- tests/source/benchmark.cpp | 7 +- tests/source/booleanOperation.cpp | 146 ++-- tests/source/computeSeams.cpp | 402 +++++------ .../source/concurrentSynchronizedContexts.cpp | 22 +- tests/source/createContext.cpp | 72 +- tests/source/debugCallback.cpp | 26 +- tests/source/debugVerboseLog.cpp | 24 +- tests/source/dispatchFilterFlags.cpp | 662 +++++++++--------- tests/source/getEventInfo.cpp | 26 +- tests/source/intersectionType.cpp | 80 +-- tests/source/polygonWithHoles.cpp | 137 ++-- tests/source/triangulation.cpp | 36 +- tests/source/userEvents.cpp | 34 +- tutorials/CMakeLists.txt | 2 - 19 files changed, 948 insertions(+), 856 deletions(-) rename LICENSE => LICENSE.txt (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97c6537..3429985 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ if(${MCUT_BUILD_TESTS} OR ${MCUT_BUILD_TUTORIALS}) # tests # if(MCUT_BUILD_TESTS) - #add_subdirectory(tests) + add_subdirectory(tests) endif() # diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/include/mcut/internal/tpool.h b/include/mcut/internal/tpool.h index 56d5833..3ab545a 100644 --- a/include/mcut/internal/tpool.h +++ b/include/mcut/internal/tpool.h @@ -503,7 +503,7 @@ void parallel_for( min_per_thread); std::vector> futures; - futures.resize(num_threads - 1); + futures.resize((std::size_t)num_threads - 1); InputStorageIteratorType block_start = first; for (uint32_t i = 0; i < (num_threads - 1); ++i) { @@ -612,7 +612,7 @@ void parallel_partial_sum(thread_pool& pool, Iterator first, Iterator last) std::vector> previous_end_values; previous_end_values.reserve(num_threads - 1); std::vector> futures; - futures.resize(num_threads - 1); + futures.resize((std::size_t)num_threads - 1); Iterator block_start = first; @@ -689,7 +689,7 @@ Iterator parallel_find(thread_pool& pool, Iterator first, Iterator last, MatchTy std::promise result; std::atomic done_flag(false); std::vector> futures; - futures.resize(num_threads - 1); + futures.resize((std::size_t)num_threads - 1); { Iterator block_start = first; @@ -767,7 +767,7 @@ Iterator parallel_find_in_map_by_key(thread_pool& pool, Iterator first, Iterator { std::vector> futures; - futures.resize(num_threads - 1); + futures.resize((std::size_t)num_threads - 1); Iterator block_start = first; for (unsigned long i = 0; i < (num_threads - 1); ++i) { @@ -846,7 +846,7 @@ Iterator parallel_find_if(thread_pool& pool, Iterator first, Iterator last, Unar std::promise result; std::atomic done_flag(false); std::vector> futures; - futures.resize(num_threads - 1); + futures.resize((std::size_t)num_threads - 1); Iterator block_start = first; for (uint32_t i = 0; i < (num_threads - 1); ++i) { diff --git a/source/kernel.cpp b/source/kernel.cpp index 33da179..04bd7f7 100644 --- a/source/kernel.cpp +++ b/source/kernel.cpp @@ -1,24 +1,38 @@ -/** - * Copyright (c) 2021-2022 Floyd M. Chitalu. - * All rights reserved. +/*************************************************************************** + * This file is part of the MCUT project, which is comprised of a library + * for surface mesh cutting, example programs and test programs. + * + * Copyright (C) 2024 CutDigital Enterprise Ltd + * + * MCUT is dual-licensed software that is available under an Open Source + * license as well as a commercial license. The Open Source license is the + * GNU Lesser General Public License v3+ (LGPL). The commercial license + * option is for users that wish to use MCUT in their products for commercial + * purposes but do not wish to release their software under the LGPL. + * Email for further information. * - * NOTE: This file is licensed under GPL-3.0-or-later (default). - * A commercial license can be purchased from Floyd M. Chitalu. + * You may not use this file except in compliance with the License. A copy of + * the Open Source license can be obtained from * - * License details: + * https://www.gnu.org/licenses/lgpl-3.0.en.html. * - * (A) GNU General Public License ("GPL"); a copy of which you should have - * recieved with this file. - * - see also: - * (B) Commercial license. - * - email: floyd.m.chitalu@gmail.com + * For your convenience, a copy of this License has been included in this + * repository. * - * The commercial license options is for users that wish to use MCUT in - * their products for comercial purposes but do not wish to release their - * software products under the GPL license. + * MCUT is distributed in the hope that it will be useful, but THE SOFTWARE IS + * PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR + * A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Author(s) : Floyd M. Chitalu - */ + * Author(s): + * + * Floyd M. Chitalu CutDigital Enterprise Ltd. + * + **************************************************************************/ + #include #include #include @@ -36,11 +50,7 @@ #include "mcut/internal/timer.h" #include "mcut/internal/utils.h" -#ifndef LICENSE_PURCHASED -#define lmsg() printf("NOTE: MCUT is copyrighted and may not be sold or included in commercial products without a license.\n") -#else -#define lmsg() -#endif // #ifndef LICENSE_PURCHASED + namespace std { // need to declare partial and explicit specializations in every translation unit @@ -1527,7 +1537,29 @@ std::vector linear_projection_sort(const std::vector // void dispatch(output_t& output, const input_t& input) { - lmsg(); + +#ifndef LICENSE_NOTICE_ACKNOWLEDGED + const char* notice_str = R"delimiter( + *************************************************************************** + * * + * The program you are running is dependent on the MCUT library. * + * * + * Copyright (C) 2024 CutDigital Enterprise Ltd * + * * + * MCUT is dual-licensed software that is available under an Open Source * + * license as well as a Commercial license. The Open Source license is * + * the GNU Lesser General Public License v3+ (LGPL). The Commercial * + * license is for users that wish to use MCUT in their products for * + * commercial purposes but do not wish to release their software under * + * LGPL. * + * * + * Email for further information. * + * * + *************************************************************************** + )delimiter"; + + printf("%s", notice_str); +#endif // #ifndef LICENSE_NOTICE_ACKNOWLEDGED TIMESTACK_PUSH(__FUNCTION__); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index edecfb9..cff1770 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,27 +1,3 @@ -# -# Copyright (c) 2021-2022 Floyd M. Chitalu. -# All rights reserved. -# -# NOTE: This file is licensed under GPL-3.0-or-later (default). -# A commercial license can be purchased from Floyd M. Chitalu. -# -# License details: -# -# (A) GNU General Public License ("GPL"); a copy of which you should have -# recieved with this file. -# - see also: -# (B) Commercial license. -# - email: floyd.m.chitalu@gmail.com -# -# The commercial license options is for users that wish to use MCUT in -# their products for comercial purposes but do not wish to release their -# software products under the GPL license. -# -# Author(s) : Floyd M. Chitalu -# - -cmake_minimum_required(VERSION 3.10) - project(mcut_tests VERSION 1.0) find_package(Threads REQUIRED) # multi-context tests @@ -38,16 +14,11 @@ enable_testing() # # Download and unpack utest at configure time # -#download_project(PROJ utest -# GIT_REPOSITORY https://github.com/sheredom/utest.h.git -# GIT_TAG master -# ${UPDATE_DISCONNECTED_IF_AVAILABLE} -#) FetchContent_Populate( utest GIT_REPOSITORY https://github.com/sheredom/utest.h.git GIT_TAG master - GIT_PROGRESS TRUE + GIT_PROGRESS FALSE ) set(utest_include_dir ${utest_SOURCE_DIR}) @@ -67,21 +38,16 @@ add_executable( ${CMAKE_CURRENT_SOURCE_DIR}/source/getDataMaps.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/polygonWithHoles.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/triangulation.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/source/off.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/getEventInfo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/concurrentSynchronizedContexts.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/userEvents.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/perturbationState.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/intersectionType.cpp) -target_include_directories(mcut_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${MCUT_INCLUDE_DIR} ${utest_include_dir} ${libigl_include_dir} ${eigen_include_dir}) -target_link_libraries(mcut_tests PRIVATE mcut Threads::Threads) +target_include_directories(mcut_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${MCUT_INCLUDE_DIR} ${utest_include_dir} ${mio_include_dir}) +target_link_libraries(mcut_tests PRIVATE mcut mio Threads::Threads) target_compile_definitions(mcut_tests PRIVATE -DMESHES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/meshes" ) target_compile_options(mcut_tests PRIVATE ${compilation_flags}) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(mcut_tests PRIVATE -Wno-class-memaccess) # utest: warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type -endif() - -if(MCUT_BUILD_AS_SHARED_LIB) - target_compile_definitions(mcut_tests PRIVATE -DMCUT_WITH_ARBITRARY_PRECISION_NUMBERS=1 ) endif() \ No newline at end of file diff --git a/tests/source/benchmark.cpp b/tests/source/benchmark.cpp index b4b6b2b..e9a6720 100644 --- a/tests/source/benchmark.cpp +++ b/tests/source/benchmark.cpp @@ -96,6 +96,9 @@ UTEST_I_TEARDOWN(Benchmark) if (utest_index < NUMBER_OF_BENCHMARKS) { EXPECT_EQ(mcReleaseContext(utest_fixture->myContext), MC_NO_ERROR); } + + mioFreeMesh(&utest_fixture->srcMesh); + mioFreeMesh(&utest_fixture->cutMesh); } UTEST_I(Benchmark, inputID, NUMBER_OF_BENCHMARKS) @@ -158,8 +161,8 @@ UTEST_I(Benchmark, inputID, NUMBER_OF_BENCHMARKS) // // We no longer need the mem of input meshes, so we can free it! // - mioFreeMesh(&srcMesh); - mioFreeMesh(&cutMesh); + mioFreeMesh(&utest_fixture->srcMesh); + mioFreeMesh(&utest_fixture->cutMesh); McUint32 connectedComponentCount = 0; diff --git a/tests/source/booleanOperation.cpp b/tests/source/booleanOperation.cpp index 88b8496..286156b 100644 --- a/tests/source/booleanOperation.cpp +++ b/tests/source/booleanOperation.cpp @@ -47,90 +47,90 @@ struct BooleanOperation { std::vector meshFaceSizes; }; -static void MCAPI_PTR mcDebugOutput_(McDebugSource source, - McDebugType type, - unsigned McInt32 id, - McDebugSeverity severity, - size_t length, - const char* message, - const void* userParam) -{ - - //printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - //printf("userParam=%p\n", userParam); - - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; - break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - //printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - - } - - std::string severity_str; - - switch (severity) { - case MC_DEBUG_SEVERITY_HIGH: - severity_str = "HIGH"; - break; - case MC_DEBUG_SEVERITY_MEDIUM: - severity_str = "MEDIUM"; - break; - case MC_DEBUG_SEVERITY_LOW: - severity_str = "LOW"; - break; - case MC_DEBUG_SEVERITY_NOTIFICATION: - severity_str = "NOTIFICATION"; - break; - case MC_DEBUG_SEVERITY_ALL: - break; - } - - printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(), severity_str.c_str(), length, message); -} +//static void MCAPI_PTR mcDebugOutput_(McDebugSource source, +// McDebugType type, +// McInt32 id, +// McDebugSeverity severity, +// size_t length, +// const char* message, +// const void* userParam) +//{ +// +// //printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); +// //printf("userParam=%p\n", userParam); +// +// std::string debug_src; +// switch (source) { +// case MC_DEBUG_SOURCE_API: +// debug_src = "API"; +// break; +// case MC_DEBUG_SOURCE_KERNEL: +// debug_src = "KERNEL"; +// break; +// case MC_DEBUG_SOURCE_ALL: +// break; +// } +// std::string debug_type; +// switch (type) { +// case MC_DEBUG_TYPE_ERROR: +// debug_type = "ERROR"; +// break; +// case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: +// debug_type = "DEPRECATION"; +// break; +// case MC_DEBUG_TYPE_OTHER: +// //printf("Type: Other"); +// debug_type = "OTHER"; +// break; +// case MC_DEBUG_TYPE_ALL: +// break; +// +// } +// +// std::string severity_str; +// +// switch (severity) { +// case MC_DEBUG_SEVERITY_HIGH: +// severity_str = "HIGH"; +// break; +// case MC_DEBUG_SEVERITY_MEDIUM: +// severity_str = "MEDIUM"; +// break; +// case MC_DEBUG_SEVERITY_LOW: +// severity_str = "LOW"; +// break; +// case MC_DEBUG_SEVERITY_NOTIFICATION: +// severity_str = "NOTIFICATION"; +// break; +// case MC_DEBUG_SEVERITY_ALL: +// break; +// } +// +// printf("MCUT[%d:%p,%s:%s:%s:%zu] %s\n", id, userParam, debug_src.c_str(), debug_type.c_str(), severity_str.c_str(), length, message); +//} UTEST_F_SETUP(BooleanOperation) { // create with no flags (default) - EXPECT_EQ(mcCreateContext(&utest_fixture->myContext, MC_DEBUG), MC_NO_ERROR); + EXPECT_EQ(mcCreateContext(&utest_fixture->myContext, MC_NULL_HANDLE), MC_NO_ERROR); EXPECT_TRUE(utest_fixture->myContext != nullptr); - // config debug output - // ----------------------- - McSize numBytes = 0; - McFlags contextFlags; - EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes), MC_NO_ERROR); + //// config debug output + //// ----------------------- + //McSize numBytes = 0; + //McFlags contextFlags; + //EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes), MC_NO_ERROR); - EXPECT_TRUE(sizeof(McFlags) == numBytes); + //EXPECT_TRUE(sizeof(McFlags) == numBytes); - EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr), MC_NO_ERROR); + //EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr), MC_NO_ERROR); - if (contextFlags & MC_DEBUG) { - EXPECT_EQ(mcDebugMessageCallback(utest_fixture->myContext, mcDebugOutput_, nullptr), MC_NO_ERROR); - EXPECT_EQ(mcDebugMessageControl(utest_fixture->myContext, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, MC_FALSE), MC_NO_ERROR); - } + //if (contextFlags & MC_DEBUG) { + // EXPECT_EQ(mcDebugMessageCallback(utest_fixture->myContext, mcDebugOutput_, nullptr), MC_NO_ERROR); + // EXPECT_EQ(mcDebugMessageControl(utest_fixture->myContext, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, MC_FALSE), MC_NO_ERROR); + //} utest_fixture->srcMeshVertices = { -1.f, -1.f, 1.f, // 0 diff --git a/tests/source/computeSeams.cpp b/tests/source/computeSeams.cpp index 8904c56..8d69e04 100644 --- a/tests/source/computeSeams.cpp +++ b/tests/source/computeSeams.cpp @@ -35,10 +35,11 @@ #include "utest.h" #include +#include "mio/mio.h" + #include #include -#include "off.h" #ifdef _WIN32 #pragma warning(disable : 26812) // Unscoped enums from mcut.h @@ -48,17 +49,33 @@ struct SeamConnectedComponent { std::vector connComps_ = {}; McContext context_ = MC_NULL_HANDLE; - McFloat* pSrcMeshVertices = NULL; - McUint32* pSrcMeshFaceIndices = NULL; - McUint32* pSrcMeshFaceSizes = NULL; - McUint32 numSrcMeshVertices = 0; - McUint32 numSrcMeshFaces = 0; - - McFloat* pCutMeshVertices = NULL; - McUint32* pCutMeshFaceIndices = NULL; - McUint32* pCutMeshFaceSizes = NULL; - McUint32 numCutMeshVertices = 0; - McUint32 numCutMeshFaces = 0; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; }; UTEST_F_SETUP(SeamConnectedComponent) @@ -66,18 +83,6 @@ UTEST_F_SETUP(SeamConnectedComponent) McResult err = mcCreateContext(&utest_fixture->context_, 0); EXPECT_TRUE(utest_fixture->context_ != nullptr); EXPECT_EQ(err, MC_NO_ERROR); - - utest_fixture->pSrcMeshVertices = nullptr; - utest_fixture->pSrcMeshFaceIndices = nullptr; - utest_fixture->pSrcMeshFaceSizes = nullptr; - utest_fixture->numSrcMeshVertices = 0; - utest_fixture->numSrcMeshFaces = 0; - - utest_fixture->pCutMeshVertices = nullptr; - utest_fixture->pCutMeshFaceIndices = nullptr; - utest_fixture->pCutMeshFaceSizes = nullptr; - utest_fixture->numCutMeshVertices = 0; - utest_fixture->numCutMeshFaces = 0; } UTEST_F_TEARDOWN(SeamConnectedComponent) @@ -92,61 +97,52 @@ UTEST_F_TEARDOWN(SeamConnectedComponent) EXPECT_EQ(mcReleaseContext(utest_fixture->context_), MC_NO_ERROR); - if (utest_fixture->pSrcMeshVertices) - free(utest_fixture->pSrcMeshVertices); - - if (utest_fixture->pSrcMeshFaceIndices) - free(utest_fixture->pSrcMeshFaceIndices); - - if (utest_fixture->pSrcMeshFaceSizes) - free(utest_fixture->pSrcMeshFaceSizes); - - if (utest_fixture->pCutMeshVertices) - free(utest_fixture->pCutMeshVertices); - - if (utest_fixture->pCutMeshFaceIndices) - free(utest_fixture->pCutMeshFaceIndices); - - if (utest_fixture->pCutMeshFaceSizes) - free(utest_fixture->pCutMeshFaceSizes); + mioFreeMesh(&utest_fixture->srcMesh); + mioFreeMesh(&utest_fixture->cutMesh); } UTEST_F(SeamConnectedComponent, queryVertices) { // partial cut intersection between a cube and a quad - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off"; + // + // read-in the source-mesh from file + // - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); + // + // read-in the cut-mesh from file + // - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnComps = 0; @@ -183,39 +179,43 @@ UTEST_F(SeamConnectedComponent, queryVertices) UTEST_F(SeamConnectedComponent, queryOriginPartialCut) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnComps = 0; @@ -237,42 +237,43 @@ UTEST_F(SeamConnectedComponent, queryOriginPartialCut) UTEST_F(SeamConnectedComponent, queryConnectedComponentType_CompleteCut) { - // complete cut: cube and quad with two polygons - //mySetup("src-mesh014.off", "cut-mesh014.off"); - - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnComps = 0; @@ -306,42 +307,43 @@ UTEST_F(SeamConnectedComponent, queryConnectedComponentType_CompleteCut) UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_CompleteCut) { - // complete cut: cube and quad with two polygons - //mySetup("src-mesh014.off", "cut-mesh014.off"); - - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnComps = 0; @@ -352,41 +354,43 @@ UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_CompleteCut) UTEST_F(SeamConnectedComponent, dispatchRequireThroughCuts_PartialCut) { - //mySetup("src-mesh013.off", "cut-mesh013.off"); - - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh013.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh013.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_REQUIRE_THROUGH_CUTS, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_REQUIRE_THROUGH_CUTS, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnComps = 0; diff --git a/tests/source/concurrentSynchronizedContexts.cpp b/tests/source/concurrentSynchronizedContexts.cpp index b4fbba1..216d6db 100644 --- a/tests/source/concurrentSynchronizedContexts.cpp +++ b/tests/source/concurrentSynchronizedContexts.cpp @@ -53,21 +53,21 @@ struct ConcurrentSynchronizedContexts { // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - McInt32 numCubeVertices; - McInt32 numCubeFaces; + std::vector cubeVertices = {}; + std::vector cubeFaces = {}; + McInt32 numCubeVertices=0; + McInt32 numCubeFaces=0; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes = {}; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices = {}; - std::vector cutMeshFaces; + std::vector cutMeshFaces = {}; - McUint32 numCutMeshVertices; - McUint32 numCutMeshFaces; + McUint32 numCutMeshVertices=0; + McUint32 numCutMeshFaces=0; }; UTEST_F_SETUP(ConcurrentSynchronizedContexts) @@ -174,7 +174,7 @@ UTEST_F(ConcurrentSynchronizedContexts, sequentialDispatchCalls) McEventCommandExecStatus dispatchEventStatus = (McEventCommandExecStatus)MC_UNDEFINED_VALUE; ASSERT_EQ(mcGetEventInfo(dispatchEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, bytes, &dispatchEventStatus, NULL), MC_NO_ERROR); - ASSERT_TRUE(dispatchEventStatus == McEventCommandExecStatus::MC_COMPLETE); + ASSERT_TRUE(dispatchEventStatus & McEventCommandExecStatus::MC_COMPLETE); ASSERT_EQ(mcReleaseEvents(1, &dispatchEvent), MC_NO_ERROR); } @@ -222,7 +222,7 @@ UTEST_F(ConcurrentSynchronizedContexts, parallelButUnsynchronisedDispatchCalls) ASSERT_EQ(mcGetEventInfo(dispatchEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, bytes, &dispatchEventStatus, NULL), MC_NO_ERROR); } } - ASSERT_EQ(dispatchEventStatus, McEventCommandExecStatus::MC_COMPLETE); + ASSERT_TRUE(dispatchEventStatus & McEventCommandExecStatus::MC_COMPLETE); ASSERT_EQ(mcReleaseEvents(1, &dispatchEvent), MC_NO_ERROR); }; diff --git a/tests/source/createContext.cpp b/tests/source/createContext.cpp index d7b6878..7172372 100644 --- a/tests/source/createContext.cpp +++ b/tests/source/createContext.cpp @@ -35,7 +35,77 @@ #include "utest.h" #include -#include "off.h" + +static void MCAPI_PTR mcDebugOutput(McDebugSource source, + McDebugType type, + McUint32 id, + McDebugSeverity severity, + size_t length, + const char* message, + const void* userParam) +{ + + // printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); + // printf("userParam=%p\n", userParam); + + std::string debug_src; + switch(source) + { + case MC_DEBUG_SOURCE_API: + debug_src = "API"; + break; + case MC_DEBUG_SOURCE_KERNEL: + debug_src = "KERNEL"; + break; + case MC_DEBUG_SOURCE_ALL: + break; + } + std::string debug_type; + switch(type) + { + case MC_DEBUG_TYPE_ERROR: + debug_type = "ERROR"; + break; + case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + debug_type = "DEPRECATION"; + break; + case MC_DEBUG_TYPE_OTHER: + // printf("Type: Other"); + debug_type = "OTHER"; + break; + case MC_DEBUG_TYPE_ALL: + break; + } + + std::string severity_str; + + switch(severity) + { + case MC_DEBUG_SEVERITY_HIGH: + severity_str = "HIGH"; + break; + case MC_DEBUG_SEVERITY_MEDIUM: + severity_str = "MEDIUM"; + break; + case MC_DEBUG_SEVERITY_LOW: + severity_str = "LOW"; + break; + case MC_DEBUG_SEVERITY_NOTIFICATION: + severity_str = "NOTIFICATION"; + break; + case MC_DEBUG_SEVERITY_ALL: + break; + } + + printf("callback: [%d:%p,%s:%s:%s:%zu] %s\n", + id, + userParam, + debug_src.c_str(), + debug_type.c_str(), + severity_str.c_str(), + length, + message); +} UTEST(CreateContext, noFlags) { diff --git a/tests/source/debugCallback.cpp b/tests/source/debugCallback.cpp index de2565a..c0ae328 100644 --- a/tests/source/debugCallback.cpp +++ b/tests/source/debugCallback.cpp @@ -40,7 +40,7 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned McInt32 id, + McUint32 id, McDebugSeverity severity, size_t length, const char* message, @@ -100,24 +100,24 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, } struct DebugCallback { - McContext context_; + McContext context_ = MC_NULL_HANDLE; // 1. Create meshes. // ----------------- // Shape to Cut: - std::vector cubeVertices; - std::vector cubeFaces; - McInt32 numCubeVertices; - McInt32 numCubeFaces; + std::vector cubeVertices = {}; + std::vector cubeFaces = {}; + McInt32 numCubeVertices=0; + McInt32 numCubeFaces=0; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes = {}; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices = {}; - std::vector cutMeshFaces; - McUint32 numCutMeshVertices; - McUint32 numCutMeshFaces; + std::vector cutMeshFaces = {}; + McUint32 numCutMeshVertices=0; + McUint32 numCutMeshFaces=0; }; UTEST_F_SETUP(DebugCallback) @@ -190,7 +190,7 @@ UTEST_F(DebugCallback, MessageControl_EnableAll) // config debug output // ----------------------- McSize numBytes = 0; - McFlags contextFlags; + McFlags contextFlags = 0; ASSERT_EQ(MC_NO_ERROR, mcGetInfo(utest_fixture->context_, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes)); ASSERT_EQ(sizeof(McFlags), numBytes); @@ -217,7 +217,7 @@ UTEST_F(DebugCallback, MessageControl_EnableOnlySevereErrors) // config debug output // ----------------------- McSize numBytes = 0; - McFlags contextFlags; + McFlags contextFlags =0; ASSERT_EQ(MC_NO_ERROR, mcGetInfo(utest_fixture->context_, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes)); ASSERT_EQ(sizeof(McFlags), numBytes); diff --git a/tests/source/debugVerboseLog.cpp b/tests/source/debugVerboseLog.cpp index 164c871..39854cd 100644 --- a/tests/source/debugVerboseLog.cpp +++ b/tests/source/debugVerboseLog.cpp @@ -41,7 +41,7 @@ #if 0 static void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, - unsigned McInt32 id, + McUint32 id, McDebugSeverity severity, size_t length, const char* message, @@ -102,24 +102,24 @@ static void MCAPI_PTR mcDebugOutput(McDebugSource source, #endif struct DebugLog { - McContext context_; + McContext context_ = MC_NULL_HANDLE; // 1. Create meshes. // ----------------- // Shape to Cut: - std::vector cubeVertices; - std::vector cubeFaces; - McInt32 numCubeVertices; - McInt32 numCubeFaces; + std::vector cubeVertices = {}; + std::vector cubeFaces = {}; + McInt32 numCubeVertices=0; + McInt32 numCubeFaces=0; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes = {}; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices = {}; - std::vector cutMeshFaces; - McUint32 numCutMeshVertices; - McUint32 numCutMeshFaces; + std::vector cutMeshFaces = {}; + McUint32 numCutMeshVertices=0; + McUint32 numCutMeshFaces=0; }; UTEST_F_SETUP(DebugLog) @@ -192,7 +192,7 @@ UTEST_F(DebugLog, MessageControl_EnableAll) // config debug output // ----------------------- McSize numBytes = 0; - McFlags contextFlags; + McFlags contextFlags = 0; ASSERT_EQ(MC_NO_ERROR, mcGetInfo(utest_fixture->context_, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes)); ASSERT_EQ(sizeof(McFlags), numBytes); diff --git a/tests/source/dispatchFilterFlags.cpp b/tests/source/dispatchFilterFlags.cpp index 913d955..ae5447d 100644 --- a/tests/source/dispatchFilterFlags.cpp +++ b/tests/source/dispatchFilterFlags.cpp @@ -35,11 +35,11 @@ #include "utest.h" #include +#include "mio/mio.h" + #include #include -#include "off.h" - #ifdef _WIN32 #pragma warning(disable : 26812) // Unscoped enums from mcut.h #endif // _WIN32 @@ -48,17 +48,33 @@ struct DispatchFilterFlags { std::vector connComps_ = {}; McContext context_ = MC_NULL_HANDLE; - McFloat* pSrcMeshVertices = NULL; - McUint32* pSrcMeshFaceIndices = NULL; - McUint32* pSrcMeshFaceSizes = NULL; - McUint32 numSrcMeshVertices = 0; - McUint32 numSrcMeshFaces = 0; - - McFloat* pCutMeshVertices = NULL; - McUint32* pCutMeshFaceIndices = NULL; - McUint32* pCutMeshFaceSizes = NULL; - McUint32 numCutMeshVertices = 0; - McUint32 numCutMeshFaces = 0; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; }; UTEST_F_SETUP(DispatchFilterFlags) @@ -66,18 +82,6 @@ UTEST_F_SETUP(DispatchFilterFlags) McResult err = mcCreateContext(&utest_fixture->context_, 0); EXPECT_TRUE(utest_fixture->context_ != NULL); EXPECT_EQ(err, MC_NO_ERROR); - - utest_fixture->pSrcMeshVertices = NULL; - utest_fixture->pSrcMeshFaceIndices = NULL; - utest_fixture->pSrcMeshFaceSizes = NULL; - utest_fixture->numSrcMeshVertices = 0; - utest_fixture->numSrcMeshFaces = 0; - - utest_fixture->pCutMeshVertices = NULL; - utest_fixture->pCutMeshFaceIndices = NULL; - utest_fixture->pCutMeshFaceSizes = NULL; - utest_fixture->numCutMeshVertices = 0; - utest_fixture->numCutMeshFaces = 0; } UTEST_F_TEARDOWN(DispatchFilterFlags) @@ -92,61 +96,49 @@ UTEST_F_TEARDOWN(DispatchFilterFlags) EXPECT_EQ(mcReleaseContext(utest_fixture->context_), MC_NO_ERROR); - if (utest_fixture->pSrcMeshVertices) - free(utest_fixture->pSrcMeshVertices); - - if (utest_fixture->pSrcMeshFaceIndices) - free(utest_fixture->pSrcMeshFaceIndices); - - if (utest_fixture->pSrcMeshFaceSizes) - free(utest_fixture->pSrcMeshFaceSizes); - - if (utest_fixture->pCutMeshVertices) - free(utest_fixture->pCutMeshVertices); - - if (utest_fixture->pCutMeshFaceIndices) - free(utest_fixture->pCutMeshFaceIndices); - - if (utest_fixture->pCutMeshFaceSizes) - free(utest_fixture->pCutMeshFaceSizes); + mioFreeMesh(&utest_fixture->srcMesh); + mioFreeMesh(&utest_fixture->cutMesh); } UTEST_F(DispatchFilterFlags, noFiltering) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); - - ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), - MC_NO_ERROR); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); + + ASSERT_EQ(mcDispatch(utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), + MC_NO_ERROR); McUint32 numConnectedComponents = 0; ASSERT_EQ(mcGetConnectedComponents(utest_fixture->context_, MC_CONNECTED_COMPONENT_TYPE_ALL, 0, NULL, &numConnectedComponents), MC_NO_ERROR); @@ -162,39 +154,43 @@ UTEST_F(DispatchFilterFlags, noFiltering) UTEST_F(DispatchFilterFlags, partialCutWithInsideSealing) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/bunny.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/bunnyCuttingPlanePartial.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/bunny.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/bunnyCuttingPlanePartial.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_UNDEFINED | MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_UNDEFINED | MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -232,39 +228,43 @@ UTEST_F(DispatchFilterFlags, partialCutWithInsideSealing) UTEST_F(DispatchFilterFlags, fragmentLocationBelowInside) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_INSIDE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -302,39 +302,43 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowInside) UTEST_F(DispatchFilterFlags, fragmentLocationBelowOutside) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( - utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + utest_fixture->context_, + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_OUTSIDE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -369,39 +373,43 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowOutside) UTEST_F(DispatchFilterFlags, fragmentLocationBelowUnsealed) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_NONE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_FRAGMENT_LOCATION_BELOW | MC_DISPATCH_FILTER_FRAGMENT_SEALING_NONE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -435,39 +443,43 @@ UTEST_F(DispatchFilterFlags, fragmentLocationBelowUnsealed) UTEST_F(DispatchFilterFlags, patchInside) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_PATCH_INSIDE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_PATCH_INSIDE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -493,39 +505,43 @@ UTEST_F(DispatchFilterFlags, patchInside) UTEST_F(DispatchFilterFlags, patchOutside) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_PATCH_OUTSIDE, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_PATCH_OUTSIDE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -553,39 +569,43 @@ UTEST_F(DispatchFilterFlags, patchOutside) UTEST_F(DispatchFilterFlags, seamFromSrcMesh) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_SEAM_SRCMESH, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_SEAM_SRCMESH, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; @@ -612,39 +632,43 @@ UTEST_F(DispatchFilterFlags, seamFromSrcMesh) UTEST_F(DispatchFilterFlags, seamFromCutMesh) { - const std::string srcMeshPath = std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/src-mesh014.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/benchmarks/cut-mesh014.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT | MC_DISPATCH_FILTER_SEAM_CUTMESH, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE | MC_DISPATCH_FILTER_SEAM_CUTMESH, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_NO_ERROR); McUint32 numConnectedComponents = 0; diff --git a/tests/source/getEventInfo.cpp b/tests/source/getEventInfo.cpp index 76ecdf0..d0537f4 100644 --- a/tests/source/getEventInfo.cpp +++ b/tests/source/getEventInfo.cpp @@ -38,27 +38,27 @@ #include struct GetEventInfo { - McContext context_; + McContext context_ = MC_NULL_HANDLE; // // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - McInt32 numCubeVertices; - McInt32 numCubeFaces; + std::vector cubeVertices = {}; + std::vector cubeFaces = {}; + McInt32 numCubeVertices=0; + McInt32 numCubeFaces=0; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes = {}; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices = {}; - std::vector cutMeshFaces; + std::vector cutMeshFaces = {}; - McUint32 numCutMeshVertices; - McUint32 numCutMeshFaces; + McUint32 numCutMeshVertices=0; + McUint32 numCutMeshFaces=0; }; UTEST_F_SETUP(GetEventInfo) @@ -154,9 +154,9 @@ UTEST_F(GetEventInfo, mcEnqueueDispatchAPI) // can be any because task runs asynchronously ASSERT_TRUE( - dispatchEventStatus == MC_SUBMITTED || // - dispatchEventStatus == MC_RUNNING || // - dispatchEventStatus == MC_COMPLETE); + dispatchEventStatus & MC_SUBMITTED || // + dispatchEventStatus & MC_RUNNING || // + dispatchEventStatus & MC_COMPLETE); } // diff --git a/tests/source/intersectionType.cpp b/tests/source/intersectionType.cpp index a7794c7..f190333 100644 --- a/tests/source/intersectionType.cpp +++ b/tests/source/intersectionType.cpp @@ -47,18 +47,18 @@ #include struct Mesh { - std::vector vertices; - std::vector faceIndices; - std::vector faceSizes; - McUint32 numVertices; - McUint32 numFaces; + std::vector vertices = {}; + std::vector faceIndices = {}; + std::vector faceSizes = {}; + McUint32 numVertices=0; + McUint32 numFaces=0; }; struct IntersectionType { - McContext context; + McContext context = MC_NULL_HANDLE; - Mesh srcMesh; - Mesh cutMesh; + Mesh srcMesh = {}; + Mesh cutMesh = {}; }; UTEST_F_SETUP(IntersectionType) @@ -81,7 +81,7 @@ UTEST_F(IntersectionType, defaultValue) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); // we have not yet called the dispatch function to the value should be undefined i.e. MC_DISPATCH_INTERSECTION_TYPE_MAX_ENUM @@ -97,7 +97,7 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble m.numFaces = 6; std::vector& verts = m.vertices; - verts.resize(m.numVertices*3); + verts.resize((McSize)m.numVertices*3); // front @@ -146,13 +146,13 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble for (McInt32 j = 0; j < 8; ++j) { - verts[j * 3 + 0] += translX; - verts[j * 3 + 1] += translY; - verts[j * 3 + 2] += translZ; + verts[(McSize)j * 3 + 0] += translX; + verts[(McSize)j * 3 + 1] += translY; + verts[(McSize)j * 3 + 2] += translZ; } std::vector& faces = m.faceIndices; - faces.resize(m.numFaces *4); + faces.resize((McSize)m.numFaces * 4); i = 0; // front @@ -192,7 +192,7 @@ Mesh makeCube(McDouble halfExtent, McDouble translX, McDouble translY, McDouble faces[i++] = 1; m.faceSizes.resize(m.numFaces); - for (McInt32 j = 0; j < m.numFaces; ++j) + for (McUint32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } @@ -209,7 +209,7 @@ Mesh makeQuad_xz( m.numFaces = 1; std::vector& verts = m.vertices; - verts.resize(m.numVertices * 3); + verts.resize((McSize)m.numVertices * 3); McInt32 i = 0; @@ -231,13 +231,13 @@ Mesh makeQuad_xz( for (McInt32 j = 0; j < 4; ++j) { - verts[j * 3 + 0] += translX; - verts[j * 3 + 1] += translY; - verts[j * 3 + 2] += translZ; + verts[(McSize)j * 3 + 0] += translX; + verts[(McSize)j * 3 + 1] += translY; + verts[(McSize)j * 3 + 2] += translZ; } std::vector& faces = m.faceIndices; - faces.resize(m.numFaces * 4); + faces.resize((McSize)m.numFaces * 4); i = 0; // front @@ -247,7 +247,7 @@ Mesh makeQuad_xz( faces[i++] = 3; m.faceSizes.resize(m.numFaces); - for (McInt32 j = 0; j < m.numFaces; ++j) + for(McUint32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } @@ -264,7 +264,7 @@ Mesh makeQuad_xy( m.numFaces = 1; std::vector& verts = m.vertices; - verts.resize(m.numVertices * 3); + verts.resize((McSize)m.numVertices * 3); McInt32 i = 0; @@ -286,13 +286,13 @@ Mesh makeQuad_xy( for (McInt32 j = 0; j < 4; ++j) { - verts[j * 3 + 0] += translX; - verts[j * 3 + 1] += translY; - verts[j * 3 + 2] += translZ; + verts[(McSize)j * 3 + 0] += translX; + verts[(McSize)j * 3 + 1] += translY; + verts[(McSize)j * 3 + 2] += translZ; } std::vector& faces = m.faceIndices; - faces.resize(m.numFaces * 4); + faces.resize((McSize)m.numFaces * 4); i = 0; // front @@ -302,7 +302,7 @@ Mesh makeQuad_xy( faces[i++] = 3; m.faceSizes.resize(m.numFaces); - for (McInt32 j = 0; j < m.numFaces; ++j) + for(McUint32 j = 0; j < m.numFaces; ++j) { m.faceSizes[j] = 4; } @@ -338,7 +338,7 @@ UTEST_F(IntersectionType, watertightCutMeshInsideWatertightSourceMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH); @@ -372,7 +372,7 @@ UTEST_F(IntersectionType, watertightSourceMeshInsideWatertightCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH); @@ -406,7 +406,7 @@ UTEST_F(IntersectionType, separatedWatertightSourceMeshAndWatertightCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE); @@ -440,7 +440,7 @@ UTEST_F(IntersectionType, stdIntersectionWatertightSourceMeshAndWatertightCutMes ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD); @@ -474,7 +474,7 @@ UTEST_F(IntersectionType, stdIntersectionWatertightSourceMeshAndWatertightCutMes ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD); @@ -511,7 +511,7 @@ UTEST_F(IntersectionType, separatedWatertightSourceMeshAndOpenCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE); @@ -545,7 +545,7 @@ UTEST_F(IntersectionType, openCutMeshInsideWatertightSourceMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_SOURCEMESH); @@ -579,7 +579,7 @@ UTEST_F(IntersectionType, openCutMeshIntersectsWatertightSourceMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD); @@ -613,7 +613,7 @@ UTEST_F(IntersectionType, watertightCutMeshIntersectsOpenSourceMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD); @@ -647,7 +647,7 @@ UTEST_F(IntersectionType, openSourceMeshInsidewatertightCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_INSIDE_CUTMESH); @@ -681,7 +681,7 @@ UTEST_F(IntersectionType, separatedOpenSourceMeshAndWatertightCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE); @@ -720,7 +720,7 @@ UTEST_F(IntersectionType, separatedOpenSourceMeshAndOpenCutMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_NONE); @@ -754,7 +754,7 @@ UTEST_F(IntersectionType, openCutMeshIntersectsOpenSourceMesh) ASSERT_EQ(bytes, sizeof(McDispatchIntersectionType)); - McDispatchIntersectionType value; + McDispatchIntersectionType value = (McDispatchIntersectionType)0; ASSERT_EQ(mcGetInfo(utest_fixture->context, MC_CONTEXT_DISPATCH_INTERSECTION_TYPE, bytes, &value, 0), MC_NO_ERROR); ASSERT_EQ(value, McDispatchIntersectionType::MC_DISPATCH_INTERSECTION_TYPE_STANDARD); diff --git a/tests/source/polygonWithHoles.cpp b/tests/source/polygonWithHoles.cpp index 2f2334d..ce34060 100644 --- a/tests/source/polygonWithHoles.cpp +++ b/tests/source/polygonWithHoles.cpp @@ -35,11 +35,11 @@ #include "utest.h" #include +#include "mio/mio.h" + #include #include -#include "off.h" - #ifdef _WIN32 #pragma warning(disable : 26812) // Unscoped enums from mcut.h #endif // _WIN32 @@ -47,17 +47,33 @@ struct PolygonsWithHoles { McContext context_ {}; - McFloat* pSrcMeshVertices {}; - McUint32* pSrcMeshFaceIndices {}; - McUint32* pSrcMeshFaceSizes {}; - McUint32 numSrcMeshVertices{}; - McUint32 numSrcMeshFaces {}; - - McFloat* pCutMeshVertices {}; - McUint32* pCutMeshFaceIndices {}; - McUint32* pCutMeshFaceSizes {}; - McUint32 numCutMeshVertices {}; - McUint32 numCutMeshFaces {}; + MioMesh srcMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; + + MioMesh cutMesh = { + nullptr, // pVertices + nullptr, // pNormals + nullptr, // pTexCoords + nullptr, // pFaceSizes + nullptr, // pFaceVertexIndices + nullptr, // pFaceVertexTexCoordIndices + nullptr, // pFaceVertexNormalIndices + 0, // numVertices + 0, // numNormals + 0, // numTexCoords + 0, // numFaces + }; }; UTEST_F_SETUP(PolygonsWithHoles) @@ -65,78 +81,57 @@ UTEST_F_SETUP(PolygonsWithHoles) McResult err = mcCreateContext(&utest_fixture->context_, 0); EXPECT_TRUE(utest_fixture->context_ != nullptr); EXPECT_EQ(err, MC_NO_ERROR); - - utest_fixture->pSrcMeshVertices = nullptr; - utest_fixture->pSrcMeshFaceIndices = nullptr; - utest_fixture->pSrcMeshFaceSizes = nullptr; - utest_fixture->numSrcMeshVertices = 0; - utest_fixture->numSrcMeshFaces = 0; - - utest_fixture->pCutMeshVertices = nullptr; - utest_fixture->pCutMeshFaceIndices = nullptr; - utest_fixture->pCutMeshFaceSizes = nullptr; - utest_fixture->numCutMeshVertices = 0; - utest_fixture->numCutMeshFaces = 0; } UTEST_F_TEARDOWN(PolygonsWithHoles) { EXPECT_EQ(mcReleaseContext(utest_fixture->context_), MC_NO_ERROR); - if (utest_fixture->pSrcMeshVertices) - free(utest_fixture->pSrcMeshVertices); - - if (utest_fixture->pSrcMeshFaceIndices) - free(utest_fixture->pSrcMeshFaceIndices); - - if (utest_fixture->pSrcMeshFaceSizes) - free(utest_fixture->pSrcMeshFaceSizes); - - if (utest_fixture->pCutMeshVertices) - free(utest_fixture->pCutMeshVertices); - - if (utest_fixture->pCutMeshFaceIndices) - free(utest_fixture->pCutMeshFaceIndices); - - if (utest_fixture->pCutMeshFaceSizes) - free(utest_fixture->pCutMeshFaceSizes); + mioFreeMesh(&utest_fixture->srcMesh); + mioFreeMesh(&utest_fixture->cutMesh); } UTEST_F(PolygonsWithHoles, outputWillHaveHoles) { // partial cut intersection between a cube and a quad - const std::string srcMeshPath = std::string(MESHES_DIR) + "/cube-flattened.off"; - - readOFF(srcMeshPath.c_str(), &utest_fixture->pSrcMeshVertices, &utest_fixture->pSrcMeshFaceIndices, &utest_fixture->pSrcMeshFaceSizes, &utest_fixture->numSrcMeshVertices, &utest_fixture->numSrcMeshFaces); - - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pSrcMeshVertices != nullptr); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numSrcMeshFaces, 0); - - const std::string cutMeshPath = std::string(MESHES_DIR) + "/cube-flattened-with-holes.off"; - - readOFF(cutMeshPath.c_str(), &utest_fixture->pCutMeshVertices, &utest_fixture->pCutMeshFaceIndices, &utest_fixture->pCutMeshFaceSizes, &utest_fixture->numCutMeshVertices, &utest_fixture->numCutMeshFaces); - ASSERT_TRUE(utest_fixture->pCutMeshVertices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceIndices != nullptr); - ASSERT_TRUE(utest_fixture->pCutMeshFaceSizes != nullptr); - ASSERT_GT((McInt32)utest_fixture->numCutMeshVertices, 2); - ASSERT_GT((McInt32)utest_fixture->numCutMeshFaces, 0); + + // + // read-in the source-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/cube-flattened.off").c_str(), + &utest_fixture->srcMesh.pVertices, + &utest_fixture->srcMesh.pFaceVertexIndices, + &utest_fixture->srcMesh.pFaceSizes, + &utest_fixture->srcMesh.numVertices, + &utest_fixture->srcMesh.numFaces); + + // + // read-in the cut-mesh from file + // + + mioReadOFF((std::string(MESHES_DIR) + "/cube-flattened-with-holes.off").c_str(), + &utest_fixture->cutMesh.pVertices, + &utest_fixture->cutMesh.pFaceVertexIndices, + &utest_fixture->cutMesh.pFaceSizes, + &utest_fixture->cutMesh.numVertices, + &utest_fixture->cutMesh.numFaces); ASSERT_EQ(mcDispatch( utest_fixture->context_, - MC_DISPATCH_VERTEX_ARRAY_FLOAT, - utest_fixture->pSrcMeshVertices, - utest_fixture->pSrcMeshFaceIndices, - utest_fixture->pSrcMeshFaceSizes, - utest_fixture->numSrcMeshVertices, - utest_fixture->numSrcMeshFaces, - utest_fixture->pCutMeshVertices, - utest_fixture->pCutMeshFaceIndices, - utest_fixture->pCutMeshFaceSizes, - utest_fixture->numCutMeshVertices, - utest_fixture->numCutMeshFaces), + MC_DISPATCH_VERTEX_ARRAY_DOUBLE, + // source mesh + utest_fixture->srcMesh.pVertices, + utest_fixture->srcMesh.pFaceVertexIndices, + utest_fixture->srcMesh.pFaceSizes, + utest_fixture->srcMesh.numVertices, + utest_fixture->srcMesh.numFaces, + // cut mesh + utest_fixture->cutMesh.pVertices, + utest_fixture->cutMesh.pFaceVertexIndices, + utest_fixture->cutMesh.pFaceSizes, + utest_fixture->cutMesh.numVertices, + utest_fixture->cutMesh.numFaces), MC_INVALID_OPERATION); } diff --git a/tests/source/triangulation.cpp b/tests/source/triangulation.cpp index bc845c8..718e769 100644 --- a/tests/source/triangulation.cpp +++ b/tests/source/triangulation.cpp @@ -34,7 +34,7 @@ **************************************************************************/ #include "utest.h" -#include "off.h" +#include #include @@ -51,24 +51,24 @@ struct Triangulation { UTEST_F_SETUP(Triangulation) { // create with no flags (default) - EXPECT_EQ(mcCreateContext(&utest_fixture->myContext, MC_DEBUG), MC_NO_ERROR); + EXPECT_EQ(mcCreateContext(&utest_fixture->myContext, MC_NULL_HANDLE), MC_NO_ERROR); EXPECT_TRUE(utest_fixture->myContext != nullptr); - // config debug output - // ----------------------- - McSize numBytes = 0; - McFlags contextFlags; - EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes), MC_NO_ERROR); - + // // config debug output + //// ----------------------- + //McSize numBytes = 0; + //McFlags contextFlags; + //EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, 0, nullptr, &numBytes), MC_NO_ERROR); + // - EXPECT_EQ(sizeof(McFlags),numBytes); + //EXPECT_EQ(sizeof(McFlags),numBytes); - EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr), MC_NO_ERROR); + //EXPECT_EQ(mcGetInfo(utest_fixture->myContext, MC_CONTEXT_FLAGS, numBytes, &contextFlags, nullptr), MC_NO_ERROR); - if (contextFlags & MC_DEBUG) { - mcDebugMessageCallback(utest_fixture->myContext, mcDebugOutput, nullptr); - mcDebugMessageControl(utest_fixture->myContext, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); - } + //if (contextFlags & MC_DEBUG) { + // mcDebugMessageCallback(utest_fixture->myContext, mcDebugOutput, nullptr); + // mcDebugMessageControl(utest_fixture->myContext, McDebugSource::MC_DEBUG_SOURCE_ALL, McDebugType::MC_DEBUG_TYPE_ALL, McDebugSeverity::MC_DEBUG_SEVERITY_ALL, true); + //} } UTEST_F_TEARDOWN(Triangulation) @@ -149,7 +149,7 @@ UTEST_F(Triangulation, oneEdgePartialCut) ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } - writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); + //writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); } } @@ -228,7 +228,7 @@ UTEST_F(Triangulation, twoEdgePartialCut) ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } - writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); + //writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); } } @@ -314,7 +314,7 @@ UTEST_F(Triangulation, threeEdgePartialCut) ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } - writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); + //writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); } } @@ -400,6 +400,6 @@ UTEST_F(Triangulation, threeEdgeVerticalPartialCut) ASSERT_LT((McUint32)triangleIndices[v], numberOfVertices); // "out of bounds vertex index" } - writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); + //writeOBJ("tri-cc"+std::to_string(c) + ".obj", vertices, triangleIndices); } } \ No newline at end of file diff --git a/tests/source/userEvents.cpp b/tests/source/userEvents.cpp index 804fcab..0d330f1 100644 --- a/tests/source/userEvents.cpp +++ b/tests/source/userEvents.cpp @@ -48,27 +48,27 @@ Each context is run in its own thread. #include #include struct UserEvents { - McContext context; - McEvent userEvent; + McContext context = MC_NULL_HANDLE; + McEvent userEvent = MC_NULL_HANDLE; // // Same inputs as Hello World tutorial // - std::vector cubeVertices; - std::vector cubeFaces; - McInt32 numCubeVertices; - McInt32 numCubeFaces; + std::vector cubeVertices = {}; + std::vector cubeFaces = {}; + McInt32 numCubeVertices = 0; + McInt32 numCubeFaces = 0; - std::vector cubeFaceSizes; + std::vector cubeFaceSizes = {}; // Cutting Shape: - std::vector cutMeshVertices; + std::vector cutMeshVertices = {}; - std::vector cutMeshFaces; + std::vector cutMeshFaces = {}; - McUint32 numCutMeshVertices; - McUint32 numCutMeshFaces; + McUint32 numCutMeshVertices=0; + McUint32 numCutMeshFaces = 0; }; UTEST_F_SETUP(UserEvents) @@ -149,10 +149,10 @@ UTEST_F(UserEvents, getExecStatus) McSize bytes = 0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, 0, NULL, &bytes), McResult::MC_NO_ERROR); - McEventCommandExecStatus status; + McEventCommandExecStatus status = (McEventCommandExecStatus)0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, bytes, &status, NULL), McResult::MC_NO_ERROR); - ASSERT_EQ(status, McEventCommandExecStatus::MC_SUBMITTED); // default value + ASSERT_TRUE(status& McEventCommandExecStatus::MC_SUBMITTED); // default value } UTEST_F(UserEvents, getContext) @@ -163,7 +163,7 @@ UTEST_F(UserEvents, getContext) McSize bytes = 0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_CONTEXT, 0, NULL, &bytes), McResult::MC_NO_ERROR); - McContext c; + McContext c = MC_NULL_HANDLE; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_CONTEXT, bytes, &c, NULL), McResult::MC_NO_ERROR); ASSERT_EQ(c, utest_fixture->context); @@ -251,10 +251,10 @@ UTEST_F(UserEvents, dependOn) McSize bytes = 0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, 0, NULL, &bytes), McResult::MC_NO_ERROR); - McEventCommandExecStatus status; + McEventCommandExecStatus status = (McEventCommandExecStatus)0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_COMMAND_EXECUTION_STATUS, bytes, &status, NULL), McResult::MC_NO_ERROR); - ASSERT_EQ(status, McEventCommandExecStatus::MC_COMPLETE); + ASSERT_TRUE(status & McEventCommandExecStatus::MC_COMPLETE); } catch (std::exception&) { ASSERT_TRUE(false); // should not reach here (it means "mcSetUserEventStatus" failed) } @@ -316,7 +316,7 @@ UTEST_F(UserEvents, dependOnWithError) McSize bytes = 0; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS, 0, NULL, &bytes), McResult::MC_NO_ERROR); - McResult status; + McResult status = McResult::MC_NO_ERROR; ASSERT_EQ(mcGetEventInfo(utest_fixture->userEvent, MC_EVENT_RUNTIME_EXECUTION_STATUS, bytes, &status, NULL), McResult::MC_NO_ERROR); ASSERT_EQ(status, McResult::MC_INVALID_OPERATION); // from "mcSetUserEventStatus" diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 8c24a04..16d4de5 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.1) - project(mcut_tutorials) function(create_tutorial_target tutorial_name) From 2e84fa71ff592ca2f3d325c7a8c2930d304568e7 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Mon, 22 Jan 2024 18:04:20 +0000 Subject: [PATCH 13/23] update CLA --- CLA | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLA b/CLA index ca1235f..b172205 100644 --- a/CLA +++ b/CLA @@ -1,6 +1,6 @@ -# MCUT CONTRIBUTOR AGREEMENTS +# CONTRIBUTOR AGREEMENTS -The MCUT project follows the Apache Software Foundation [model](https://apache.org/licenses/contributor-agreements.html) when handling contribution. The project relies on two agreements to accept contributions of software code and documentation from individuals and corporations, respectively. +The MCUT project follows the Apache Software Foundation [model](https://apache.org/licenses/contributor-agreements.html) when handling contributions. The project relies on two agreements to accept contributions of software code and documentation from individuals and corporations, respectively. These agreements help achieve the goal of providing a reliable and long-lived software product through collaborative, open-source software development. In all cases, contributors retain full rights to use their original contributions for any other purpose outside of MCUT, while providing CutDigital Enterprise Ltd (copyright owner) the right to distribute and build upon their work. From 26a562e2d00eee70b575cd58153e766637cdf3bb Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Mon, 22 Jan 2024 18:05:04 +0000 Subject: [PATCH 14/23] update error message when partitioning algorithm fails --- source/preproc.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/source/preproc.cpp b/source/preproc.cpp index 467f4ca..1d317c0 100644 --- a/source/preproc.cpp +++ b/source/preproc.cpp @@ -903,10 +903,25 @@ void resolve_floating_polygons( } // while (fp_edge_pair_priority_queue.size() > 0 && successivelyPartitionedOriginFaceWithCurrentEdgePair == false) { if (!haveSegmentOnFP) { - // OH OH! - // You have encountered an extremely rare problem case. - // Email the developers (there is a solution but it requires numerical perturbation on "fpSegment"). - throw std::logic_error("Floating-polygon partitioning step could not find a usable fpSegment"); + // Your input meshes have been found to be in a problematic configuration for which a (clear and robust) + // solution is unknown. + std::string user_msg = "Floating-polygon Partitioning algorithm could not find a usable fpSegment\n"; + if(detected_floating_polygons.size() > 1) + { + std::string workaround_msg = + "\t WORKAROUND: Consider mesh-refinement around face f" + + std::to_string((unsigned int)parent_face) + " in " + + (parent_face_from_source_hmesh ? "source" : "cut") + "-mesh"; + user_msg.append(workaround_msg); + + // There might be a solution to this issue but finding it would require significant time. + // GIST: You have a polygon P (i.e. "parent_face"). And inside (the area) of P are child polygons 'c' that + // where produced as a result of P slicing some solid volume (e.g. sphere or torus). In the simplest case there is + // only one child (imagine a plane slicing a sphere). However, in the more general (and hence more complex) case, the are two or more. + // The problem to solve is that of determining the polyline that runs from one edge in P to another + // (different) edge of P, while also plassing through the area of each child polygon 'c'. + } + throw std::logic_error(user_msg); } // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: From ff6a63db84e64f04da5734db75f4e9503242fe3c Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Thu, 1 Feb 2024 21:01:31 +0000 Subject: [PATCH 15/23] fix minor typos and remove redundant text --- CLA | 6 +++--- LICENSE.txt | 8 ++++---- README.md | 20 ++++---------------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/CLA b/CLA index b172205..8c711fc 100644 --- a/CLA +++ b/CLA @@ -8,7 +8,7 @@ These agreements help achieve the goal of providing a reliable and long-lived so ## Overview -The Individual Contributor License Agreement (ICLA) is provided below. The purpose of this agreement is to clearly define the terms under which intellectual property has been contributed to the MCUT project and thereby allow the copyright holder of the MCUT project to defend it should there be a legal dispute regarding the software. By contribution of ideas, code, or documentation to the MCUT project, a contributor acknowledges that they are bound by the terms laid out herein. The ICLA an individual signs is not tied to any employer they may have. +The Individual Contributor License Agreement (ICLA) is provided below. The purpose of this agreement is to clearly define the terms under which intellectual property has been contributed to the MCUT project and thereby allow the copyright holder of the MCUT project to defend it should there be a legal dispute regarding the software. By contribution of ideas, code, or documentation to the MCUT project, a contributor acknowledges that they are bound by the terms laid out herein. The ICLA an individual acknowledges is not tied to any employer they may have. The Corporate Contributor License Agreement (CCLA) is also provided below. The CCLA is available to cover contributing intellectual property via a corporation that may have been assigned as part of an employment agreement. Note that a Corporate CLA does not remove the need for every developer to acknowledge their own ICLA as an individual, which covers both contributions the corporation owns, and those it does not own. The CCLA legally binds the corporation, so a person with authority to enter into legal contracts on behalf of the corporation must acknowledge it. @@ -26,7 +26,7 @@ You accept and agree to the following terms and conditions for Your Contribution "You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with CutDigital Enterprise. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. -"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to CutDigital Enterprise for inclusion in, or documentation of, any of the products owned or managed by CutDigital Enterprise (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to CutDigital Enterprise or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, CutDigital Enterprise for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." +"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to CutDigital Enterprise for inclusion in, or documentation of, any of the products owned or managed by CutDigital Enterprise (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to CutDigital Enterprise or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, CutDigital Enterprise for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." 2. Grant of Copyright License. @@ -38,7 +38,7 @@ Subject to the terms and conditions of this Agreement, You hereby grant to CutDi 4. You represent that you are legally entitled to grant the above license. -If your employer(s) has rights to intellectual propertythat you create that includes your Contributions, you representthat you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to CutDigital Enterprise, or that your employer has executed a separate Corporate CLA with CutDigital Enterprise. +If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to CutDigital Enterprise, or that your employer has executed a separate Corporate CLA with CutDigital Enterprise. 5. You represent that each of Your Contributions is Your original creation (see section 7 for submissions on behalf of others). diff --git a/LICENSE.txt b/LICENSE.txt index a3cbd7e..0e5377d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,13 +4,13 @@ MCUT is available under an [Open Source](https://opensource.org/) license as wel ## Open Source License -The Open Source license is the GNU [Lesser General Public License (v3+)](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. +The Open Source license is the GNU [Lesser General Public License, Version 3](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. -Users of code licensed under LGPL must: +In general, users of code that is licensed under LGPL must: * Include a copy of the full license text and the original copyright notice -* Make available the source updates when you distribute a derivative work based on the licensed library -* License any derivative works of the library under the same or later version of the LGPL or GPL as described above +* Make available the source updates when distributing a derivative work based on the licensed sofware +* License any derivative works of the sofware under the same or later version of the LGPL or GPL as described above In sum, the LGPL license gives you the right to use and copy the source code of MCUT freely. It is also possible to modify the MCUT code under the condition that the resulting modifications are released as source code under LGPL with any binary distribution of your software that uses these LGPL parts. diff --git a/README.md b/README.md index fc703bd..6d549f8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MCUT Overview -Gist: _A robust library for detecting and resolving surface intersections between two objects._ +Gist: _A library for detecting and resolving surface-mesh intersections._ [![Windows](https://github.com/cutdigital/mcut/actions/workflows/windows.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/windows.yml) [![MacOS](https://github.com/cutdigital/mcut/actions/workflows/macos.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/macos.yml) [![Linux](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml) @@ -18,7 +18,7 @@ The project is designed for a broad range of real-world problems relating to 3D MCUT is a tool for partitioning objects represented as meshes that model solids or open surfaces: It is a code library for cutting 3D mesh objects using their geometry to produce crisp fragments at fine scale, which is useful for operations like slicing and boolean operations (union, subtraction and intersection). Supported features include (see images below): -* **Stencilling**: exact cut-outs of the cutting surface +* **Stenciling**: exact cut-outs of the cutting surface * **Intersection curve access**: geometry representing lines of intersection-contour points * **Partial cuts**: producing valid results where an open-surface is not necessarily completely cutting through a solid. * **Concatenation**: merging a solids or open-surfaces with another. @@ -82,26 +82,14 @@ The following images show more examples of what users can do with MCUT: Figure 11: An example of sectioning with a flat plane, which can be used to eliminate material/volume on either side of this plane or create hollow carve-outs.

-# Source code and test applications - -The source code is available for your perusal and evaluation. You can access right here on Github. This is an opportunity for you to trial and experiment with MCUT for your needs. Here is a quick example of how you clone and build the library: - -* `git clone https://github.com/cutdigital/mcut.git` -* `mkdir build` -* `cd build` -* `cmake ..` (see `CMakeLists.txt` for available build configuration options) -* run `make -j4` *IF* you are on Linux/MacOS terminal, *ELSE* open the generated `.sln` with e.g. Visual Studio - -Next, try out one of the tutorials! - # Licensing MCUT is available under an Open Source license as well as a commercial license. Users choosing to use MCUT under the free-of-charge Open Source license (e.g. for academic purposes) simply need to comply to its terms, otherwise a commercial license is required. -* The Open Source license is the GNU [Lesser General Public License (v3+)](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. +* The Open Source license is the GNU [LGPL v3](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. * The commercial license option is for users that wish to use MCUT in their products for commercial purposes but do not wish to release their software under the LGPL. You can buy a commercial license from [CutDigital Enterprise](contact@cut-digital.com). The commercial offer is adapted based on company size (number of employees). -These options facilitate the adoption of MCUT in other [Open Source](https://opensource.org/) projects, while protecting its commercial value and thus make it possible to guarantee long term support, maintenance and further development of the code for the benefit of its users. +These options facilitate winder adoption of MCUT in other [Open Source](https://opensource.org/) projects, while ensuring long term support, maintenance and further development of the code for the benefit of its users. --- From 8242c1a13c2d658c88bcaead373f0f01cb11e7f7 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Thu, 1 Feb 2024 21:14:42 +0000 Subject: [PATCH 16/23] minor --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3429985..0733b9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,7 +218,7 @@ if(${MCUT_BUILD_TESTS} OR ${MCUT_BUILD_TUTORIALS}) set(mio_include_dir ${mio_SOURCE_DIR}/include) - add_subdirectory(${mio_SOURCE_DIR}) + add_subdirectory(${mio_SOURCE_DIR} build) # # tests From ea08e3d56134c960499d468bd68001f72e0f4121 Mon Sep 17 00:00:00 2001 From: Floyd Chitalu Date: Thu, 1 Feb 2024 21:17:42 +0000 Subject: [PATCH 17/23] add #include --- include/mcut/internal/hmesh.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mcut/internal/hmesh.h b/include/mcut/internal/hmesh.h index 73a58c3..2c01d93 100644 --- a/include/mcut/internal/hmesh.h +++ b/include/mcut/internal/hmesh.h @@ -44,6 +44,7 @@ #include #include #include +#include template class descriptor_t_ { From c638e6e803fb5722f5b0690063ecc7172bcea442 Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Wed, 14 Feb 2024 07:11:10 +0000 Subject: [PATCH 18/23] fix linux build errors and warnings --- source/frontend.cpp | 1 + source/preproc.cpp | 3 +- tests/source/createContext.cpp | 13 ++--- tests/source/debugVerboseLog.cpp | 4 +- tests/source/perturbationState.cpp | 2 +- tutorials/AdjacentFaces/AdjacentFaces.cpp | 1 + tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp | 12 ++-- tutorials/CSGBoolean/CSGBoolean.cpp | 12 ++-- tutorials/InOutQuery/InOutQuery.cpp | 55 +++++++++--------- .../MultipleContextsInParallel.cpp | 7 ++- .../PlanarSectioning/PlanarSectioning.cpp | 56 +++++++++---------- .../TextureCoordinates/TextureCoordinates.cpp | 1 + .../TriangulatedFaceMaps.cpp | 18 +++--- 13 files changed, 94 insertions(+), 91 deletions(-) diff --git a/source/frontend.cpp b/source/frontend.cpp index 6f6c173..e478dbd 100644 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -190,6 +190,7 @@ inline int trailing_zeroes(uint32_t v) #if __linux__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic ignored "-Wuninitialized" #endif r = (*(uint32_t*)&f >> 23) - 0x7f; diff --git a/source/preproc.cpp b/source/preproc.cpp index 1d317c0..3b1447e 100644 --- a/source/preproc.cpp +++ b/source/preproc.cpp @@ -2780,7 +2780,6 @@ extern "C" void preproc( const McUint32 numConnectedComponentsCreatedDefault = 2; // source-mesh and cut-mesh (potentially modified due to poly partitioning) const bool haveStandardIntersection = numConnectedComponentsCreated > numConnectedComponentsCreatedDefault; - const bool haveNoIntersection = numConnectedComponentsCreated == numConnectedComponentsCreatedDefault; if (dispatchFlags & MC_DISPATCH_INCLUDE_INTERSECTION_TYPE) // only determine the intersection-type if the user requested for it. { @@ -2797,7 +2796,7 @@ extern "C" void preproc( } else { - MCUT_ASSERT(haveNoIntersection); // we are dealing with the case where there exists no intersection of the input surfaces + MCUT_ASSERT(numConnectedComponentsCreated == numConnectedComponentsCreatedDefault); // we are dealing with the case where there exists no intersection of the input surfaces check_and_store_input_mesh_intersection_type( context_ptr, // diff --git a/tests/source/createContext.cpp b/tests/source/createContext.cpp index 7172372..d1b03fa 100644 --- a/tests/source/createContext.cpp +++ b/tests/source/createContext.cpp @@ -44,10 +44,6 @@ static void MCAPI_PTR mcDebugOutput(McDebugSource source, const char* message, const void* userParam) { - - // printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - // printf("userParam=%p\n", userParam); - std::string debug_src; switch(source) { @@ -57,8 +53,10 @@ static void MCAPI_PTR mcDebugOutput(McDebugSource source, case MC_DEBUG_SOURCE_KERNEL: debug_src = "KERNEL"; break; - case MC_DEBUG_SOURCE_ALL: - break; + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: + break; } std::string debug_type; switch(type) @@ -70,10 +68,9 @@ static void MCAPI_PTR mcDebugOutput(McDebugSource source, debug_type = "DEPRECATION"; break; case MC_DEBUG_TYPE_OTHER: - // printf("Type: Other"); debug_type = "OTHER"; break; - case MC_DEBUG_TYPE_ALL: + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: break; } diff --git a/tests/source/debugVerboseLog.cpp b/tests/source/debugVerboseLog.cpp index 39854cd..f510448 100644 --- a/tests/source/debugVerboseLog.cpp +++ b/tests/source/debugVerboseLog.cpp @@ -226,7 +226,7 @@ UTEST_F(DebugLog, MessageControl_EnableAll) ASSERT_EQ(MC_NO_ERROR, mcGetDebugMessageLog(utest_fixture->context_, numMsgs, msgData.size(), &sources[0], &types[0], &severities[0], &lengths[0], &msgData[0], &numFound)); - ASSERT_GT(numFound, 0); + ASSERT_GT(numFound, (McUint32)0); sources.resize(numFound); types.resize(numFound); @@ -238,7 +238,7 @@ UTEST_F(DebugLog, MessageControl_EnableAll) std::vector::iterator currPos = msgData.begin(); for (size_t msg = 0; msg < lengths.size(); ++msg) { - ASSERT_GT(lengths[msg], 0); + ASSERT_GT(lengths[msg], (McSize)0); messages.push_back(std::string(currPos, currPos + lengths[msg])); currPos = currPos + lengths[msg]; diff --git a/tests/source/perturbationState.cpp b/tests/source/perturbationState.cpp index 88b309f..12c6fae 100644 --- a/tests/source/perturbationState.cpp +++ b/tests/source/perturbationState.cpp @@ -123,7 +123,7 @@ UTEST_F(PerturbationState, getCCPerturbationVector) sqrd_magnitude += component*component; } - ASSERT_TRUE(sqrd_magnitude > 0); + ASSERT_TRUE(sqrd_magnitude > 0.0); } } diff --git a/tutorials/AdjacentFaces/AdjacentFaces.cpp b/tutorials/AdjacentFaces/AdjacentFaces.cpp index 5b67312..d338697 100644 --- a/tutorials/AdjacentFaces/AdjacentFaces.cpp +++ b/tutorials/AdjacentFaces/AdjacentFaces.cpp @@ -59,6 +59,7 @@ #include #include #include +#include McUint32 getAdjFacesBaseOffset(const McUint32 faceIdx, const McUint32* faceAdjFacesSizes); diff --git a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp index b0a39a9..176d360 100644 --- a/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp +++ b/tutorials/BasicCmdLineApp/BasicCmdLineApp.cpp @@ -51,7 +51,7 @@ #include // PRId64 #include #include - +#include #define my_assert(cond) \ if(!(cond)) \ { \ @@ -71,11 +71,11 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, const char* message, const void* userParam); -McUint32 main(McUint32 argc, char* argv[]) +int main(int argc, char* argv[]) { bool help = false; - for (McUint32 i = 0; help == false && i < argc; ++i) { + for (int i = 0; help == false && i < argc; ++i) { if (!strcmp("--help", argv[i]) || !strcmp("-h", argv[i])) { help = true; } @@ -346,7 +346,9 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, case MC_DEBUG_SOURCE_KERNEL: debug_src = "KERNEL"; break; - case MC_DEBUG_SOURCE_ALL: + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: break; } @@ -362,7 +364,7 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, //printf("Type: Other"); debug_type = "OTHER"; break; - case MC_DEBUG_TYPE_ALL: + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: break; } diff --git a/tutorials/CSGBoolean/CSGBoolean.cpp b/tutorials/CSGBoolean/CSGBoolean.cpp index d7bfe2c..d73472a 100644 --- a/tutorials/CSGBoolean/CSGBoolean.cpp +++ b/tutorials/CSGBoolean/CSGBoolean.cpp @@ -47,7 +47,8 @@ #include #include #include - +#include +#include #if defined(_WIN32) #define _CRT_SECURE_NO_WARNINGS 1 @@ -328,9 +329,6 @@ int main(int argc, const char* argv[]) my_assert(status == MC_NO_ERROR); #endif - - const McUint32 ccFaceCount = static_cast(ccFaceSizes.size()); - /// ------------------------------------------------------------------------------------ // Here we show, how to know when connected components pertain particular boolean operations. @@ -422,7 +420,9 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, case MC_DEBUG_SOURCE_KERNEL: debug_src = "KERNEL"; break; - case MC_DEBUG_SOURCE_ALL: + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: break; } @@ -438,7 +438,7 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, //printf("Type: Other"); debug_type = "OTHER"; break; - case MC_DEBUG_TYPE_ALL: + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: break; } diff --git a/tutorials/InOutQuery/InOutQuery.cpp b/tutorials/InOutQuery/InOutQuery.cpp index 18af7fa..4539e27 100644 --- a/tutorials/InOutQuery/InOutQuery.cpp +++ b/tutorials/InOutQuery/InOutQuery.cpp @@ -262,35 +262,36 @@ void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, const void* userParam) { - // printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - // printf("userParam=%p\n", userParam); - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; + switch(source) + { + case MC_DEBUG_SOURCE_API: + debug_src = "API"; + break; + case MC_DEBUG_SOURCE_KERNEL: + debug_src = "KERNEL"; + break; + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - // printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - } + } + std::string debug_type; + switch(type) + { + case MC_DEBUG_TYPE_ERROR: + debug_type = "ERROR"; + break; + case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + debug_type = "DEPRECATION"; + break; + case MC_DEBUG_TYPE_OTHER: + debug_type = "OTHER"; + break; + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: + break; + } + std::string severity_str; diff --git a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp index 5f8d1e1..ac96fee 100644 --- a/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp +++ b/tutorials/MultipleContextsInParallel/MultipleContextsInParallel.cpp @@ -779,7 +779,9 @@ void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, case MC_DEBUG_SOURCE_KERNEL: debug_src = "KERNEL"; break; - case MC_DEBUG_SOURCE_ALL: + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: break; } std::string debug_type; @@ -791,10 +793,9 @@ void MCAPI_PTR mcDebugOutputCALLBACK(McDebugSource source, debug_type = "DEPRECATION"; break; case MC_DEBUG_TYPE_OTHER: - // printf("Type: Other"); debug_type = "OTHER"; break; - case MC_DEBUG_TYPE_ALL: + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: break; } diff --git a/tutorials/PlanarSectioning/PlanarSectioning.cpp b/tutorials/PlanarSectioning/PlanarSectioning.cpp index 8795be9..0b820c3 100644 --- a/tutorials/PlanarSectioning/PlanarSectioning.cpp +++ b/tutorials/PlanarSectioning/PlanarSectioning.cpp @@ -62,36 +62,36 @@ void MCAPI_PTR mcDebugOutput(McDebugSource source, const void* userParam) { - //printf("Debug message ( %d ), length=%zu\n%s\n--\n", id, length, message); - //printf("userParam=%p\n", userParam); - std::string debug_src; - switch (source) { - case MC_DEBUG_SOURCE_API: - debug_src = "API"; - break; - case MC_DEBUG_SOURCE_KERNEL: - debug_src = "KERNEL"; - break; - case MC_DEBUG_SOURCE_ALL: - break; - } - std::string debug_type; - switch (type) { - case MC_DEBUG_TYPE_ERROR: - debug_type = "ERROR"; + switch(source) + { + case MC_DEBUG_SOURCE_API: + debug_src = "API"; + break; + case MC_DEBUG_SOURCE_KERNEL: + debug_src = "KERNEL"; + break; + case MC_DEBUG_SOURCE_FRONTEND: + debug_src = "FRONTEND"; + case MC_DEBUG_SOURCE_ALL:case MC_DEBUG_SOURCE_IGNORE: break; - case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - debug_type = "DEPRECATION"; - break; - case MC_DEBUG_TYPE_OTHER: - //printf("Type: Other"); - debug_type = "OTHER"; - break; - case MC_DEBUG_TYPE_ALL: - break; - - } + } + std::string debug_type; + switch(type) + { + case MC_DEBUG_TYPE_ERROR: + debug_type = "ERROR"; + break; + case MC_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + debug_type = "DEPRECATION"; + break; + case MC_DEBUG_TYPE_OTHER: + debug_type = "OTHER"; + break; + case MC_DEBUG_TYPE_ALL:case MC_DEBUG_TYPE_IGNORE: + break; + } + std::string severity_str; diff --git a/tutorials/TextureCoordinates/TextureCoordinates.cpp b/tutorials/TextureCoordinates/TextureCoordinates.cpp index dd514ba..9cf4567 100644 --- a/tutorials/TextureCoordinates/TextureCoordinates.cpp +++ b/tutorials/TextureCoordinates/TextureCoordinates.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #define my_assert(cond) \ if (!(cond)) \ diff --git a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp index e87428c..4b862f6 100644 --- a/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp +++ b/tutorials/TriangulatedFaceMaps/TriangulatedFaceMaps.cpp @@ -284,19 +284,19 @@ int main() // for (McInt32 i = 0; i < (McInt32)connectedComponents.size(); ++i) { - McConnectedComponent connComp = connectedComponents[i]; // connected compoene + McConnectedComponent cc = connectedComponents[i]; // // vertices // McSize numBytes = 0; - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes); my_assert(status == MC_NO_ERROR); McUint32 ccVertexCount = (McUint32)(numBytes / (sizeof(double) * 3)); std::vector ccVertices((size_t)ccVertexCount * 3u, 0.0); - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)ccVertices.data(), NULL); my_assert(status == MC_NO_ERROR); // @@ -304,20 +304,20 @@ int main() // numBytes = 0; - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes); my_assert(status == MC_NO_ERROR); std::vector ccTriangulatedFaceIndices(numBytes / sizeof(McUint32), 0); - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccTriangulatedFaceIndices.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, ccTriangulatedFaceIndices.data(), NULL); my_assert(status == MC_NO_ERROR); // // vertex map // - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, 0, NULL, &numBytes); my_assert(status == MC_NO_ERROR); std::vector ccVertexMap(numBytes / sizeof(McUint32), 0); - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_VERTEX_MAP, numBytes, ccVertexMap.data(), NULL); my_assert(status == MC_NO_ERROR); // @@ -325,12 +325,12 @@ int main() // const McUint32 ccTriangulatedFaceCount = static_cast(ccTriangulatedFaceIndices.size()/3); - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, 0, NULL, &numBytes); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, 0, NULL, &numBytes); my_assert(status == MC_NO_ERROR); std::vector ccTriangleFaceMap(numBytes / sizeof(McUint32), 0); - status = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, numBytes, ccTriangleFaceMap.data(), NULL); + status = mcGetConnectedComponentData(context, cc, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION_MAP, numBytes, ccTriangleFaceMap.data(), NULL); my_assert(status == MC_NO_ERROR); From 2d9bb3a3a6796f8da76a370e1f033b7944ab2f7d Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Wed, 14 Feb 2024 07:13:53 +0000 Subject: [PATCH 19/23] removing warnings from shewchuck file --- source/shewchuk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shewchuk.c b/source/shewchuk.c index 67c0195..86792d0 100644 --- a/source/shewchuk.c +++ b/source/shewchuk.c @@ -2770,7 +2770,7 @@ REAL permanent; REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8]; int cxtaalen, cxtbblen, cytaalen, cytbblen; REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8]; - int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen; + int axtbclen=0, aytbclen=0, bxtcalen, bytcalen=0, cxtablen, cytablen=0; REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16]; int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen; REAL axtbctt[8], aytbctt[8], bxtcatt[8]; From 9056d758ea6516df1effdfafd6be958b79a18f18 Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Sun, 18 Feb 2024 06:42:45 +0000 Subject: [PATCH 20/23] update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6d549f8..c510f53 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MCUT Overview -Gist: _A library for detecting and resolving surface-mesh intersections._ +Gist: _A library for detecting and resolving intersections between two surface meshes._ [![Windows](https://github.com/cutdigital/mcut/actions/workflows/windows.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/windows.yml) [![MacOS](https://github.com/cutdigital/mcut/actions/workflows/macos.yml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/macos.yml) [![Linux](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml/badge.svg)](https://github.com/cutdigital/mcut/actions/workflows/linux.yaml) @@ -12,7 +12,7 @@ This project is called "MCUT" (short for 'mesh cutting'), and it provides functi Figure 1: Generate, slice and perform Booleans without errors.

-The project is designed for a broad range of real-world problems relating to 3D modelling and design tasks. Application areas include computer animation, aerospace and automotive engineering, mining, civil and mechanical engineering amongst others. +The project is designed for a broad range of real-world problems relating to 3D modelling and design tasks. Application areas include computer animation, aerospace and automotive engineering, digital dental modelling, mining, civil and mechanical engineering amongst others. # Capabilities @@ -38,9 +38,9 @@ What is being offered is a general solution to the problem of resolving solid- a # Practical benefits and advantages for users -The expert capabilities of MCUT will allow companies, individuals and researchers-alike to develop robust (and fast) Computer-Aided Design (CAD) and Manufacturing (CAM) tools. For example, these tools could cater to the design of industry-specific structural models like tunnels, drill holes, mechanical instruments and rock-block models. All this alongside the ability to handle general 3D modelling tasks that are typical in industry and academic-fields related to computer graphics (e.g. game-engine level design) and mechanical engineering (e.g. fracture simulation). In essence, users of MCUT are provided with the capability to create robust derivative products and tools for generating (and testing) structural designs in a virtual setting for short- and long-term production operations and feasibility tests/studies. +The capabilities of MCUT will allow users to develop robust design tools. For example, these tools could cater to the design of industry-specific structural models like open-pit mines, tunnels, drill holes, mechanical instruments and rock-block models. All this alongside the ability to handle general 3D modelling tasks that are typical in industry and academic-fields related to computer graphics (e.g. game-engine level design) and mechanical engineering (e.g. fracture simulation). In essence, users of MCUT are provided with the capability to create robust derivative products and tools for generating (and testing) structural designs in a virtual setting for short- and long-term production operations and feasibility tests/studies. -The following images show more examples of what users can do with MCUT: +The following images show more examples of what you can do with MCUT:

From d3bb6e64c3a92c545f8a36e1d4e3eac5fe1fbf44 Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Sun, 18 Feb 2024 07:49:17 +0000 Subject: [PATCH 21/23] resolve build errors and remove warnings --- tests/source/createContext.cpp | 1 + tutorials/FaceNormals/FaceNormals.cpp | 12 ++++----- .../TextureCoordinates/TextureCoordinates.cpp | 26 +++++++++---------- tutorials/VertexNormals/VertexNormals.cpp | 24 ++++++++--------- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/tests/source/createContext.cpp b/tests/source/createContext.cpp index d1b03fa..0d71743 100644 --- a/tests/source/createContext.cpp +++ b/tests/source/createContext.cpp @@ -35,6 +35,7 @@ #include "utest.h" #include +#include static void MCAPI_PTR mcDebugOutput(McDebugSource source, McDebugType type, diff --git a/tutorials/FaceNormals/FaceNormals.cpp b/tutorials/FaceNormals/FaceNormals.cpp index 0275c75..1c5e456 100644 --- a/tutorials/FaceNormals/FaceNormals.cpp +++ b/tutorials/FaceNormals/FaceNormals.cpp @@ -466,14 +466,14 @@ int main() // vertices of the origin face (i.e. the face from which the current face came from). // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation // will be more complex, which is unnecessary for now. - vec3 a = {0.0, 0.0, 0.0}; + vec3 a = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[0]*3; a.x = ptr[0]; a.y = ptr[1]; a.z = ptr[2]; } - vec3 b = {0.0, 0.0, 0.0}; + vec3 b = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[1]*3; b.x = ptr[0]; @@ -481,7 +481,7 @@ int main() b.z = ptr[2]; } - vec3 c = {0.0, 0.0, 0.0}; + vec3 c = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFace[2]*3; c.x = ptr[0]; @@ -500,21 +500,21 @@ int main() // normal coordinates of vertices in the origin face - vec3 normalA = {0.0, 0.0, 0.0}; + vec3 normalA = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0]*3); normalA.x = ptr[0]; normalA.y = ptr[1]; normalA.z = ptr[2]; } - vec3 normalB = {0.0, 0.0, 0.0}; + vec3 normalB = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1]*3); normalB.x = ptr[0]; normalB.y = ptr[1]; normalB.z = ptr[2]; } - vec3 normalC = {0.0, 0.0, 0.0}; + vec3 normalC = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2]*3); normalC.x = ptr[0]; diff --git a/tutorials/TextureCoordinates/TextureCoordinates.cpp b/tutorials/TextureCoordinates/TextureCoordinates.cpp index 9cf4567..efe40ee 100644 --- a/tutorials/TextureCoordinates/TextureCoordinates.cpp +++ b/tutorials/TextureCoordinates/TextureCoordinates.cpp @@ -86,7 +86,7 @@ struct vec2 vec2 operator*(const McDouble c) const { - vec2 result = {0.0, 0.0}; + vec2 result = {{0.0, 0.0}}; result.x = x * c; result.y = y * c; return result; @@ -94,7 +94,7 @@ struct vec2 vec2 operator+(const vec2& rhs) const { - vec2 result = {0.0, 0.0}; + vec2 result = {{0.0, 0.0}}; result.x = x + rhs.x; result.y = y + rhs.y; return result; @@ -102,7 +102,7 @@ struct vec2 vec2 operator-(const vec2& rhs) const { - vec2 result = {0.0, 0.0}; + vec2 result = {{0.0, 0.0}}; result.x = x - rhs.x; result.y = y - rhs.y; return result; @@ -127,7 +127,7 @@ struct vec3 vec3 operator*(const McDouble c) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x * c; result.y = y * c; result.z = z * c; @@ -136,7 +136,7 @@ struct vec3 vec3 operator+(const vec3& rhs) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x + rhs.x; result.y = y + rhs.y; result.z = z + rhs.z; @@ -145,7 +145,7 @@ struct vec3 vec3 operator-(const vec3& rhs) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x - rhs.x; result.y = y - rhs.y; result.z = z - rhs.z; @@ -166,7 +166,7 @@ getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x vec3 crossProduct(const vec3& u, const vec3& v) { - vec3 out = {0.0, 0.0, 0.0}; + vec3 out = {{0.0, 0.0, 0.0}}; out.x = u.y * v.z - u.z * v.y; out.y = u.z * v.x - u.x * v.z; out.z = u.x * v.y - u.y * v.x; @@ -208,7 +208,7 @@ vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec ood = 1.0f / m.z; } - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.u = nu * ood; result.v = nv * ood; result.w = 1.0f - result.u - result.v; @@ -461,7 +461,7 @@ McInt32 main() // the face on which the current cc face came from const McIndex* imFaceVertexIndices = inputMeshPtr->pFaceVertexIndices + (imFaceIdx * 3); - vec2 texCoord = {0.0, 0.0}; + vec2 texCoord = {{0.0, 0.0}};; if (vertexIsIntersectionPoint) { // texture coords unknown and must be computed @@ -471,7 +471,7 @@ McInt32 main() // // coordinates of current point (whose barycentric coords we want) - vec3 p = {0.0, 0.0, 0.0}; + vec3 p = {{0.0, 0.0, 0.0}}; p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); @@ -479,14 +479,14 @@ McInt32 main() // vertices of the origin face (i.e. the face from which the current face came from). // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation // will be more complex, which is unnecessary for now. - vec3 a = {0.0, 0.0, 0.0}; + vec3 a = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[0] * 3; a.x = ptr[0]; a.y = ptr[1]; a.z = ptr[2]; } - vec3 b = {0.0, 0.0, 0.0}; + vec3 b = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[1] * 3; b.x = ptr[0]; @@ -494,7 +494,7 @@ McInt32 main() b.z = ptr[2]; } - vec3 c = {0.0, 0.0, 0.0}; + vec3 c = {{0.0, 0.0, 0.0}}; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[2] * 3; c.x = ptr[0]; diff --git a/tutorials/VertexNormals/VertexNormals.cpp b/tutorials/VertexNormals/VertexNormals.cpp index 8a6a3cb..a7293bf 100644 --- a/tutorials/VertexNormals/VertexNormals.cpp +++ b/tutorials/VertexNormals/VertexNormals.cpp @@ -74,7 +74,7 @@ struct vec3 vec3 operator*(const McDouble c) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x * c; result.y = y * c; result.z = z * c; @@ -83,7 +83,7 @@ struct vec3 vec3 operator+(const vec3& rhs) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x + rhs.x; result.y = y + rhs.y; result.z = z + rhs.z; @@ -92,7 +92,7 @@ struct vec3 vec3 operator-(const vec3& rhs) const { - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}}; result.x = x - rhs.x; result.y = y - rhs.y; result.z = z - rhs.z; @@ -114,7 +114,7 @@ getTriangleArea2D(McDouble x1, McDouble y1, McDouble x2, McDouble y2, McDouble x vec3 crossProduct(const vec3& u, const vec3& v) { - vec3 out = {0.0, 0.0, 0.0}; + vec3 out = {{0.0, 0.0, 0.0}};; out.x = u.y * v.z - u.z * v.y; out.y = u.z * v.x - u.x * v.z; out.z = u.x * v.y - u.y * v.x; @@ -156,7 +156,7 @@ vec3 getBarycentricCoords(const vec3& p, const vec3& a, const vec3& b, const vec ood = 1.0f / m.z; } - vec3 result = {0.0, 0.0, 0.0}; + vec3 result = {{0.0, 0.0, 0.0}};; result.u = nu * ood; result.v = nv * ood; result.w = 1.0f - result.u - result.v; @@ -460,7 +460,7 @@ McInt32 main() // interpolate normal vector components from input-mesh values // coordinates of current point (whose barycentric coords we want) - vec3 p = {0.0, 0.0, 0.0}; + vec3 p = {{0.0, 0.0, 0.0}};; p.x = (ccVertices[((McSize)ccVertexIdx * 3u) + 0u]); p.y = (ccVertices[((McSize)ccVertexIdx * 3u) + 1u]); p.z = (ccVertices[((McSize)ccVertexIdx * 3u) + 2u]); @@ -468,14 +468,14 @@ McInt32 main() // vertices of the origin face (i.e. the face from which the current face came from). // NOTE: we have assumed triangulated input meshes for simplicity. Otherwise, interpolation // will be more complex, which is unnecessary for now. - vec3 a = {0.0, 0.0, 0.0}; + vec3 a = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[0] * 3; a.x = ptr[0]; a.y = ptr[1]; a.z = ptr[2]; } - vec3 b = {0.0, 0.0, 0.0}; + vec3 b = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[1] * 3; b.x = ptr[0]; @@ -483,7 +483,7 @@ McInt32 main() b.z = ptr[2]; } - vec3 c = {0.0, 0.0, 0.0}; + vec3 c = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pVertices + imFaceVertexIndices[2] * 3; c.x = ptr[0]; @@ -495,21 +495,21 @@ McInt32 main() // normal coordinates of vertices in the origin face - vec3 normalA = {0.0, 0.0, 0.0}; + vec3 normalA = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[0] * 3); normalA.x = ptr[0]; normalA.y = ptr[1]; normalA.z = ptr[2]; } - vec3 normalB = {0.0, 0.0, 0.0}; + vec3 normalB = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[1] * 3); normalB.x = ptr[0]; normalB.y = ptr[1]; normalB.z = ptr[2]; } - vec3 normalC = {0.0, 0.0, 0.0}; + vec3 normalC = {{0.0, 0.0, 0.0}};; { const McDouble* ptr = inputMeshPtr->pNormals + (imFaceNormalIndices[2] * 3); normalC.x = ptr[0]; From 297f1c403df3cad786a1909a6769ea20561f5a64 Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Sun, 18 Feb 2024 07:54:36 +0000 Subject: [PATCH 22/23] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c510f53..886b16c 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ MCUT is available under an Open Source license as well as a commercial license. * The Open Source license is the GNU [LGPL v3](https://www.gnu.org/licenses/lgpl-3.0.en.html) (LGPL), which is allows developers to easily build on top of MCUT. * The commercial license option is for users that wish to use MCUT in their products for commercial purposes but do not wish to release their software under the LGPL. You can buy a commercial license from [CutDigital Enterprise](contact@cut-digital.com). The commercial offer is adapted based on company size (number of employees). -These options facilitate winder adoption of MCUT in other [Open Source](https://opensource.org/) projects, while ensuring long term support, maintenance and further development of the code for the benefit of its users. +These options facilitate wider adoption of MCUT in other [Open Source](https://opensource.org/) projects, while ensuring long term support, maintenance and further development of the code for the benefit of its users. --- From 28daefcc35085ea39d0d2c1aa07510ef8240ea2f Mon Sep 17 00:00:00 2001 From: "Floyd M. Chitalu" Date: Sun, 18 Feb 2024 08:08:00 +0000 Subject: [PATCH 23/23] minor --- source/frontend.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/frontend.cpp b/source/frontend.cpp index e478dbd..f698fb8 100644 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -2035,15 +2035,15 @@ void get_connected_component_data_impl_detail( case MC_CONNECTED_COMPONENT_DATA_DISPATCH_PERTURBATION_VECTOR: { SCOPED_TIMER("MC_CONNECTED_COMPONENT_DATA_DISPATCH_PERTURBATION_VECTOR"); if (pMem == nullptr) { - *pNumBytes = sizeof(vec3); + *pNumBytes = sizeof(McDouble)*3; } else { - if (bytes > sizeof(vec3)) { + if (bytes > sizeof(McDouble)*3) { throw std::invalid_argument("out of bounds memory access"); } - if (bytes % sizeof(vec3) != 0) { + if (bytes % (sizeof(McDouble)*3) != 0) { throw std::invalid_argument("invalid number of bytes"); } - + ((McDouble*)pMem)[0] = cc_uptr->perturbation_vector[0]; ((McDouble*)pMem)[1] = cc_uptr->perturbation_vector[1]; ((McDouble*)pMem)[2] = cc_uptr->perturbation_vector[2];