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
10 changes: 9 additions & 1 deletion bindings/Modules/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ project(Bindings.Modules)

set(MODULEBINDINGS_MODULE_LIST SofaBaseTopology SofaDeformable)

find_package(Sofa.GL QUIET)
if(Sofa.GL_FOUND)
list(APPEND MODULEBINDINGS_MODULE_LIST SofaGL)
else()
message("Sofa.GL not detected. Python3 Bindings for Sofa.SofaGL will not be compiled.")
endif()


foreach(modulebindings_module ${MODULEBINDINGS_MODULE_LIST})
add_subdirectory(src/SofaPython3/${modulebindings_module})
endforeach()
Expand All @@ -19,4 +27,4 @@ install(TARGETS ${PROJECT_NAME} EXPORT BindingsTargets)

if(SP3_BUILD_TEST)
add_subdirectory(tests)
endif()
endif()
55 changes: 55 additions & 0 deletions bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/******************************************************************************
* SofaPython3 plugin *
* (c) 2021 CNRS, University of Lille, INRIA *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/

#include <pybind11/pybind11.h>

#include <sofa/simulation/Node.h>
using sofa::simulation::Node;

#include <sofa/core/visual/VisualParams.h>

#include <sofa/simulation/Simulation.h>
#include <sofa/gl/DrawToolGL.h>

#include <SofaPython3/SofaGL/Binding_DrawToolGL.h>
#include <SofaPython3/SofaGL/Binding_DrawToolGL_doc.h>


namespace sofapython3 {

using DrawToolGL = sofa::gl::DrawToolGL;


namespace py { using namespace pybind11; }

void moduleAddDrawToolGL(pybind11::module& m) {
m.def("draw", [](Node* node){
auto* vparam = sofa::core::visual::VisualParams::defaultInstance();
vparam->drawTool() = new sofa::gl::DrawToolGL();
vparam->setSupported(sofa::core::visual::API_OpenGL);
sofa::simulation::getSimulation()->draw(vparam, node);
}, doc::SofaGL::draw);

m.def("glewInit", [](){
glewInit();
}, doc::SofaGL::glewInit);
}

} // namespace sofapython3
29 changes: 29 additions & 0 deletions bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/******************************************************************************
* SOFA, Simulation Open-Framework Architecture *
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/

#pragma once

#include <pybind11/pybind11.h>

namespace sofapython3 {

void moduleAddDrawToolGL(pybind11::module& m);

} // namespace sofapython3
36 changes: 36 additions & 0 deletions bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL_doc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/******************************************************************************
* SOFA, Simulation Open-Framework Architecture *
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/

#pragma once

namespace sofapython3::doc::SofaGL {
static auto draw =
R"(
Draw the openGL visual loop from the provided Node.
:param node: Node to start visualize from
:type node: Sofa::Simulation::Node
)";

static auto glewInit =
R"(
Initialize GLEW. This should be called once before drawing.
)";

} // sofapython3::doc::SofaGL
28 changes: 28 additions & 0 deletions bindings/Modules/src/SofaPython3/SofaGL/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
project(Bindings.Modules.SofaGL)

set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaGL.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.cpp
)

set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL_doc.h
)

if (NOT TARGET SofaPython3::Plugin)
find_package(SofaPython3 REQUIRED)
endif()

find_package(Sofa.GL REQUIRED)

SP3_add_python_module(
TARGET ${PROJECT_NAME}
PACKAGE Bindings
MODULE SofaGL
DESTINATION Sofa
SOURCES ${SOURCE_FILES}
HEADERS ${HEADER_FILES}
DEPENDS Sofa.GL SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core

)
35 changes: 35 additions & 0 deletions bindings/Modules/src/SofaPython3/SofaGL/Module_SofaGL.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/******************************************************************************
* SOFA, Simulation Open-Framework Architecture *
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 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 Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Contact information: [email protected] *
******************************************************************************/

#include <pybind11/pybind11.h>
#include <SofaPython3/SofaGL/Binding_DrawToolGL.h>


namespace py { using namespace pybind11; }

namespace sofapython3
{

PYBIND11_MODULE(SofaGL, m)
{
moduleAddDrawToolGL(m);
}

} // namespace sofapython3
135 changes: 135 additions & 0 deletions examples/additional-examples/pygame_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import Sofa
import Sofa.SofaGL
import SofaRuntime
import Sofa.Simulation as sim
import os
import time
sofa_directory = os.environ['SOFA_ROOT']
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *


pygame.display.init()
display_size = (800, 600)
pygame.display.set_mode(display_size, pygame.DOUBLEBUF | pygame.OPENGL)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_DEPTH_TEST)
Sofa.SofaGL.glewInit()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

def simple_render(rootNode):
"""
Get the OpenGL Context to render an image (snapshot) of the simulation state
"""
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

cameraMVM = rootNode.visuals.camera.getOpenGLModelViewMatrix()
glMultMatrixd(cameraMVM)

Sofa.SofaGL.draw(rootNode.visuals)

pygame.display.get_surface().fill((0,0,0))
pygame.display.flip()


class scene_interface:
"""Scene_interface provides step and reset methods"""

def __init__(self, max_steps=1000):
# max_steps, how long the simulator should run. Total length: dt*max_steps
self.max_steps = max_steps

# the current step in the simulation
self.current_step = 0
# Register all the common component in the factory.
SofaRuntime.PluginRepository.addFirstPath(os.path.join(sofa_directory, 'plugins'))
SofaRuntime.importPlugin('SofaOpenglVisual')
SofaRuntime.importPlugin("SofaComponentAll")
SofaRuntime.importPlugin("SofaGeneralLoader")
SofaRuntime.importPlugin("SofaImplicitOdeSolver")
SofaRuntime.importPlugin("SofaLoader")
SofaRuntime.importPlugin("SofaSimpleFem")
SofaRuntime.importPlugin("SofaBoundaryCondition")
SofaRuntime.importPlugin("SofaMiscForceField")

self.root = Sofa.Core.Node("myroot")

### create some objects to observe
self.place_objects_in_scene(self.root)

# place light and a camera
self.visuals = self.root.addChild('visuals')
self.visuals.addObject("LightManager")
self.visuals.addObject("SpotLight", position=[0,10,0], direction=[0,-1,0])
self.visuals.addObject("InteractiveCamera", name="camera", position=[0,10, 0],
lookAt=[0,0,0], distance=37,
fieldOfView=45, zNear=0.63, zFar=55.69)

# start the simulator
Sofa.Simulation.init(self.root)

def place_objects_in_scene(self, root):
### these are just some things that stay still and move around
# so you know the animation is actually happening
root.gravity = [0, -1., 0]
root.addObject("VisualStyle", displayFlags="showBehaviorModels showAll")
root.addObject("MeshGmshLoader", name="meshLoaderCoarse",
filename="mesh/liver.msh")
root.addObject("MeshObjLoader", name="meshLoaderFine",
filename="mesh/liver-smooth.obj")

root.addObject("EulerImplicitSolver")
root.addObject("CGLinearSolver", iterations="200",
tolerance="1e-09", threshold="1e-09")

liver = root.addChild("liver")

liver.addObject("TetrahedronSetTopologyContainer",
name="topo", src="@../meshLoaderCoarse" )
liver.addObject("TetrahedronSetGeometryAlgorithms",
template="Vec3d", name="GeomAlgo")
liver.addObject("MechanicalObject",
template="Vec3d",
name="MechanicalModel", showObject="1", showObjectScale="3")

liver.addObject("TetrahedronFEMForceField", name="fem", youngModulus="1000",
poissonRatio="0.4", method="large")

liver.addObject("MeshMatrixMass", massDensity="1")
liver.addObject("FixedConstraint", indices="2 3 50")

def step(self):
# this steps the simulation
Sofa.Simulation.animate(self.root, self.root.getDt())
self.visuals.camera.position = self.visuals.camera.position + [-0.002, 0, 0]
simple_render(self.root)

# just to keep track of where we are
self.current_step += 1

# return true if done
return self.current_step >= self.max_steps


if __name__ == '__main__':
a = scene_interface()
done = False
while not done:
factor = a.current_step
done = a.step()
time.sleep(a.root.getDt())
Loading