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.