Skip to content

Commit 8151cfe

Browse files
psomers3ac133451
andauthored
[SofaGL] Start a Sofa.SofaGL Module (#109)
* [Sofa.GL] Create SofaGL Module * Set up bindings structure for SofaGL * Added just basic draw() and initGlew() functions * [examples] Added example viewers using pygame and pyqt * [examples] Added example viewers using pygame and pyqt * cleaned commit issue * [cmake] added QUIET to Sofa.GL find * [cmake] Sofa.gl -> Sofa.GL * [SofaGL] added function descriptions * [examples] cleaned examples a bit Co-authored-by: ac133451 <[email protected]>
1 parent b293cc4 commit 8151cfe

File tree

8 files changed

+483
-1
lines changed

8 files changed

+483
-1
lines changed

bindings/Modules/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ project(Bindings.Modules)
22

33
set(MODULEBINDINGS_MODULE_LIST SofaBaseTopology SofaDeformable)
44

5+
find_package(Sofa.GL QUIET)
6+
if(Sofa.GL_FOUND)
7+
list(APPEND MODULEBINDINGS_MODULE_LIST SofaGL)
8+
else()
9+
message("Sofa.GL not detected. Python3 Bindings for Sofa.SofaGL will not be compiled.")
10+
endif()
11+
12+
513
foreach(modulebindings_module ${MODULEBINDINGS_MODULE_LIST})
614
add_subdirectory(src/SofaPython3/${modulebindings_module})
715
endforeach()
@@ -19,4 +27,4 @@ install(TARGETS ${PROJECT_NAME} EXPORT BindingsTargets)
1927

2028
if(SP3_BUILD_TEST)
2129
add_subdirectory(tests)
22-
endif()
30+
endif()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/******************************************************************************
2+
* SofaPython3 plugin *
3+
* (c) 2021 CNRS, University of Lille, INRIA *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#include <pybind11/pybind11.h>
22+
23+
#include <sofa/simulation/Node.h>
24+
using sofa::simulation::Node;
25+
26+
#include <sofa/core/visual/VisualParams.h>
27+
28+
#include <sofa/simulation/Simulation.h>
29+
#include <sofa/gl/DrawToolGL.h>
30+
31+
#include <SofaPython3/SofaGL/Binding_DrawToolGL.h>
32+
#include <SofaPython3/SofaGL/Binding_DrawToolGL_doc.h>
33+
34+
35+
namespace sofapython3 {
36+
37+
using DrawToolGL = sofa::gl::DrawToolGL;
38+
39+
40+
namespace py { using namespace pybind11; }
41+
42+
void moduleAddDrawToolGL(pybind11::module& m) {
43+
m.def("draw", [](Node* node){
44+
auto* vparam = sofa::core::visual::VisualParams::defaultInstance();
45+
vparam->drawTool() = new sofa::gl::DrawToolGL();
46+
vparam->setSupported(sofa::core::visual::API_OpenGL);
47+
sofa::simulation::getSimulation()->draw(vparam, node);
48+
}, doc::SofaGL::draw);
49+
50+
m.def("glewInit", [](){
51+
glewInit();
52+
}, doc::SofaGL::glewInit);
53+
}
54+
55+
} // namespace sofapython3
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
#include <pybind11/pybind11.h>
24+
25+
namespace sofapython3 {
26+
27+
void moduleAddDrawToolGL(pybind11::module& m);
28+
29+
} // namespace sofapython3
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
namespace sofapython3::doc::SofaGL {
24+
static auto draw =
25+
R"(
26+
Draw the openGL visual loop from the provided Node.
27+
:param node: Node to start visualize from
28+
:type node: Sofa::Simulation::Node
29+
)";
30+
31+
static auto glewInit =
32+
R"(
33+
Initialize GLEW. This should be called once before drawing.
34+
)";
35+
36+
} // sofapython3::doc::SofaGL
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
project(Bindings.Modules.SofaGL)
2+
3+
set(SOURCE_FILES
4+
${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaGL.cpp
5+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.cpp
6+
)
7+
8+
set(HEADER_FILES
9+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.h
10+
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL_doc.h
11+
)
12+
13+
if (NOT TARGET SofaPython3::Plugin)
14+
find_package(SofaPython3 REQUIRED)
15+
endif()
16+
17+
find_package(Sofa.GL REQUIRED)
18+
19+
SP3_add_python_module(
20+
TARGET ${PROJECT_NAME}
21+
PACKAGE Bindings
22+
MODULE SofaGL
23+
DESTINATION Sofa
24+
SOURCES ${SOURCE_FILES}
25+
HEADERS ${HEADER_FILES}
26+
DEPENDS Sofa.GL SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core
27+
28+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#include <pybind11/pybind11.h>
22+
#include <SofaPython3/SofaGL/Binding_DrawToolGL.h>
23+
24+
25+
namespace py { using namespace pybind11; }
26+
27+
namespace sofapython3
28+
{
29+
30+
PYBIND11_MODULE(SofaGL, m)
31+
{
32+
moduleAddDrawToolGL(m);
33+
}
34+
35+
} // namespace sofapython3
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import Sofa
2+
import Sofa.SofaGL
3+
import SofaRuntime
4+
import Sofa.Simulation as sim
5+
import os
6+
import time
7+
sofa_directory = os.environ['SOFA_ROOT']
8+
import pygame
9+
from OpenGL.GL import *
10+
from OpenGL.GLU import *
11+
12+
13+
pygame.display.init()
14+
display_size = (800, 600)
15+
pygame.display.set_mode(display_size, pygame.DOUBLEBUF | pygame.OPENGL)
16+
17+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
18+
glEnable(GL_LIGHTING)
19+
glEnable(GL_DEPTH_TEST)
20+
Sofa.SofaGL.glewInit()
21+
glMatrixMode(GL_PROJECTION)
22+
glLoadIdentity()
23+
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
24+
25+
glMatrixMode(GL_MODELVIEW)
26+
glLoadIdentity()
27+
28+
def simple_render(rootNode):
29+
"""
30+
Get the OpenGL Context to render an image (snapshot) of the simulation state
31+
"""
32+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
33+
glEnable(GL_LIGHTING)
34+
glEnable(GL_DEPTH_TEST)
35+
glMatrixMode(GL_PROJECTION)
36+
glLoadIdentity()
37+
gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)
38+
glMatrixMode(GL_MODELVIEW)
39+
glLoadIdentity()
40+
41+
cameraMVM = rootNode.visuals.camera.getOpenGLModelViewMatrix()
42+
glMultMatrixd(cameraMVM)
43+
44+
Sofa.SofaGL.draw(rootNode.visuals)
45+
46+
pygame.display.get_surface().fill((0,0,0))
47+
pygame.display.flip()
48+
49+
50+
class scene_interface:
51+
"""Scene_interface provides step and reset methods"""
52+
53+
def __init__(self, max_steps=1000):
54+
# max_steps, how long the simulator should run. Total length: dt*max_steps
55+
self.max_steps = max_steps
56+
57+
# the current step in the simulation
58+
self.current_step = 0
59+
# Register all the common component in the factory.
60+
SofaRuntime.PluginRepository.addFirstPath(os.path.join(sofa_directory, 'plugins'))
61+
SofaRuntime.importPlugin('SofaOpenglVisual')
62+
SofaRuntime.importPlugin("SofaComponentAll")
63+
SofaRuntime.importPlugin("SofaGeneralLoader")
64+
SofaRuntime.importPlugin("SofaImplicitOdeSolver")
65+
SofaRuntime.importPlugin("SofaLoader")
66+
SofaRuntime.importPlugin("SofaSimpleFem")
67+
SofaRuntime.importPlugin("SofaBoundaryCondition")
68+
SofaRuntime.importPlugin("SofaMiscForceField")
69+
70+
self.root = Sofa.Core.Node("myroot")
71+
72+
### create some objects to observe
73+
self.place_objects_in_scene(self.root)
74+
75+
# place light and a camera
76+
self.visuals = self.root.addChild('visuals')
77+
self.visuals.addObject("LightManager")
78+
self.visuals.addObject("SpotLight", position=[0,10,0], direction=[0,-1,0])
79+
self.visuals.addObject("InteractiveCamera", name="camera", position=[0,10, 0],
80+
lookAt=[0,0,0], distance=37,
81+
fieldOfView=45, zNear=0.63, zFar=55.69)
82+
83+
# start the simulator
84+
Sofa.Simulation.init(self.root)
85+
86+
def place_objects_in_scene(self, root):
87+
### these are just some things that stay still and move around
88+
# so you know the animation is actually happening
89+
root.gravity = [0, -1., 0]
90+
root.addObject("VisualStyle", displayFlags="showBehaviorModels showAll")
91+
root.addObject("MeshGmshLoader", name="meshLoaderCoarse",
92+
filename="mesh/liver.msh")
93+
root.addObject("MeshObjLoader", name="meshLoaderFine",
94+
filename="mesh/liver-smooth.obj")
95+
96+
root.addObject("EulerImplicitSolver")
97+
root.addObject("CGLinearSolver", iterations="200",
98+
tolerance="1e-09", threshold="1e-09")
99+
100+
liver = root.addChild("liver")
101+
102+
liver.addObject("TetrahedronSetTopologyContainer",
103+
name="topo", src="@../meshLoaderCoarse" )
104+
liver.addObject("TetrahedronSetGeometryAlgorithms",
105+
template="Vec3d", name="GeomAlgo")
106+
liver.addObject("MechanicalObject",
107+
template="Vec3d",
108+
name="MechanicalModel", showObject="1", showObjectScale="3")
109+
110+
liver.addObject("TetrahedronFEMForceField", name="fem", youngModulus="1000",
111+
poissonRatio="0.4", method="large")
112+
113+
liver.addObject("MeshMatrixMass", massDensity="1")
114+
liver.addObject("FixedConstraint", indices="2 3 50")
115+
116+
def step(self):
117+
# this steps the simulation
118+
Sofa.Simulation.animate(self.root, self.root.getDt())
119+
self.visuals.camera.position = self.visuals.camera.position + [-0.002, 0, 0]
120+
simple_render(self.root)
121+
122+
# just to keep track of where we are
123+
self.current_step += 1
124+
125+
# return true if done
126+
return self.current_step >= self.max_steps
127+
128+
129+
if __name__ == '__main__':
130+
a = scene_interface()
131+
done = False
132+
while not done:
133+
factor = a.current_step
134+
done = a.step()
135+
time.sleep(a.root.getDt())

0 commit comments

Comments
 (0)