diff --git a/examples/BaseCamera.py b/examples/BaseCamera.py index 88f0b402..e2ac348c 100644 --- a/examples/BaseCamera.py +++ b/examples/BaseCamera.py @@ -78,7 +78,7 @@ def Sphere(rootNode, name, position, color): #### Visualization of the sphere sphereVisu = sphere.addChild("VisualModel") sphereVisu.loader = sphereVisu.addObject('MeshObjLoader', name="loader", - filename="mesh/ball.obj", scale=0.5) + filename="mesh/ball.obj", scale=0.5) sphereVisu.addObject('OglModel', name="model", src="@loader", color=color) sphereVisu.addObject('RigidMapping') return sphere diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8161aff2..3f444712 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,25 +1,24 @@ project(Examples) set(EXAMPLES_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/BaseCamera.py ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}/ControllerScene.py - ${CMAKE_CURRENT_SOURCE_DIR}/easingSceneMatplotlib.py - ${CMAKE_CURRENT_SOURCE_DIR}/easingScene.py + ${CMAKE_CURRENT_SOURCE_DIR}/basic.py + ${CMAKE_CURRENT_SOURCE_DIR}/basic-addGUI.py ${CMAKE_CURRENT_SOURCE_DIR}/emptyController.py ${CMAKE_CURRENT_SOURCE_DIR}/emptyDataEngine.py ${CMAKE_CURRENT_SOURCE_DIR}/emptyForceField.py ${CMAKE_CURRENT_SOURCE_DIR}/example-forcefield2.py ${CMAKE_CURRENT_SOURCE_DIR}/example-forcefield.py - ${CMAKE_CURRENT_SOURCE_DIR}/example.pyscn ${CMAKE_CURRENT_SOURCE_DIR}/example-scriptcontroller.py + ${CMAKE_CURRENT_SOURCE_DIR}/BaseCamera.py + ${CMAKE_CURRENT_SOURCE_DIR}/easingSceneMatplotlib.py + ${CMAKE_CURRENT_SOURCE_DIR}/easingScene.py ${CMAKE_CURRENT_SOURCE_DIR}/keyEvents.py + ${CMAKE_CURRENT_SOURCE_DIR}/realTimeClockScene.py + ${CMAKE_CURRENT_SOURCE_DIR}/ReadTheDocs_Example.py ${CMAKE_CURRENT_SOURCE_DIR}/pygame_renderingloop/backend_pygame.py ${CMAKE_CURRENT_SOURCE_DIR}/pygame_renderingloop/pygame_test.py - ${CMAKE_CURRENT_SOURCE_DIR}/ReadTheDocs_Example.py - ${CMAKE_CURRENT_SOURCE_DIR}/realTimeClockScene.py - ${CMAKE_CURRENT_SOURCE_DIR}/SofaGui.py - ${CMAKE_CURRENT_SOURCE_DIR}/test.scn + ${CMAKE_CURRENT_SOURCE_DIR}/additional-examples/ControllerScene.py ) add_custom_target(${PROJECT_NAME} SOURCES ${EXAMPLES_FILES}) diff --git a/examples/SofaGui.py b/examples/SofaGui.py deleted file mode 100644 index 9a63d385..00000000 --- a/examples/SofaGui.py +++ /dev/null @@ -1,21 +0,0 @@ -import Sofa -import Sofa.Core -import Sofa.Simulation -import Sofa.Gui - -print ("Supported GUIs are " + Sofa.Gui.GUIManager.ListSupportedGUI(",")) - - -root = Sofa.Core.Node("root") -# Create the rest of the scene here... - - -# Initialize all components found in the scene -Sofa.Simulation.init(root) - - -# Launch the GUI -Sofa.Gui.GUIManager.Init("simple_scene", "qt") -Sofa.Gui.GUIManager.createGUI(root) -Sofa.Gui.GUIManager.MainLoop(root) -Sofa.Gui.GUIManager.closeGUI() diff --git a/examples/ControllerScene.py b/examples/additional-examples/ControllerScene.py similarity index 88% rename from examples/ControllerScene.py rename to examples/additional-examples/ControllerScene.py index db26a1d5..18ebcc83 100755 --- a/examples/ControllerScene.py +++ b/examples/additional-examples/ControllerScene.py @@ -81,6 +81,7 @@ def onKeypressedEvent(self, c): print("You just switch to rotation control ") self.move = 1 + def createScene(root): # rpath =os.environ["SOFA_ROOT"]+"../src/share/mesh/" @@ -91,8 +92,8 @@ def createScene(root): loader = root.addObject('MeshObjLoader', name='loader', filename="mesh/liver.obj") - te = root.addObject( - "TransformEngine", name="te", input_position=loader.position.getLinkPath(), rotation=[0,0,0]) + te = root.addObject("TransformEngine", name="te", + input_position=loader.position.getLinkPath(), rotation=[0,0,0]) mo = root.addObject("MechanicalObject", name="mo", position=te.output_position.getLinkPath()) @@ -100,26 +101,32 @@ def createScene(root): visu.addObject('OglModel', name="visu", src=loader.getLinkPath()) visu.addObject('IdentityMapping', name="BM", src=mo.getLinkPath()) + # If script is loaded by SOFA (runSofa), this script must be added as a controller if not _runAsPythonScript: root.addObject(RotationController(name="MyController", engine=root.te)) def main(): - # can be executed from terminal directly: - - # Register all the common component in the factory. + # Load the required plugins SofaRuntime.importPlugin("SofaOpenglVisual") + SofaRuntime.importPlugin("SofaGeneralEngine") + + # Check and save if the script is called from python environment global _runAsPythonScript _runAsPythonScript = True - root = Sofa.Core.Node() + # Create and initialize the scene + root = Sofa.Core.Node() createScene(root) Sofa.Simulation.init(root) + + # Run simulation for i in range(0, 360): Sofa.Simulation.animate(root, root.dt.value) root.te.rotation[0] += 1 - #print("For i = "+ str(i)+", we have : "+str(root.te.rotation.value[0])) + print("Last value is : "+ str(root.te.rotation.value[0])) + if __name__ == '__main__': main() diff --git a/examples/basic-addGUI.py b/examples/basic-addGUI.py new file mode 100644 index 00000000..b7df9bb5 --- /dev/null +++ b/examples/basic-addGUI.py @@ -0,0 +1,62 @@ +# Required import for python +import Sofa +import SofaRuntime +import Sofa.Gui + + +# Choose in your script to activate or not the GUI +USE_GUI = True + + +def main(): + # Make sure to load all SOFA libraries + SofaRuntime.importPlugin("SofaOpenglVisual") + + #Create the root node + root = Sofa.Core.Node("root") + # Call the below 'createScene' function to create the scene graph + createScene(root) + Sofa.Simulation.init(root) + + if not USE_GUI: + for iteration in range(10): + Sofa.Simulation.animate(root, root.dt.value) + else: + # Find out the supported GUIs + print ("Supported GUIs are: " + Sofa.Gui.GUIManager.ListSupportedGUI(",")) + # Launch the GUI (qt or qglviewer) + Sofa.Gui.GUIManager.Init("myscene", "qglviewer") + Sofa.Gui.GUIManager.createGUI(root, __file__) + Sofa.Gui.GUIManager.SetDimension(1080, 1080) + # Initialization of the scene will be done here + Sofa.Gui.GUIManager.MainLoop(root) + Sofa.Gui.GUIManager.closeGUI() + print("GUI was closed") + + print("Simulation is done.") + + +# Function called when the scene graph is being created +def createScene(root): + # Scene must now include a VisualLoop + root.addObject('DefaultVisualManagerLoop') + + # Scene must now include a AnimationLoop + root.addObject('DefaultAnimationLoop') + + # Add new nodes and objects in the scene + node1 = root.addChild("Node1") + node2 = root.addChild("Node2") + + node1.addObject("MechanicalObject") + node1.addObject("OglModel") + + node2.addObject("MechanicalObject") + node2.addObject("OglModel") + + return root + + +# Function used only if this script is called from a python environment +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/basic.py b/examples/basic.py new file mode 100644 index 00000000..f27ad13e --- /dev/null +++ b/examples/basic.py @@ -0,0 +1,43 @@ +# Required import for python +import Sofa +import SofaRuntime + + +def main(): + # Make sure to load all SOFA libraries + SofaRuntime.importPlugin("SofaOpenglVisual") + + # Call the above function to create the scene graph + root = Sofa.Core.Node("root") + createScene(root) + + # Once defined, initialization of the scene graph + Sofa.Simulation.init(root) + + # Run the simulation for 10 steps + for iteration in range(10): + print(f'Iteration #{iteration}') + Sofa.Simulation.animate(root, root.dt.value) + + print("Simulation made 10 time steps. Done") + + +# Function called when the scene graph is being created +def createScene(root): + + # Add new nodes and objects in the scene + node1 = root.addChild("Node1") + node2 = root.addChild("Node2") + + node1.addObject("MechanicalObject", position="0 0 0") + node1.addObject("OglModel") + + node2.addObject("MechanicalObject", position="1 1 1") + node2.addObject("OglModel") + + return root + + +# Function used only if this script is called from a python environment +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/emptyController.py b/examples/emptyController.py index 03670eb8..e3dcd1c4 100644 --- a/examples/emptyController.py +++ b/examples/emptyController.py @@ -1,44 +1,110 @@ -import Sofa.Core +import Sofa +import Sofa.Gui + +# This python script shows the functions to be implemented +# in order to create your Controller in python class EmptyController(Sofa.Core.Controller): - """ custom %EmptyController% component for SOFA """ def __init__(self, *args, **kwargs): + # These are needed (and the normal way to override from a python class) Sofa.Core.Controller.__init__(self, *args, **kwargs) + + # Default BaseObject functions******************************** + def init(self): pass - def init(): + def bwdInit(): pass def reinit(): pass - # DEFAULT EVENTS: - def onAnimateBeginEvent(self, event): - """ called at the beginning of each time step """ + # Default Events ********************************************* + def onAnimateBeginEvent(self, event): # called at each begin of animation step pass - def onAnimateEndEvent(self, event): - """ called at the end of each time step """ + def onAnimateEndEvent(self, event): # called at each end of animation step pass def onKeypressedEvent(self, event): - """ called when a key release event is triggered from the UI """ - pass + key = event['key'] + if ord(key) == 19: # up + print("You pressed the Up key") + + if ord(key) == 21: # down + print("You pressed the Down key") + + if ord(key) == 18: # left + print("You pressed the Left key") + + if ord(key) == 20: # right + print("You pressed the Right key") def onKeyreleasedEvent(self, event): - """ called when a key release event is triggered from the UI """ - pass + key = event['key'] + if ord(key) == 19: # up + print("You released the Up key") + + if ord(key) == 21: # down + print("You released the Down key") + + if ord(key) == 18: # left + print("You released the Left key") + + if ord(key) == 20: # right + print("You released the Right key") def onMouseEvent(self, event): - """ called when a mouse event is triggered from the UI """ - pass + if (event['State']== 0): # mouse moving + print("Mouse is moving (x,y) = "+str(event['mouseX'])+" , "+str(event['mouseY'])) + + if (event['State']==1): # left mouse clicked + print("Left mouse clicked") + + if (event['State']==2): # left mouse released + print("Left mouse released") + + if (event['State']==3): # right mouse released + print("Right mouse clicked") + + if (event['State']==4): # right mouse released + print("Right mouse released") + + if (event['State']==5): # wheel clicked + print("Mouse wheel clicked") + + if (event['State']==6): # wheel released + print("Mouse wheel released") def onScriptEvent(self, event): - """ catches events sent from other python scripts """ pass def onEvent(self, event): - """ generic method called when no script method exists for the sent event """ pass + +def createScene(root): + root.dt = 0.01 + root.addObject('DefaultVisualManagerLoop') + root.addObject('DefaultAnimationLoop') + + # Add our python controller in the scene + root.addObject( EmptyController(name="MyEmptyController") ) + + +def main(): + root=Sofa.Core.Node("root") + createScene(root) + + 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() + + print("End of simulation.") + + +if __name__ == '__main__': + main() diff --git a/examples/emptyDataEngine.py b/examples/emptyDataEngine.py index d822cfc0..5b43f0fe 100644 --- a/examples/emptyDataEngine.py +++ b/examples/emptyDataEngine.py @@ -1,22 +1,47 @@ -import Sofa.Core +import Sofa +import Sofa.Gui from Sofa.Helper import msg_info +# This python script shows the functions to be implemented +# in order to create your DataEngine in python class EmptyDataEngine(Sofa.Core.DataEngine): - """ custom %EmptyDataEngine% component for SOFA """ def __init__(self, *args, **kwargs): Sofa.Core.DataEngine.__init__(self, *args, **kwargs) pass - def init(): + def init(self): pass def update(): - """ - called anytime an output is accessed while the component - is dirty (input has changed) - """ + # Function called anytime an output is accessed while the component + # is dirty (input has changed) msg_info('Not implemented yet') pass - + + +def createScene(root): + root.dt = 0.01 + root.addObject('DefaultVisualManagerLoop') + + # Add our python forcefield in the scene + root.addObject( EmptyDataEngine(name="MyEmptyDataEngine") ) + + +def main(): + root=Sofa.Core.Node("root") + createScene(root) + Sofa.Simulation.init(root) + + 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() + + print("End of simulation.") + + +if __name__ == '__main__': + main() diff --git a/examples/emptyForceField.py b/examples/emptyForceField.py index 9362933a..f033fcc2 100644 --- a/examples/emptyForceField.py +++ b/examples/emptyForceField.py @@ -1,24 +1,69 @@ -import Sofa.Core -import numpy as np +import Sofa +import Sofa.Gui from Sofa.Helper import msg_info +import numpy as np -class EmptyForcefield(Sofa.Core.ForceField): + +# This python script shows the functions to be implemented +# in order to create your ForceField in python +class EmptyForceField(Sofa.Core.ForceField): def __init__(self, *args, **kwargs): Sofa.Core.ForceField.__init__(self, *args, **kwargs) pass + # Function called at the component initialization def init(self): + msg_info('init: not implemented yet') pass + # Function implementing the explicit force f(x(t), v(t)) def addForce(self, m, forces, pos, vel): - msg_info('Not implemented yet') + msg_info('addForce: not implemented yet') pass + # Function implementing the matrix-vector multiplication + # between the derivative of the force f with regards to + # the degrees of freedom, multiplied by a vector dx def addDForce(self, m, dforce, dx): - msg_info('Not implemented yet') + msg_info('addDForce: not implemented yet') pass + # Function implementing the matrix corresponding to the + # derivative of the force f with regards to the degrees + # of freedom def addKToMatrix(self, mparams, nNodes, nDofs): - msg_info('Not implemented yet') + msg_info('addKToMatrix: not implemented yet') pass + +def createScene(root): + root.dt = 0.01 + root.addObject('DefaultVisualManagerLoop') + root.addObject('DefaultAnimationLoop') + + node1 = root.addChild("Node1") + + node1.addObject('EulerImplicitSolver') + node1.addObject('CGLinearSolver', iterations="100", tolerance="10-3", threshold="10-3") + node1.addObject('MechanicalObject', template="Vec3d") + + # Add our python forcefield in the scene + node1.addObject( EmptyForceField(name="MyEmptyForceField") ) + + +def main(): + root=Sofa.Core.Node("root") + createScene(root) + Sofa.Simulation.init(root) + + 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() + + print("End of simulation.") + + +if __name__ == '__main__': + main() diff --git a/examples/example.pyscn b/examples/example.pyscn deleted file mode 100644 index 99475184..00000000 --- a/examples/example.pyscn +++ /dev/null @@ -1,16 +0,0 @@ -# coding: utf8 - -import sys -import Sofa - -def createScene(root): - node1 = root.addChild("Node1") - node2 = root.addChild("Node2") - - node1.addObject("MechanicalObject") - node1.addObject("OglModel") - - node2.addObject("MechanicalObject") - node2.addObject("OglModel") - - return root diff --git a/examples/liver.py b/examples/liver.py new file mode 100644 index 00000000..97ac43fe --- /dev/null +++ b/examples/liver.py @@ -0,0 +1,71 @@ +# Required import for python +import Sofa +import SofaRuntime +import Sofa.Gui + + +# Choose in your script to activate or not the GUI +USE_GUI = True + + +def main(): + SofaRuntime.importPlugin("SofaOpenglVisual") + + 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, -9.81, 0] + root.dt=0.02 + + root.addObject('DefaultVisualManagerLoop') + root.addObject('DefaultAnimationLoop') + + root.addObject('VisualStyle', displayFlags="showCollisionModels") + root.addObject('RequiredPlugin', pluginName="SofaOpenglVisual SofaBoundaryCondition SofaGeneralLoader SofaGeneralSimpleFem") + root.addObject('DefaultPipeline', name="CollisionPipeline") + root.addObject('BruteForceDetection', name="N2") + root.addObject('DefaultContactManager', name="CollisionResponse", response="default") + root.addObject('DiscreteIntersection') + + root.addObject('MeshObjLoader', name="LiverSurface", filename="mesh/liver-smooth.obj") + + liver = root.addChild('Liver') + liver.addObject('EulerImplicitSolver', name="cg_odesolver", rayleighStiffness="0.1", rayleighMass="0.1") + liver.addObject('CGLinearSolver', name="linear_solver", iterations="25", tolerance="1e-09", threshold="1e-09") + liver.addObject('MeshGmshLoader', name="meshLoader", filename="mesh/liver.msh") + liver.addObject('TetrahedronSetTopologyContainer', name="topo", src="@meshLoader") + liver.addObject('MechanicalObject', name="dofs", src="@meshLoader") + liver.addObject('TetrahedronSetGeometryAlgorithms', template="Vec3d", name="GeomAlgo") + liver.addObject('DiagonalMass', name="Mass", massDensity="1.0") + liver.addObject('TetrahedralCorotationalFEMForceField', template="Vec3d", name="FEM", method="large", poissonRatio="0.3", youngModulus="3000", computeGlobalMatrix="0") + liver.addObject('FixedConstraint', name="FixedConstraint", indices="3 39 64") + + visu = liver.addChild('Visu') + visu.addObject('OglModel', name="VisualModel", src="@../../LiverSurface") + visu.addObject('BarycentricMapping', name="VisualMapping", input="@../dofs", output="@VisualModel") + + surf = liver.addChild('Surf') + surf.addObject('SphereLoader', name="sphereLoader", filename="mesh/liver.sph") + surf.addObject('MechanicalObject', name="spheres", position="@sphereLoader.position") + surf.addObject('SphereCollisionModel', name="CollisionModel", listRadius="@sphereLoader.listRadius") + surf.addObject('BarycentricMapping', name="CollisionMapping", input="@../dofs", output="@spheres") + + return root + + +# Function used only if this script is called from a python environment +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/test.scn b/examples/test.scn deleted file mode 100644 index f5e9e027..00000000 --- a/examples/test.scn +++ /dev/null @@ -1,3 +0,0 @@ - - -