Występuje pewien problem podczas próby uruchomienia wielu okien renderowania w aplikacji Python VTK, którą piszę. Aplikacja jest próbą renderowania modelu 3D w dwóch osobnych widokach dla aplikacji stereo (tj. Lewy render i prawy render), ale mam problem z aktualizowaniem kamer każdego okna jednocześnie. Obecnie mam dwa prawie identyczne skonfigurowane potoki, z których każdy ma własny vtkCamera
, vtkRenderWindow
, vtkRenderer
i vtkRenderWindowInteractor
, z tą różnicą, że prawa kamera jest przesunięta w kierunku 30 jednostek wzdłuż osi X.Pozycja aktualizacji VTK wielu okien renderowania
Każdy z interwałów okna renderowania jest aktualizowany za pomocą metody vtkRenderWindowInteractor.AddObserver()
, która wywołuje prostą funkcję resetowania kamer do ich oryginalnych pozycji i orientacji. Największym problemem jest to, że zdaje się, że dzieje się to tylko w jednym oknie na raz, a konkretnie w tym samym oknie. To tak, jakby zegar interaktora po prostu się wyłączył, gdy interaktor straci ostrość. Ponadto, gdy przytrzymam mysz (i tym samym przesuniemy kamerę), renderowany obraz zaczyna "dryfować", resetując się do coraz mniejszej poprawnej pozycji, mimo że wczytałem współrzędne do tej funkcji.
Oczywiście jestem bardzo nowy w VTK, a wiele z tego, co się dzieje, jest dość mylące, ponieważ wiele z nich jest ukrytych w zapleczu, więc byłoby wspaniale uzyskać pomoc w tej sprawie. Mój kod znajduje się poniżej. Dzięki chłopaki!
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:
Po dalsze przeglądanie Wydaje się, że TimerEvents nie strzelają więcej niż raz z rzędu po MouseClickEvent i nie mam pojęcia dlaczego.
EDYCJA 2: Zarysuj to, są one absolutnie wyzwalane, jak na niektórych wynikach testu osadzonych w kodzie. Zmodyfikowałem kod, aby zaakceptować dane wejściowe użytkownika dla wywołania self.leftCam.SetPosition()
w metodzie vtkGyroCallback.execute()
(W ten sposób zastąpienie zakodowanych na stałe "10, 40, 100" parametrów trzema zmiennymi wejściowymi), a następnie wyprowadziłem wyjście skryptu, który po prostu wyświetlał trzy przypadkowe wartości w moim głównym program. To, co osiągnęło, to miało okno renderowania, które stale zmieniało położenie. Zamiast tego nic się nie dzieje, dopóki nie kliknę ekranu, w którym to momencie zaczyna się oczekiwana funkcjonalność. Przez cały czas zdarzenia timera są nadal wyzwalane, a wejścia są nadal akceptowane, ale kamery odmawiają aktualizacji, dopóki zdarzenie myszy nie pojawi się w zasięgu ich okna. O co chodzi?
EDYCJA 3: Wykopałem trochę więcej i odkryłem, że w metodzie vtkObject::InvokeEvent()
, która jest wywoływana w każdym zdarzeniu interakcji, istnieje pętla ostrości, która przesłania wszystkie obserwatory, które nie dotyczą obiektu, na którym jest fokus. Zamierzam zbadać, czy istnieje sposób na usunięcie fokusa, aby zamiast tego obejść tę pętlę ostrości i przejść do nieokreślonej pętli, która obsługuje nieostre obiekty.
Wszystko stałe! Jeśli chcesz otrzymać nagrodę, powiedz mi, jak sprawić, by działała płynnie (Framerate aktualnie znajduje się na poziomie 2-3 FPS z rozwiązaniem pokazanym w moim komentarzu poniżej): D – SwarthyMantooth
Złom to również rozwiązało ten problem! Powinienem zapłacić za te rzeczy;) Moja metoda używania dwóch oddzielnych 'vtkRenderWindow's była powolna i nieporęczna. Przestawiłem się na używanie dwóch 'vtkRenderer'ów wewnątrz pojedynczego' vtkRenderWindow', a framerate do 60FPS. Dodatkowo, Oculus Rift nie wymaga wielu okien, ponieważ każdy z nich jest technicznie częścią tego samego monitora, więc cała aplikacja może znajdować się w jednym oknie. – SwarthyMantooth