From fb9a90ba4756b60175eb547dae88414f72002696 Mon Sep 17 00:00:00 2001 From: epernod Date: Wed, 26 Oct 2022 21:16:27 +0200 Subject: [PATCH 1/5] Add example scene in python --- .../SofaCarving/examples/SimpleCarving.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 applications/plugins/SofaCarving/examples/SimpleCarving.py diff --git a/applications/plugins/SofaCarving/examples/SimpleCarving.py b/applications/plugins/SofaCarving/examples/SimpleCarving.py new file mode 100644 index 00000000000..1ce05e88086 --- /dev/null +++ b/applications/plugins/SofaCarving/examples/SimpleCarving.py @@ -0,0 +1,102 @@ +import Sofa + + +#Choose in your script to activate or not the GUI +USE_GUI = True + + +def main(): + import SofaRuntime + import Sofa.Gui + SofaRuntime.importPlugin("SofaOpenglVisual") + SofaRuntime.importPlugin("SofaImplicitOdeSolver") + + root = Sofa.Core.Node("root") + createScene(root) + Sofa.Simulation.init(root) + + if not USE_GUI: + for iteration in range(10): + Sofa.Simulation.animate(root, root.dt.value) + else: + Sofa.Gui.GUIManager.Init("myscene", "qglviewer") + Sofa.Gui.GUIManager.createGUI(root, __file__) + Sofa.Gui.GUIManager.SetDimension(1080, 1080) + Sofa.Gui.GUIManager.MainLoop(root) + Sofa.Gui.GUIManager.closeGUI() + +def createScene(root): + + root.gravity=[0, 0, 0] + root.dt=0.05 + root.showBoundingTree = 0 + root.addObject('RequiredPlugin', name="plug1", pluginName="Sofa.Component.Collision.Detection.Algorithm Sofa.Component.Collision.Detection.Intersection Sofa.Component.Collision.Geometry Sofa.Component.Collision.Response.Contact") + root.addObject('RequiredPlugin', name="plug2", pluginName="Sofa.Component.Constraint.Projective Sofa.Component.LinearSolver.Iterative Sofa.Component.ODESolver.Backward") + root.addObject('RequiredPlugin', name="plug3", pluginName="Sofa.Component.Engine.Select Sofa.Component.IO.Mesh Sofa.Component.Mass ") + root.addObject('RequiredPlugin', name="plug4", pluginName="Sofa.Component.Mapping.Linear Sofa.Component.Mapping.NonLinear Sofa.Component.SolidMechanics.FEM.Elastic Sofa.Component.StateContainer") + root.addObject('RequiredPlugin', name="plug5", pluginName="Sofa.Component.Topology.Container.Dynamic Sofa.Component.Topology.Mapping") + root.addObject('RequiredPlugin', name="plug6", pluginName="Sofa.Component.Visual Sofa.GL.Component.Rendering3D") + root.addObject('RequiredPlugin', name="plug7", pluginName="Sofa.Component.Collision.Detection.Algorithm SofaCarving") + + root.addObject('VisualStyle',displayFlags="") + root.addObject('DefaultAnimationLoop') + root.addObject('DefaultPipeline',verbose="0") + root.addObject('BruteForceBroadPhase') + root.addObject('BVHNarrowPhase') + root.addObject('DefaultContactManager',response="PenalityContactForceField") + root.addObject('MinProximityIntersection',name="Proximity",alarmDistance="0.08",contactDistance="0.05",useSurfaceNormals="false") + root.addObject('CarvingManager',active="true",carvingDistance="-0.01") + + + + TT = root.addChild('TT') + + TT.addObject('EulerImplicitSolver',name="cg_odesolver",printLog="false",rayleighStiffness="0.1",rayleighMass="0.1") + TT.addObject('CGLinearSolver',iterations="25",name="linear solver",tolerance="1.0e-9",threshold="1.0e-9") + TT.addObject('MeshGmshLoader',filename="mesh/liver.msh",name="loader",scale="1") + + TT.addObject('MechanicalObject',template="Vec3d",src="@loader",name="Volume") + + TT.addObject('TetrahedronSetTopologyContainer', name="topo", src="@loader") + TT.addObject('TetrahedronSetTopologyModifier', name="topoMod") + TT.addObject('TetrahedronSetGeometryAlgorithms', template="Vec3d", name="GeomAlgo") + + TT.addObject('DiagonalMass',massDensity="0.5") + TT.addObject('FixedConstraint',indices="1 3 50") + TT.addObject('TetrahedralCorotationalFEMForceField',name="CFEM",youngModulus="160",poissonRatio="0.3",method="large") + + T=TT.addChild('T') + T.addObject('TriangleSetTopologyContainer', name="Container") + T.addObject('TriangleSetTopologyModifier', name="Modifier") + T.addObject('TriangleSetGeometryAlgorithms',name="GeomAlgo",template="Vec3d") + T.addObject('Tetra2TriangleTopologicalMapping', input="@../topo", output="@Container") + + T.addObject('TriangleCollisionModel', tags="CarvingSurface") + + Visu = T.addChild('Visu') + Visu.addObject('OglModel',name="Visual",material="Default Diffuse 1 0 1 0 1 Ambient 0 1 1 1 1 Specular 1 1 1 0 1 Emissive 0 1 1 0 1 Shininess 1 100") + Visu.addObject('IdentityMapping',input="@Volume",output="@Visual") + + + Instrument = root.addChild('Instrument') + Instrument.addObject('EulerImplicitSolver',name="cg_odesolver",printLog="false") + Instrument.addObject('CGLinearSolver',iterations="25",name="linear solver",tolerance="1.0e-9",threshold="1.0e-9") + Instrument.addObject('MechanicalObject',template="Rigid3d",name="instrumentState",tags="Omni",rotation="90 45 0",translation="0 0 1") + Instrument.addObject('UniformMass',template="Rigid3d",name="mass",totalMass="5") + visuIns = Instrument.addChild('visuIns') + visuIns.addObject('MeshOBJLoader',name="meshLoader_0",filename="mesh/dental_instrument_light.obj",scale3d="1 1 1",translation="-0.412256 -0.067639 3.35",rotation="180 0 150",handleSeams="1") + visuIns.addObject('OglModel',template="Vec3d",name="InstrumentVisualModel",src="@meshLoader_0",material="Default Diffuse 1 1 0.2 0.2 1 Ambient 1 0.2 0.04 0.04 1 Specular 0 1 0.2 0.2 1 Emissive 0 1 0.2 0.2 1 Shininess 0 45") + visuIns.addObject('RigidMapping',template="Rigid3d,Vec3d",name="MM->VM mapping",input="@instrumentState",output="@InstrumentVisualModel") + + colIns = Instrument.addChild('colIns') + colIns.addObject('MechanicalObject',template="Vec3d",name="Particle",position="-0.2 -0.2 -0.2") + colIns.addObject('SphereCollisionModel',name="ParticleModel",radius="0.2",tags="CarvingTool") + #colIns.addObject('SphereCollisionModel',name="ParticleModel",radius="0.2") + colIns.addObject('RigidMapping',template="Rigid3d,Vec3d",name="MM->CM mapping",input="@instrumentState",output="@Particle") + + return root + + +#Function used only if this script is called from a python environment +if __name__ == '__main__': + main() From 2311cf7b2fdd24d9b790821f860373a7cd589132 Mon Sep 17 00:00:00 2001 From: erik pernod Date: Mon, 7 Nov 2022 09:05:48 +0100 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Frederick Roy --- applications/plugins/SofaCarving/examples/SimpleCarving.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/applications/plugins/SofaCarving/examples/SimpleCarving.py b/applications/plugins/SofaCarving/examples/SimpleCarving.py index 1ce05e88086..41bc1b1baa5 100644 --- a/applications/plugins/SofaCarving/examples/SimpleCarving.py +++ b/applications/plugins/SofaCarving/examples/SimpleCarving.py @@ -8,8 +8,6 @@ def main(): import SofaRuntime import Sofa.Gui - SofaRuntime.importPlugin("SofaOpenglVisual") - SofaRuntime.importPlugin("SofaImplicitOdeSolver") root = Sofa.Core.Node("root") createScene(root) From bb9fde71171d99417da37cd3c00055a4590d3a8d Mon Sep 17 00:00:00 2001 From: erik pernod Date: Tue, 5 Sep 2023 10:13:53 +0200 Subject: [PATCH 3/5] Update SimpleCarving.py --- .../SofaCarving/examples/SimpleCarving.py | 114 +++++++++--------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/applications/plugins/SofaCarving/examples/SimpleCarving.py b/applications/plugins/SofaCarving/examples/SimpleCarving.py index 41bc1b1baa5..5700e375cdc 100644 --- a/applications/plugins/SofaCarving/examples/SimpleCarving.py +++ b/applications/plugins/SofaCarving/examples/SimpleCarving.py @@ -1,96 +1,90 @@ import Sofa - - -#Choose in your script to activate or not the GUI -USE_GUI = True - +import Sofa.Simulation def main(): - import SofaRuntime - import Sofa.Gui - root = Sofa.Core.Node("root") createScene(root) Sofa.Simulation.init(root) - if not USE_GUI: - for iteration in range(10): - Sofa.Simulation.animate(root, root.dt.value) - else: - Sofa.Gui.GUIManager.Init("myscene", "qglviewer") - Sofa.Gui.GUIManager.createGUI(root, __file__) - Sofa.Gui.GUIManager.SetDimension(1080, 1080) - Sofa.Gui.GUIManager.MainLoop(root) - Sofa.Gui.GUIManager.closeGUI() + Sofa.Gui.GUIManager.Init("myscene", "qglviewer") + Sofa.Gui.GUIManager.createGUI(root, __file__) + Sofa.Gui.GUIManager.SetDimension(1080, 1080) + Sofa.Gui.GUIManager.MainLoop(root) + Sofa.Gui.GUIManager.closeGUI() def createScene(root): root.gravity=[0, 0, 0] root.dt=0.05 root.showBoundingTree = 0 - root.addObject('RequiredPlugin', name="plug1", pluginName="Sofa.Component.Collision.Detection.Algorithm Sofa.Component.Collision.Detection.Intersection Sofa.Component.Collision.Geometry Sofa.Component.Collision.Response.Contact") - root.addObject('RequiredPlugin', name="plug2", pluginName="Sofa.Component.Constraint.Projective Sofa.Component.LinearSolver.Iterative Sofa.Component.ODESolver.Backward") - root.addObject('RequiredPlugin', name="plug3", pluginName="Sofa.Component.Engine.Select Sofa.Component.IO.Mesh Sofa.Component.Mass ") - root.addObject('RequiredPlugin', name="plug4", pluginName="Sofa.Component.Mapping.Linear Sofa.Component.Mapping.NonLinear Sofa.Component.SolidMechanics.FEM.Elastic Sofa.Component.StateContainer") - root.addObject('RequiredPlugin', name="plug5", pluginName="Sofa.Component.Topology.Container.Dynamic Sofa.Component.Topology.Mapping") - root.addObject('RequiredPlugin', name="plug6", pluginName="Sofa.Component.Visual Sofa.GL.Component.Rendering3D") - root.addObject('RequiredPlugin', name="plug7", pluginName="Sofa.Component.Collision.Detection.Algorithm SofaCarving") - root.addObject('VisualStyle',displayFlags="") + # Load required plugins + plugins = root.addChild('Plugins') + plugins.addObject('RequiredPlugin', name="Mechanical", pluginName="Sofa.Component.AnimationLoop Sofa.Component.LinearSolver.Direct Sofa.Component.ODESolver.Backward Sofa.Component.SolidMechanics.Spring Sofa.Component.StateContainer") + plugins.addObject('RequiredPlugin', name="Collision", pluginName="Sofa.Component.Collision.Detection.Algorithm Sofa.Component.Collision.Detection.Intersection Sofa.Component.Collision.Geometry Sofa.Component.Collision.Response.Contact") + plugins.addObject('RequiredPlugin', name="Constraint", pluginName="Sofa.Component.Constraint.Lagrangian.Correction Sofa.Component.Constraint.Lagrangian.Solver Sofa.Component.Constraint.Projective") + plugins.addObject('RequiredPlugin', name="Topology", pluginName="Sofa.Component.Topology.Container.Constant Sofa.Component.Topology.Container.Dynamic Sofa.Component.Topology.Container.Grid") + plugins.addObject('RequiredPlugin', name="Visual", pluginName="Sofa.Component.Visual Sofa.GL.Component.Rendering3D") + + root.addObject('VisualStyle',displayFlags="showVisualModels") + + # Add main scene pipeline components + root.addObject('DefaultVisualManagerLoop') root.addObject('DefaultAnimationLoop') - root.addObject('DefaultPipeline',verbose="0") + root.addObject('CollisionPipeline', depth=6, verbose=False, draw=False) root.addObject('BruteForceBroadPhase') - root.addObject('BVHNarrowPhase') - root.addObject('DefaultContactManager',response="PenalityContactForceField") - root.addObject('MinProximityIntersection',name="Proximity",alarmDistance="0.08",contactDistance="0.05",useSurfaceNormals="false") - root.addObject('CarvingManager',active="true",carvingDistance="-0.01") + root.addObject('BVHNarrowPhase') + root.addObject('LocalMinDistance', name="localmindistance", alarmDistance=0.1, contactDistance=0.01, angleCone=0.8, coneFactor=0.8) + root.addObject('DefaultContactManager', response="FrictionContactConstraint") + root.addObject('CarvingManager',active=True, carvingDistance=-0.01) - - - TT = root.addChild('TT') + # Add Volume mechanical object to be carved + TT = root.addChild('TetraVolume') + + TT.addObject('EulerImplicitSolver',name="cg_odesolver", printLog=False, rayleighStiffness=0.1, rayleighMass=0.1) + TT.addObject('CGLinearSolver', name="linear solver", iterations=25, tolerance=1.0e-9, threshold=1.0e-9) + TT.addObject('MeshGmshLoader', name="loader", filename="mesh/liver.msh") - TT.addObject('EulerImplicitSolver',name="cg_odesolver",printLog="false",rayleighStiffness="0.1",rayleighMass="0.1") - TT.addObject('CGLinearSolver',iterations="25",name="linear solver",tolerance="1.0e-9",threshold="1.0e-9") - TT.addObject('MeshGmshLoader',filename="mesh/liver.msh",name="loader",scale="1") - - TT.addObject('MechanicalObject',template="Vec3d",src="@loader",name="Volume") + TT.addObject('MechanicalObject',template="Vec3d", name="Volume", src="@loader") TT.addObject('TetrahedronSetTopologyContainer', name="topo", src="@loader") TT.addObject('TetrahedronSetTopologyModifier', name="topoMod") TT.addObject('TetrahedronSetGeometryAlgorithms', template="Vec3d", name="GeomAlgo") - TT.addObject('DiagonalMass',massDensity="0.5") - TT.addObject('FixedConstraint',indices="1 3 50") - TT.addObject('TetrahedralCorotationalFEMForceField',name="CFEM",youngModulus="160",poissonRatio="0.3",method="large") - - T=TT.addChild('T') + TT.addObject('DiagonalMass', massDensity=0.5) + TT.addObject('FixedConstraint', indices=[1, 3, 50]) + TT.addObject('TetrahedralCorotationalFEMForceField', name="CFEM", youngModulus=160, poissonRatio=0.3, method="large") + + # Add corresponding surface topology + T = TT.addChild('TriangleSurface') T.addObject('TriangleSetTopologyContainer', name="Container") T.addObject('TriangleSetTopologyModifier', name="Modifier") - T.addObject('TriangleSetGeometryAlgorithms',name="GeomAlgo",template="Vec3d") + T.addObject('TriangleSetGeometryAlgorithms', template="Vec3d", name="GeomAlgo") T.addObject('Tetra2TriangleTopologicalMapping', input="@../topo", output="@Container") T.addObject('TriangleCollisionModel', tags="CarvingSurface") - Visu = T.addChild('Visu') - Visu.addObject('OglModel',name="Visual",material="Default Diffuse 1 0 1 0 1 Ambient 0 1 1 1 1 Specular 1 1 1 0 1 Emissive 0 1 1 0 1 Shininess 1 100") - Visu.addObject('IdentityMapping',input="@Volume",output="@Visual") + Visu = T.addChild('VisualModel') + Visu.addObject('OglModel', name="Visual", material="Default Diffuse 1 0 1 0 1 Ambient 0 1 1 1 1 Specular 1 1 1 0 1 Emissive 0 1 1 0 1 Shininess 1 100") + Visu.addObject('IdentityMapping', input="@Volume", output="@Visual") + # Add instrument object Instrument = root.addChild('Instrument') - Instrument.addObject('EulerImplicitSolver',name="cg_odesolver",printLog="false") - Instrument.addObject('CGLinearSolver',iterations="25",name="linear solver",tolerance="1.0e-9",threshold="1.0e-9") - Instrument.addObject('MechanicalObject',template="Rigid3d",name="instrumentState",tags="Omni",rotation="90 45 0",translation="0 0 1") - Instrument.addObject('UniformMass',template="Rigid3d",name="mass",totalMass="5") - visuIns = Instrument.addChild('visuIns') - visuIns.addObject('MeshOBJLoader',name="meshLoader_0",filename="mesh/dental_instrument_light.obj",scale3d="1 1 1",translation="-0.412256 -0.067639 3.35",rotation="180 0 150",handleSeams="1") - visuIns.addObject('OglModel',template="Vec3d",name="InstrumentVisualModel",src="@meshLoader_0",material="Default Diffuse 1 1 0.2 0.2 1 Ambient 1 0.2 0.04 0.04 1 Specular 0 1 0.2 0.2 1 Emissive 0 1 0.2 0.2 1 Shininess 0 45") - visuIns.addObject('RigidMapping',template="Rigid3d,Vec3d",name="MM->VM mapping",input="@instrumentState",output="@InstrumentVisualModel") + Instrument.addObject('EulerImplicitSolver', name="cg_odesolver") + Instrument.addObject('CGLinearSolver', name="linear solver", iterations=25, tolerance=1.0e-9, threshold=1.0e-9) + Instrument.addObject('MechanicalObject', template="Rigid3d", name="instrumentState", rotation=[90, 45, 0], translation=[0, 0, 1]) + Instrument.addObject('UniformMass', template="Rigid3d", name="mass", totalMass=5.0) + + visuIns = Instrument.addChild('VisualModel') + visuIns.addObject('MeshOBJLoader', name="meshLoader_0", filename="mesh/dental_instrument_light.obj", translation=[-0.412256, -0.067639, 3.35], rotation=[180, 0, 150], handleSeams=True) + visuIns.addObject('OglModel',template="Vec3d", name="InstrumentVisualModel", src="@meshLoader_0", material="Default Diffuse 1 1 0.2 0.2 1 Ambient 1 0.2 0.04 0.04 1 Specular 0 1 0.2 0.2 1 Emissive 0 1 0.2 0.2 1 Shininess 0 45") + visuIns.addObject('RigidMapping', name="mecha mapping", input="@instrumentState", output="@InstrumentVisualModel") - colIns = Instrument.addChild('colIns') - colIns.addObject('MechanicalObject',template="Vec3d",name="Particle",position="-0.2 -0.2 -0.2") - colIns.addObject('SphereCollisionModel',name="ParticleModel",radius="0.2",tags="CarvingTool") - #colIns.addObject('SphereCollisionModel',name="ParticleModel",radius="0.2") - colIns.addObject('RigidMapping',template="Rigid3d,Vec3d",name="MM->CM mapping",input="@instrumentState",output="@Particle") + colIns = Instrument.addChild('CollisionModel') + colIns.addObject('MechanicalObject', template="Vec3d", name="Particle", position=[-0.2, -0.2, -0.2]) + colIns.addObject('SphereCollisionModel', name="ParticleModel", radius=0.2, tags="CarvingTool") + colIns.addObject('RigidMapping', name="mecha mapping", input="@instrumentState", output="@Particle") return root From d42c159c3cec486f0b3f8aa9d81aa6e0561cec07 Mon Sep 17 00:00:00 2001 From: erik pernod Date: Tue, 5 Sep 2023 11:35:42 +0200 Subject: [PATCH 4/5] Update SimpleCarving.py --- .../SofaCarving/examples/SimpleCarving.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/applications/plugins/SofaCarving/examples/SimpleCarving.py b/applications/plugins/SofaCarving/examples/SimpleCarving.py index 5700e375cdc..e5e3f28def5 100644 --- a/applications/plugins/SofaCarving/examples/SimpleCarving.py +++ b/applications/plugins/SofaCarving/examples/SimpleCarving.py @@ -20,23 +20,25 @@ def createScene(root): # Load required plugins plugins = root.addChild('Plugins') - plugins.addObject('RequiredPlugin', name="Mechanical", pluginName="Sofa.Component.AnimationLoop Sofa.Component.LinearSolver.Direct Sofa.Component.ODESolver.Backward Sofa.Component.SolidMechanics.Spring Sofa.Component.StateContainer") + plugins.addObject('RequiredPlugin', name="MechanicalLoop", pluginName="Sofa.Component.AnimationLoop Sofa.Component.ODESolver.Backward Sofa.Component.LinearSolver.Iterative Sofa.Component.Mapping.NonLinear Sofa.Component.Mapping.Linear") + plugins.addObject('RequiredPlugin', name="MechanicalModel", pluginName="Sofa.Component.StateContainer Sofa.Component.Mass Sofa.Component.SolidMechanics.FEM.Elastic") plugins.addObject('RequiredPlugin', name="Collision", pluginName="Sofa.Component.Collision.Detection.Algorithm Sofa.Component.Collision.Detection.Intersection Sofa.Component.Collision.Geometry Sofa.Component.Collision.Response.Contact") plugins.addObject('RequiredPlugin', name="Constraint", pluginName="Sofa.Component.Constraint.Lagrangian.Correction Sofa.Component.Constraint.Lagrangian.Solver Sofa.Component.Constraint.Projective") - plugins.addObject('RequiredPlugin', name="Topology", pluginName="Sofa.Component.Topology.Container.Constant Sofa.Component.Topology.Container.Dynamic Sofa.Component.Topology.Container.Grid") + plugins.addObject('RequiredPlugin', name="Topology", pluginName="Sofa.Component.Topology.Container.Constant Sofa.Component.Topology.Container.Dynamic Sofa.Component.Topology.Mapping") plugins.addObject('RequiredPlugin', name="Visual", pluginName="Sofa.Component.Visual Sofa.GL.Component.Rendering3D") + plugins.addObject('RequiredPlugin', name="Utils", pluginName="Sofa.Component.IO.Mesh SofaCarving") root.addObject('VisualStyle',displayFlags="showVisualModels") # Add main scene pipeline components root.addObject('DefaultVisualManagerLoop') root.addObject('DefaultAnimationLoop') - root.addObject('CollisionPipeline', depth=6, verbose=False, draw=False) + root.addObject('CollisionPipeline', verbose=False, draw=False) root.addObject('BruteForceBroadPhase') root.addObject('BVHNarrowPhase') - root.addObject('LocalMinDistance', name="localmindistance", alarmDistance=0.1, contactDistance=0.01, angleCone=0.8, coneFactor=0.8) - root.addObject('DefaultContactManager', response="FrictionContactConstraint") - root.addObject('CarvingManager',active=True, carvingDistance=-0.01) + root.addObject('MinProximityIntersection', name="Proximity", alarmDistance=0.08, contactDistance=0.05, useSurfaceNormals=False) + root.addObject('CollisionResponse', response="PenalityContactForceField") + root.addObject('CarvingManager',active=True, carvingDistance=-0.01, narrowPhaseDetection="@narrowPhase", toolModel="@Instrument/CollisionModel/ParticleModel") # Add Volume mechanical object to be carved TT = root.addChild('TetraVolume') @@ -66,7 +68,7 @@ def createScene(root): Visu = T.addChild('VisualModel') Visu.addObject('OglModel', name="Visual", material="Default Diffuse 1 0 1 0 1 Ambient 0 1 1 1 1 Specular 1 1 1 0 1 Emissive 0 1 1 0 1 Shininess 1 100") - Visu.addObject('IdentityMapping', input="@Volume", output="@Visual") + Visu.addObject('IdentityMapping', input="@../../Volume", output="@Visual") # Add instrument object From 83a4dbc029d3d2028902b69258aa0d981e670dae Mon Sep 17 00:00:00 2001 From: erik pernod Date: Wed, 6 Sep 2023 09:46:09 +0200 Subject: [PATCH 5/5] Update SimpleCarving.py --- .../plugins/SofaCarving/examples/SimpleCarving.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/applications/plugins/SofaCarving/examples/SimpleCarving.py b/applications/plugins/SofaCarving/examples/SimpleCarving.py index e5e3f28def5..037de56f25b 100644 --- a/applications/plugins/SofaCarving/examples/SimpleCarving.py +++ b/applications/plugins/SofaCarving/examples/SimpleCarving.py @@ -12,8 +12,10 @@ def main(): Sofa.Gui.GUIManager.MainLoop(root) Sofa.Gui.GUIManager.closeGUI() + +# This scene demonstrate how the use the CarvingManager component to perform carving operations (deleting topological element like triangle/tetrahedron) between a tool and a target object on a target object. +# The tool performing the carving as well as the object to be carved need to be represented by collision models. def createScene(root): - root.gravity=[0, 0, 0] root.dt=0.05 root.showBoundingTree = 0 @@ -35,12 +37,15 @@ def createScene(root): root.addObject('DefaultAnimationLoop') root.addObject('CollisionPipeline', verbose=False, draw=False) root.addObject('BruteForceBroadPhase') - root.addObject('BVHNarrowPhase') + root.addObject('BVHNarrowPhase', name="narrowPhase") root.addObject('MinProximityIntersection', name="Proximity", alarmDistance=0.08, contactDistance=0.05, useSurfaceNormals=False) root.addObject('CollisionResponse', response="PenalityContactForceField") + + # Add the CarvingManger object, linking the collision pipeline, as well as the collision model of the tool used to carve. The collisions models to be carved are found using the tags: CarvingSurface. + # the carvingDistance need to be lower than the contactDistance of the collision pipeline. root.addObject('CarvingManager',active=True, carvingDistance=-0.01, narrowPhaseDetection="@narrowPhase", toolModel="@Instrument/CollisionModel/ParticleModel") - # Add Volume mechanical object to be carved + # Add Volume mechanical object to be carved TT = root.addChild('TetraVolume') TT.addObject('EulerImplicitSolver',name="cg_odesolver", printLog=False, rayleighStiffness=0.1, rayleighMass=0.1)