Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing 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 4ee7e1ac authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Further work on refactoring the camera API. Added proof-of-concept...

Further work on refactoring the camera API. Added proof-of-concept implementation into MprRenderer and MprDemo. Thereby fixed various issues of the new CameraData API that occured:
* tgt::Navigation::updateClippingPlanes() yielding NaNs if the scene bounds were not defined
* NumericProperty yielding endless loops in case of NaN values
* Updated AbstractProcessor::process() to automatically validate level XYZ after calling updateXYZ().
* Adapted changes through renaming tgt into cgt

refs #141
refs #386
parent 35a402e5
......@@ -32,7 +32,7 @@
namespace campvis {
CameraData::CameraData(const tgt::Camera& camera /*= tgt::Camera()*/)
CameraData::CameraData(const cgt::Camera& camera /*= cgt::Camera()*/)
: AbstractData()
, _camera(camera)
{
......@@ -55,15 +55,15 @@ namespace campvis {
return 0;
}
const tgt::Camera& CameraData::getCamera() const {
const cgt::Camera& CameraData::getCamera() const {
return _camera;
}
tgt::Camera& CameraData::getCamera() {
cgt::Camera& CameraData::getCamera() {
return _camera;
}
void CameraData::setCamera(const tgt::Camera& camera) {
void CameraData::setCamera(const cgt::Camera& camera) {
_camera = camera;
}
......
......@@ -30,13 +30,10 @@
#ifndef CAMERADATA_H__
#define CAMERADATA_H__
#include "tgt/camera.h"
#include "cgt/camera.h"
#include "core/datastructures/abstractdata.h"
#include <vector>
namespace tgt {
}
namespace campvis {
/**
* Data object storing camera data.
......@@ -47,7 +44,7 @@ namespace campvis {
* Constructor, creating a new CameraData object initialized by \a camera.
* \param camera Camera object used for initialization (optional)
*/
explicit CameraData(const tgt::Camera& camera = tgt::Camera());
explicit CameraData(const cgt::Camera& camera = cgt::Camera());
/**
* Destructor.
......@@ -69,22 +66,22 @@ namespace campvis {
* Const getter for the camera settings.
* \return _camera
*/
const tgt::Camera& getCamera() const;
const cgt::Camera& getCamera() const;
/**
* Non-const getter for the camera settings.
* \return _camera
*/
tgt::Camera& getCamera();
cgt::Camera& getCamera();
/**
* Sets the camera settings to \a camera.
* \param camera New camera settings.
*/
void setCamera(const tgt::Camera& camera);
void setCamera(const cgt::Camera& camera);
protected:
tgt::Camera _camera; ///< The tgt::Camera object storing the camera setup
cgt::Camera _camera; ///< The cgt::Camera object storing the camera setup
};
......
......@@ -145,6 +145,14 @@ namespace campvis {
AbstractProcessor::ScopedLock lock(this);
cgtAssert(_locked == true, "Processor not locked, this should not happen!");
if (hasInvalidShader()) {
updateShader();
validate(INVALID_SHADER);
}
if (hasInvalidProperties()) {
updateProperties(data);
validate(INVALID_PROPERTIES);
}
if (hasInvalidResult()) {
updateResult(data);
validate(INVALID_RESULT);
......
......@@ -25,6 +25,7 @@
#ifndef NUMERICPROPERTY_H__
#define NUMERICPROPERTY_H__
#include "cgt/logmanager.h"
#include "cgt/vector.h"
#include "core/coreapi.h"
......@@ -50,11 +51,15 @@ namespace {
return value;
}
else {
if (tgt::LogManager::isInited())
if (cgt::LogManager::isInited())
LDEBUGC("CAMPVis.core.properties.NumericProperty", "Validating value " << value << ": Out of bounds [" << minValue << ", " << maxValue << "], clamping to range!");
return (value < minValue) ? minValue : maxValue;
}
}
static bool isNan(const T& value) {
return (value != value);
};
};
/**
......@@ -67,7 +72,7 @@ namespace {
for (size_t i = 0; i < value.size; ++i) {
if (toReturn[i] < minValue[i]) {
if (tgt::LogManager::isInited())
if (cgt::LogManager::isInited())
LDEBUGC("CAMPVis.core.properties.NumericProperty", "Validating value " << value << ": Out of bounds [" << minValue << ", " << maxValue << "], clamping to range!");
toReturn[i] = minValue[i];
}
......@@ -77,6 +82,15 @@ namespace {
}
return toReturn;
}
static bool isNan(const T& value) {
bool toReturn = false;
for (size_t i = 0; i < value.size; ++i) {
toReturn |= (value[i] != value[i]);
}
return toReturn;
};
};
}
......@@ -181,6 +195,12 @@ namespace campvis {
*/
virtual void decrement();
/**
* See GenericProperty::unlock()
* This one additionally checks for NaN values, as they break the existing code.
*/
virtual void unlock();
/// Signal emitted, when the property's minimum or maximum value changes.
sigslot::signal1<const AbstractProperty*> s_minMaxChanged;
......@@ -317,6 +337,14 @@ namespace campvis {
void campvis::NumericProperty<T>::decrement() {
this->setValue(this->_value - this->_stepValue);
}
template<typename T>
void campvis::NumericProperty<T>::unlock() {
if (NumericPropertyTraits<T, std::numeric_limits<T>::is_specialized>::isNan(_backBuffer) && NumericPropertyTraits<T, std::numeric_limits<T>::is_specialized>::isNan(_value))
AbstractProperty::unlock();
else
GenericProperty<T>::unlock();
}
}
#endif // NUMERICPROPERTY_H__
......@@ -166,10 +166,12 @@ void Navigation::setSceneBounds(const cgt::Bounds& bounds) {
}
void Navigation::updateClippingPlanes() {
float diag = cgt::length(_sceneBounds.diagonal()) * 0.75f;
float dist = cgt::distance(getCamera()->getPosition(), _sceneBounds.center());
if (_sceneBounds.isDefined()) {
float diag = length(_sceneBounds.diagonal()) * 0.75f;
float dist = distance(getCamera()->getPosition(), _sceneBounds.center());
getCamera()->setNearDist(std::max(dist - diag, 0.1f));
getCamera()->setFarDist(diag + 2 * dist);
}
}
const cgt::Bounds& Navigation::getSceneBounds() const {
......
......@@ -31,10 +31,10 @@
#include "core/datastructures/cameradata.h"
namespace campvis {
static const GenericOption<tgt::Camera::ProjectionMode> projectionOptions[3] = {
GenericOption<tgt::Camera::ProjectionMode>("perspective", "Perspective", tgt::Camera::PERSPECTIVE),
GenericOption<tgt::Camera::ProjectionMode>("orthographic", "Orthographice", tgt::Camera::ORTHOGRAPHIC),
GenericOption<tgt::Camera::ProjectionMode>("frustum", "Frustum", tgt::Camera::FRUSTUM)
static const GenericOption<cgt::Camera::ProjectionMode> projectionOptions[3] = {
GenericOption<cgt::Camera::ProjectionMode>("perspective", "Perspective", cgt::Camera::PERSPECTIVE),
GenericOption<cgt::Camera::ProjectionMode>("orthographic", "Orthographice", cgt::Camera::ORTHOGRAPHIC),
GenericOption<cgt::Camera::ProjectionMode>("frustum", "Frustum", cgt::Camera::FRUSTUM)
};
const std::string CameraProvider::loggerCat_ = "CAMPVis.modules.io.CameraProvider";
......@@ -42,12 +42,12 @@ namespace campvis {
CameraProvider::CameraProvider()
: AbstractProcessor()
, p_cameraId("CameraId", "Camera ID", "camera", DataNameProperty::WRITE)
, p_position("Position", "Camera Position", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f))
, p_focus("Focus", "Camera Focus", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f))
, p_upVector("UpVector", "Camera Up Vector", tgt::vec3(0.f, 1.f, 0.f), tgt::vec3(-1.f), tgt::vec3(1.f))
, p_position("Position", "Camera Position", cgt::vec3(0.f, 0.f, -100.f), cgt::vec3(-10000.f), cgt::vec3(10000.f))
, p_focus("Focus", "Camera Focus", cgt::vec3(0.f), cgt::vec3(-10000.f), cgt::vec3(10000.f))
, p_upVector("UpVector", "Camera Up Vector", cgt::vec3(0.f, 1.f, 0.f), cgt::vec3(-1.f), cgt::vec3(1.f))
, p_fov("FoV", "Field of View", 45.f, 1.f, 180.f)
, p_aspectRatio("AspectRatio", "Aspect Ratio", 1.f, .001f, 100.f)
, p_clippingPlanes("ClippingPlanes", "Near/Far Clipping Planes", tgt::vec2(.1f, 50.f), tgt::vec2(0.f), tgt::vec2(10000.f))
, p_clippingPlanes("ClippingPlanes", "Near/Far Clipping Planes", cgt::vec2(.1f, 1000.f), cgt::vec2(0.f), cgt::vec2(10000.f))
, p_projectionMode("ProjectionMode", "Projection Mode", projectionOptions, 3)
{
addProperty(p_cameraId);
......@@ -65,7 +65,7 @@ namespace campvis {
}
void CameraProvider::updateResult(DataContainer& dataContainer) {
CameraData* cameraData = new CameraData(tgt::Camera(
CameraData* cameraData = new CameraData(cgt::Camera(
p_position.getValue(),
p_focus.getValue(),
p_upVector.getValue(),
......
......@@ -32,7 +32,8 @@
#include <string>
#include "tgt/camera.h"
#include "cgt/camera.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/numericproperty.h"
......@@ -78,7 +79,7 @@ namespace campvis {
FloatProperty p_aspectRatio; ///< Aspect Ratio
Vec2Property p_clippingPlanes; ///< Near and far clipping planes
GenericOptionProperty<tgt::Camera::ProjectionMode> p_projectionMode; ///< Projection mode
GenericOptionProperty<cgt::Camera::ProjectionMode> p_projectionMode; ///< Projection mode
protected:
......
......@@ -27,8 +27,8 @@
//
// ================================================================================================
#include "tgt/assert.h"
#include "tgt/event/mouseevent.h"
#include "cgt/assert.h"
#include "cgt/event/mouseevent.h"
#include "trackballcameraprovider.h"
#include "core/datastructures/cameradata.h"
......@@ -52,8 +52,8 @@ namespace campvis {
: CameraProvider()
, p_automationMode("AutomationMode", "Automation Mode", automationOptions, 3)
, p_image("ReferenceImage", "Reference Image", "", DataNameProperty::READ)
, p_llf("LLF", "Bounding Box LLF", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f))
, p_urb("URB", "Bounding Box URB", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f))
, p_llf("LLF", "Bounding Box LLF", cgt::vec3(0.f), cgt::vec3(-10000.f), cgt::vec3(10000.f))
, p_urb("URB", "Bounding Box URB", cgt::vec3(0.f), cgt::vec3(-10000.f), cgt::vec3(10000.f))
, _canvasSize(canvasSize)
, _trackball(0)
{
......@@ -64,7 +64,7 @@ namespace campvis {
addProperty(p_llf);
addProperty(p_urb);
_trackball = new tgt::Trackball(this, _canvasSize->getValue());
_trackball = new cgt::Trackball(this, _canvasSize->getValue());
_canvasSize->s_changed.connect(this, &TrackballCameraProvider::onRenderTargetSizeChanged);
}
......@@ -73,33 +73,33 @@ namespace campvis {
delete _trackball;
}
void TrackballCameraProvider::onEvent(tgt::Event* e) {
if (typeid(*e) == typeid(tgt::MouseEvent)) {
tgt::MouseEvent* me = static_cast<tgt::MouseEvent*>(e);
if (me->action() == tgt::MouseEvent::PRESSED) {
void TrackballCameraProvider::onEvent(cgt::Event* e) {
if (typeid(*e) == typeid(cgt::MouseEvent)) {
cgt::MouseEvent* me = static_cast<cgt::MouseEvent*>(e);
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() == tgt::MouseEvent::RELEASED) {
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() == tgt::MouseEvent::MOTION) {
else if (me->action() == cgt::MouseEvent::MOTION) {
_trackball->mouseMoveEvent(me);
}
else if (me->action() == tgt::MouseEvent::WHEEL)
else if (me->action() == cgt::MouseEvent::WHEEL)
_trackball->wheelEvent(me);
}
else if (typeid(*e) == typeid(tgt::KeyEvent)) {
_trackball->keyEvent(static_cast<tgt::KeyEvent*>(e));
else if (typeid(*e) == typeid(cgt::KeyEvent)) {
_trackball->keyEvent(static_cast<cgt::KeyEvent*>(e));
}
}
tgt::Camera* TrackballCameraProvider::getCamera() {
cgt::Camera* TrackballCameraProvider::getCamera() {
if (!_dirty) {
_localCopy = tgt::Camera(
_localCopy = cgt::Camera(
p_position.getValue(),
p_focus.getValue(),
p_upVector.getValue(),
......@@ -121,16 +121,17 @@ namespace campvis {
p_upVector.setValue(_localCopy.getUpVector());
p_fov.setValue(_localCopy.getFovy());
p_aspectRatio.setValue(_localCopy.getRatio());
p_clippingPlanes.setValue(tgt::vec2(_localCopy.getNearDist(), _localCopy.getFarDist()));
if (cgt::isNumber(_localCopy.getNearDist()) && cgt::isNumber(_localCopy.getFarDist()))
p_clippingPlanes.setValue(cgt::vec2(_localCopy.getNearDist(), _localCopy.getFarDist()));
switch (_localCopy.getProjectionMode()) {
case tgt::Camera::PERSPECTIVE:
case cgt::Camera::PERSPECTIVE:
p_projectionMode.selectById("perspective");
break;
case tgt::Camera::ORTHOGRAPHIC:
case cgt::Camera::ORTHOGRAPHIC:
p_projectionMode.selectById("orthographic");
break;
case tgt::Camera::FRUSTUM:
case cgt::Camera::FRUSTUM:
p_projectionMode.selectById("frustum");
break;
}
......@@ -151,8 +152,8 @@ namespace campvis {
// convert data
ScopedTypedData<ImageData> img(data, p_image.getValue());
if (img != 0) {
tgt::Bounds volumeExtent = img->getWorldBounds();
tgt::vec3 pos = volumeExtent.center() - tgt::vec3(0, 0, tgt::length(volumeExtent.diagonal()));
cgt::Bounds volumeExtent = img->getWorldBounds();
cgt::vec3 pos = volumeExtent.center() - cgt::vec3(0, 0, cgt::length(volumeExtent.diagonal()));
if (_trackball->getSceneBounds() != volumeExtent) {
_trackball->setSceneBounds(volumeExtent);
......@@ -164,8 +165,8 @@ namespace campvis {
}
void TrackballCameraProvider::addLqModeProcessor(VisualizationProcessor* vp) {
tgtAssert(vp != 0, "Pointer to processor must not be 0.");
tgtAssert(std::find(_lqModeProcessors.begin(), _lqModeProcessors.end(), vp) == _lqModeProcessors.end(), "Processor already in list of LQ mode processors.");
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);
}
......
......@@ -31,12 +31,12 @@
#define TRACKBALLCAMERAPROVIDER_H__
#include "tbb/atomic.h"
#include "tgt/bounds.h"
#include "tgt/event/eventlistener.h"
#include "tgt/navigation/trackball.h"
#include "cgt/bounds.h"
#include "cgt/event/eventlistener.h"
#include "cgt/navigation/trackball.h"
#include "modules/base/processors/cameraprovider.h"
namespace tgt {
namespace cgt {
class Trackball;
}
......@@ -46,7 +46,7 @@ namespace campvis {
/**
* Generates CameraData objects.
*/
class TrackballCameraProvider : public CameraProvider, public tgt::EventListener , public tgt::IHasCamera {
class TrackballCameraProvider : public CameraProvider, public cgt::EventListener , public cgt::IHasCamera {
public:
/// Trackball automation mode
enum AutomationMode {
......@@ -69,13 +69,13 @@ namespace campvis {
/// \see AbstractProcessor::updateProperties()
virtual void updateProperties(DataContainer& dataContainer);
/// \see tgt::EventListener::onEvent()
virtual void onEvent(tgt::Event* e);
/// \see cgt::EventListener::onEvent()
virtual void onEvent(cgt::Event* e);
/// \see tgt::Camera::IHasCamera::getCamera()
virtual tgt::Camera* getCamera();
/// \see cgt::Camera::IHasCamera::getCamera()
virtual cgt::Camera* getCamera();
/// \see tgt::Camera::IHasCamera::update()
/// \see cgt::Camera::IHasCamera::update()
virtual void update();
......@@ -107,9 +107,9 @@ namespace campvis {
IVec2Property* _canvasSize;
/// Temporary copy of the property's camera which will be modified and written back to the property upon update().
tgt::Camera _localCopy;
/// The tgt::Trackball for the navigation logic
tgt::Trackball* _trackball;
cgt::Camera _localCopy;
/// The cgt::Trackball for the navigation logic
cgt::Trackball* _trackball;
tbb::atomic<bool> _dirty;
......
......@@ -34,34 +34,27 @@ namespace campvis {
MprDemo::MprDemo(DataContainer* dc)
: AutoEvaluationPipeline(dc)
, _camera("camera", "Camera")
, _tcp(&_canvasSize)
, _lsp()
, _imageReader()
, _mprRenderer(&_canvasSize)
, _compositor(&_canvasSize)
, _trackballEH(0)
{
addProperty(_camera);
_trackballEH = new TrackballNavigationEventListener(&_camera, &_canvasSize);
addEventListenerToBack(_trackballEH);
addProcessor(&_tcp);
addProcessor(&_lsp);
addProcessor(&_imageReader);
addProcessor(&_mprRenderer);
addProcessor(&_compositor);
addEventListenerToBack(&_tcp);
}
MprDemo::~MprDemo() {
delete _trackballEH;
}
void MprDemo::init() {
AutoEvaluationPipeline::init();
_imageReader.s_validated.connect(this, &MprDemo::onProcessorValidated);
_camera.addSharedProperty(&_mprRenderer.p_camera);
_mprRenderer.p_targetImageID.setValue("MPR");
_mprRenderer.p_targetImageID.addSharedProperty(&_compositor.p_firstImageId);
_mprRenderer.p_planeSize.setValue(250.f);
......@@ -79,20 +72,4 @@ namespace campvis {
_mprRenderer.p_transferFunction.replaceTF(tf);
}
void MprDemo::deinit() {
_canvasSize.s_changed.disconnect(this);
AutoEvaluationPipeline::deinit();
}
void MprDemo::onProcessorValidated(AbstractProcessor* processor) {
if (processor == &_imageReader) {
// update camera
ScopedTypedData<ImageData> img(*_data, _imageReader.p_targetImageID.getValue());
if (img != 0) {
_trackballEH->reinitializeCamera(img);
}
}
}
}
\ No newline at end of file
......@@ -28,6 +28,7 @@
#include "core/eventhandlers/trackballnavigationeventlistener.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/properties/cameraproperty.h"
#include "modules/base/processors/trackballcameraprovider.h"
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/vis/processors/mprrenderer.h"
......@@ -49,31 +50,18 @@ namespace campvis {
/// \see AutoEvaluationPipeline::init()
virtual void init();
/// \see AutoEvaluationPipeline::deinit()
virtual void deinit();
/// \see AbstractPipeline::getName()
virtual const std::string getName() const { return getId(); };
static const std::string getId() { return "MprDemo"; };
protected:
/**
* Slot getting called when one of the observed processors got validated.
* Updates the camera properties, when the input image has changed.
* \param processor The processor that emitted the signal
*/
virtual void onProcessorValidated(AbstractProcessor* processor);
CameraProperty _camera;
TrackballCameraProvider _tcp;
LightSourceProvider _lsp;
MhdImageReader _imageReader;
MprRenderer _mprRenderer;
RenderTargetCompositor _compositor;
TrackballNavigationEventListener* _trackballEH;
};
}
......
......@@ -28,6 +28,7 @@
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
#include "core/datastructures/cameradata.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
......@@ -47,7 +48,7 @@ namespace campvis {
: VisualizationProcessor(viewportSizeProp)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
, p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
, p_camera("Camera", "Camera")
, p_camera("Camera", "Camera ID", "camera", DataNameProperty::READ)
, p_planeNormal("PlaneNormal", "Clipping Plane Normal", cgt::vec3(0.f, 0.f, 1.f), cgt::vec3(-1.f), cgt::vec3(1.f), cgt::vec3(.1f), cgt::ivec3(2))
, p_planeDistance("PlaneDistance", "Clipping Plane Distance", 0.f, -1000.f, 1000.f, 1.f, 1)
, p_planeSize("PlaneSize", "Clipping Plane Size", 100.f, 0.f, 1000.f, 1.f, 1)
......@@ -85,15 +86,15 @@ namespace campvis {
void MprRenderer::updateResult(DataContainer& data) {
ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
ScopedTypedData<CameraData> camera(data, p_camera.getValue());
if (img != 0) {
if (img->getDimensionality() == 3) {
const cgt::Camera& cam = p_camera.getValue();
if (p_use2DProjection.getValue() || camera != nullptr) {
// Construct the clipping plane in world coordinates
cgt::vec3 n = cgt::normalize(p_planeNormal.getValue());
cgt::vec3 temp(1.0, 0.0, 0.0);
if (abs(cgt::dot(temp, n)) > 0.9)
if (abs(cgt::dot(temp, n) > 0.9))
temp = cgt::vec3(0.0, 1.0, 0.0);
cgt::vec3 inPlaneA = cgt::normalize(cgt::cross(n, temp)) * 0.5f * p_planeSize.getValue();
......@@ -133,8 +134,8 @@ namespace campvis {
_shader->setUniform("_viewMatrix", c.getViewMatrix());
}
else {
_shader->setUniform("_projectionMatrix", cam.getProjectionMatrix());
_shader->setUniform("_viewMatrix", cam.getViewMatrix());
_shader->setUniform("_projectionMatrix", camera->getCamera().getProjectionMatrix());
_shader->setUniform("_viewMatrix", camera->getCamera().getViewMatrix());
}
cgt::TextureUnit inputUnit, tfUnit;
......@@ -155,7 +156,11 @@ namespace campvis {
data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
}
else {
LERROR("Input image must have dimensionality of 3.");
LDEBUG("Could not find camera data.");
}
}
else {
LDEBUG("Input image must have dimensionality of 3.");
}
}
else {
......
......@@ -70,7 +70,7 @@ namespace campvis {
DataNameProperty p_sourceImageID; ///< image ID for input image
DataNameProperty p_targetImageID; ///< image ID for output image
CameraProperty p_camera;
DataNameProperty p_camera;
Vec3Property p_planeNormal; ///< Clipping plane normal
FloatProperty p_planeDistance; ///< Clipping plane distance
......
Markdown is supported
0% or .