Skip to content

MeshTetraStuffing

Create a tetrahedral volume mesh from a surface, using the algorithm from F. Labelle and J.R. Shewchuk, "Isosurface Stuffing: Fast Tetrahedral Meshes with Good Dihedral Angles", SIGGRAPH 2007.

Target: Sofa.Component.Engine.Generate

namespace: sofa::component::engine::generate

parents:

  • BaseObject

Data

Name Description Default value
name object name unnamed
printLog if true, emits extra messages at runtime. 0
tags list of the subsets the objet belongs to
bbox this object bounding box
componentState The state of the component among (Dirty, Valid, Undefined, Loading, Invalid). Undefined
listening if true, handle the events, otherwise ignore the events 0
vbbox BBox to restrict the volume to
size Size of the generate tetrahedra. If negative, number of grid cells in the largest bbox dimension -8
outputPoints Output volume mesh points
outputTetrahedra Output volume mesh tetrahedra
Inputs
inputPoints Input surface mesh points
inputTriangles Input surface mesh triangles
inputQuads Input surface mesh quads
alphaLong Minimum alpha values on long edges when snapping points 0.24999
alphaShort Minimum alpha values on short edges when snapping points 0.42978
snapPoints Snap points to the surface if intersections on edges are closed to given alpha values 0
splitTetrahedra Split tetrahedra crossing the surface 0
Visualization
draw Activate rendering of internal datasets 0
Name Description Destination type name
context Graph Node containing this object (or BaseContext::getDefault() if no graph is used) BaseContext
slaves Sub-objects used internally by this object BaseObject
master nullptr for regular objects, or master object for which this object is one sub-objects BaseObject

Examples

MeshTetraStuffing.scn

<?xml version="1.0" ?>
<Node>
    <RequiredPlugin name="Sofa.Component.Constraint.Projective"/> <!-- Needed to use components [FixedProjectiveConstraint] -->
    <RequiredPlugin name="Sofa.Component.Engine.Generate"/> <!-- Needed to use components [MeshTetraStuffing] -->
    <RequiredPlugin name="Sofa.Component.Engine.Select"/> <!-- Needed to use components [BoxROI] -->
    <RequiredPlugin name="Sofa.Component.IO.Mesh"/> <!-- Needed to use components [MeshOBJLoader] -->
    <RequiredPlugin name="Sofa.Component.LinearSolver.Iterative"/> <!-- Needed to use components [CGLinearSolver] -->
    <RequiredPlugin name="Sofa.Component.Mapping.Linear"/> <!-- Needed to use components [BarycentricMapping Mesh2PointTopologicalMapping] -->
    <RequiredPlugin name="Sofa.Component.Mass"/> <!-- Needed to use components [DiagonalMass] -->
    <RequiredPlugin name="Sofa.Component.ODESolver.Backward"/> <!-- Needed to use components [EulerImplicitSolver] -->
    <RequiredPlugin name="Sofa.Component.SolidMechanics.FEM.Elastic"/> <!-- Needed to use components [TetrahedralCorotationalFEMForceField] -->
    <RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
    <RequiredPlugin name="Sofa.Component.Topology.Container.Constant"/> <!-- Needed to use components [MeshTopology] -->
    <RequiredPlugin name="Sofa.Component.Topology.Container.Dynamic"/> <!-- Needed to use components [PointSetTopologyContainer PointSetTopologyModifier TetrahedronSetGeometryAlgorithms TetrahedronSetTopologyContainer] -->
    <RequiredPlugin name="Sofa.Component.Visual"/> <!-- Needed to use components [VisualStyle] -->
    <RequiredPlugin name="Sofa.GL.Component.Rendering3D"/> <!-- Needed to use components [OglModel] -->

    <!--
    <CollisionPipeline verbose="0" name="CollisionPipeline"/>
    <BruteForceBroadPhase/>
    <BVHNarrowPhase/>
    <DiscreteIntersection/>
    <CollisionResponse response="PenalityContactForceField" name="collision response"/>
-->
    <DefaultAnimationLoop/>    
    <VisualStyle displayFlags="showForceFields" />
    <Node name="input">
        <MeshTopology name="surface" filename="mesh/liver-smooth.obj" />
        <MeshTetraStuffing name="stuffing" snapPoints="true" splitTetras="true" draw="true" size="0.7" alphaLong="0.3" alphaShort="0.4" inputPoints="@surface.points" inputTriangles="@surface.triangles" />
    </Node>
    <Node activated="1" name="output">
        <EulerImplicitSolver name="odesolver"  rayleighStiffness="0.1" rayleighMass="0.1" />
        <CGLinearSolver iterations="10" name="linear solver" tolerance="1.0e-9" threshold="1.0e-9" />
        <TetrahedronSetTopologyContainer name="volume" points="@../input/stuffing.outputPoints" tetras="@../input/stuffing.outputTetras" />
        <MechanicalObject />
        <!-- Algorithms: used in DiagonalMass to compute the mass -->
        <TetrahedronSetGeometryAlgorithms name="GeomAlgo" />
        <DiagonalMass massDensity="1" name="computed using mass density" />
        <TetrahedralCorotationalFEMForceField name="FEM" youngModulus="3000" poissonRatio="0.3" method="large" />
        <BoxConstraint box="-6 0 -2 -2 1.5 3" />
        <!--<SphereCollisionModel radius="0.4" />-->
        <!--
        <Node name="Surface">
      <include href="Objects/TriangleSetTopology.xml" />
      <Tetra2TriangleTopologicalMapping input="@../volume" output="@Container"/>
          <TriangularFEMForceField name="FEM" youngModulus="60" poissonRatio="0.3" method="large" /> 
        </Node>
-->
        <Node name="VM">
            <MeshOBJLoader name='myLoader' filename='mesh/liver-smooth.obj'/>  
            <OglModel name="visual" src="@myLoader" />
            <BarycentricMapping output="@visual" />
        </Node>
        <Node name="Circumcenters">
            <PointSetTopologyContainer name="Container2" />
            <PointSetTopologyModifier />
            <Mesh2PointTopologicalMapping input="@volume" output="@Container2" tetraBaryCoords="0.25 0.25 0.25" />
            <MechanicalObject />
            <!--<BarycentricMapping />-->
            <!--<CircumcenterMapping/>-->
            <!--<SphereCollisionModel radius="0.1" />-->
        </Node>
    </Node>
<!--
    <Node activated="0" name="output-gpu">
        <EulerImplicitSolver name="odesolver" />
        <CGLinearSolver iterations="10" name="linear solver" tolerance="1.0e-9" threshold="1.0e-9" />
        <MeshTopology name="volume" points="@../input/stuffing.outputPoints" tetras="@../input/stuffing.outputTetras" />
        <MechanicalObject template="CudaVec3f" />
        <UniformMass totalMass="5" name="mass" />
        <TetrahedronFEMForceField name="FEM" youngModulus="3000" poissonRatio="0.3" method="large" />
        <BoxConstraint box="-6 0 -2 -2 1.5 3" />
        <Node name="VM">
            <OglModel name="visual" filename="mesh/liver-smooth.obj" />
            <BarycentricMapping output="@visual" />
        </Node>
    </Node>
-->
</Node>
def createScene(root_node):

   node = root_node.addChild('node')

   node.addObject('RequiredPlugin', name="Sofa.Component.Constraint.Projective")
   node.addObject('RequiredPlugin', name="Sofa.Component.Engine.Generate")
   node.addObject('RequiredPlugin', name="Sofa.Component.Engine.Select")
   node.addObject('RequiredPlugin', name="Sofa.Component.IO.Mesh")
   node.addObject('RequiredPlugin', name="Sofa.Component.LinearSolver.Iterative")
   node.addObject('RequiredPlugin', name="Sofa.Component.Mapping.Linear")
   node.addObject('RequiredPlugin', name="Sofa.Component.Mass")
   node.addObject('RequiredPlugin', name="Sofa.Component.ODESolver.Backward")
   node.addObject('RequiredPlugin', name="Sofa.Component.SolidMechanics.FEM.Elastic")
   node.addObject('RequiredPlugin', name="Sofa.Component.StateContainer")
   node.addObject('RequiredPlugin', name="Sofa.Component.Topology.Container.Constant")
   node.addObject('RequiredPlugin', name="Sofa.Component.Topology.Container.Dynamic")
   node.addObject('RequiredPlugin', name="Sofa.Component.Visual")
   node.addObject('RequiredPlugin', name="Sofa.GL.Component.Rendering3D")
   node.addObject('DefaultAnimationLoop', )
   node.addObject('VisualStyle', displayFlags="showForceFields")

   input = node.addChild('input')

   input.addObject('MeshTopology', name="surface", filename="mesh/liver-smooth.obj")
   input.addObject('MeshTetraStuffing', name="stuffing", snapPoints="true", splitTetras="true", draw="true", size="0.7", alphaLong="0.3", alphaShort="0.4", inputPoints="@surface.points", inputTriangles="@surface.triangles")

   output = node.addChild('output', activated="1")

   output.addObject('EulerImplicitSolver', name="odesolver", rayleighStiffness="0.1", rayleighMass="0.1")
   output.addObject('CGLinearSolver', iterations="10", name="linear solver", tolerance="1.0e-9", threshold="1.0e-9")
   output.addObject('TetrahedronSetTopologyContainer', name="volume", points="@../input/stuffing.outputPoints", tetras="@../input/stuffing.outputTetras")
   output.addObject('MechanicalObject', )
   output.addObject('TetrahedronSetGeometryAlgorithms', name="GeomAlgo")
   output.addObject('DiagonalMass', massDensity="1", name="computed using mass density")
   output.addObject('TetrahedralCorotationalFEMForceField', name="FEM", youngModulus="3000", poissonRatio="0.3", method="large")
   output.addObject('BoxConstraint', box="-6 0 -2 -2 1.5 3")

   vm = output.addChild('VM')

   vm.addObject('MeshOBJLoader', name="myLoader", filename="mesh/liver-smooth.obj")
   vm.addObject('OglModel', name="visual", src="@myLoader")
   vm.addObject('BarycentricMapping', output="@visual")

   circumcenters = output.addChild('Circumcenters')

   circumcenters.addObject('PointSetTopologyContainer', name="Container2")
   circumcenters.addObject('PointSetTopologyModifier', )
   circumcenters.addObject('Mesh2PointTopologicalMapping', input="@volume", output="@Container2", tetraBaryCoords="0.25 0.25 0.25")
   circumcenters.addObject('MechanicalObject', )