Fellow Ogres,
I am writing a CAD software that uses Ogre3d, G+Smo and pybind11. It is multithreaded and Ogre3d rendering occurs in a dedicated thread.
https://github.com/andre-caldas/ParaCADis/
The CAD data is kept in a very parametric data structure. The parameters are the essential parameters for each structure type. Because of multithreading, in order for these parameters to be accessed, a "lock" must be acquired. I call it a "gate". And you use this gate to access the data. There are gates for reading and gates for writing.
Changes to this structure are propagated, via a messaging system, to a thread (or some threads) that constructs G+Smo objects. Those objects can be used, in the near future, to do IgA (isogeometric analysis)... it is some sort of more efficient FEM (finite element method).
Changes to this other structure are propagated, via a messaging system, to the Ogre3d thread. Between the renderings, a hook is called to pull those messages and update the Ogre Scene.
Here are two very very non-exciting videos:
The script I used is here:
Code: Select all
import Ogre
import Ogre.Bites
import Ogre.RTShader
import threading
class KeyListener(Ogre.Bites.InputListener):
def keyPressed(self, evt):
if evt.keysym.sym == Ogre.Bites.SDLK_ESCAPE:
Ogre.Root.getSingleton().queueEndRendering()
return True
class App(threading.Thread):
def run(self):
ctx = Ogre.Bites.ApplicationContext("PySample")
ctx.initApp()
root = ctx.getRoot()
self.root = root
scn_mgr = root.createSceneManager()
self.scn_mgr = scn_mgr
# register for input events
klistener = KeyListener() # must keep a reference around
ctx.addInputListener(klistener)
shadergen = Ogre.RTShader.ShaderGenerator.getSingleton()
shadergen.addSceneManager(scn_mgr) # must be done before we do anything with the scene
# without light we would just get a black screen
scn_mgr.setAmbientLight((.1, .1, .1))
light = scn_mgr.createLight("MainLight")
lightnode = scn_mgr.getRootSceneNode().createChildSceneNode()
lightnode.setPosition(0, 10, 15)
lightnode.attachObject(light)
# create the camera
cam = scn_mgr.createCamera("myCam")
cam.setNearClipDistance(5)
cam.setAutoAspectRatio(True)
camnode = scn_mgr.getRootSceneNode().createChildSceneNode()
camnode.attachObject(cam)
# map input events to camera controls
camman = Ogre.Bites.CameraMan(camnode)
camman.setStyle(Ogre.Bites.CS_ORBIT)
camman.setYawPitchDist(0, 0.3, 15)
ctx.addInputListener(camman)
self.camman = camman
# and tell it to render into the main window
vp = ctx.getRenderWindow().addViewport(cam)
vp.setBackgroundColour((.3, .3, .3))
# finally something to render
ent = scn_mgr.createEntity("Sinbad.mesh")
self.sinbad = ent
node = scn_mgr.getRootSceneNode().createChildSceneNode()
node.attachObject(ent)
root.startRendering()
ctx.closeApp()
app = App()
app.start()
import paracadis as pc
import paracadis.geometric_primitives as geo
import paracadis_scene_graph as sg
try:
doc = pc.document.Document()
circle = geo.CirclePointRadius2Normal([0,0,0], 25, [0,0,1])
sphere = geo.SphereCenterSurfacePoint([0,0,0], [2,2,2])
# doc.add_element(circle)
# doc.add_element(sphere)
scene = sg.Scene(app.scn_mgr)
scene.populate(doc)
# input('paused... press <enter>... ')
# print('pressed enter... continuing')
circle = geo.CirclePointRadius2Normal([0,0,1], 25, [0,0,1])
# sphere = geo.SphereCenterSurfacePoint([1,1,1], [3,3,3])
sphere = geo.SphereCenterRadius2([1,1,1], 25)
# doc.add_element(sphere)
cont_a = pc.document.Container()
cont_a.add_element(circle)
# cont_a.add_element(sphere)
# pos = geo.DeferenceableCoordinatePointsXY([1,2,3])
# cont_a.set_coordinates(pos)
doc.add_container(cont_a)
import time
import math
ref = geo.ReferenceToReal(circle, "radius2")
# ref = geo.ReferenceToReal(sphere, "radius2")
res = ref.resolve()
delta = 1/10
for x in range(100):
print(x)
wl = res.wgate()
wl.access().set((4 + 3 * math.sin(time.time()))**2)
wl = None # Release the lock
time.sleep(delta)
except Exception as e:
print('Exception', e)
print('End!')
For Ogre multithreading, I do not use "allowPyThread()". Instead, I have patched the Ogre SWIG configuration in order to make ogre calls in python to be thread safe without the rendering thread needing to holding the GIL lock for so long. I call "startRendering()" in a new thread, and Ogre rendering loop occurs in this thread. There is no "rendering one single frame" in the python code. Changes to the Ogre Scene (or any code to be executed between frames) are sent via messaging system. This is my Ogre3d branch:
https://github.com/andre-caldas/ogre/tr ... ringThread
In order to have a GUI, it would be nice to know how to get Ogre to render to a "canvas" inside the main window. Then the GUI could call python code and display the results, like FreeCAD does. See: viewtopic.php?t=97359