Renderer

The Renderer is the substructure of SystemContainer that collects rendering and visualization interaction, in particular starting and stopping the renderer, image retrieval and materials. Rendering is done for a single SystemContainer, which may include several MainSystems. Note that visualizationSettings are directly accessible from the SystemContainer.

import exudyn as exu
from exudyn.utilities import *
import exudyn.graphics as graphics
SC = exu.SystemContainer()
mbs = SC.AddSystem()
mbs.CreateMassPoint(mass=1)

mbs.Assemble()
SC.visualizationSettings.view0.scene.drawWorldBasis = True
SC.renderer.Start()
SC.renderer.DoIdleTasks() #wait until user presses space, etc.
mbs.SolveDynamic()
SC.renderer.Stop()

python/Notebooks/reference/systemContainer.ipynb

The class MainRenderer has the following functions and structures:

  • Start(verbose = 0): Start OpenGL rendering engine (in separate thread) for visualization of rigid or flexible multibody system; use verbose=1 to output information during OpenGL window creation; verbose=2 produces more output and verbose=3 gives a debug level; some of the information will only be seen in windows command (powershell) windows or linux shell, but not inside iPython of e.g., Spyder

  • Stop(): Stop OpenGL rendering engine; uses timeout in multithreading.

  • IsActive(): returns True if GLFW renderer is available and running; otherwise False

  • Attach(): Links the SystemContainer to the render engine, such that the changes in the graphics structure drawn upon updates, etc.; done automatically on creation of SystemContainer; return False, if no renderer exists (e.g., compiled without GLFW) or cannot be linked (if other SystemContainer already linked)

  • Detach(): DEPRECATED; Releases the SystemContainer from the render engine; return True if successfully released, False if no GLFW available or detaching failed; removed in 2029

  • StopSimulation(forceQuit = True): Stop the simulation as closing the render window does: a running simulation ends after its current step, quietly and without an error, as if the user had stopped it; with forceQuit=True (default) a simulation that starts later ends before its first step as well, until mbs.SetRenderEngineStopFlag(False) resets it - which is what pressing Escape or closing the window does. Works without an open renderer, e.g. from a user function, another thread or a test

    Example:

    SC.renderer.StopSimulation()
    
  • DoIdleTasks(waitSeconds = -1., printPauseMessage = True, pollEvents = True): Interrupt further computation until user input (Space, ‘Q’, Escape-key), representing a PAUSE function; this command runs a loop in the background to have active response of the render window, e.g., to open the visualization dialog or use the right-mouse-button; replaces former SC.WaitForRenderEngineStopFlag() and mbs.WaitForUserToContinue(); call this function in order to interact with Renderer window; use waitSeconds in order to run this idle tasks while animating a model (e.g., waitSeconds=0.04), use waitSeconds=0 without waiting, or use waitSeconds=-1 (default) to wait until window is closed; pollEvents=False: the renderer draws and runs queued commands, but leaves the window events to the event loop that called it - a tkinter dialog calling this from its after-callback on macOS, where both share one event loop; NOTE: may also first initialize renderState from visualizationSettings (if renderer is inactive)

    Example:

    SC.renderer.DoIdleTasks()
    
  • EnableView(viewID, createWindow = True): Enables a specified view (1,2 or 3) additionally to the main view (0); a window is created if createWindow=True, otherwise, the view is only enabled to use it with the raytracer; NOTE: additional views cause slightly more workload for the renderer which is why they are disabled by default; failure to create the view usually results in an exception; to check whether the view exists, check the according RenderState regarding viewEnabled and windowOpen

  • DisableView(viewID): Disables a specified view (1,2 or 3) and (if created) closes the according window; NOTE: in case of renderer.Stop(), all views are closed; NOTE: if you still aim to use the view without the window, you have to enable the view again EnableView(…, createWindow=False)

  • ZoomAll(computeMaxScene = True, viewID = 0): Send zoom all signal, which will perform zoom all at next redraw request; if renderer is inactive (renderer.IsActive()=0), it will perform computations for renderState, thus at the next RedrawAndGetImage() having the full view as with the OpenGL renderer; NOTE: in case of OpenGL, call ZoomAll() after renderer.Start(); NOTE: may also first initialize renderState from visualizationSettings (if renderer is inactive)

  • SetModelView(zoom = 0, rotationVector = [0,0,0], centerPoint = [0,0,0], viewID = 0): Function to adjusts the current view in renderState; rotationVector and centerPoint transform the modelView while zoom equals the visible scene height; rotationVector is the axis of rotation times the angle in radiant; if zoom=0 then zoom will be computed automatically like in autoFitScene with openGL; use this function in particular for raytracing before RedrawAndGetImage() or with regular OpenGL after renderer.Start(); you can also store the renderState and write the full renderState alternatively; NOTE: may also first initialize renderState from visualizationSettings (if renderer is inactive)

    Example:

    SC.renderer.SetModelView(10,[0,0,pi],[2.5,0,0])
    image=SC.renderer.RedrawAndGetImage()
    
  • RedrawAndSaveImage(viewID = 0): Redraw openGL scene and save image (command waits until process is finished); uses the current rendering engine (OpenGL or raytracer).

  • RedrawAndGetImage(useRaytracer = False, viewID = 0): Redraw scene and return image in numpy-format, containing a 3-dimensional array with 3 matrices of RGB channels; the shape is according to (height,width,3) where height and width represent the window pixels defined in visualizationSettings.window.renderWindowSize (Note: in case that raytracer.imageSizeFactor>1 the retrieved image size is smaller by the imageSizeFactor!); command waits until process is finished; if useRaytracer=False, the openGL render is used and the render window needs to be opened before; if useRaytracer=True, the software raytracer is used which runs completely without GLFW and OpenGL (e.g., on a supercomputer); NOTE: in case of useRaytracer=True the displayScaling factor is only available if the OpenGL renderer has been opened once; otherwise e.g., SC.renderer.SetState({‘displayScaling’:1.5}) has to be used to adjust it; NOTE: may also first initialize renderState from visualizationSettings (if renderer is inactive)

    Example:

    import matplotlib.pyplot as plt
    image=SC.renderer.RedrawAndGetImage()
    plt.imshow(image)
    plt.axis('off')
    plt.show()
    
  • GetGraphicsData(flatShapes = False): the drawing elements of the scene as a dictionary of numpy arrays: what the renderer would draw, as data. It is built without a window, the way RedrawAndGetImage(True) builds it, so it works with EXUDYN_SUPPRESS_UI_WINDOW_OPEN set and needs no OpenGL; zoom, model view and window size are not part of it. The keys lines, spheres, circles, texts and triangles each hold a dictionary whose items is an int array of shape (n,3) - the system number, the exudyn.ItemType value and the index of the item that drew the element, or [-1, 0, code] for a static element of the scene; then points and colors (RGBA, per vertex for lines and triangles), and per kind radius and resolution (spheres), radius and numberOfSegments (circles), fontSize, offset and the list text (texts), normals (triangles). The curved shapes are kept as they are under triangles6 (6-node triangles: points, normals and colors of shape (n,6,3) / (n,6,4), nodes as in the key triangles6 of a TriangleList; the normals given, else those of the geometry) and lines3 (quadratic lines: points (n,3,3) and colors (n,3,4), the end points and then the mid node); with flatShapes=True these two are empty and their shapes are among triangles and lines instead, refined once - 4 triangles on the 6 nodes, 2 lines on the 3 nodes - independently of the tiling settings, which only the renderers apply. formatVersion is 1. It is the oracle of the graphics tests: the number of elements per item is exact, coordinates are floats and are compared with a tolerance

    Example:

    data = SC.renderer.GetGraphicsData()
    print(len(data['triangles']['items']), 'triangles')
    
  • GetState(viewID = 0): Get dictionary with current render state (openGL zoom, modelview, etc.)

    Example:

    SC = exu.SystemContainer()
    renderState = SC.renderer.GetState()
    print(renderState['zoom'])
    
  • SetState(renderState, waitForRendererFullStartup = True, viewID = 0): Set current render state (openGL zoom, modelview, etc.) with given dictionary; usually, this dictionary has been obtained with GetRenderState; waitForRendererFullStartup is used to wait at startup for the first frame to be drawn (and zoom all to be set), but be be set False in case of performance issues; NOTE: before setting available state values, this function may also first initialize renderState from visualizationSettings (if renderer is inactive)

    Example:

    SC = exu.SystemContainer()
    SC.renderer.SetState(renderState)
    
  • RestoreSavedState(viewID = 0): Restore the render state that exu.sys holds: renderer.Stop() saves the state of every open view there, so this brings back the view of the previous run; returns False if nothing has been saved yet, which is not an error but the ordinary case on the first run of a script; it replaces the two lines that tested for renderState in exu.sys and called SetState with it

    Example:

    SC = exu.SystemContainer()
    SC.renderer.Start()
    SC.renderer.RestoreSavedState()
    
  • GetMouseCoordinates(useOpenGLcoordinates = False, viewID = 0): Get current mouse coordinates as list [x, y]; x and y being floats, as returned by GLFW, measured from top left corner of window; use GetCurrentMouseCoordinates(useOpenGLcoordinates=True) to obtain OpenGLcoordinates of projected plane

  • GetItemSelection(resetSelection = True, viewID = 0): Get selected item in render state; option to reset selected item afterwards; item is selected in render window by clicking left mouse button; returns [mbs number, ItemType, ItemIndex, depth] where depth is the Z-depth in the current view; note that only items of the categories activated in visualizationSettings.interactive.selectionLeftMouseItemTypes are returned; NOTE: if itemType == 0, no item has been selected

  • ResetState(): Reset renderState in all views to default values using current visualizationSettings; usually this does not have to be called!

  • SendRedrawSignal(): This function is used to send a signal to the renderer that all MainSystems (mbs) shall be redrawn

  • GetRenderCount(): Returns the number of rendered OpenGL images; can be used to determine if image has been drawn by comparing to previous counter; also shows that first image has been drawn (needed for zoom all)

  • materials: GraphicsMaterialList used for raytracer (possibly for OpenGL in future); list can be accessed with [] operator, reset and extended. Note that after Reset() there are at least 10 materials available, which are copied from visualizationSettings.raytracer.materials which are synced continuously