Commit a4252322 authored by Jakob Weiss's avatar Jakob Weiss
Browse files

improved gui for MatrixProcessor

parent a4f616d0
...@@ -47,8 +47,10 @@ namespace campvis { ...@@ -47,8 +47,10 @@ namespace campvis {
_matrixProcessor.s_validated.connect(this, &StreamingOIGTLDemo::onProcessorValidated); _matrixProcessor.s_validated.connect(this, &StreamingOIGTLDemo::onProcessorValidated);
_renderTargetID.setValue("IGTL.image.ImagerClient"); _renderTargetID.setValue("IGTL.image.ImagerClient");
_matrixProcessor.p_matrixA.setValue("IGTL.transform.ProbeToTracker"); _matrixProcessor.p_matrixAID.setValue("IGTL.transform.ProbeToTracker");
_matrixProcessor.p_matrixB.setValue("IGTL.transform.ReferenceToTracker"); _matrixProcessor.p_matrixAType.selectByOption("data");
_matrixProcessor.p_matrixBID.setValue("IGTL.transform.ReferenceToTracker");
_matrixProcessor.p_matrixBType.selectByOption("data");
_igtlClient.p_address.setValue("127.0.0.1"); _igtlClient.p_address.setValue("127.0.0.1");
......
...@@ -35,185 +35,235 @@ ...@@ -35,185 +35,235 @@
namespace campvis { namespace campvis {
const std::string MatrixProcessor::loggerCat_ = "CAMPVis.modules.core.MatrixProcessor"; const std::string MatrixProcessor::loggerCat_ = "CAMPVis.modules.core.MatrixProcessor";
MatrixProcessor::MatrixProcessor() GenericOption<std::string> typeOptions[2] = {
: AbstractProcessor() GenericOption<std::string>("fixed", "Fixed Matrix"),
, p_matrixA("MatrixA", "Matrix A", "matrixA") GenericOption<std::string>("data", "Matrix from Data Container")
, p_matrixB("MatrixB", "Matrix B", "matrixB") };
, p_matrixAModifiers("MatrixAModifiers", "Matrix A Modifiers")
, p_matrixBModifiers("MatrixBModifiers", "Matrix B Modifiers") MatrixProcessor::MatrixProcessor()
, p_targetMatrixID("TargetMatrixID", "Target Matrix ID", "result.matrix", DataNameProperty::WRITE) : AbstractProcessor()
, lastdc_(nullptr) , p_matrixAType("MatrixA_Type", "Matrix A Source", typeOptions, 2)
, p_matrixAID("MatrixA_ID", "Matrix A", "matrixA", DataNameProperty::READ)
, p_matrixAString("MatrixA_String", "Matrix A String", "identity")
, p_matrixAModifiers("MatrixAModifiers", "Matrix A Modifiers")
, p_matrixBType("MatrixB_Type", "Matrix B Source", typeOptions, 2)
, p_matrixBID("MatrixB_ID", "Matrix B", "matrixB", DataNameProperty::READ)
, p_matrixBString("MatrixB_String", "Matrix B String", "identity")
, p_matrixBModifiers("MatrixBModifiers", "Matrix B Modifiers")
, p_targetMatrixID("TargetMatrixID", "Target Matrix ID", "result.matrix", DataNameProperty::WRITE)
, _lastdc(nullptr)
{ {
addProperty(p_matrixA, VALID); addProperty(p_matrixAType, INVALID_PROPERTIES);
addProperty(p_matrixAModifiers, VALID); addProperty(p_matrixAID, INVALID_RESULT);
addProperty(p_matrixB, VALID); addProperty(p_matrixAString, INVALID_RESULT);
addProperty(p_matrixBModifiers, VALID); addProperty(p_matrixAModifiers, INVALID_RESULT);
addProperty(p_targetMatrixID, VALID);
addProperty(p_matrixBType, INVALID_PROPERTIES);
addProperty(p_matrixBID, INVALID_RESULT);
addProperty(p_matrixBString, INVALID_RESULT);
addProperty(p_matrixBModifiers, INVALID_RESULT);
addProperty(p_targetMatrixID, INVALID_RESULT);
invalidate(INVALID_PROPERTIES);
} }
MatrixProcessor::~MatrixProcessor() { MatrixProcessor::~MatrixProcessor() {
if (lastdc_) if (_lastdc)
lastdc_->s_dataAdded.disconnect(this); _lastdc->s_dataAdded.disconnect(this);
} }
void MatrixProcessor::init() { void MatrixProcessor::init() {
} }
void MatrixProcessor::deinit() { void MatrixProcessor::deinit() {
} }
void MatrixProcessor::updateResult(DataContainer& data) { void MatrixProcessor::updateResult(DataContainer& data) {
if (&data != lastdc_) { LINFO("Updating Result");
if (lastdc_) {
lastdc_->s_dataAdded.disconnect(this); //if (&data != _lastdc) {
} // if (_lastdc) {
// _lastdc->s_dataAdded.disconnect(this);
data.s_dataAdded.connect(this, &MatrixProcessor::DataContainerDataAdded); // }
lastdc_ = &data;
}
tgt::mat4 matA = processMatrixString(p_matrixA.getValue(), data); // data.s_dataAdded.connect(this, &MatrixProcessor::DataContainerDataAdded);
tgt::mat4 matB = processMatrixString(p_matrixB.getValue(), data); // _lastdc = &data;
//}
tgt::mat4 matAProcessed = processModifierString(matA, p_matrixAModifiers.getValue()); tgt::mat4 matA = tgt::mat4::createIdentity();
tgt::mat4 matBProcessed = processModifierString(matB, p_matrixBModifiers.getValue()); if(p_matrixAType.getOptionValue() == "fixed")
matA = processMatrixString(p_matrixAString.getValue(), data);
else {
ScopedTypedData<TransformData> td(data, p_matrixAID.getValue());
if (td != 0) matA = td->getTransform();
}
tgt::mat4 matB = tgt::mat4::createIdentity();
if (p_matrixBType.getOptionValue() == "fixed")
matB = processMatrixString(p_matrixBString.getValue(), data);
else {
ScopedTypedData<TransformData> td(data, p_matrixBID.getValue());
if (td != 0) matB = td->getTransform();
}
tgt::mat4 matAProcessed = processModifierString(matA, p_matrixAModifiers.getValue());
tgt::mat4 matBProcessed = processModifierString(matB, p_matrixBModifiers.getValue());
tgt::mat4 result = matAProcessed * matBProcessed;
LDEBUG("Matrix A: " << std::endl << matA); tgt::mat4 result = matAProcessed * matBProcessed;
LDEBUG("Matrix A':" << std::endl << matAProcessed);
LDEBUG("Matrix B " << std::endl << matB);
LDEBUG("Matrix B':" << std::endl << matBProcessed);
LDEBUG("Result Matrix: " << std::endl << result);
LDEBUG(std::endl);
TransformData * td = new TransformData(result); LDEBUG("Matrix A: " << std::endl << matA);
LDEBUG("Matrix A':" << std::endl << matAProcessed);
LDEBUG("Matrix B: " << std::endl << matB);
LDEBUG("Matrix B':" << std::endl << matBProcessed);
LDEBUG("Result Matrix: " << std::endl << result);
LDEBUG(std::endl);
data.addData(p_targetMatrixID.getValue(), td); TransformData * td = new TransformData(result);
data.addData(p_targetMatrixID.getValue(), td);
validate(INVALID_RESULT); validate(INVALID_RESULT);
} }
void MatrixProcessor::updateProperties(DataContainer& dataContainer) void MatrixProcessor::updateProperties(DataContainer& dataContainer)
{ {
// we invalidate just in case a hardcoded matrix or its modifiers have changed LINFO("Updating Properties");
invalidate(INVALID_RESULT); if (p_matrixAType.getOptionValue() == "fixed") {
} p_matrixAID.setVisible(false);
p_matrixAString.setVisible(true);
tgt::mat4 MatrixProcessor::processMatrixString(std::string matrixString, DataContainer& data) }
{ else {
std::vector<std::string> tokens = StringUtils::split(matrixString, " "); p_matrixAID.setVisible(true);
p_matrixAString.setVisible(false);
if (tokens.size() == 0 || tokens[0] == "identity") { }
return tgt::mat4(tgt::mat4::identity);
} if (p_matrixBType.getOptionValue() == "fixed") {
// if we have exactly 16 tokens, we assume we have a matrix in numerical form p_matrixBID.setVisible(false);
else if (tokens.size() == 16) { p_matrixBString.setVisible(true);
tgt::mat4 mat; }
float * p = mat.elem; else {
for (int i = 0; i < 16; i++) { p_matrixBID.setVisible(true);
*p = static_cast<float>(atof(tokens[i].c_str())); p_matrixBString.setVisible(false);
p++; }
}
return mat; validate(INVALID_PROPERTIES);
} }
// if the first token is "rot", we create an angle axis rotation matrix with the specified arguments
else if (tokens[0] == "rot") { tgt::mat4 MatrixProcessor::processMatrixString(std::string matrixString, DataContainer& data)
if (tokens.size() != 5) { {
LWARNING("Rotation matrix string does not have the correct number of arguments!"); std::vector<std::string> tokens = StringUtils::split(matrixString, " ");
return tgt::mat4::createIdentity();
} if (tokens.size() == 0 || tokens[0] == "identity") {
float angle; return tgt::mat4(tgt::mat4::identity);
tgt::vec3 axis; }
angle = static_cast<float>(atof(tokens[1].c_str())); // if we have exactly 16 tokens, we assume we have a matrix in numerical form
axis[0] = static_cast<float>(atof(tokens[2].c_str())); else if (tokens.size() == 16) {
axis[1] = static_cast<float>(atof(tokens[3].c_str())); tgt::mat4 mat;
axis[2] = static_cast<float>(atof(tokens[4].c_str())); float * p = mat.elem;
return tgt::mat4::createRotation(angle, axis); for (int i = 0; i < 16; i++) {
} *p = static_cast<float>(atof(tokens[i].c_str()));
else if (tokens[0] == "trans") { p++;
if (tokens.size() != 4) { }
LWARNING("Translation matrix string does not have the correct number of arguments!"); return mat;
return tgt::mat4::createIdentity(); }
} // if the first token is "rot", we create an angle axis rotation matrix with the specified arguments
else if (tokens[0] == "rot") {
tgt::vec3 translation; if (tokens.size() != 5) {
translation[0] = static_cast<float>(atof(tokens[1].c_str())); LWARNING("Rotation matrix string does not have the correct number of arguments!");
translation[1] = static_cast<float>(atof(tokens[2].c_str())); return tgt::mat4::createIdentity();
translation[2] = static_cast<float>(atof(tokens[3].c_str())); }
return tgt::mat4::createTranslation(translation); float angle;
} tgt::vec3 axis;
else if (tokens[0] == "scale") { angle = static_cast<float>(atof(tokens[1].c_str()));
if (tokens.size() != 2 && tokens.size() != 4) { axis[0] = static_cast<float>(atof(tokens[2].c_str()));
LWARNING("Scaling matrix string does not have the correct number of arguments!"); axis[1] = static_cast<float>(atof(tokens[3].c_str()));
return tgt::mat4::createIdentity(); axis[2] = static_cast<float>(atof(tokens[4].c_str()));
} return tgt::mat4::createRotation(angle, axis);
}
tgt::vec3 scale; else if (tokens[0] == "trans") {
scale[0] = static_cast<float>(atof(tokens[1].c_str())); if (tokens.size() != 4) {
if (tokens.size() == 4) { LWARNING("Translation matrix string does not have the correct number of arguments!");
scale[1] = static_cast<float>(atof(tokens[2].c_str())); return tgt::mat4::createIdentity();
scale[2] = static_cast<float>(atof(tokens[3].c_str())); }
}
else { tgt::vec3 translation;
scale[1] = scale[2] = scale[0]; translation[0] = static_cast<float>(atof(tokens[1].c_str()));
} translation[1] = static_cast<float>(atof(tokens[2].c_str()));
translation[2] = static_cast<float>(atof(tokens[3].c_str()));
return tgt::mat4::createScale(scale); return tgt::mat4::createTranslation(translation);
} }
// if we cannot find another pattern, we assume we have a data container ID else if (tokens[0] == "scale") {
else { if (tokens.size() != 2 && tokens.size() != 4) {
ScopedTypedData<TransformData> td(data, matrixString); LWARNING("Scaling matrix string does not have the correct number of arguments!");
if (td == 0) { return tgt::mat4::createIdentity();
LWARNING("Data Container ID \"" << matrixString << "\" was not suitable as input Matrix"); }
return tgt::mat4::createIdentity();
} tgt::vec3 scale;
scale[0] = static_cast<float>(atof(tokens[1].c_str()));
return td->getTransform(); if (tokens.size() == 4) {
} scale[1] = static_cast<float>(atof(tokens[2].c_str()));
scale[2] = static_cast<float>(atof(tokens[3].c_str()));
} }
else {
tgt::mat4 MatrixProcessor::processModifierString(tgt::mat4 matrix, std::string modifiers) scale[1] = scale[2] = scale[0];
{ }
int pos = 0;
tgt::mat4 result = matrix, tmp; return tgt::mat4::createScale(scale);
}
while (pos < modifiers.size()) // if we cannot find another pattern, we assume we have a data container ID
{ else {
switch (modifiers[pos]) { ScopedTypedData<TransformData> td(data, matrixString);
case 'I': if (td == 0) {
if (!result.invert(tmp)) { LWARNING("Data Container ID \"" << matrixString << "\" was not suitable as input Matrix");
LWARNING("Matrix Inversion failed."); return tgt::mat4::createIdentity();
} }
else result = tmp;
break; return td->getTransform();
case 'T': }
result = tgt::transpose(result);
break; }
case '-':
result = tgt::mat4::zero - result; tgt::mat4 MatrixProcessor::processModifierString(tgt::mat4 matrix, std::string modifiers)
break; {
case 'r': int pos = 0;
result = result.getRotationalPart(); tgt::mat4 result = matrix, tmp;
break;
case 's': while (pos < modifiers.size())
result = tgt::mat4::createScale(result.getScalingPart()); {
break; switch (modifiers[pos]) {
default: case 'I':
LWARNING("Ignoring unknown modifier: " << modifiers[pos]); if (!result.invert(tmp)) {
} LWARNING("Matrix Inversion failed.");
} }
return result; else result = tmp;
} break;
case 'T':
void MatrixProcessor::DataContainerDataAdded(const std::string &name, const DataHandle &data) result = tgt::transpose(result);
{ break;
if (name == p_matrixA.getValue() || name == p_matrixB.getValue()) case '-':
invalidate(INVALID_RESULT); result = tgt::mat4::zero - result;
} break;
case 'r':
result = result.getRotationalPart();
break;
case 's':
result = tgt::mat4::createScale(result.getScalingPart());
break;
default:
LWARNING("Ignoring unknown modifier: " << modifiers[pos]);
}
}
return result;
}
void MatrixProcessor::DataContainerDataAdded(const std::string &name, const DataHandle &data)
{
if (name == p_matrixAID.getValue() || name == p_matrixBID.getValue())
invalidate(INVALID_RESULT);
}
} }
\ No newline at end of file
...@@ -31,10 +31,7 @@ ...@@ -31,10 +31,7 @@
#include <tgt/matrix.h> #include <tgt/matrix.h>
#include "core/pipeline/abstractprocessor.h" #include "core/pipeline/abstractprocessor.h"
#include "core/properties/buttonproperty.h" #include "core/properties/allproperties.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/stringproperty.h"
namespace campvis { namespace campvis {
/** /**
...@@ -51,6 +48,11 @@ namespace campvis { ...@@ -51,6 +48,11 @@ namespace campvis {
*/ */
class MatrixProcessor : public AbstractProcessor { class MatrixProcessor : public AbstractProcessor {
public: public:
enum SourceType {
FIXED = 0,
DATA = 1
};
/// Constructor /// Constructor
MatrixProcessor(); MatrixProcessor();
...@@ -71,12 +73,17 @@ namespace campvis { ...@@ -71,12 +73,17 @@ namespace campvis {
/// \see AbstractProcessor::getProcessorState() /// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; }; virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
StringProperty p_matrixA; ///< first Matrix input for the computation. \see MatrixProcessor::processMatrixString() GenericOptionProperty<std::string> p_matrixAType;
StringProperty p_matrixB; ///< second Matrix input for the computation. \see MatrixProcessor::processMatrixString() DataNameProperty p_matrixAID; ///< first Matrix input for the computation. \see MatrixProcessor::processMatrixString()
StringProperty p_matrixAString;
StringProperty p_matrixAModifiers; ///< modifier string to be applied to matrix A. \see MatrixProcessor::processModifierString()
GenericOptionProperty<std::string> p_matrixBType;
DataNameProperty p_matrixBID; ///< first Matrix input for the computation. \see MatrixProcessor::processMatrixString()
StringProperty p_matrixBString;
StringProperty p_matrixBModifiers; ///< modifier string to be applied to matrix A. \see MatrixProcessor::processModifierString()
StringProperty p_matrixAModifiers; ///< modifier string to be applied to matrix A. \see MatrixProcessor::processModifierString()
StringProperty p_matrixBModifiers; ///< modifier string to be applied to matrix B. \see MatrixProcessor::processModifierString()
DataNameProperty p_targetMatrixID; ///< image ID for read image DataNameProperty p_targetMatrixID; ///< image ID for read image
...@@ -129,7 +136,7 @@ namespace campvis { ...@@ -129,7 +136,7 @@ namespace campvis {
*/ */
tgt::mat4 processMatrixString(std::string matrixString, DataContainer& data); tgt::mat4 processMatrixString(std::string matrixString, DataContainer& data);
DataContainer * lastdc_; DataContainer * _lastdc;
static const std::string loggerCat_; static const std::string loggerCat_;
}; };
......
...@@ -39,7 +39,7 @@ namespace campvis { ...@@ -39,7 +39,7 @@ namespace campvis {
OpenIGTLinkClient::OpenIGTLinkClient() OpenIGTLinkClient::OpenIGTLinkClient()
: AbstractProcessor() : AbstractProcessor()
, p_address("ServerAddress", "Server Address", "127.0.0.1", StringProperty::BASIC_STRING) , p_address("ServerAddress", "Server Address", "127.0.0.1")
, p_port("ServerPort", "Server Port", 18944, 1, 65535, 1) , p_port("ServerPort", "Server Port", 18944, 1, 65535, 1)
, p_deviceName("ServerDeviceName", "Device Name (empty to accept all)") , p_deviceName("ServerDeviceName", "Device Name (empty to accept all)")
, p_connect("Connect", "Connect to Server") , p_connect("Connect", "Connect to Server")
......
...@@ -52,6 +52,7 @@ void main() { ...@@ -52,6 +52,7 @@ void main() {
} }
} }
else { else {
discard; out_Color = vec4(1, 0, 0, 1);
//discard;
} }
} }
...@@ -39,6 +39,8 @@ namespace campvis { ...@@ -39,6 +39,8 @@ namespace campvis {
, _imageReader() , _imageReader()
, _mprRenderer(&_canvasSize) , _mprRenderer(&_canvasSize)
, _compositor(&_canvasSize) , _compositor(&_canvasSize)
, _trackerPose()
, _igtlClient()
, _trackballEH(0) , _trackballEH(0)
{ {
addProperty(_camera); addProperty(_camera);
...@@ -47,9 +49,12 @@ namespace campvis { ...@@ -47,9 +49,12 @@ namespace campvis {
addEventListenerToBack(_trackballEH); addEventListenerToBack(_trackballEH);
addProcessor(&_lsp); addProcessor(&_lsp);
addProcessor(&_igtlClient);
addProcessor(&_imageReader); addProcessor(&_imageReader);
addProcessor(&_trackerPose);
addProcessor(&_mprRenderer); addProcessor(&_mprRenderer);
addProcessor(&_compositor); addProcessor(&_compositor);
} }
MprDemo::~MprDemo() { MprDemo::~MprDemo() {
...@@ -60,6 +65,8 @@ namespace campvis { ...@@ -60,6 +65,8 @@ namespace campvis {
AutoEvaluationPipeline::init(); AutoEvaluationPipeline::init();
_imageReader.s_validated.connect(this, &MprDemo::onProcessorValidated); _imageReader.s_validated.connect(this, &MprDemo::onProcessorValidated);
_trackerPose.s_validated.connect(this, &MprDemo::onProcessorValidated);
_igtlClient.s_validated.connect(this, &MprDemo::onProcessorValidated);
_camera.addSharedProperty(&_mprRenderer.p_camera); _camera.addSharedProperty(&_mprRenderer.p_camera);
_mprRenderer.p_targetImageID.setValue("MPR"); _mprRenderer.p_targetImageID.setValue("MPR");
...@@ -77,6 +84,14 @@ namespace campvis { ...@@ -77,6 +84,14 @@ namespace campvis {
Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .08f)); Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .08f));
tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255))); tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255)));
_mprRenderer.p_transferFunction.replaceTF(tf); _mprRenderer.p_transferFunction.replaceTF(tf);
_trackerPose.p_matrixAID.setValue("IGTL.transform.ProbeToTracker");
_trackerPose.p_matrixAType.selectByOption("data");
_trackerPose.p_matrixBID.setValue("IGTL.transform.ReferenceToTracker");
_trackerPose.p_matrixBType.selectByOption("data");
_trackerPose.p_matrixBModifiers.setValue("I");
_trackerPose.p_targetMatrixID.setValue("ProbeToReference");
_trackerPose.p_targetMatrixID.addSharedProperty(&_mprRenderer.p_transformationID);
} }
void MprDemo::deinit() { void MprDemo::deinit() {
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#include "modules/vis/processors/mprrenderer.h" #include "modules/vis/processors/mprrenderer.h"
#include "modules/vis/processors/rendertargetcompositor.h" #include "modules/vis/processors/rendertargetcompositor.h"
#include "modules/openigtlink/processors/openigtlinkclient.h"
#include "modules/openigtlink/processors/matrixprocessor.h"
namespace campvis { namespace campvis {