The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 3c921952 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Finished work on refactoring the camera API

* Removed CameraProperty, CameraPropertyWidget and TrackballNavigationEventListener
* replaces all known occurrences of the above three with the new TrackballCameraProvider processor
* introduced TrackballCameraProvider::reinitializeCamera()

refs #141
parent b55e85c4
......@@ -50,7 +50,6 @@ SET(CampvisApplicationToBeMocced
gui/properties/abstracttransferfunctioneditor.h
gui/properties/boolpropertywidget.h
gui/properties/buttonpropertywidget.h
gui/properties/camerapropertywidget.h
gui/properties/datanamepropertywidget.h
gui/properties/intpropertywidget.h
gui/properties/floatpropertywidget.h
......
......@@ -84,15 +84,6 @@ namespace campvis {
CampVisApplication::~CampVisApplication() {
cgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
// delete everything in the right order:
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete it->_painter;
delete it->_pipeline;
}
for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
delete *it;
}
sigslot::signal_manager::getRef().stop();
sigslot::signal_manager::deinit();
}
......@@ -216,6 +207,15 @@ namespace campvis {
_mainWindow->deinit();
QuadRenderer::deinit();
// now delete everything in the right order:
for (std::vector<PipelineRecord>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete it->_painter;
delete it->_pipeline;
}
for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
delete *it;
}
// deinit OpenGL and cgt
cgt::deinitGL();
}
......
......@@ -61,8 +61,8 @@ namespace campvis {
, _quadSize(0, 0)
, _localDataContainer("Local DataContainer for DataContainerInspectorCanvas")
, p_viewportSize("ViewportSize", "Viewport Size", cgt::ivec2(200), cgt::ivec2(0, 0), cgt::ivec2(10000))
, _tcp(&p_viewportSize)
, _geometryRenderer(&p_viewportSize)
, _trackballEH(nullptr)
{
static_cast<Geometry1DTransferFunction*>(p_transferFunction.getTF())->addGeometry(TFGeometry1D::createQuad(cgt::vec2(0.f, 1.f), cgt::col4(0, 0, 0, 255), cgt::col4(255, 255, 255, 255)));
......@@ -128,9 +128,6 @@ namespace campvis {
_dataContainer->s_dataAdded.disconnect(this);
}
delete _trackballEH;
_trackballEH = nullptr;
_geometryRenderer.deinit();
_handles.clear();
......@@ -254,9 +251,12 @@ namespace campvis {
void DataContainerInspectorCanvas::invalidate() {
// only if inited
if (_quad != 0 && _paintShader != 0) {
// TODO: check, whether this should be done in an extra thread
cgt::GLContextScopedLock lock(this);
paint();
// avoid recursive paints.
if (! cgt::GlContextManager::getRef().checkWhetherThisThreadHasAcquiredOpenGlContext()) {
// TODO: check, whether this should be done in an extra thread
cgt::GLContextScopedLock lock(this);
paint();
}
}
}
......@@ -320,8 +320,9 @@ namespace campvis {
void DataContainerInspectorCanvas::onEvent(cgt::Event* e) {
cgt::EventListener::onEvent(e);
if (_trackballEH && !e->isAccepted()) {
_trackballEH->onEvent(e);
if (!e->isAccepted()) {
_tcp.onEvent(e);
_tcp.process(_localDataContainer);
e->accept();
_geometriesDirty = true;
invalidate();
......@@ -445,6 +446,7 @@ namespace campvis {
_geometryRenderer.p_geometryID.setValue(name + ".geometry");
_geometryRenderer.p_renderTargetID.setValue(name + ".rendered");
_geometryRenderer.validate(AbstractProcessor::INVALID_PROPERTIES);
_geometryRenderer.invalidate(AbstractProcessor::INVALID_RESULT);
_geometryRenderer.process(_localDataContainer);
// grab render result texture from local DataContainer and push into texture vector.
......@@ -469,12 +471,8 @@ namespace campvis {
cgtAssert(false, "The rendered geometry does exist. Something went wrong.");
}
}
void DataContainerInspectorCanvas::resetTrackball() {
// delete old trackball
delete _trackballEH;
_trackballEH = nullptr;
// check whether we have to render geometries
cgt::Bounds unionBounds;
for (std::map<QString, QtDataHandle>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
......@@ -485,9 +483,11 @@ namespace campvis {
// if so, create a new trackball
if (unionBounds.isDefined()) {
_trackballEH = new TrackballNavigationEventListener(&_geometryRenderer.p_camera, &p_viewportSize);
_trackballEH->reinitializeCamera(unionBounds);
_tcp.reinitializeCamera(unionBounds);
}
_tcp.invalidate(AbstractProcessor::INVALID_RESULT);
_tcp.process(_localDataContainer);
}
}
......@@ -39,9 +39,9 @@
#include "core/properties/numericproperty.h"
#include "core/properties/propertycollection.h"
#include "core/properties/transferfunctionproperty.h"
#include "core/eventhandlers/trackballnavigationeventlistener.h"
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/base/processors/trackballcameraprovider.h"
#include "modules/vis/processors/geometryrenderer.h"
......@@ -220,8 +220,9 @@ namespace campvis {
DataContainer _localDataContainer; ///< Local DataContainer the GeometryRenderer works on
IVec2Property p_viewportSize;
TrackballCameraProvider _tcp; ///< TrackballCameraProvider to do camera stuff
GeometryRenderer _geometryRenderer; ///< GeometryRenderer used to render geometries
TrackballNavigationEventListener* _trackballEH;
};
}
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "camerapropertywidget.h"
#include <QGridLayout>
#include <QLabel>
#include "core/tools/stringutils.h"
namespace campvis {
CameraPropertyWidget::CameraPropertyWidget(CameraProperty* property, DataContainer* dataContainer, QWidget* parent /*= 0*/)
: AbstractPropertyWidget(property, true, dataContainer, parent)
, _lblCameraPosition(0)
, _lblLookDirection(0)
, _lblUpVector(0)
{
_widget = new QWidget(this);
QGridLayout* gridLayout = new QGridLayout(_widget);
_widget->setLayout(gridLayout);
_lblCameraPosition = new QLabel("Position: ", _widget);
gridLayout->addWidget(_lblCameraPosition, 0, 0);
_lblFocusPosition = new QLabel("Focus: ", _widget);
gridLayout->addWidget(_lblFocusPosition, 1, 0);
_lblLookDirection = new QLabel("Look Direction: ", _widget);
gridLayout->addWidget(_lblLookDirection, 2, 0);
_lblUpVector = new QLabel("Up Vector: ", _widget);
gridLayout->addWidget(_lblUpVector, 3, 0);
addWidget(_widget);
updateWidgetFromProperty();
}
CameraPropertyWidget::~CameraPropertyWidget() {
}
void CameraPropertyWidget::updateWidgetFromProperty() {
CameraProperty* prop = static_cast<CameraProperty*>(_property);
_lblCameraPosition->setText("Position: " + QString::fromStdString(StringUtils::toString(prop->getValue().getPosition())));
_lblFocusPosition->setText("Focus: " + QString::fromStdString(StringUtils::toString(prop->getValue().getFocus())));
_lblLookDirection->setText("Look Direction: " + QString::fromStdString(StringUtils::toString(prop->getValue().getLook())));
_lblUpVector->setText("Up Vector: " + QString::fromStdString(StringUtils::toString(prop->getValue().getUpVector())));
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef CAMERAPROPERTYWIDGET_H__
#define CAMERAPROPERTYWIDGET_H__
#include "application/gui/properties/abstractpropertywidget.h"
#include "application/gui/properties/propertywidgetfactory.h"
#include "core/properties/cameraproperty.h"
class QLabel;
namespace campvis {
/**
* Widget for a Camera.
* For now just offering read-access.
*/
class CameraPropertyWidget : public AbstractPropertyWidget {
Q_OBJECT;
public:
/**
* Creates a new CameraPropertyWidget for the property \a property.
* \param property The property the widget shall handle
* \param dataContainer DataContainer to use (optional), defaults to nullptr.
* \param parent Parent Qt widget
*/
CameraPropertyWidget(CameraProperty* property, DataContainer* dataContainer, QWidget* parent = 0);
/**
* Destructor
*/
virtual ~CameraPropertyWidget();
protected:
/**
* Gets called when the property has changed, so that widget can update its state.
*/
virtual void updateWidgetFromProperty();
private:
QWidget* _widget;
QLabel* _lblCameraPosition;
QLabel* _lblFocusPosition;
QLabel* _lblLookDirection;
QLabel* _lblUpVector;
};
// explicitly instantiate template, so that it gets registered also over DLL boundaries.
template class PropertyWidgetRegistrar<CameraPropertyWidget, CameraProperty>;
}
#endif // CAMERAPROPERTYWIDGET_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "trackballnavigationeventlistener.h"
#include "cgt/assert.h"
#include "cgt/event/mouseevent.h"
#include "core/datastructures/abstractdata.h"
#include "core/properties/cameraproperty.h"
#include "core/pipeline/visualizationprocessor.h"
namespace campvis {
CamPropNavigationWrapper::CamPropNavigationWrapper(CameraProperty* camProp)
: _cameraProperty(camProp)
, _dirty(false)
{
}
CamPropNavigationWrapper::~CamPropNavigationWrapper() {
}
cgt::Camera* CamPropNavigationWrapper::getCamera() {
if (! _dirty) {
// perform deep copy (hopefully thread-safe...)
_localCopy = _cameraProperty->getValue();
_dirty = true;
}
return &_localCopy;
}
void CamPropNavigationWrapper::update() {
_cameraProperty->setValue(_localCopy);
_dirty = false;
}
// = TrackballNavigationEventListener ==============================================================
const std::string TrackballNavigationEventListener::loggerCat_ = "CAMPVis.core.eventhandler.TrackballNavigationEventListener";
TrackballNavigationEventListener::TrackballNavigationEventListener(CameraProperty* cameraProperty, IVec2Property* viewportSizeProp)
: cgt::EventListener()
, _cameraProperty(cameraProperty)
, _viewportSizeProp(viewportSizeProp)
, _cpnw(cameraProperty)
, _trackball(0)
, _sceneBounds(cgt::vec3(0.f))
{
cgtAssert(_cameraProperty != 0, "Assigned camera property must not be 0.");
cgtAssert(_viewportSizeProp != 0, "Assigned viewport size property must not be 0.");
_trackball = new cgt::Trackball(&_cpnw, viewportSizeProp->getValue());
_viewportSizeProp->s_changed.connect(this, &TrackballNavigationEventListener::onViewportSizePropChanged);
}
TrackballNavigationEventListener::~TrackballNavigationEventListener() {
_viewportSizeProp->s_changed.disconnect(this);
delete _trackball;
}
void TrackballNavigationEventListener::onEvent(cgt::Event* e) {
if (typeid(*e) == typeid(cgt::MouseEvent)) {
cgt::MouseEvent* me = static_cast<cgt::MouseEvent*>(e);
_trackball->setViewprtSize(me->viewport());
if (me->action() == cgt::MouseEvent::PRESSED) {
for (std::vector<VisualizationProcessor*>::iterator it = _lqModeProcessors.begin(); it != _lqModeProcessors.end(); ++it)
(*it)->p_lqMode.setValue(true);
_trackball->mousePressEvent(me);
}
else if (me->action() == cgt::MouseEvent::RELEASED) {
for (std::vector<VisualizationProcessor*>::iterator it = _lqModeProcessors.begin(); it != _lqModeProcessors.end(); ++it)
(*it)->p_lqMode.setValue(false);
_trackball->mouseReleaseEvent(me);
}
else if (me->action() == cgt::MouseEvent::MOTION)
_trackball->mouseMoveEvent(me);
else if (me->action() == cgt::MouseEvent::WHEEL)
_trackball->wheelEvent(me);
}
else if (typeid(*e) == typeid(cgt::KeyEvent)) {
_trackball->keyEvent(static_cast<cgt::KeyEvent*>(e));
}
}
void TrackballNavigationEventListener::reinitializeCamera(const cgt::vec3& position, const cgt::vec3& focus, const cgt::vec3& upVector) {
_trackball->reinitializeCamera(position, focus, upVector);
}
void TrackballNavigationEventListener::reinitializeCamera(const IHasWorldBounds* hwb) {
reinitializeCamera(hwb->getWorldBounds());
}
void TrackballNavigationEventListener::reinitializeCamera(const cgt::Bounds& worldBounds) {
if (_sceneBounds != worldBounds) {
cgt::vec3 pos = worldBounds.center() - cgt::vec3(0, 0, cgt::length(worldBounds.diagonal()));
setSceneBounds(worldBounds);
setCenter(worldBounds.center());
reinitializeCamera(pos, worldBounds.center(), _cameraProperty->getValue().getUpVector());
}
}
void TrackballNavigationEventListener::setCenter(const cgt::vec3& center) {
_trackball->setCenter(center);
}
void TrackballNavigationEventListener::setSceneBounds(const cgt::Bounds& bounds) {
_sceneBounds = bounds;
_trackball->setSceneBounds(bounds);
}
const cgt::Bounds& TrackballNavigationEventListener::getSceneBounds() const {
return _trackball->getSceneBounds();
}
cgt::Trackball* TrackballNavigationEventListener::getTrackball() {
return _trackball;
}
void TrackballNavigationEventListener::addLqModeProcessor(VisualizationProcessor* vp) {
cgtAssert(vp != 0, "Pointer to processor must not be 0.");
cgtAssert(std::find(_lqModeProcessors.begin(), _lqModeProcessors.end(), vp) == _lqModeProcessors.end(), "Processor already in list of LQ mode processors.");
_lqModeProcessors.push_back(vp);
}
void TrackballNavigationEventListener::removeLqModeProcessor(VisualizationProcessor* vp) {
for (std::vector<VisualizationProcessor*>::iterator it = _lqModeProcessors.begin(); it != _lqModeProcessors.end(); ++it) {
if (*it == vp) {
_lqModeProcessors.erase(it);
return;
}
}
}
void TrackballNavigationEventListener::onViewportSizePropChanged(const AbstractProperty* p) {
cgtAssert(p == _viewportSizeProp, "Signal from unexpected property! Expected p == _viewportSizeProp.");
_trackball->setViewprtSize(_viewportSizeProp->getValue());
float ratio = static_cast<float>(_viewportSizeProp->getValue().x) / static_cast<float>(_viewportSizeProp->getValue().y);
if (ratio == 0) {
LERROR("Window ratio must not be 0.");
}
else {
_trackball->setWindowRatio(ratio);
}
}
void TrackballNavigationEventListener::setViewportSizeProperty(IVec2Property* viewportSizeProp) {
_viewportSizeProp->s_changed.disconnect(this);
cgtAssert(viewportSizeProp != nullptr, "The property must not be 0.");
_viewportSizeProp = viewportSizeProp;
onViewportSizePropChanged(_viewportSizeProp);
_viewportSizeProp->s_changed.connect(this, &TrackballNavigationEventListener::onViewportSizePropChanged);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef TRACKBALLNAVIGATIONEVENTHANDLER_H__
#define TRACKBALLNAVIGATIONEVENTHANDLER_H__
#include <sigslot/sigslot.h>
#include "cgt/bounds.h"
#include "cgt/logmanager.h"
#include "cgt/event/eventlistener.h"
#include "cgt/navigation/trackball.h"
#include "core/coreapi.h"
#include "core/datastructures/datahandle.h"
#include "core/properties/numericproperty.h"
#include <vector>
namespace campvis {
class CameraProperty;
class IHasWorldBounds;
class VisualizationProcessor;
/**
* Wrapper to adapt a CameraProperty to the cgt::Trackball interface.
*/
class CAMPVIS_CORE_API CamPropNavigationWrapper : public cgt::IHasCamera {
public:
/**
* Constructor
* \param camProp The CameraProperty to wrap around.
*/
explicit CamPropNavigationWrapper(CameraProperty* camProp);
/// Virtual Destructor
virtual ~CamPropNavigationWrapper();
/// \see cgt::IHasCamera::getCamera()
virtual cgt::Camera* getCamera();
/// \see cgt::IHasCamera::update()
virtual void update();
private:
CameraProperty* _cameraProperty; ///< CameraProperty this class wraps around
/// Temporary copy of the property's camera which will be modified and written back to the property upon update().
cgt::Camera _localCopy;
/// Flag whether _localCopy is dirty (needs to be written back)
bool _dirty;
};
/**
* EventListener implementing a trackball navigation for a CameraProperty.
* Implementation inspired by http://www.opengl.org/wiki/Trackball
*
* \note Also takes care of automatically adjusting the window ratio for the wrapped
* camera when the viewport size changes.
*/
class CAMPVIS_CORE_API TrackballNavigationEventListener : public cgt::EventListener, public sigslot::has_slots {
public:
/**
* Creates a TrackballNavigationEventListener.
* \note TrackballNavigationEventListener keeps and accesses \a viewportSizeProp during the whole
* lifetime. Hence make sure the pointer is valid at all times.
* \param cameraProperty Pointer to the CameraProperty to apply the navigation to, must not be 0.
* \param viewportSizeProp Pointer to the property defining the viewport size, must not be 0.
*/
TrackballNavigationEventListener(CameraProperty* cameraProperty, IVec2Property* viewportSizeProp);
/**
* Virtual Destructor
**/
virtual ~TrackballNavigationEventListener();
/// \see cgt::EventListener::onEvent()
virtual void onEvent(cgt::Event* e);
/**
* Sets the property defining the viewport size.
* \param viewportSizeProp The new property defining the viewport size, must not be 0.
*/
void setViewportSizeProperty(IVec2Property* viewportSizeProp);
/**
* Reinitializes the camera using the data in \a hwb.
* If the scene bounds have changed, the camera setup is reinitialized positioning the
* camera in front of the data along the z-axis and looking at the center of the data.
*
* \param hwb Data to use for reinitialization, must not be 0.
*/
void reinitializeCamera(const IHasWorldBounds* hwb);
/**
* Reinitializes the camera using the data in \a hwb.
* If the scene bounds have changed, the camera setup is reinitialized positioning the
* camera in front of the data along the z-axis and looking at the center of the data.
*
* \param hwb Data to use for reinitialization, must not be 0.
*/
void reinitializeCamera(const cgt::Bounds& worldBounds);