Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/flip volume #184

Merged
merged 8 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions agave_app/AppearanceSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,32 +134,48 @@ QAppearanceSettingsWidget::QAppearanceSettingsWidget(QWidget* pParent,
m_xscaleSpinner->setDecimals(6);
m_xscaleSpinner->setValue(1.0);
scaleSectionLayout->addWidget(m_xscaleSpinner, 0, 1);
m_xFlipCheckBox = new QCheckBox("Flip");
m_xFlipCheckBox->setStatusTip(tr("Invert volume in X dimension"));
m_xFlipCheckBox->setToolTip(tr("Invert volume in X dimension"));
scaleSectionLayout->addWidget(m_xFlipCheckBox, 0, 2);
QObject::connect(m_xscaleSpinner,
QOverload<double>::of(&QDoubleSpinner::valueChanged),
this,
&QAppearanceSettingsWidget::OnSetScaleX);
QObject::connect(m_xFlipCheckBox, &QCheckBox::clicked, this, &QAppearanceSettingsWidget::OnFlipX);
scaleSectionLayout->addWidget(new QLabel("Y"), 1, 0);
m_yscaleSpinner = new QDoubleSpinner();
m_yscaleSpinner->setStatusTip(tr("Scale volume in Y dimension"));
m_yscaleSpinner->setToolTip(tr("Scale volume in Y dimension"));
m_yscaleSpinner->setDecimals(6);
m_yscaleSpinner->setValue(1.0);
scaleSectionLayout->addWidget(m_yscaleSpinner, 1, 1);
m_yFlipCheckBox = new QCheckBox("Flip");
m_yFlipCheckBox->setStatusTip(tr("Invert volume in Y dimension"));
m_yFlipCheckBox->setToolTip(tr("Invert volume in Y dimension"));
scaleSectionLayout->addWidget(m_yFlipCheckBox, 1, 2);
QObject::connect(m_yscaleSpinner,
QOverload<double>::of(&QDoubleSpinner::valueChanged),
this,
&QAppearanceSettingsWidget::OnSetScaleY);
QObject::connect(m_yFlipCheckBox, &QCheckBox::clicked, this, &QAppearanceSettingsWidget::OnFlipY);
scaleSectionLayout->addWidget(new QLabel("Z"), 2, 0);
m_zscaleSpinner = new QDoubleSpinner();
m_zscaleSpinner->setStatusTip(tr("Scale volume in Z dimension"));
m_zscaleSpinner->setToolTip(tr("Scale volume in Z dimension"));
m_zscaleSpinner->setDecimals(6);
m_zscaleSpinner->setValue(1.0);
m_zscaleSpinner->setMinimum(-m_zscaleSpinner->maximum());
scaleSectionLayout->addWidget(m_zscaleSpinner, 2, 1);
m_zFlipCheckBox = new QCheckBox("Flip");
m_zFlipCheckBox->setStatusTip(tr("Invert volume in Z dimension"));
m_zFlipCheckBox->setToolTip(tr("Invert volume in Z dimension"));
scaleSectionLayout->addWidget(m_zFlipCheckBox, 2, 2);
QObject::connect(m_zscaleSpinner,
QOverload<double>::of(&QDoubleSpinner::valueChanged),
this,
&QAppearanceSettingsWidget::OnSetScaleZ);
QObject::connect(m_zFlipCheckBox, &QCheckBox::clicked, this, &QAppearanceSettingsWidget::OnFlipZ);

m_scaleSection->setContentLayout(*scaleSectionLayout);
m_MainLayout.addRow(m_scaleSection);
Expand Down Expand Up @@ -369,6 +385,34 @@ QAppearanceSettingsWidget::createSkyLightingControls()
return section;
}

void
QAppearanceSettingsWidget::OnFlipX(bool value)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just making a note of my suggestion to change these 3 functions to one that takes in an axis value to reduce the copied code

{
if (!m_scene)
return;
glm::vec3 v = m_scene->m_volume->getVolumeAxesFlipped();
m_scene->m_volume->setVolumeAxesFlipped(value ? -1 : 1, v.y, v.z);
m_qrendersettings->renderSettings()->m_DirtyFlags.SetFlag(CameraDirty);
}
void
QAppearanceSettingsWidget::OnFlipY(bool value)
{
if (!m_scene)
return;
glm::vec3 v = m_scene->m_volume->getVolumeAxesFlipped();
m_scene->m_volume->setVolumeAxesFlipped(v.x, value ? -1 : 1, v.z);
m_qrendersettings->renderSettings()->m_DirtyFlags.SetFlag(CameraDirty);
}
void
QAppearanceSettingsWidget::OnFlipZ(bool value)
{
if (!m_scene)
return;
glm::vec3 v = m_scene->m_volume->getVolumeAxesFlipped();
m_scene->m_volume->setVolumeAxesFlipped(v.x, v.y, value ? -1 : 1);
m_qrendersettings->renderSettings()->m_DirtyFlags.SetFlag(CameraDirty);
}

void
QAppearanceSettingsWidget::OnSetScaleX(double value)
{
Expand Down Expand Up @@ -848,6 +892,10 @@ QAppearanceSettingsWidget::onNewImage(Scene* scene)
m_xscaleSpinner->setValue(m_scene->m_volume->physicalSizeX());
m_yscaleSpinner->setValue(m_scene->m_volume->physicalSizeY());
m_zscaleSpinner->setValue(m_scene->m_volume->physicalSizeZ());
glm::vec3 v = m_scene->m_volume->getVolumeAxesFlipped();
m_xFlipCheckBox->setChecked(v.x < 0);
m_yFlipCheckBox->setChecked(v.y < 0);
m_zFlipCheckBox->setChecked(v.z < 0);

QColor cbbox = QColor::fromRgbF(m_scene->m_material.m_boundingBoxColor[0],
m_scene->m_material.m_boundingBoxColor[1],
Expand Down
6 changes: 6 additions & 0 deletions agave_app/AppearanceSettingsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public slots:
void OnSetScaleX(double value);
void OnSetScaleY(double value);
void OnSetScaleZ(double value);
void OnFlipX(bool value);
void OnFlipY(bool value);
void OnFlipZ(bool value);

private:
Scene* m_scene;
Expand All @@ -95,8 +98,11 @@ public slots:

Section* m_scaleSection;
QDoubleSpinner* m_xscaleSpinner;
QCheckBox* m_xFlipCheckBox;
QDoubleSpinner* m_yscaleSpinner;
QCheckBox* m_yFlipCheckBox;
QDoubleSpinner* m_zscaleSpinner;
QCheckBox* m_zFlipCheckBox;
QCheckBox m_showBoundingBoxCheckBox;
QColorPushButton m_boundingBoxColorButton;
QCheckBox m_showScaleBarCheckBox;
Expand Down
40 changes: 21 additions & 19 deletions agave_app/Serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ struct ViewerState
// [[xm, xM], [ym, yM], [zm, zM]]
std::array<std::array<float, 2>, 3> clipRegion = { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f };

std::array<float, 3> scale = { 1, 1, 1 }; // m_scaleX, m_scaleY, m_scaleZ
std::array<float, 3> scale = { 1, 1, 1 }; // m_scaleX, m_scaleY, m_scaleZ
std::array<float, 3> flipAxis = { 1, 1, 1 }; // 1 is unflipped, -1 is flipped

CameraSettings_V1 camera;

Expand All @@ -106,28 +107,29 @@ struct ViewerState
{
return datasets == other.datasets && version == other.version && pathTracer == other.pathTracer &&
timeline == other.timeline && clipRegion == other.clipRegion && scale == other.scale &&
camera == other.camera && backgroundColor == other.backgroundColor &&
flipAxis == other.flipAxis && camera == other.camera && backgroundColor == other.backgroundColor &&
boundingBoxColor == other.boundingBoxColor && showBoundingBox == other.showBoundingBox &&
showScaleBar == other.showScaleBar && channels == other.channels && density == other.density &&
lights == other.lights && capture == other.capture;
}
NLOHMANN_DEFINE_TYPE_INTRUSIVE(ViewerState,
datasets,
version,
rendererType,
pathTracer,
timeline,
clipRegion,
scale,
camera,
backgroundColor,
boundingBoxColor,
showBoundingBox,
channels,
density,
lights,
capture,
showScaleBar)
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(ViewerState,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment why this macro is here and why it usees WITH_DEFAULT

datasets,
version,
rendererType,
pathTracer,
timeline,
clipRegion,
scale,
flipAxis,
camera,
backgroundColor,
boundingBoxColor,
showBoundingBox,
channels,
density,
lights,
capture,
showScaleBar)
};

ViewerState
Expand Down
7 changes: 6 additions & 1 deletion agave_app/ViewerState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ stateToPythonScript(const Serialize::ViewerState& s)
ss << obj << SetRenderIterationsCommand({ s.capture.samples }).toPythonString() << std::endl;
ss << obj << SetPrimaryRayStepSizeCommand({ s.pathTracer.primaryStepSize }).toPythonString() << std::endl;
ss << obj << SetSecondaryRayStepSizeCommand({ s.pathTracer.secondaryStepSize }).toPythonString() << std::endl;
ss << obj << SetVoxelScaleCommand({ s.scale[0], s.scale[1], s.scale[2] }).toPythonString() << std::endl;
ss << obj << SetVoxelScaleCommand({ abs(s.scale[0]), abs(s.scale[1]), abs(s.scale[2]) }).toPythonString()
<< std::endl;
ss << obj
<< SetFlipAxisCommand({ s.scale[0] < 0 ? -1 : 1, s.scale[1] < 0 ? -1 : 1, s.scale[2] < 0 ? -1 : 1 })
.toPythonString()
<< std::endl;
ss << obj
<< SetClipRegionCommand({ s.clipRegion[0][0],
s.clipRegion[0][1],
Expand Down
7 changes: 6 additions & 1 deletion agave_app/agaveGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,8 @@ agaveGui::viewerStateToApp(const Serialize::ViewerState& v)

m_currentScene = v.datasets[0].scene;

m_appScene.m_volume->setPhysicalSize(v.scale[0], v.scale[1], v.scale[2]);
m_appScene.m_volume->setPhysicalSize(abs(v.scale[0]), abs(v.scale[1]), abs(v.scale[2]));
m_appScene.m_volume->setVolumeAxesFlipped(v.flipAxis[0], v.flipAxis[1], v.flipAxis[2]);

m_appScene.m_material.m_backgroundColor[0] = v.backgroundColor[0];
m_appScene.m_material.m_backgroundColor[1] = v.backgroundColor[1];
Expand Down Expand Up @@ -1039,6 +1040,10 @@ agaveGui::appToViewerState()
v.scale[0] = m_appScene.m_volume->physicalSizeX();
v.scale[1] = m_appScene.m_volume->physicalSizeY();
v.scale[2] = m_appScene.m_volume->physicalSizeZ();
glm::vec3 vflip = m_appScene.m_volume->getVolumeAxesFlipped();
v.flipAxis[0] = vflip.x > 0 ? 1 : -1;
v.flipAxis[1] = vflip.y > 0 ? 1 : -1;
v.flipAxis[2] = vflip.z > 0 ? 1 : -1;
}

v.backgroundColor = { m_appScene.m_material.m_backgroundColor[0],
Expand Down
1 change: 1 addition & 0 deletions agave_app/commandBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ commandBuffer::processBuffer()
CMD_CASE(TrackballCameraCommand);
CMD_CASE(LoadDataCommand);
CMD_CASE(ShowScaleBarCommand);
CMD_CASE(SetFlipAxisCommand);
default:
// ERROR UNRECOGNIZED COMMAND SIGNATURE.
// PRINT OUT PREVIOUS! BAIL OUT! OR DO SOMETHING CLEVER AND CORRECT!
Expand Down
16 changes: 16 additions & 0 deletions agave_pyclient/agave_pyclient/agave.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,22 @@ def show_scale_bar(self, on: int):
# 45
self.cb.add_command("SHOW_SCALE_BAR", on)

def set_flip_axis(self, x: int, y: int, z: int):
"""
Flip the volume data on any axis

Parameters
----------
x: int
-1 to flip, 1 to not flip
y: int
-1 to flip, 1 to not flip
z: int
-1 to flip, 1 to not flip
"""
# 46
self.cb.add_command("SET_FLIP_AXIS", x, y, z)

def batch_render_turntable(
self, number_of_frames=90, direction=1, output_name="frame", first_frame=0
):
Expand Down
1 change: 1 addition & 0 deletions agave_pyclient/agave_pyclient/commandbuffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
# path, scene, multiresolution level, t, channel indices, region
"LOAD_DATA": [44, "S", "I32", "I32", "I32", "I32A", "I32A"],
"SHOW_SCALE_BAR": [45, "I32"],
"SET_FLIP_AXIS": [46, "I32", "I32", "I32"],
}


Expand Down
19 changes: 16 additions & 3 deletions renderlib/ImageXYZC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ ImageXYZC::ImageXYZC(uint32_t x,
, m_scaleY(sy)
, m_scaleZ(sz)
, m_spatialUnits(spatialUnits)
, m_flipped(1.0, 1.0, 1.0)
{
for (uint32_t i = 0; i < m_c; ++i) {
m_channels.push_back(new Channelu16(x, y, z, reinterpret_cast<uint16_t*>(ptr(i))));
Expand Down Expand Up @@ -79,9 +80,21 @@ ImageXYZC::maxPixelDimension() const
void
ImageXYZC::setPhysicalSize(float x, float y, float z)
{
m_scaleX = x;
m_scaleY = y;
m_scaleZ = z;
m_scaleX = abs(x);
m_scaleY = abs(y);
m_scaleZ = abs(z);
}

void
ImageXYZC::setVolumeAxesFlipped(float x, float y, float z)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this really should be storing ints or booleans

{
m_flipped = glm::vec3(x < 0 ? -1 : 1, y < 0 ? -1 : 1, z < 0 ? -1 : 1);
}

glm::vec3
ImageXYZC::getVolumeAxesFlipped() const
{
return m_flipped;
}

float
Expand Down
10 changes: 10 additions & 0 deletions renderlib/ImageXYZC.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,28 @@ class ImageXYZC

void setPhysicalSize(float x, float y, float z);

// +1 means do not flip, -1 means flip
void setVolumeAxesFlipped(float x, float y, float z);

uint32_t sizeX() const;
uint32_t sizeY() const;
uint32_t sizeZ() const;
uint32_t maxPixelDimension() const;

// should always return positive values
float physicalSizeX() const;
float physicalSizeY() const;
float physicalSizeZ() const;

std::string spatialUnits() const;

glm::vec3 getNormalizedDimensions() const;

glm::vec3 getPhysicalDimensions() const;

// +1 means do not flip, -1 means flip
glm::vec3 getVolumeAxesFlipped() const;

uint32_t sizeC() const;

uint32_t sizeOfElement() const;
Expand All @@ -114,6 +123,7 @@ class ImageXYZC
uint32_t m_x, m_y, m_z, m_c, m_bpp;
uint8_t* m_data;
float m_scaleX, m_scaleY, m_scaleZ;
glm::vec3 m_flipped;
std::string m_spatialUnits;
std::vector<Channelu16*> m_channels;
};
45 changes: 43 additions & 2 deletions renderlib/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,7 @@ LoadVolumeFromFileCommand::execute(ExecutionContext* c)
void
SetTimeCommand::execute(ExecutionContext* c)
{
LOG_DEBUG << "SetTime command: "
<< " T=" << m_data.m_time;
LOG_DEBUG << "SetTime command: " << " T=" << m_data.m_time;

// setting same time is a no-op.
if (m_data.m_time == c->m_appScene->m_timeLine.currentTime()) {
Expand Down Expand Up @@ -733,13 +732,22 @@ ShowScaleBarCommand::execute(ExecutionContext* c)
c->m_appScene->m_showScaleBar = m_data.m_on ? true : false;
}

void
SetFlipAxisCommand::execute(ExecutionContext* c)
{
LOG_DEBUG << "SetFlipAxis " << m_data.m_x << " " << m_data.m_y << " " << m_data.m_z;
c->m_appScene->m_volume->setVolumeAxesFlipped(m_data.m_x, m_data.m_y, m_data.m_z);
c->m_renderSettings->m_DirtyFlags.SetFlag(CameraDirty);
}

SessionCommand*
SessionCommand::parse(ParseableStream* c)
{
SessionCommandD data;
data.m_name = c->parseString();
return new SessionCommand(data);
}

size_t
SessionCommand::write(WriteableStream* o) const
{
Expand Down Expand Up @@ -1630,6 +1638,27 @@ ShowScaleBarCommand::write(WriteableStream* o) const
return bytesWritten;
}

SetFlipAxisCommand*
SetFlipAxisCommand::parse(ParseableStream* c)
{
SetFlipAxisCommandD data;
data.m_x = c->parseInt32();
data.m_y = c->parseInt32();
data.m_z = c->parseInt32();
return new SetFlipAxisCommand(data);
}

size_t
SetFlipAxisCommand::write(WriteableStream* o) const
{
size_t bytesWritten = 0;
bytesWritten += o->writeInt32(m_ID);
bytesWritten += o->writeInt32(m_data.m_x);
bytesWritten += o->writeInt32(m_data.m_y);
bytesWritten += o->writeInt32(m_data.m_z);
return bytesWritten;
}

std::string
SessionCommand::toPythonString() const
{
Expand Down Expand Up @@ -2082,3 +2111,15 @@ ShowScaleBarCommand::toPythonString() const
ss << ")";
return ss.str();
}

std::string
SetFlipAxisCommand::toPythonString() const
{
std::ostringstream ss;
ss << PythonName() << "(";
ss << m_data.m_x << ", ";
ss << m_data.m_y << ", ";
ss << m_data.m_z;
ss << ")";
return ss.str();
}
Loading
Loading