fixed vtk containerbox handler

This commit is contained in:
AndreaRigoni
2026-03-18 21:32:33 +00:00
parent 0e8ac47fcf
commit cca29ef837
16 changed files with 279 additions and 272 deletions

View File

@@ -46,15 +46,7 @@ namespace uLib {
namespace Vtk {
vtkDetectorChamber::vtkDetectorChamber(DetectorChamber *content)
: vtkContainerBox(content), m_Actor(vtkActor::New()),
m_Widget(vtkBoxWidget::New()) {
m_Callback = vtkWidgetCallback::New();
m_PickerCallback = vtkSelectionCallback::New();
m_Callback->SetChamber(this);
m_PickerCallback->SetChamber(this);
m_Widget->AddObserver(vtkCommand::InteractionEvent, m_Callback);
: vtkContainerBox(content), m_Actor(vtkActor::New()) {
m_InitialTransform = vtkSmartPointer<vtkTransform>::New();
m_RelativeTransform = vtkSmartPointer<vtkTransform>::New();
m_TotalTransform = vtkSmartPointer<vtkTransform>::New();
@@ -64,9 +56,6 @@ vtkDetectorChamber::vtkDetectorChamber(DetectorChamber *content)
vtkDetectorChamber::~vtkDetectorChamber() {
m_Actor->Delete();
m_Widget->Delete();
m_Callback->Delete();
m_PickerCallback->Delete();
}
DetectorChamber *vtkDetectorChamber::GetContent() {
@@ -77,20 +66,8 @@ void vtkDetectorChamber::PrintSelf(std::ostream &o) const {
vtkContainerBox::PrintSelf(o);
}
/**
* Connect the interactor to the widget
*/
void vtkDetectorChamber::ConnectInteractor(
vtkRenderWindowInteractor *interactor) {
if (!interactor)
return;
m_Widget->SetInteractor(interactor);
m_Widget->SetProp3D(m_Actor);
interactor->AddObserver(vtkCommand::LeftButtonPressEvent, m_PickerCallback);
}
void vtkDetectorChamber::SetTransform(vtkTransform *t) {
if (!t) return;
m_RelativeTransform->SetMatrix(t->GetMatrix());
m_RelativeTransform->Update();
@@ -107,11 +84,22 @@ void vtkDetectorChamber::SetTransform(vtkTransform *t) {
this->Update();
}
vtkBoxWidget *vtkDetectorChamber::GetWidget() { return m_Widget; }
void vtkDetectorChamber::Update() {
if (m_Actor->GetMapper())
m_Actor->GetMapper()->Update();
// If the actor has a UserMatrix, we update the content.
if (m_Actor->GetUserMatrix()) {
vtkMatrix4x4* vmat = m_Actor->GetUserMatrix();
Matrix4f transform;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
transform(i, j) = vmat->GetElement(i, j);
this->GetContent()->SetMatrix(transform);
this->GetContent()->Updated();
}
BaseClass::Update();
}
@@ -144,56 +132,14 @@ void vtkDetectorChamber::InstallPipe() {
m_Actor->GetProperty()->SetOpacity(0.4);
m_Actor->GetProperty()->SetAmbient(0.7);
// Temporarily disable UserTransform to place widget on local base
m_Widget->SetProp3D(m_Actor);
m_TotalTransform->SetInput(m_RelativeTransform);
m_TotalTransform->Concatenate(m_InitialTransform);
m_Actor->SetUserTransform(m_TotalTransform);
m_TotalTransform->Update();
m_Widget->PlaceWidget();
m_Widget->SetPlaceFactor(2);
this->SetProp(m_Actor);
this->Update();
}
void vtkDetectorChamber::vtkWidgetCallback::Execute(vtkObject *caller,
unsigned long, void *) {
vtkBoxWidget *widget = reinterpret_cast<vtkBoxWidget *>(caller);
// Get the Relative transform from the widget //
vtkSmartPointer<vtkTransform> t = vtkSmartPointer<vtkTransform>::New();
widget->GetTransform(t);
chamber->SetTransform(t);
// Apply to both the content and the actor state //
chamber->Update();
}
void vtkDetectorChamber::vtkSelectionCallback::Execute(vtkObject *caller,
unsigned long, void *) {
vtkRenderWindowInteractor *interactor =
reinterpret_cast<vtkRenderWindowInteractor *>(caller);
vtkSmartPointer<vtkPropPicker> picker = vtkSmartPointer<vtkPropPicker>::New();
int *pos = interactor->GetEventPosition();
picker->Pick(
pos[0], pos[1], 0,
interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());
vtkProp *picked = picker->GetViewProp();
if (picked == chamber->m_Actor) {
if (!chamber->m_Widget->GetEnabled()) {
chamber->m_Widget->SetInteractor(interactor);
chamber->m_Widget->On();
}
} else {
if (chamber->m_Widget->GetEnabled()) {
chamber->m_Widget->Off();
}
}
}
} // namespace Vtk
} // namespace uLib

View File

@@ -56,11 +56,7 @@ public:
void SetTransform(class vtkTransform *t);
class vtkBoxWidget *GetWidget();
void Update();
void ConnectInteractor(vtkRenderWindowInteractor *interactor) override;
void Update() override;
void PrintSelf(std::ostream &o) const;
@@ -68,30 +64,7 @@ protected:
void InstallPipe() override;
private:
class vtkWidgetCallback : public vtkCommand {
public:
static vtkWidgetCallback *New() { return new vtkWidgetCallback; }
void SetChamber(uLib::Vtk::vtkDetectorChamber *ch) { this->chamber = ch; }
virtual void Execute(vtkObject *caller, unsigned long, void *) override;
private:
uLib::Vtk::vtkDetectorChamber *chamber;
};
class vtkSelectionCallback : public vtkCommand {
public:
static vtkSelectionCallback *New() { return new vtkSelectionCallback; }
void SetChamber(uLib::Vtk::vtkDetectorChamber *ch) { this->chamber = ch; }
virtual void Execute(vtkObject *caller, unsigned long, void *) override;
private:
uLib::Vtk::vtkDetectorChamber *chamber;
};
vtkActor *m_Actor;
vtkBoxWidget *m_Widget;
vtkWidgetCallback *m_Callback;
vtkSelectionCallback *m_PickerCallback;
vtkSmartPointer<vtkTransform> m_InitialTransform;
vtkSmartPointer<vtkTransform> m_RelativeTransform;

View File

@@ -110,21 +110,13 @@ BOOST_AUTO_TEST_CASE(vtkVoxRaytracerRepresentationTest) {
// renderer //
Vtk::Viewer viewer;
// widget //
vtkBoxWidget *widget = v_grid.GetWidget();
vtkWidgetCallback *cbk = vtkWidgetCallback::New();
cbk->SetTracer(&v_rt);
cbk->SetMuon(&muon);
cbk->SetAnnotation(viewer.GetAnnotation());
widget->AddObserver(vtkCommand::InteractionEvent, cbk);
widget->SetInteractor(viewer.GetInteractor());
widget->PlaceWidget();
widget->On();
viewer.AddPuppet(v_grid);
viewer.AddPuppet(v_rt);
viewer.AddPuppet(v_muon);
// Select grid to show handler widget
viewer.SelectPuppet(&v_grid);
viewer.Start();
}

View File

@@ -42,35 +42,52 @@ namespace Vtk {
////////////////////////////////////////////////////////////////////////////////
vtkVoxRaytracerRepresentation::vtkVoxRaytracerRepresentation(Content &content)
: m_Content(&content), m_Assembly(vtkAssembly::New()),
: m_Content(&content),
m_Sphere1(vtkSphereSource::New()), m_Sphere2(vtkSphereSource::New()),
m_Line1(vtkLineSource::New()), m_Line2(vtkLineSource::New()),
m_Line3(vtkLineSource::New()), m_RayLine(vtkAppendPolyData::New()),
m_RayLineActor(vtkActor::New()),
m_RayRepresentation(vtkAppendPolyData::New()),
m_RayRepresentationActor(vtkActor::New()),
m_Transform(vtkTransform::New()) {
m_Transform(vtkTransform::New()),
m_HasMuon(false), m_HasPoca(false) {
default_radius = content.GetImage()->GetSpacing()(0) / 4;
m_Sphere1->SetRadius(default_radius);
m_Sphere2->SetRadius(default_radius);
m_SelectedElement = m_RayLine;
this->SetSelectable(false);
InstallPipe();
if (m_Content && m_Content->GetImage()) {
Object::connect(m_Content->GetImage(), &StructuredGrid::Updated, this, &vtkVoxRaytracerRepresentation::imageUpdate);
}
}
vtkVoxRaytracerRepresentation::~vtkVoxRaytracerRepresentation() {
m_Assembly->Delete();
m_RayLine->Delete();
m_RayLineActor->Delete();
m_RayRepresentationActor->Delete();
m_Transform->Delete();
}
VoxRaytracer *vtkVoxRaytracerRepresentation::GetRaytracerAlgorithm() {
uLib::VoxRaytracer *vtkVoxRaytracerRepresentation::GetRaytracerAlgorithm() {
return m_Content;
}
vtkProp *vtkVoxRaytracerRepresentation::GetProp() { return m_Assembly; }
void vtkVoxRaytracerRepresentation::Update() {
this->imageUpdate();
}
void vtkVoxRaytracerRepresentation::imageUpdate() {
if (m_HasMuon) {
if (m_HasPoca) {
this->SetMuon(m_Muon, m_Poca);
} else {
this->SetMuon(m_Muon);
}
}
}
vtkPolyData *vtkVoxRaytracerRepresentation::GetPolyData() const {
std::cout << "get Raytracer polydata\n";
@@ -94,6 +111,10 @@ void vtkVoxRaytracerRepresentation::SetRepresentationElements(
}
void vtkVoxRaytracerRepresentation::SetMuon(MuonScatter &muon) {
m_Muon = muon;
m_HasMuon = true;
m_HasPoca = false;
HPoint3f pt1, pt2, src;
src = muon.LineIn().origin;
m_Content->GetEntryPoint(muon.LineIn(), pt1);
@@ -152,6 +173,11 @@ void vtkVoxRaytracerRepresentation::SetMuon(MuonScatter &muon) {
}
void vtkVoxRaytracerRepresentation::SetMuon(MuonScatter &muon, HPoint3f poca) {
m_Muon = muon;
m_Poca = poca;
m_HasMuon = true;
m_HasPoca = true;
HPoint3f pt1, pt2, src;
src = muon.LineIn().origin;
m_Content->GetEntryPoint(muon.LineIn(), pt1);

View File

@@ -58,7 +58,7 @@ class vtkActor;
namespace uLib {
namespace Vtk {
class vtkVoxRaytracerRepresentation : public Puppet {
class vtkVoxRaytracerRepresentation : public Puppet, public Object {
typedef VoxRaytracer Content;
public:
@@ -67,7 +67,9 @@ public:
uLib::VoxRaytracer *GetRaytracerAlgorithm();
vtkProp *GetProp();
virtual void Update() override;
void imageUpdate();
vtkPolyData *GetPolyData() const;
@@ -99,9 +101,12 @@ private:
void SetColor(vtkActor *actor, Vector4f rgba);
VoxRaytracer *m_Content;
MuonScatter m_Muon;
HPoint3f m_Poca;
bool m_HasMuon;
bool m_HasPoca;
Scalarf default_radius;
vtkAssembly *m_Assembly;
vtkAppendPolyData *m_RayLine;
vtkActor *m_RayLineActor;
vtkActor *m_RayRepresentationActor;

View File

@@ -44,5 +44,5 @@ BOOST_AUTO_TEST_CASE(vtkStructuredGridTest) {
viewer.Start();
}
BOOST_CHECK(grid_viewer.GetWidget() != nullptr);
BOOST_CHECK(grid_viewer.GetProp() != nullptr);
}

54
src/Vtk/Math/vtkDense.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef U_VTK_DENSE_H
#define U_VTK_DENSE_H
#include "Math/Dense.h"
#include <vtkMatrix4x4.h>
namespace uLib {
namespace Vtk {
/**
* @brief Converts a uLib::Matrix4f to an existing vtkMatrix4x4.
* @param src The source Eigen matrix.
* @param dst The destination vtkMatrix4x4.
*/
inline void Matrix4fToVtk(const Matrix4f& src, vtkMatrix4x4* dst) {
if (!dst)
return;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
dst->SetElement(i, j, src(i, j));
}
/**
* @brief Converts a uLib::Matrix4f to a new vtkMatrix4x4.
* @param src The source Eigen matrix.
* @return A new vtkMatrix4x4 (caller is responsible for management/deletion).
*/
inline vtkMatrix4x4* Matrix4fToVtk(const Matrix4f& src) {
vtkMatrix4x4* dst = vtkMatrix4x4::New();
Matrix4fToVtk(src, dst);
return dst;
}
/**
* @brief Converts a vtkMatrix4x4 to a uLib::Matrix4f.
* @param src The source vtkMatrix4x4.
* @return The converted uLib::Matrix4f matrix.
*/
inline Matrix4f VtkToMatrix4f(vtkMatrix4x4* src) {
Matrix4f dst;
if (!src) {
dst.setIdentity();
return dst;
}
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
dst(i, j) = src->GetElement(i, j);
return dst;
}
} // namespace Vtk
} // namespace uLib
#endif // U_VTK_DENSE_H

View File

@@ -30,6 +30,8 @@
#include "Math/StructuredGrid.h"
#include "Vtk/Math/vtkStructuredGrid.h"
#include "Vtk/Math/vtkDense.h"
namespace uLib {
namespace Vtk {
@@ -39,73 +41,64 @@ namespace Vtk {
vtkStructuredGrid::vtkStructuredGrid(Content &content)
: m_Content(&content), m_Actor(vtkActor::New()),
m_Widget(vtkBoxWidget::New()), m_Transform(vtkTransform::New()) {
vtkSmartPointer<vtkWidgetCallback> callback =
vtkSmartPointer<vtkWidgetCallback>::New();
callback->SetGrid(this);
m_Widget->AddObserver(vtkCommand::InteractionEvent, callback);
m_Transform(vtkTransform::New()) {
this->InstallPipe();
}
vtkStructuredGrid::~vtkStructuredGrid() {
m_Actor->Delete();
m_Widget->Delete();
m_Transform->Delete();
}
void vtkStructuredGrid::SetTransform(vtkTransform *t) {
vtkMatrix4x4 *vmat = t->GetMatrix();
Matrix4f mat;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
mat(i, j) = vmat->GetElement(i, j);
Matrix4f mat = VtkToMatrix4f(vmat);
m_Content->SetMatrix(mat);
vtkSmartPointer<vtkMatrix4x4> vmat2 = vtkSmartPointer<vtkMatrix4x4>::New();
mat = m_Content->GetWorldMatrix();
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
vmat2->SetElement(i, j, mat(i, j));
Matrix4fToVtk(mat, vmat2);
m_Transform->SetMatrix(vmat2);
m_Transform->Update();
this->Update();
}
vtkBoxWidget *vtkStructuredGrid::GetWidget() { return m_Widget; }
void vtkStructuredGrid::Update() {
if (!m_Content) return;
void vtkStructuredGrid::Update() { m_Actor->GetMapper()->Update(); }
vtkProp3D* actor = vtkProp3D::SafeDownCast(this->GetProp());
if (!actor) return;
vtkMatrix4x4* vmat = actor->GetUserMatrix();
if (!vmat) return;
Matrix4f transform = VtkToMatrix4f(vmat);
m_Content->SetMatrix(transform);
m_Content->Updated(); // Notify others (like raytracer)
}
void vtkStructuredGrid::InstallPipe() {
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
vtkSmartPointer<vtkTransformPolyDataFilter> filter =
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
vtkSmartPointer<vtkMatrix4x4> vmat = vtkSmartPointer<vtkMatrix4x4>::New();
Matrix4f mat = m_Content->GetWorldMatrix();
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
vmat->SetElement(i, j, mat(i, j));
m_Transform->SetMatrix(vmat);
filter->SetTransform(m_Transform);
filter->SetInputConnection(cube->GetOutputPort());
Vector3i dims = m_Content->GetDims();
cube->SetBounds(0, dims(0), 0, dims(1), 0, dims(2));
cube->Update();
filter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(filter->GetOutputPort());
mapper->SetInputConnection(cube->GetOutputPort());
m_Actor->SetMapper(mapper);
m_Actor->GetProperty()->SetRepresentationToSurface();
m_Actor->GetProperty()->SetEdgeVisibility(true);
m_Actor->GetProperty()->SetOpacity(0.4);
m_Actor->GetProperty()->SetAmbient(0.7);
this->Update();
m_Widget->SetProp3D(m_Actor);
vtkNew<vtkMatrix4x4> vmat;
Matrix4fToVtk(m_Content->GetWorldMatrix(), vmat);
m_Actor->SetUserMatrix(vmat);
this->SetProp(m_Actor);
}

View File

@@ -56,32 +56,12 @@ public:
void SetTransform(class vtkTransform *t);
class vtkBoxWidget *GetWidget();
void Update();
virtual void Update() override;
private:
void InstallPipe();
class vtkWidgetCallback : public vtkCommand {
public:
static vtkWidgetCallback *New() { return new vtkWidgetCallback; }
void SetGrid(uLib::Vtk::vtkStructuredGrid *grid) { this->grid = grid; }
virtual void Execute(vtkObject *caller, unsigned long, void *) {
vtkSmartPointer<vtkTransform> t = vtkSmartPointer<vtkTransform>::New();
vtkBoxWidget *widget = reinterpret_cast<vtkBoxWidget *>(caller);
widget->GetTransform(t);
grid->SetTransform(t);
}
private:
uLib::Vtk::vtkStructuredGrid *grid;
};
vtkActor *m_Actor;
vtkBoxWidget *m_Widget;
StructuredGrid *m_Content;
vtkTransform *m_Transform;
};

View File

@@ -36,9 +36,16 @@ int main() {
BEGIN_TESTING(vtk ContainerBox Test);
ContainerBox box;
box.SetSize(Vector3f(2, 3, 4));
box.SetPosition(Vector3f(1, 2, 3));
box.Scale(Vector3f(1,5,1));
box.SetPosition(Vector3f(0,1,0));
Vtk::vtkContainerBox v_box(&box);
v_box.SetRepresentation(Vtk::Puppet::Surface);
v_box.SetOpacity(0.5);
v_box.SetSelectable(true);
box.findOrAddSignal(&ContainerBox::Updated)->connect([&box](){
std::cout << "box updated: " << box.GetWorldPoint(HPoint3f(1,1,1)) << std::endl;
});
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
Vtk::Viewer v_viewer;

View File

@@ -45,8 +45,9 @@
#include <vtkActor.h>
#include <vtkPropCollection.h>
#include <vtkProp3DCollection.h>
#include <vtkRendererCollection.h>
#include <vtkPropAssembly.h>
#include <vtkAssembly.h>
#include <vtkOutlineSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkCubeAxesActor.h>
@@ -82,7 +83,7 @@ class PuppetData {
public:
PuppetData() :
m_Renderers(vtkSmartPointer<vtkRendererCollection>::New()),
m_Assembly(vtkSmartPointer<vtkPropAssembly>::New()),
m_Assembly(vtkSmartPointer<vtkAssembly>::New()),
m_ShowBoundingBox(false),
m_ShowScaleMeasures(false),
m_Representation(-1),
@@ -99,7 +100,7 @@ public:
// members //
vtkSmartPointer<vtkRendererCollection> m_Renderers;
vtkSmartPointer<vtkPropAssembly> m_Assembly;
vtkSmartPointer<vtkAssembly> m_Assembly;
vtkSmartPointer<vtkOutlineSource> m_OutlineSource;
vtkSmartPointer<vtkActor> m_OutlineActor;
@@ -160,19 +161,16 @@ public:
m_HighlightActor->GetProperty()->SetLighting(0);
}
// Update highlight data and transform from first actor
vtkPropCollection *parts = m_Assembly->GetParts();
parts->InitTraversal();
for (int i = 0; i < parts->GetNumberOfItems(); ++i) {
vtkActor *actor = vtkActor::SafeDownCast(parts->GetNextProp());
if (actor) {
// Sync transform
m_HighlightActor->SetUserTransform(actor->GetUserTransform());
m_HighlightActor->SetPosition(actor->GetPosition());
m_HighlightActor->SetOrientation(actor->GetOrientation());
m_HighlightActor->SetScale(actor->GetScale());
break;
}
// Update highlight matrix from the root prop
vtkProp3D* root = nullptr;
if (m_Assembly->GetParts()->GetNumberOfItems() == 1) {
root = vtkProp3D::SafeDownCast(m_Assembly->GetParts()->GetLastProp());
} else {
root = m_Assembly;
}
if (root) {
m_HighlightActor->SetUserMatrix(root->GetMatrix());
}
m_Renderers->InitTraversal();
@@ -209,18 +207,17 @@ Puppet::~Puppet()
vtkProp *Puppet::GetProp()
{
if (d->m_Assembly->GetParts()->GetNumberOfItems() == 1)
{
// d->m_Assembly->GetParts()->InitTraversal();
// return d->m_Assembly->GetParts()->GetNextProp();
return d->m_Assembly->GetParts()->GetLastProp();
}
else return d->m_Assembly;
else
return d->m_Assembly;
}
void Puppet::SetProp(vtkProp *prop)
{
if(prop) {
d->m_Assembly->AddPart(prop);
if (auto* p3d = vtkProp3D::SafeDownCast(prop)) {
d->m_Assembly->AddPart(p3d);
}
d->ApplyAppearance(prop);
}
}
@@ -240,14 +237,8 @@ void Puppet::ConnectRenderer(vtkRenderer *renderer)
{
if(renderer) {
this->GetRenderers()->AddItem(renderer);
if(d->m_Assembly->GetParts()->GetNumberOfItems() == 1)
renderer->AddActor(this->GetProp());
else if(d->m_Assembly->GetParts()->GetNumberOfItems() >0)
{
vtkPropCollection *props = d->m_Assembly->GetParts();
props->InitTraversal();
for (int i=0; i<props->GetNumberOfItems(); ++i)
renderer->AddActor(props->GetNextProp());
if(vtkProp* prop = this->GetProp()) {
renderer->AddViewProp(prop);
}
if (d->m_ShowBoundingBox && d->m_OutlineActor) renderer->AddActor(d->m_OutlineActor);
@@ -265,15 +256,8 @@ void Puppet::ConnectRenderer(vtkRenderer *renderer)
void Puppet::DisconnectRenderer(vtkRenderer *renderer)
{
if(renderer) {
if(this->GetProp())
renderer->RemoveViewProp(this->GetProp());
else if(d->m_Assembly->GetParts()->GetNumberOfItems() >0)
{
vtkPropCollection *props = d->m_Assembly->GetParts();
props->InitTraversal();
for (int i=0; i<props->GetNumberOfItems(); ++i)
renderer->RemoveViewProp(props->GetNextProp());
}
if(vtkProp* prop = this->GetProp())
renderer->RemoveViewProp(prop);
if (d->m_ShowBoundingBox && d->m_OutlineActor) renderer->RemoveActor(d->m_OutlineActor);
if (d->m_ShowScaleMeasures && d->m_CubeAxesActor) renderer->RemoveActor(d->m_CubeAxesActor);
@@ -382,10 +366,10 @@ void Puppet::SetRepresentation(Representation mode)
}
d->m_Representation = rep;
vtkPropCollection *props = d->m_Assembly->GetParts();
vtkProp3DCollection *props = d->m_Assembly->GetParts();
props->InitTraversal();
for (int i = 0; i < props->GetNumberOfItems(); ++i) {
d->ApplyAppearance(props->GetNextProp());
d->ApplyAppearance(props->GetNextProp3D());
}
}
@@ -403,10 +387,10 @@ void Puppet::SetColor(double r, double g, double b)
d->m_Color[1] = g;
d->m_Color[2] = b;
vtkPropCollection *props = d->m_Assembly->GetParts();
vtkProp3DCollection *props = d->m_Assembly->GetParts();
props->InitTraversal();
for (int i = 0; i < props->GetNumberOfItems(); ++i) {
d->ApplyAppearance(props->GetNextProp());
d->ApplyAppearance(props->GetNextProp3D());
}
}
@@ -414,10 +398,10 @@ void Puppet::SetOpacity(double alpha)
{
d->m_Opacity = alpha;
vtkPropCollection *props = d->m_Assembly->GetParts();
vtkProp3DCollection *props = d->m_Assembly->GetParts();
props->InitTraversal();
for (int i = 0; i < props->GetNumberOfItems(); ++i) {
d->ApplyAppearance(props->GetNextProp());
d->ApplyAppearance(props->GetNextProp3D());
}
}
@@ -450,6 +434,24 @@ bool Puppet::IsSelected() const
return d->m_Selected;
}
void Puppet::Update()
{
if (d->m_Selected) {
d->UpdateHighlight();
}
if (d->m_ShowBoundingBox) {
double* bounds = d->m_Assembly->GetBounds();
d->m_OutlineSource->SetBounds(bounds);
d->m_OutlineSource->Update();
}
if (d->m_ShowScaleMeasures) {
double* bounds = d->m_Assembly->GetBounds();
d->m_CubeAxesActor->SetBounds(bounds);
}
}
void Puppet::ConnectInteractor(vtkRenderWindowInteractor *interactor)
{
}

View File

@@ -86,6 +86,8 @@ public:
void SetSelected(bool selected = true);
bool IsSelected() const;
virtual void Update();
virtual void ConnectInteractor(class vtkRenderWindowInteractor *interactor);
protected:

View File

@@ -41,21 +41,24 @@
#include <vtkSmartPointer.h>
#include <vtkTransform.h>
#include "Math/vtkDense.h"
namespace uLib {
namespace Vtk {
vtkContainerBox::vtkContainerBox(vtkContainerBox::Content *content)
: m_Cube(vtkActor::New()), m_Axes(vtkActor::New()),
m_Pivot(vtkActor::New()),
// m_Pivot(vtkActor::New()),
m_Content(content) {
this->InstallPipe();
Object::connect(m_Content, &Content::Updated, this, &vtkContainerBox::contentUpdate);
}
vtkContainerBox::~vtkContainerBox() {
m_Cube->Delete();
m_Axes->Delete();
m_Pivot->Delete();
// m_Pivot->Delete();
}
vtkPolyData *vtkContainerBox::GetPolyData() const {
@@ -63,21 +66,52 @@ vtkPolyData *vtkContainerBox::GetPolyData() const {
return NULL;
}
void vtkContainerBox::Update() {
void vtkContainerBox::contentUpdate() {
if (!m_Content)
return;
vtkSmartPointer<vtkMatrix4x4> vmat = vtkSmartPointer<vtkMatrix4x4>::New();
vtkProp3D* root = vtkProp3D::SafeDownCast(this->GetProp());
if (!root) return;
vtkMatrix4x4* vmat = root->GetUserMatrix();
if (!vmat) {
// Should have been set in InstallPipe, but let's be safe
vtkNew<vtkMatrix4x4> mat;
root->SetUserMatrix(mat);
vmat = mat;
}
Matrix4f transform = m_Content->GetMatrix();
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
for (int j = 0; j < 4; ++j) {
vmat->SetElement(i, j, transform(i, j));
}
// std::cout << "transform: " << transform << std::endl;
// m_RelativeTransform->SetMatrix(vmat);
// m_RelativeTransform->Update();
root->Modified();
Puppet::Update();
}
m_Cube->SetUserMatrix(vmat);
m_Axes->SetUserMatrix(vmat);
void vtkContainerBox::Update() {
if (!m_Content) return;
vtkProp3D* assembly = vtkProp3D::SafeDownCast(this->GetProp());
if (!assembly) return;
vtkMatrix4x4* vmat = assembly->GetUserMatrix();
if (!vmat) return;
Matrix4f transform = VtkToMatrix4f(vmat);
// Update uLib model's affine transform
if (m_Content->GetParent()) {
Matrix4f localT = m_Content->GetParent()->GetWorldMatrix().inverse() * transform;
m_Content->SetMatrix(localT);
} else {
m_Content->SetMatrix(transform);
}
m_Content->Updated(); // Notify change
}
@@ -91,24 +125,7 @@ void vtkContainerBox::InstallPipe() {
// CUBE
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
Vector3f p = c->GetPosition();
// cube->SetCenter(p(0), p(1), p(2));
// Vector4f p1 = c->GetWorldPoint(HPoint3f(0, 0, 0));
// Vector4f p2 = c->GetWorldPoint(HPoint3f(1, 1, 1));
// vtkSmartPointer<vtkLineSource> line =
// vtkSmartPointer<vtkLineSource>::New(); line->SetPoint1(p1(0), p1(1),
// p1(2)); line->SetPoint2(p2(0), p2(1), p2(2)); line->Update();
// cube->SetBounds(line->GetOutput()->GetBounds());
vtkSmartPointer<vtkMatrix4x4> vmat = vtkSmartPointer<vtkMatrix4x4>::New();
Matrix4f transform = c->GetMatrix();
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
vmat->SetElement(i, j, transform(i, j));
m_Cube->SetUserMatrix(vmat);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
cube->SetBounds(0, 1, 0, 1, 0, 1);
@@ -125,9 +142,6 @@ void vtkContainerBox::InstallPipe() {
mapper->SetInputConnection(axes->GetOutputPort());
mapper->Update();
m_Axes->SetMapper(mapper);
m_Axes->SetUserMatrix(vmat);
Vector3f s = c->GetSize();
// m_Axes->SetScale(s(0),s(1),s(2));
m_Axes->GetProperty()->SetLineWidth(3);
m_Axes->GetProperty()->SetAmbient(0.4);
m_Axes->GetProperty()->SetSpecular(0);
@@ -138,24 +152,16 @@ void vtkContainerBox::InstallPipe() {
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(axes->GetOutputPort());
mapper->Update();
m_Pivot->SetUserMatrix(vmat);
m_Pivot->SetMapper(mapper);
Matrix4f pivotTransform = c->AffineTransform::GetWorldMatrix();
vtkSmartPointer<vtkMatrix4x4> pmat = vtkSmartPointer<vtkMatrix4x4>::New();
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
pmat->SetElement(i, j, pivotTransform(i, j));
m_Pivot->SetUserMatrix(pmat);
s = c->GetScale();
// m_Pivot->SetScale(s(0),s(1),s(2));
m_Pivot->GetProperty()->SetLineWidth(3);
m_Pivot->GetProperty()->SetAmbient(0.4);
m_Pivot->GetProperty()->SetSpecular(0);
this->SetProp(m_Cube);
this->SetProp(m_Axes);
this->SetProp(m_Pivot);
vtkProp3D* root = vtkProp3D::SafeDownCast(this->GetProp());
if (root) {
vtkNew<vtkMatrix4x4> vmat;
Matrix4fToVtk(c->GetMatrix(), vmat);
root->SetUserMatrix(vmat);
}
}
} // namespace Vtk

View File

@@ -43,15 +43,16 @@ public:
virtual class vtkPolyData *GetPolyData() const;
virtual void Update();
virtual void contentUpdate();
virtual void Update();
protected:
virtual void InstallPipe();
vtkActor *m_Cube;
vtkActor *m_Axes;
vtkActor *m_Pivot;
// vtkActor *m_Pivot;
Content *m_Content;
};

View File

@@ -616,10 +616,11 @@ void vtkHandlerWidget::UpdateGizmoPosition() {
mat_gizmo->SetElement(1, 3, center[1]);
mat_gizmo->SetElement(2, 3, center[2]);
} else if (m_Frame == GLOBAL) {
::vtkMatrix4x4 *mat = this->Prop3D->GetMatrix();
mat_gizmo->Identity();
mat_gizmo->SetElement(0, 3, pos[0]);
mat_gizmo->SetElement(1, 3, pos[1]);
mat_gizmo->SetElement(2, 3, pos[2]);
mat_gizmo->SetElement(0, 3, mat->GetElement(0, 3));
mat_gizmo->SetElement(1, 3, mat->GetElement(1, 3));
mat_gizmo->SetElement(2, 3, mat->GetElement(2, 3));
} else if (m_Frame == CENTER) {
mat_gizmo->Identity();
mat_gizmo->SetElement(0, 3, center[0]);

View File

@@ -1,7 +1,9 @@
#include "vtkViewport.h"
#include <vtkPropAssembly.h>
#include <vtkAssembly.h>
#include <vtkPropCollection.h>
#include <vtkProp3D.h>
#include <vtkProp3DCollection.h>
#include <vtkCamera.h>
#include <algorithm>
#include <vtkInteractorStyleTrackballCamera.h>
@@ -126,6 +128,19 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
m_HandlerWidget->GetOverlayRenderer()->SetLayer(1);
}
// Observe InteractionEvent to update the selected puppet when the widget moves it
vtkNew<vtkCallbackCommand> widgetInteractionCallback;
widgetInteractionCallback->SetClientData(this);
widgetInteractionCallback->SetCallback([](vtkObject*, unsigned long, void* clientdata, void*){
auto* self = static_cast<Viewport*>(clientdata);
for (auto* p : self->m_Puppets) {
if (p->IsSelected()) {
p->Update();
}
}
});
m_HandlerWidget->AddObserver(vtkCommand::InteractionEvent, widgetInteractionCallback);
// Picking for selection
m_Picker = vtkSmartPointer<vtkCellPicker>::New();
vtkNew<vtkCallbackCommand> clickCallback;
@@ -145,10 +160,14 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
target = p;
break;
}
auto* assembly = vtkPropAssembly::SafeDownCast(p->GetProp());
if (assembly) {
auto* propAssembly = vtkPropAssembly::SafeDownCast(p->GetProp());
auto* actorAssembly = vtkAssembly::SafeDownCast(p->GetProp());
vtkPropCollection* parts = nullptr;
if (propAssembly) parts = propAssembly->GetParts();
else if (actorAssembly) parts = actorAssembly->GetParts();
if (parts) {
bool found = false;
auto* parts = assembly->GetParts();
parts->InitTraversal();
for (int i=0; i<parts->GetNumberOfItems(); ++i) {
if (parts->GetNextProp() == picked) {