fix a Python<->Mitsuba<->Qt issue reported by Marios Papas

metadata
Wenzel Jakob 2014-02-04 21:05:13 +01:00
parent 74a7d81fac
commit 8e5a146785
4 changed files with 21 additions and 9 deletions

View File

@ -585,6 +585,7 @@ class MitsubaRenderBuffer(RenderListener):
RENDERING_FINISHED = 0 RENDERING_FINISHED = 0
RENDERING_CANCELLED = 1 RENDERING_CANCELLED = 1
RENDERING_UPDATED = 2 RENDERING_UPDATED = 2
GEOMETRY_CHANGED = 3
def __init__(self, queue, callback): def __init__(self, queue, callback):
super(MitsubaRenderBuffer, self).__init__() super(MitsubaRenderBuffer, self).__init__()
@ -613,7 +614,7 @@ class MitsubaRenderBuffer(RenderListener):
do this occasionally). Hence, tonemap the full film. """ do this occasionally). Hence, tonemap the full film. """
film = self._get_film_ensure_initialized(job) film = self._get_film_ensure_initialized(job)
film.develop(Point2i(0), self.size, Point2i(0), self.bitmap) film.develop(Point2i(0), self.size, Point2i(0), self.bitmap)
self._potentially_send_update(force=True) self._potentially_send_update()
def finishJobEvent(self, job, cancelled): def finishJobEvent(self, job, cancelled):
""" Callback: the rendering job has finished or was cancelled. """ Callback: the rendering job has finished or was cancelled.
@ -646,12 +647,14 @@ class MitsubaRenderBuffer(RenderListener):
# (i.e. without doing unnecessary bitmap copy operations) # (i.e. without doing unnecessary bitmap copy operations)
self.qimage = QImage(self.bitmap.getNativeBuffer(), self.size.x, self.qimage = QImage(self.bitmap.getNativeBuffer(), self.size.x,
self.size.y, QImage.Format_RGB888) self.size.y, QImage.Format_RGB888)
self.callback(MitsubaRenderBuffer.GEOMETRY_CHANGED)
return film return film
def _potentially_send_update(self, force = False): def _potentially_send_update(self):
""" Send an update request to any attached widgets, but not too often """ """ Send an update request to any attached widgets, but not too often """
now = time.time() now = time.time()
if now - self.time > .25 or force: if now - self.time > .25:
self.time = now self.time = now
self.callback(MitsubaRenderBuffer.RENDERING_UPDATED) self.callback(MitsubaRenderBuffer.RENDERING_UPDATED)
@ -660,20 +663,22 @@ class RenderWidget(QWidget):
and displays the progress of everything that's being rendered """ and displays the progress of everything that's being rendered """
renderingUpdated = Signal(int) renderingUpdated = Signal(int)
def __init__(self, parent, queue): def __init__(self, parent, queue, default_size = Vector2i(0, 0)):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
self.buffer = MitsubaRenderBuffer(queue, self.renderingUpdated.emit) self.buffer = MitsubaRenderBuffer(queue, self.renderingUpdated.emit)
# Need a queued conn. to avoid threading issues between Qt and Mitsuba # Need a queued conn. to avoid threading issues between Qt and Mitsuba
self.renderingUpdated.connect(self._handle_update, Qt.QueuedConnection) self.renderingUpdated.connect(self._handle_update, Qt.QueuedConnection)
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
self.default_size = default_size
def sizeHint(self): def sizeHint(self):
return QSize(self.buffer.size.x, self.buffer.size.y) size = self.buffer.size if not self.buffer.size.isZero() else self.default_size
return QSize(size.x, size.y)
def _handle_update(self, event): def _handle_update(self, event):
image = self.buffer.qimage image = self.buffer.qimage
# Detect when an image of different resolution is being rendered # Detect when an image of different resolution is being rendered
if image.width() < self.width() or image.height() < self.height(): if image.width() > self.width() or image.height() > self.height():
self.updateGeometry() self.updateGeometry()
self.repaint() self.repaint()
@ -702,10 +707,11 @@ class MitsubaDemo(QMainWindow):
# Initialize Mitsuba # Initialize Mitsuba
self.initializeMitsuba() self.initializeMitsuba()
self.job = self.createRenderJob() self.job = self.createRenderJob()
self.job.setInteractive(True)
# Initialize the user interface # Initialize the user interface
status = self.statusBar() status = self.statusBar()
self.rwidget = RenderWidget(self, self.queue) self.rwidget = RenderWidget(self, self.queue, self.scene.getFilm().getSize())
progress = QProgressBar(status) progress = QProgressBar(status)
status.setContentsMargins(0,0,5,0) status.setContentsMargins(0,0,5,0)
status.addPermanentWidget(progress) status.addPermanentWidget(progress)

View File

@ -92,6 +92,9 @@ public:
*/ */
inline bool isInteractive() const { return m_interactive; } inline bool isInteractive() const { return m_interactive; }
/// Define whether or not this is an interactive job
inline void setInteractive(bool interactive) { m_interactive = interactive; }
/// Get a pointer to the underlying scene /// Get a pointer to the underlying scene
inline Scene *getScene() { return m_scene.get(); } inline Scene *getScene() { return m_scene.get(); }

View File

@ -70,6 +70,7 @@
.def(bp::self / Scalar()) \ .def(bp::self / Scalar()) \
.def(bp::self /= Scalar()) \ .def(bp::self /= Scalar()) \
.def("serialize", &Name::serialize) \ .def("serialize", &Name::serialize) \
.def("isZero", &Name::isZero) \
.def("length", &Name::length) \ .def("length", &Name::length) \
.def("lengthSquared", &Name::lengthSquared) \ .def("lengthSquared", &Name::lengthSquared) \
.def("__repr__", &Name::toString) \ .def("__repr__", &Name::toString) \
@ -95,6 +96,7 @@
.def(bp::self / Scalar()) \ .def(bp::self / Scalar()) \
.def(bp::self /= Scalar()) \ .def(bp::self /= Scalar()) \
.def("serialize", &Name::serialize) \ .def("serialize", &Name::serialize) \
.def("isZero", &Name::isZero) \
.def("__repr__", &Name::toString) \ .def("__repr__", &Name::toString) \
.def("__len__", &FixedSizeSupport<Name, Scalar, Size>::len) \ .def("__len__", &FixedSizeSupport<Name, Scalar, Size>::len) \
.def("__getitem__", &FixedSizeSupport<Name, Scalar, Size>::get) \ .def("__getitem__", &FixedSizeSupport<Name, Scalar, Size>::get) \

View File

@ -363,11 +363,12 @@ void export_render() {
Scene *(RenderJob::*renderJob_getScene)(void) = &RenderJob::getScene; Scene *(RenderJob::*renderJob_getScene)(void) = &RenderJob::getScene;
RenderQueue *(RenderJob::*renderJob_getRenderQueue)(void) = &RenderJob::getRenderQueue; RenderQueue *(RenderJob::*renderJob_getRenderQueue)(void) = &RenderJob::getRenderQueue;
BP_CLASS(RenderJob, Thread, (bp::init<const std::string &, Scene *, RenderQueue *>())) BP_CLASS(RenderJob, Thread, (bp::init<const std::string &, Scene *, RenderQueue *, bp::optional<int, int, int, bool, bool> >()))
.def(bp::init<const std::string &, Scene *, RenderQueue *, int, bp::optional<int, int> >())
.def("flush", &RenderJob::flush) .def("flush", &RenderJob::flush)
.def("cancel", renderJob_cancel) .def("cancel", renderJob_cancel)
.def("wait", &RenderJob::wait) .def("wait", &RenderJob::wait)
.def("isInteractive", &RenderJob::isInteractive)
.def("setInteractive", &RenderJob::setInteractive)
.def("getScene", renderJob_getScene, BP_RETURN_VALUE) .def("getScene", renderJob_getScene, BP_RETURN_VALUE)
.def("getRenderQueue", renderJob_getRenderQueue, BP_RETURN_VALUE); .def("getRenderQueue", renderJob_getRenderQueue, BP_RETURN_VALUE);