Commit 2b6f52dc authored by Hina Shah's avatar Hina Shah
Browse files

FEAT: Adding color and opacity changing capabilities for imstkGeometry.

FEAT: Adding color for text
ENH: Enabling Depth peeling in vtkViewer for proper rendering of opacity.
ENH: Removing unwanted functions from imstkInteractorStyle
parent b5c311af
......@@ -31,6 +31,7 @@ Geometry::print() const
LOG(INFO) << "Position: " << "(" << m_position.x() << ", " << m_position.y() << ", " << m_position.z() << ")";
LOG(INFO) << "Orientation:\n" << m_orientation.toRotationMatrix();
LOG(INFO) << "Scaling: " << m_scaling;
LOG(INFO) << "Color: " << m_color;
}
void
......@@ -178,6 +179,11 @@ Geometry::resetConfiguration()
m_configurationModified = true;
}
void
Geometry::setColorProperty(double r, double g, double b, double a)
{
m_color.setValue(r, g, b, a);
}
const std::string
Geometry::getTypeName() const
......
......@@ -24,6 +24,7 @@
#include "g3log/g3log.hpp"
#include "imstkMath.h"
#include "imstkColor.h"
// Eigen
#include <Eigen/Geometry>
......@@ -134,31 +135,59 @@ public:
///
const std::string getTypeName() const;
///
/// \brief Returns true if one of position, orientation or scaling is modified
///
bool isConfigurationModified() const { return m_configurationModified; }
///
/// \brief Returns true if one of position, orientation or scaling is modified
///
bool isConfigurationModified() const { return m_configurationModified; }
///
/// \brief Sets the state of configuration modified to desired value
///
void setConfigurationModified(const bool state)
{
///
/// \brief Sets the state of configuration modified to desired value
///
void setConfigurationModified(const bool state)
{
m_configurationModified = state;
}
///
/// \brief Reset the geometric configuration to identity
///
void resetConfiguration();
///
/// \brief
///
const AffineTransform3d& getEigenTransform() const
{
}
///
/// \brief Reset the geometric configuration to identity
///
void resetConfiguration();
///
/// \brief
///
const AffineTransform3d& getEigenTransform() const
{
return m_transform;
}
}
///
/// \brief
///
void setColorProperty(double r, double g, double b, double a);
///
/// \brief
///
imstk::Color getGeometryColor()
{
return m_color;
}
///
/// \brief
///
void setWireFrameMode(bool wireFrameModeOn)
{
m_wireframeMode = wireFrameModeOn;
}
///
/// \brief
bool getWireFrameMode()
{
return m_wireframeMode;
}
protected:
......@@ -170,10 +199,13 @@ protected:
const Quatd& orientation = Quatd::Identity()) :
m_type(type),
m_position(position),
m_orientation(orientation), m_transform()
{
m_transform.setIdentity();
}
m_orientation(orientation),
m_transform(),
m_color(1.,1.,1.),
m_wireframeMode(false)
{
m_transform.setIdentity();
}
Type m_type; ///> Geometry type
......@@ -181,9 +213,11 @@ protected:
Quatd m_orientation; ///> orientation
double m_scaling = 1; ///> Scaling
AffineTransform3d m_transform; ///> Compounded transform of the geometry
AffineTransform3d m_transform; ///> Compounded transform of the geometry
imstk::Color m_color;
bool m_configurationModified = true; // true if one of position, orientation or scaling is modified
bool m_configurationModified = true; // true if one of position, orientation or scaling is modified
bool m_wireframeMode;
};
} //imstk
......
......@@ -41,6 +41,7 @@
#include "vtkPolyDataMapper.h"
#include "vtkPolyDataNormals.h"
#include "vtkTransform.h"
#include "vtkProperty.h"
namespace imstk
{
......@@ -106,6 +107,8 @@ RenderDelegate::setActorMapper(vtkAlgorithmOutput *source)
mapper->SetInputConnection(normalGen->GetOutputPort());
m_actor->SetMapper(mapper);
this->setColorAndOpacity();
this->setWireFrameMode();
}
vtkSmartPointer<vtkActor>
......@@ -121,6 +124,23 @@ RenderDelegate::update()
this->updateActorTransform();
}
void
RenderDelegate::setColorAndOpacity()
{
imstk::Color geomColor = this->getGeometry()->getGeometryColor();
this->m_actor->GetProperty()->SetColor(geomColor.r, geomColor.g, geomColor.b);
this->m_actor->GetProperty()->SetOpacity(geomColor.a);
}
void
RenderDelegate::setWireFrameMode()
{
if (this->getGeometry()->getWireFrameMode())
this->m_actor->GetProperty()->SetRepresentationToWireframe();
else
this->m_actor->GetProperty()->SetRepresentationToSurface();
}
void
RenderDelegate::setVtkTrasnformFromEigen(const AffineTransform3d& t)
{
......
......@@ -78,10 +78,20 @@ public:
///
void updateActorTransform();
///
/// \brief
///
void setVtkTrasnformFromEigen(const AffineTransform3d& t);
///
/// \brief
///
void setVtkTrasnformFromEigen(const AffineTransform3d& t);
///
/// \brief
///
void setColorAndOpacity();
///
/// \brief
///
void setWireFrameMode();
protected:
///
......
......@@ -30,6 +30,7 @@
#include <vtkImageReader2.h>
#include <vtkTexture.h>
#include <vtkProperty.h>
#include <vtkPolyDataNormals.h>
#include "g3log/g3log.hpp"
......@@ -69,6 +70,10 @@ SurfaceMeshRenderDelegate::SurfaceMeshRenderDelegate(std::shared_ptr<SurfaceMesh
polydata->SetPoints(points);
polydata->SetPolys(triangles);
/* auto normalGen = vtkSmartPointer<vtkPolyDataNormals>::New();
normalGen->SetInputData(polydata);
normalGen->SplittingOff();*/
// Mapper
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polydata);
......@@ -129,6 +134,9 @@ SurfaceMeshRenderDelegate::SurfaceMeshRenderDelegate(std::shared_ptr<SurfaceMesh
// Actor
m_actor->SetMapper(mapper);
this->setColorAndOpacity();
this->setWireFrameMode();
// Transform
this->updateActorTransform();
}
......
......@@ -51,10 +51,10 @@ public:
///
SurfaceMeshRenderDelegate(std::shared_ptr<SurfaceMesh>SurfaceMesh);
///
/// \brief
///
void mapVertices();
///
/// \brief
///
void mapVertices();
///
......
......@@ -115,6 +115,7 @@ Renderer::setup(Mode mode)
}
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
m_vtkRenderer->SetUseDepthPeeling(true);
}
else if( mode == Mode::DEBUG && m_currentMode != Mode::DEBUG )
{
......@@ -131,6 +132,7 @@ Renderer::setup(Mode mode)
m_vtkRenderer->SetActiveCamera(m_defaultVtkCamera);
m_vtkRenderer->ResetCamera();
m_vtkRenderer->SetUseDepthPeeling(true);
}
else if ( mode == Mode::SIMULATION && m_currentMode != Mode::SIMULATION )
{
......@@ -149,6 +151,10 @@ Renderer::setup(Mode mode)
m_vtkRenderer->SetActiveCamera(m_sceneVtkCamera);
m_vtkRenderer->ResetCameraClippingRange();
// Choose to use depth peeling (if supported) (initial value is 0 (false)):
m_vtkRenderer->SetUseDepthPeeling(true);
}
m_currentMode = mode;
......@@ -167,7 +173,7 @@ Renderer::updateSceneCamera(std::shared_ptr<Camera> imstkCam)
m_sceneVtkCamera->SetFocalPoint(f[0], f[1], f[2]);
m_sceneVtkCamera->SetViewUp(v[0], v[1], v[2]);
m_sceneVtkCamera->SetViewAngle(imstkCam->getViewAngle());
m_sceneVtkCamera->Zoom(imstkCam->getZoomFactor());
m_sceneVtkCamera->Zoom(imstkCam->getZoomFactor());
}
void
......
......@@ -51,236 +51,236 @@ namespace imstk
{
vtkStandardNewMacro(InteractorStyle);
bool
InteractorStyle::parseLogFileAndCalculateMetrics(std::string filename, vtkSmartPointer<vtkPoints> outPoints,
vtkSmartPointer<vtkFloatArray> outVelocities,
vtkSmartPointer<vtkFloatArray> outAccelerations,
vtkSmartPointer<vtkFloatArray> outJerks)
{
// open logger file
fstream fstr(filename.c_str(), fstream::in);
if (!fstr.is_open() || !fstr.good() || fstr.eof())
{
LOG(WARNING) << "ERROR opening " << filename ;
return false;
}
// parse logger file
double min = MAX_D;
double max = MIN_D;
char line[1024];
while (fstr.good())
{
fstr.getline(line, 1024);
if (line[0] == '\0') continue;
char *ptr;
double x = 0.0, y = 0.0, z = 0.0;
int columnNumber = 0;
bool reTokenise = false;
if (strncmp(line, ",", 1) == 0)
{
ptr = nullptr;
reTokenise = true;
}
else
{
ptr = strtok(line, ",");
}
// Read columns
while (columnNumber < 4)
{
if (ptr != nullptr)
{
if (columnNumber == 1)
{
x = atof(ptr);
}
else if (columnNumber == 2)
{
y = atof(ptr);
}
else if (columnNumber == 3)
{
z = atof(ptr);
}
}
if (reTokenise == false)
{
ptr = strtok(NULL, ",");
}
else
{
ptr = strtok(line, ",");
reTokenise = false;
}
columnNumber++;
}
// Add points or velocities
if (line[0] == 'P')
{
outPoints->InsertNextPoint(x, y, z);
}
else if (line[0] == 'V')
{
auto norm = Vec3d(x, y, z).norm();
outVelocities->InsertNextValue(norm);
}
}
auto numpts = outPoints->GetNumberOfPoints();
auto numdata = outVelocities->GetNumberOfValues();
if (numpts != numdata)
{
LOG(WARNING) << "ERROR reading " << filename << " : inconsistant number of points & velocity "
<< "(" << numpts << " & " << numdata << ")";
return false;
}
//Calculate accelerations and jerks for each point
for (auto index = 0; index < numpts; index++)
{
if (index < 2 || index >= numpts - 2)
{
//Ignoring the boundary points
outJerks->InsertNextTuple3(0., 0., 0.);
if (index == 0 || index == numpts - 1)
outAccelerations->InsertNextTuple3(0., 0., 0.);
continue;
}
Vec3d x(0., 0., 0.);
Vec3d x_min1(0., 0., 0.);
Vec3d x_min2(0., 0., 0.);
Vec3d x_plus1(0., 0., 0.);
Vec3d x_plus2(0., 0., 0.);
outPoints->GetPoint(index, x.data());
auto newInd = index - 1;
outPoints->GetPoint(newInd, x_min1.data());
newInd = index - 2;
outPoints->GetPoint(newInd, x_min2.data());
newInd = index + 1;
outPoints->GetPoint(newInd, x_plus1.data());
newInd = index + 2;
outPoints->GetPoint(newInd, x_plus2.data());
//acceleration calculated as a second central derivative of position wrt time, h=1
auto acceleration = x_plus1 - 2 * x + x_min1;
//jerk calculated as the third derivative of position wrt time, h=1
auto jerk = 0.5*(x_plus2 - x_min2 - 2 * x_plus1 + 2 * x_min1);
LOG(INFO) << index << ", acceleration: " << acceleration << ", jerk: " << jerk;
outAccelerations->InsertNextTuple3(acceleration[0], acceleration[1], acceleration[2]);
outJerks->InsertNextTuple3(jerk[0], jerk[1], jerk[2]);
}
return true;
}
void
InteractorStyle::displayPath(std::string deviceName)
{
auto points = vtkSmartPointer<vtkPoints>::New();
auto dataArray = vtkSmartPointer<vtkFloatArray>::New();
dataArray->SetName("Velocity");
auto accelArray = vtkSmartPointer<vtkFloatArray>::New();
accelArray->SetName("Acceleration");
accelArray->SetNumberOfComponents(3);
auto jerkArray = vtkSmartPointer<vtkFloatArray>::New();
jerkArray->SetName("Jerk");
jerkArray->SetNumberOfComponents(3);
// Precalculate all the metrics from device's log file
if (!parseLogFileAndCalculateMetrics(deviceName + ".log", points, dataArray, accelArray, jerkArray))
return;
// Set up spline points
auto polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints( points );
polyData->GetPointData()->AddArray( dataArray );
polyData->GetPointData()->SetActiveScalars("Velocity");
// Set up curves between adjacent points
auto numpts = points->GetNumberOfPoints();
polyData->Allocate( numpts-1 );
for (vtkIdType i = 0; i < numpts-1; ++i)
{
vtkIdType ii[2];
ii[0] = i;
ii[1] = i+1;
polyData->InsertNextCell( VTK_LINE, 2, ii );
}
auto writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
writer->SetFileName((deviceName+".vtp").c_str());
writer->SetInputData(polyData);
writer->SetDataModeToAscii();
writer->Write();
// Lookup Table
double velocityRange[2];
dataArray->GetRange(velocityRange);
LOG(INFO) << "Velocity Norms range: " << velocityRange[0] << " " << velocityRange[1];
auto colors = vtkSmartPointer<vtkColorTransferFunction>::New();
colors->AddRGBPoint(velocityRange[0], 1, 0, 0);
colors->AddRGBPoint((velocityRange[1]-velocityRange[0])/3, 1, 0.5, 0);
colors->AddRGBPoint((velocityRange[1]-velocityRange[0])*2/3, 1, 1, 0);
colors->AddRGBPoint(velocityRange[1], 0, 1, 0);
colors->SetColorSpaceToRGB();
// Setup actor and mapper
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(polyData);
mapper->SetScalarRange(velocityRange[0], velocityRange[1]);
mapper->SetLookupTable(colors);
mapper->ScalarVisibilityOn();
auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
//Add actor for jerk glyphs
vtkSmartPointer<vtkArrowSource> arrow =
vtkSmartPointer<vtkArrowSource>::New();
polyData->GetPointData()->SetVectors(jerkArray);
vtkSmartPointer<vtkGlyph3D> glyphs =
vtkSmartPointer<vtkGlyph3D>::New();
glyphs->SetInputData(polyData);
glyphs->SetSourceConnection(arrow->GetOutputPort());
glyphs->ScalingOn();
glyphs->SetScaleModeToScaleByVector();
glyphs->SetColorModeToColorByVector();
glyphs->OrientOn();
glyphs->ClampingOff();
glyphs->SetVectorModeToUseVector();
glyphs->SetIndexModeToOff();
vtkSmartPointer<vtkPolyDataMapper> glyphMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
glyphMapper->SetInputConnection(glyphs->GetOutputPort());
glyphMapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> glyphActor =
vtkSmartPointer<vtkActor>::New();
glyphActor->SetMapper(glyphMapper);
glyphActor->GetProperty()->SetColor(0., 0., 1.);
m_simManager->getViewer()->getCurrentRenderer()->getVtkRenderer()->AddActor(actor);
m_simManager->getViewer()->getCurrentRenderer()->getVtkRenderer()->AddActor(glyphActor);
}
//
//bool
//InteractorStyle::parseLogFileAndCalculateMetrics(std::string filename, vtkSmartPointer<vtkPoints> outPoints,
// vtkSmartPointer<vtkFloatArray> outVelocities,
// vtkSmartPointer<vtkFloatArray> outAccelerations,
// vtkSmartPointer<vtkFloatArray> outJerks)
//{
// // open logger file
// fstream fstr(filename.c_str(), fstream::in);
// if (!fstr.is_open() || !fstr.good() || fstr.eof())
// {
// LOG(WARNING) << "ERROR opening " << filename ;
// return false;
// }
//
// // parse logger file
// double min = MAX_D;
// double max = MIN_D;
// char line[1024];
// while (fstr.good())
// {
// fstr.getline(line, 1024);
// if (line[0] == '\0') continue;
//
// char *ptr;
// double x = 0.0, y = 0.0, z = 0.0;
// int columnNumber = 0;
// bool reTokenise = false;
//
// if (strncmp(line, ",", 1) == 0)
// {
// ptr = nullptr;
// reTokenise = true;
// }
// else
// {
// ptr = strtok(line, ",");
// }
//
// // Read columns
// while (columnNumber < 4)
// {
// if (ptr != nullptr)
// {
// if (columnNumber == 1)
// {
// x = atof(ptr);
// }
// else if (columnNumber == 2)
// {
// y = atof(ptr);
// }
// else if (columnNumber == 3)
// {
// z = atof(ptr);
// }
// }
//
// if (reTokenise == false)
// {
// ptr = strtok(NULL, ",");
// }
// else
// {
// ptr = strtok(line, ",");
// reTokenise = false;
// }
// columnNumber++;
// }
//
// // Add points or velocities
// if (line[0] == 'P')
// {
// outPoints->InsertNextPoint(x, y, z);
// }
// else if (line[0] == 'V')
// {
// auto norm = Vec3d(x, y, z).norm();
// outVelocities->InsertNextValue(norm);
// }
// }
//
// auto numpts = outPoints->GetNumberOfPoints();
// auto numdata = outVelocities->GetNumberOfValues();
// if (numpts != numdata)
// {
// LOG(WARNING) << "ERROR reading " << filename << " : inconsistant number of points & velocity "