Looking for a simple window renderer for Python - python

I'm currently looking for a simple step-by-step window renderer library for Python.
The main idea behind what I need is that I want to be able to change the input data before I call the window render function, by doing so the window would render a moving point with some additional static points. The rendered window would refresh while the program is running. For example:
# Some points
data_points_x = [2,4,6,11,22]
data_points_y = [5,-1,23,41,1]
window.add(x, y, style="point")
# Another point
important_point_x = 23
important_point_y = 13
window.add(important_point_x, important_point_y, style="star")
# Main rendering loop
while True:
# Move one point
important_point_x = important_point_x + 1
window.render()
I know matplotlib can do something similar, but I'm interested if there is any other library capable of doing more, for example, rendering text, lines and so on. Finally, pyplot does not refresh the window when calling plot.show() when the program is running.

Related

Blender: Rendering images and producing an animation

I am new to Blender and I’m having a bit of a tough time understanding its key concepts. I am using Blender 2.82 and working with Python scripting. My project consists of using Python to do the following:
Move object slightly.
Take picture with camera 1, camera 2, camera 3, and camera 4.
Repeat.
I had a script that did that. However, I wanted to save the position of my object (a sphere) every time I changed it during the loop in an animation, so I could later see what I did. When trying to insert keyframes for animation in my loop, it seems as if my sphere didn’t move. Below is my code. When I remove the lines that include frame_set and keyframe_insert, my sphere moves as I can see from my rendered images. I think I am confusing some kind of concept… Any help would be appreciated. The goal of this is to produce the images I would obtain from four cameras placed around an object, that is moving, so as to simulate a mocap system.
Why does inserting a keyframe change all of the images being rendered?
import bpy, bgl, blf,sys
import numpy as np
from bpy import data, ops, props, types, context
cameraNames=''
# Loop all command line arguments and try to find "cameras=east" or similar
for arg in sys.argv:
words=arg.split('=')
if ( words[0] == 'cameras'):
cameraNames = words[1]
sceneKey = bpy.data.scenes.keys()[0]
# Loop all objects and try to find Cameras
bpy.data.scenes[sceneKey].render.image_settings.file_format = 'JPEG'
bpy.data.scenes[sceneKey].cycles.max_bounces=12
bpy.data.scenes[sceneKey].render.tile_x=8
bpy.data.scenes[sceneKey].render.tile_y=8
bpy.data.scenes[sceneKey].cycles.samples = 16
bpy.data.scenes[sceneKey].cycles.caustics_reflective = False
bpy.data.scenes[sceneKey].cycles.caustics_refractive = False
bpy.data.objects['Sphere'].location=[1,1,1]
frame_num=0
for i in range(0,2): #nframes
bpy.context.scene.frame_set(frame_num)
for obj in bpy.data.objects:
# Find cameras that match cameraNames
if ( obj.type =='CAMERA') and ( cameraNames == '' or obj.name.find(cameraNames) != -1) :
# Set Scenes camera and output filename
bpy.data.scenes[sceneKey].camera = obj
bpy.data.scenes[sceneKey].render.filepath = '//'+obj.name+"_"+str(i)
# Render Scene and store the scene
bpy.ops.render.render( write_still=True )
bpy.data.objects['Sphere'].keyframe_insert(data_path="location",index=-1)
frame_num+=1
bpy.data.objects['Sphere'].location=[2,2,1]
I have no knowledge of python, but you can try to do key frame animation manually and make a script which will render the pictures after a set of key frames(whenever the object has moved to a new location)
It is not too hard (I'm talking about only the animation), just press the circle button near the play animation button on the timeline. This will turn on auto key framing and you just have to go to the desired key frame and move the object according to your need.

How to create many instances of vtkContourWidget

I want to be able to create many instances of vtkContourWidget, letting the user draw lines and manipulating the nodes, but it seems I'm not doing it right.
Here is the code:
import vtk
def main():
# Create a renderer, render window, and interactor
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
Interactor = vtk.vtkRenderWindowInteractor()
Interactor.SetRenderWindow(renderWindow)
style = vtk.vtkInteractorStyleTerrain()
Interactor.SetInteractorStyle(style)
Interactor.AddObserver("KeyPressEvent", keyPressEvent)
# Render and interact
renderWindow.Render()
Interactor.Start()
def keyPressEvent(obj, event):
key = obj.GetKeySym()
if key == 'n':
contourRep = vtk.vtkOrientedGlyphContourRepresentation()
contourWidget = vtk.vtkContourWidget()
contourWidget.SetInteractor(obj)
contourWidget.SetRepresentation(contourRep)
contourWidget.On()
#contourWidget.SetEnabled()
obj.Start()
return
main()
It almost works fine this way, the problem is that, when I want to close the application window, I have to click the button to close the window many times. And I have to click one time for each vtkContourWidget created.
It seems that each time I call the function keyPressEvent and create a vtkContourWidget, the obj.Start() (that is the same of Interactor.Start()) line instantiates kind of another instance of the application?
I've also tried contourWidget.SetEnabled() (with obj.Start() commented out), and it works to create new instances of vtkContourWidget, but when I try to close the app window, the app freezes.
With both obj.Start() and contourWidget.SetEnabled() on the code, I can create many instances, but each time I create a new instance, the previous one disappears.
I think this topic may have the solution, but I don't know how to implement it.
Just copy-pasting your code and running it with VTK 6.3 on Ubuntu 16.04 seems to work correctly. The window closes as expected using the closing button or "q".
So this seems to be a bug related to the VTK release you are using on your system.
Kind regards.

Can't initialize turtle in Maya through scripting

I have a maya python tool that is supposed to load turtle, set it as the renderer, and then bake vertex AO on the selected object. The whole thing works except that when the user first opens Maya, it won't actually initialize the first time. It doesn't create the "TurtleDefaultBakeLayer" node for the script to modify attributes on. The user has to manually open the render settings window and then click on the "TURTLE" tab next to the "Common" tab for it to bake anything. After that it works exactly how it should with or without that Render Settings window open.
My question is, how do I get a freshly opened maya to get Turtle to initialize and instantiate those components without the user needing to open the Render Settings window?
def initializeTurtle(self):
#Load Turtle
cmds.loadPlugin('Turtle')
#Set renderer
cmds.setAttr("defaultRenderGlobals.currentRenderer", "turtle", type="string")
For anyone that was curious about solving this problem without opening the render settings window, the only viable solution we could come up with was to manually create the nodes Turtle needed, instead of relying on its automatic instantiation.
def initializeTurtle(self):
#Load Turtle
pluginStatus = cmds.pluginInfo( "Turtle", q = True, l = True, n = True )
if pluginStatus == False:
cmds.loadPlugin( "Turtle")
#Create bake nodes
cmds.setAttr("defaultRenderGlobals.currentRenderer", "turtle", type="string")
tOptions = cmds.createNode ("ilrOptionsNode", name="TurtleRenderOptions")
tBakeLayer = cmds.createNode ("ilrBakeLayer", name="TurtleDefaultBakeLayer")
tbakeLayerMgr = cmds.createNode ("ilrBakeLayerManager", name="TurtleBakeLayerManager")
cmds.connectAttr(tOptions+".message", tBakeLayer+".renderOptions")
cmds.connectAttr(tBakeLayer+".index", tbakeLayerMgr+".bakeLayerId[0]")

Plot in python that updates on keyboard hit

I've been struggling to achieve something that is trivial in Octave: to produce a series of plots, that change when I hit a key. Here's my octave code sample.
x = [1:10];
for c=1:3
plot(x,c.*x);
hold off;
input('a');
end
When I try to do the same in python, I realized that python matplotlib has the save function, which puts it in non-blocking mode, and so I have to close the figure using a mouse, for the next figure to be produced. And the next figure is at a random other location on the screen. How can I get python to imitate the above behavior? I've tried various combinations of ion(), ioff(), plt.show(), plt.draw(), but haven't succeeded.
You can do something fancier if you want, using mpl_connect
First import pylab
from pylab import *
Then define an updateData function that can be connected to the figure canvas.
i = 1
def updateData(event):
global i,x
i +=1
y = i*x
data.set_data(x,y)
ylim(y[0],y[-1])
draw()
i and x are global variables in this case. (This could be treated in better way, this is just an example!)
Then, create you plot and connect with your defined function.
f = figure()
data, = plot(x,x)
i=1
f.canvas.mpl_connect("key_press_event",updateData)
show()
Whenever you hit any key in the keyboard (When the figure window is selected) the function updateData is called, i is incremented and the plot updated.
Have fun!

VTK update position of multiple render windows

I'm running into a bit of a problem when trying to run multiple render windows in a Python VTK application I'm writing. The application is an attempt to render a 3D model in two separate views for a stereo application (i.e. Left render and right render), but I'm having an issue with updating the cameras of each window simultaneously. I currently have two nearly identical pipelines set up, each with its own vtkCamera, vtkRenderWindow, vtkRenderer, and vtkRenderWindowInteractor, the only difference being that the right camera is positionally shifted 30 units along the X axis.
Each of the render window interactors is being updated via the vtkRenderWindowInteractor.AddObserver() method that calls a simple function to reset the cameras to their original positions and orientations. The biggest issue is that this only seems to occur on one window at a time, specifically the window in focus at the time. It's as if the interactor's timer just shuts off once the interactor loses focus. In addition, when I hold down the mouse (And thus move the camera around), the rendered image begins to 'drift', resetting to a less and less correct position even though I have hardcoded the coordinates into the function.
Obviously I'm very new to VTK, and much of what goes on is fairly confusing as so much is hidden in the backend, so it would be amazing to acquire some assistance on the matter. My code is below. Thanks guys!
from vtk import*
from parse import *
import os
import time, signal, threading
def ParseSIG(signum, stack):
print signum
return
class vtkGyroCallback():
def __init__(self):
pass
def execute(self, obj, event):
#Modified segment to accept input for leftCam position
gyro = (raw_input())
xyz = parse("{} {} {}", gyro)
#This still prints every 100ms, but camera doesn't update!
print xyz
#These arguments are updated and the call is made.
self.leftCam.SetPosition(float(xyz[0]), float(xyz[1]), float(xyz[2]))
self.leftCam.SetFocalPoint(0,0,0)
self.leftCam.SetViewUp(0,1,0)
self.leftCam.OrthogonalizeViewUp()
self.rightCam.SetPosition(10, 40, 100)
self.rightCam.SetFocalPoint(0,0,0)
self.rightCam.SetViewUp(0,1,0)
self.rightCam.OrthogonalizeViewUp()
#Just a guess
obj.Update()
return
def main():
# create two cameras
cameraR = vtkCamera()
cameraR.SetPosition(0,0,200)
cameraR.SetFocalPoint(0,0,0)
cameraL = vtkCamera()
cameraL.SetPosition(40,0,200)
cameraL.SetFocalPoint(0,0,0)
# create a rendering window and renderer
renR = vtkRenderer()
renR.SetActiveCamera(cameraR)
renL = vtkRenderer()
renL.SetActiveCamera(cameraL)
# create source
reader = vtkPolyDataReader()
path = "/home/compilezone/Documents/3DSlicer/SlicerScenes/LegoModel-6_25/Model_5_blood.vtk"
reader.SetFileName(path)
reader.Update()
# create render window
renWinR = vtkRenderWindow()
renWinR.AddRenderer(renR)
renWinR.SetWindowName("Right")
renWinL = vtkRenderWindow()
renWinL.AddRenderer(renL)
renWinL.SetWindowName("Left")
# create a render window interactor
irenR = vtkRenderWindowInteractor()
irenR.SetRenderWindow(renWinR)
irenL = vtkRenderWindowInteractor()
irenL.SetRenderWindow(renWinL)
# mapper
mapper = vtkPolyDataMapper()
mapper.SetInput(reader.GetOutput())
# actor
actor = vtkActor()
actor.SetMapper(mapper)
# assign actor to the renderer
renR.AddActor(actor)
renL.AddActor(actor)
# enable user interface interactor
renWinR.Render()
renWinL.Render()
irenR.Initialize()
irenL.Initialize()
#Create callback object for camera manipulation
cb = vtkGyroCallback()
cb.rightCam = cameraR
cb.leftCam = cameraL
renWinR.AddObserver('InteractionEvent', cb.execute)
renWinL.AddObserver('InteractionEvent', cb.execute)
irenR.AddObserver('TimerEvent', cb.execute)
irenL.AddObserver('TimerEvent', cb.execute)
timerIDR = irenR.CreateRepeatingTimer(100)
timerIDL = irenL.CreateRepeatingTimer(100)
irenR.Start()
irenL.Start()
if __name__ == '__main__':
main()
EDIT:
Upon further viewing it seems like the TimerEvents aren't firing more than once in a row after a MouseClickEvent and I have no idea why.
EDIT 2: Scratch that, they are most definitely firing as per some test outputs I embedded in the code. I modified the code to accept user input for the self.leftCam.SetPosition() call within the vtkGyroCallback.execute() method (Thus replacing the hardcoded "10, 40, 100" parameters with three input variables) then piped the output of a script that simply displayed three random values into my main program. What this should have accomplished was having a render window that would constantly change position. Instead, nothing happens until I click on the screen, at which point the expected functionality begins. The whole time, timer events are still firing and inputs are still being accepted, yet the cameras refuse to update until a mouse event occurs within the scope of their window. What is the deal?
EDIT 3: I've dug around some more and found that within the vtkObject::InvokeEvent() method that is called within every interaction event there is a focus loop that overrides all observers that do not pertain to the object in focus. I'm going to investigate if there is a way to remove focus so that it will instead bypass this focus loop and go to the unfocused loop that handles non focused objects.
So the solution was surprisingly simple, but thanks to the lack of quality documentation provided by VTK, I was left to dig through the source to find it. Effectively all you have to do is pseudo-thread Render() calls from each of the interactors via whatever callback method you're using to handle your TimerEvents. I did this using ID properties added to each interactor (seen in code provided below). You can see that every time a TimerEvent is fired from the irenR interactor's internal timer (irenR handles the right eye), the irenL's Render() function is called, and vice versa.
To solve this I first realized that the standard interactor functionalities (Mouse events and the like), worked normally. So I dug around the source in vtkRenderWindowInteractor.cxx and realized that those methods were abstracted to the individual vtkInteractorStyle implementations. After rooting around in the vtkInteractorStyleTrackball.cxx source, I found that there was actually a Render() function within the vtkRenderWindowInteractor class. Go figure! The documentation sure didn't mention that!
Unfortunately, two renders at once is actually very slow. If I do this method with just one window (At which point it becomes unnecessary), it runs wonderfully. Framerate tanks with a second window though. Oh well, what can you do?
Here's my corrected code (Finally I can start working on what I was supposed to be developing):
from vtk import*
from parse import *
import os
import time, signal, threading
def ParseSIG(signum, stack):
print signum
return
class vtkGyroCallback():
def __init__(self):
pass
def execute(self, obj, event):
#Modified segment to accept input for leftCam position
gyro = (raw_input())
xyz = parse("{} {} {}", gyro)
#print xyz
# "Thread" the renders. Left is called on a right TimerEvent and right is called on a left TimerEvent.
if obj.ID == 1 and event == 'TimerEvent':
self.leftCam.SetPosition(float(xyz[0]), float(xyz[1]), float(xyz[2]))
self.irenL.Render()
#print "Left"
elif obj.ID == 2 and event == 'TimerEvent':
self.rightCam.SetPosition(float(xyz[0]), float(xyz[1]), float(xyz[2]))
self.irenR.Render()
#print "Right"
return
def main():
# create two cameras
cameraR = vtkCamera()
cameraR.SetPosition(0,0,200)
cameraR.SetFocalPoint(0,0,0)
cameraL = vtkCamera()
cameraL.SetPosition(40,0,200)
cameraL.SetFocalPoint(0,0,0)
# create a rendering window and renderer
renR = vtkRenderer()
renR.SetActiveCamera(cameraR)
renL = vtkRenderer()
renL.SetActiveCamera(cameraL)
# create source
reader = vtkPolyDataReader()
path = "/home/compilezone/Documents/3DSlicer/SlicerScenes/LegoModel-6_25/Model_5_blood.vtk"
reader.SetFileName(path)
reader.Update()
# create render window
renWinR = vtkRenderWindow()
renWinR.AddRenderer(renR)
renWinR.SetWindowName("Right")
renWinL = vtkRenderWindow()
renWinL.AddRenderer(renL)
renWinL.SetWindowName("Left")
# create a render window interactor
irenR = vtkRenderWindowInteractor()
irenR.SetRenderWindow(renWinR)
irenL = vtkRenderWindowInteractor()
irenL.SetRenderWindow(renWinL)
# mapper
mapper = vtkPolyDataMapper()
mapper.SetInput(reader.GetOutput())
# actor
actor = vtkActor()
actor.SetMapper(mapper)
# assign actor to the renderer
renR.AddActor(actor)
renL.AddActor(actor)
# enable user interface interactor
renWinR.Render()
renWinL.Render()
irenR.Initialize()
irenL.Initialize()
#Create callback object for camera manipulation
cb = vtkGyroCallback()
cb.rightCam = renR.GetActiveCamera()#cameraR
cb.leftCam = renL.GetActiveCamera()#cameraL
cb.irenR = irenR
cb.irenL = irenL
irenR.ID = 1
irenL.ID = 2
irenR.AddObserver('TimerEvent', cb.execute)
irenL.AddObserver('TimerEvent', cb.execute)
timerIDR = irenR.CreateRepeatingTimer(100)
timerIDL = irenL.CreateRepeatingTimer(100)
irenL.Start()
irenR.Start()
if __name__ == '__main__':
main()

Categories