Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
##############################################################################

cmake_minimum_required(VERSION 3.12)
project(InfinyToolkit VERSION 0.1 LANGUAGES CXX)
project(InfinyToolkit VERSION 0.2 LANGUAGES CXX)

include(cmake/environment.cmake)

Expand Down Expand Up @@ -171,6 +171,11 @@ target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_BIN
target_include_directories(${PROJECT_NAME} PUBLIC "$<INSTALL_INTERFACE:include>")

## Install rules for the library; CMake package configurations files
if(MeshRefinement_FOUND)
sofa_add_subdirectory(plugin extensions/MeshRefinement InfinyToolkit.MeshRefinement
BINARY_DIR "${CMAKE_BINARY_DIR}/InfinyToolkit.MeshRefinement")
endif()

sofa_create_package_with_targets(
PACKAGE_NAME ${PROJECT_NAME}
PACKAGE_VERSION ${PROJECT_VERSION}
Expand Down
51 changes: 51 additions & 0 deletions extensions/MeshRefinement/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.12)
project(InfinyToolkit.MeshRefinement VERSION 0.1 LANGUAGES CXX)

# This plugin provides a component controller that will be used in SOFA scene to use the public interface MeshRefinementAPI of the MeshRefinement plugin.
set(INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR src/InfinyToolkit/MeshRefinement)

set(HEADER_FILES
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/config.h.in
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/init.h
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/TetrahedronSubdivisionController.h
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/TetrahedronSubdivisionController.inl
)

set(SOURCE_FILES
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/init.cpp
${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/TetrahedronSubdivisionController.cpp
)

sofa_find_package(MeshRefinement REQUIRED)
sofa_find_package(Sofa.Component.Topology.Container.Dynamic REQUIRED)

# Optional: the Cuda template instantiations of the controller.
# Not yet working
#sofa_find_package(SofaCUDA QUIET)
#sofa_find_package(MeshRefinement.CUDA QUIET)
#if(SofaCUDA_FOUND AND MeshRefinement.CUDA_FOUND)
# message("${PROJECT_NAME}: SofaCUDA found - adding the Cuda subdivision controller")
# list(APPEND SOURCE_FILES ${INFINYTOOLKIT_MESHREFINEMENT_SRC_DIR}/CudaSubdivisionController.cpp)
# add_definitions(-DINFINYTOOLKIT_MESHREFINEMENT_USES_SOFACUDA)
#endif()

add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES})
target_compile_definitions(${PROJECT_NAME} PRIVATE "-DSOFA_BUILD_INFINYTOOLKIT_MESHREFINEMENT")
target_link_libraries(${PROJECT_NAME} MeshRefinement Sofa.Component.Topology.Container.Dynamic)

#if(SofaCUDA_FOUND AND MeshRefinement.CUDA_FOUND)
# target_link_libraries(${PROJECT_NAME} SofaCUDA MeshRefinement.CUDA)
#endif()

sofa_create_package_with_targets(
PACKAGE_NAME ${PROJECT_NAME}
PACKAGE_VERSION ${Sofa_VERSION}
TARGETS ${PROJECT_NAME} AUTO_SET_TARGET_PROPERTIES
INCLUDE_SOURCE_DIR "src"
INCLUDE_INSTALL_DIR "${PROJECT_NAME}"
RELOCATABLE "plugins"
)

if(SOFA_BUILD_TESTS)
add_subdirectory(tests)
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# CMake package configuration file for the InfinyToolkit.MeshRefinement library

@PACKAGE_GUARD@
@PACKAGE_INIT@

find_package(MeshRefinement QUIET REQUIRED)
find_package(Sofa.Component.Topology.Container.Dynamic QUIET REQUIRED)

check_required_components(InfinyToolkit.MeshRefinement)
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* - Copyright (C) 2026-Present InfinyTech3D - *
* All Rights Reserved *
* *
* The contents of this file are confidential and proprietary to InfinyTech3D. *
* Unauthorized copying, modification, distribution or disclosure of this *
* file, via any medium, is strictly prohibited. *
* *
* This file may only be used under the terms and conditions of a valid *
* commercial license agreement with InfinyTech3D. *
* *
* For licensing inquiries: contact@infinytech3d.com *
* Further information: https://infinytech3d.com *
******************************************************************************/

/// Instantiates and registers the controller for the Cuda vector types.
/// The matching MeshRefinementAPI instantiations are provided by MeshRefinement.CUDA,
/// Only compiled when both SofaCUDA and MeshRefinement.CUDA are found.
Comment thread
epernod marked this conversation as resolved.

#include <InfinyToolkit/MeshRefinement/TetrahedronSubdivisionController.inl>
#include <sofa/gpu/cuda/CudaTypes.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa::infinytoolkit::meshrefinement
{

void registerCudaTetrahedronSubdivisionController(sofa::core::ObjectFactory* factory)
{
factory->registerObjects(sofa::core::ObjectRegistrationData("Controller handling subdivision operations on a tetrahedral mesh, on Cuda vector types.")
.add< sofa::infinytoolkit::TetrahedronSubdivisionController<sofa::gpu::cuda::CudaVec3fTypes> >()
#ifdef SOFA_GPU_CUDA_DOUBLE
.add< sofa::infinytoolkit::TetrahedronSubdivisionController<sofa::gpu::cuda::CudaVec3dTypes> >()
#endif
);
}

} // namespace sofa::infinytoolkit::meshrefinement

namespace sofa::infinytoolkit
{

template class SOFA_INFINYTOOLKIT_MESHREFINEMENT_API TetrahedronSubdivisionController<sofa::gpu::cuda::CudaVec3fTypes>;

#ifdef SOFA_GPU_CUDA_DOUBLE
template class SOFA_INFINYTOOLKIT_MESHREFINEMENT_API TetrahedronSubdivisionController<sofa::gpu::cuda::CudaVec3dTypes>;
#endif

} // namespace sofa::infinytoolkit
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*******************************************************************************
* - Copyright (C) 2019-Present InfinyTech3D - *
* All Rights Reserved *
* *
* The contents of this file are confidential and proprietary to InfinyTech3D. *
* Unauthorized copying, modification, distribution or disclosure of this *
* file, via any medium, is strictly prohibited. *
* *
* This file may only be used under the terms and conditions of a valid *
* commercial license agreement with InfinyTech3D. *
* *
* For licensing inquiries: contact@infinytech3d.com *
* Further information: https://infinytech3d.com *
******************************************************************************/
#define SOFA_INFINYTOOLKIT_TETRAHEDRON_SUBDIVISION_CONTROLLER_CPP

#include <InfinyToolkit/MeshRefinement/TetrahedronSubdivisionController.inl>
#include <sofa/core/ObjectFactory.h>

namespace sofa::infinytoolkit::meshrefinement
{

using namespace sofa::core::topology;
using namespace sofa::component::topology;

void registerTetrahedronSubdivisionController(sofa::core::ObjectFactory* factory)
{
factory->registerObjects(sofa::core::ObjectRegistrationData("Controller handling subdivision operations on a tetrahedral mesh: cutting along a plane or between two surface triangles, and refining the whole mesh or a given set of tetrahedra.")
.add< sofa::infinytoolkit::TetrahedronSubdivisionController<sofa::defaulttype::Vec3Types> >());
}

} // namespace sofa::infinytoolkit::meshrefinement

namespace sofa::infinytoolkit
{
template class SOFA_INFINYTOOLKIT_MESHREFINEMENT_API TetrahedronSubdivisionController<sofa::defaulttype::Vec3Types>;

} // namespace sofa::infinytoolkit
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*******************************************************************************
* - Copyright (C) 2019-Present InfinyTech3D - *
* All Rights Reserved *
* *
* The contents of this file are confidential and proprietary to InfinyTech3D. *
* Unauthorized copying, modification, distribution or disclosure of this *
* file, via any medium, is strictly prohibited. *
* *
* This file may only be used under the terms and conditions of a valid *
* commercial license agreement with InfinyTech3D. *
* *
* For licensing inquiries: contact@infinytech3d.com *
* Further information: https://infinytech3d.com *
******************************************************************************/
#pragma once

#include <InfinyToolkit/MeshRefinement/config.h>
#include <MeshRefinement/MeshRefinementAPI.h>
#include <sofa/defaulttype/VecTypes.h>
#include <sofa/core/behavior/BaseController.h>
#include <sofa/component/topology/container/dynamic/TetrahedronSetTopologyContainer.h>

#include <set>
#include <string>


namespace sofa::infinytoolkit
{

/**
* Cuts and refines a tetrahedral mesh, driving the MeshRefinement plugin's engine.
*
* Four operations: cut along a plane, cut between two surface triangles, refine a
* given set of tetrahedra, and refine the whole mesh.
*
* Cutting is two-phase: the path is built first and applied second, so a scene can
* draw the plane and inspect it before the topology changes. prepareCutFrom*()
* followed by applyCut() does that; cutFrom*() does both in one call.
*
* Interactive keys, used by the example scenes:
* '1' build the cut plane from the cutPointA / cutPointB / cutDir / cutDepth Data
* '2' apply the cut built by '1'
* '3' refine the tetrahedra listed in testID
* '4' refine the whole mesh
*/
template <class DataTypes>
class TetrahedronSubdivisionController : public core::behavior::BaseController
{
public:
SOFA_CLASS(SOFA_TEMPLATE(TetrahedronSubdivisionController, DataTypes), sofa::core::behavior::BaseController);

using Real = typename DataTypes::Real;
using Coord = typename DataTypes::Coord;
using VecCoord = typename DataTypes::VecCoord;

using Vec3 = sofa::type::Vec3;
using TetrahedronSetTopologyContainer = sofa::component::topology::container::dynamic::TetrahedronSetTopologyContainer;

using TriangleID = sofa::core::topology::Topology::TriangleID;

/// Sofa API init method of the component
void init() override;

/// Handles the key presses listed in the class description.
void handleEvent(sofa::core::objectmodel::Event* event) override;

/// Draws the subdivided tetrahedra and the cut plane, per @sa d_drawTetra and
/// @sa d_drawDebugCut.
void draw(const core::visual::VisualParams* vparams) override;


/// @name Cutting
/// @{

/// Cuts along the quad spanned by @p pointA, @p pointB and @p direction over
/// @p depth, building and applying the cut in one call. @p createSurface also
/// creates the new surface mesh and its components on the cut faces.
/// @return false if the controller is unusable or the cut could not be built.
bool cutFromPlane(const Vec3& pointA, const Vec3& pointB, const Vec3& direction,
SReal depth, bool createSurface = false);

/// Cuts between the barycentres of triangles @p triangleA and @p triangleB, over
/// @p depth along the normal of @p triangleA, in one call.
/// @return false if the controller is unusable or either id is out of range.
bool cutFromTriangles(TriangleID triangleA, TriangleID triangleB,
SReal depth, bool createSurface = false);

/// Builds a cut path without applying it, so that it can be drawn and inspected.
/// @sa applyCut
bool prepareCutFromPlane(const Vec3& pointA, const Vec3& pointB, const Vec3& direction,
SReal depth);

/// Builds a cut path between two surface triangles without applying it.
/// @sa applyCut
bool prepareCutFromTriangles(TriangleID triangleA, TriangleID triangleB, SReal depth);

/// Applies the path built by either prepareCutFrom* method.
/// @return false if the controller is unusable.
bool applyCut(bool createSurface);
/// @}


/// @name Refinement
/// @{

/// Subdivides every tetrahedron of the mesh.
/// @return false if the controller is unusable.
bool refineFullMesh();

/// Subdivides the tetrahedra given by @p ids. @p criteria is the edge length
/// under which an edge is left whole; 0 subdivides regardless of length.
/// @return false if the controller is unusable.
bool refineTetrahedra(const std::set<unsigned int>& ids, SReal criteria = 0.0);
/// @}


protected:
/// Default constructor
TetrahedronSubdivisionController();

/// Default destructor
~TetrahedronSubdivisionController() override;

/// Builds the cut path from @sa d_cutPointA, @sa d_cutPointB, @sa d_cutDirection
/// and @sa d_cutDepth. Used by the '1' key and by @sa d_performCut.
bool prepareCutFromData();

/// Refines the tetrahedra in @sa d_testID, honouring @sa d_delayMode.
void refineFromData();


public:
/// Performs a cut at the next time step, then resets itself to false.
Data <bool> d_performCut;

/// The cut plane: the quad spanned by the two points below, extruded along
/// @sa d_cutDirection over @sa d_cutDepth.
Data <Vec3> d_cutPointA; ///< First point of the cut plane
Data <Vec3> d_cutPointB; ///< Second point of the cut plane
Data <Vec3> d_cutDirection; ///< Direction the plane is extruded along
Data <SReal> d_cutDepth; ///< Depth of the cut along @sa d_cutDirection

/// Creates a new surface mesh, and the components to render it, on the cut faces.
Data <bool> d_surfaceCut;
/// Texture applied to the surface created by the cut. Only used when
/// @sa d_surfaceCut is true.
Data <std::string> d_textureName;

/// Tetrahedra subdivided by the '3' key. @sa refineTetrahedra
Data <std::set<unsigned int> > d_testID;
/// Edge length under which an edge is left whole; 0 subdivides regardless.
Data <SReal> d_refineCriteria;
/// Splits the '3' key in two presses: the first computes the neighbourhood table,
/// the second subdivides from it.
Data <bool> d_delayMode;

Data <bool> d_drawTetra; ///< Draw the tetrahedra held by the subdividers
Data <float> d_drawScaleTetrahedra; ///< Scale of the drawn tetrahedra; below 1.0 it leaves gaps between them
Data <bool> d_drawDebugCut; ///< Draw the cut plane and the intersections it computed


private:
/// The subdivision engine. Owned, because a cut is built by one call and applied
/// by another and both have to reach the same engine.
std::unique_ptr<sofa::meshrefinement::MeshRefinementAPI<DataTypes> > m_mgr = nullptr;

/// The topology this controller operates on, used to range-check the ids given to it.
TetrahedronSetTopologyContainer::SPtr m_topoCon = nullptr;

/// True once init() has found a topology and the engine has initialised.
bool m_controllerReady = false;

/// Press counter for the two-phase '3' key. @sa d_delayMode
int m_refineStatus = 0;
};

#if !defined(SOFA_INFINYTOOLKIT_TETRAHEDRON_SUBDIVISION_CONTROLLER_CPP)
extern template class SOFA_INFINYTOOLKIT_MESHREFINEMENT_API TetrahedronSubdivisionController<sofa::defaulttype::Vec3Types>;
#endif

} // namespace sofa::infinytoolkit
Loading
Loading