diff --git a/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx b/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx index e0beae8..78c9674 100644 --- a/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx +++ b/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx @@ -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::New(); m_RelativeTransform = vtkSmartPointer::New(); m_TotalTransform = vtkSmartPointer::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(caller); - - // Get the Relative transform from the widget // - vtkSmartPointer t = vtkSmartPointer::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(caller); - vtkSmartPointer picker = vtkSmartPointer::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 \ No newline at end of file diff --git a/src/Vtk/HEP/Detectors/vtkDetectorChamber.h b/src/Vtk/HEP/Detectors/vtkDetectorChamber.h index b7564cc..914d547 100644 --- a/src/Vtk/HEP/Detectors/vtkDetectorChamber.h +++ b/src/Vtk/HEP/Detectors/vtkDetectorChamber.h @@ -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 m_InitialTransform; vtkSmartPointer m_RelativeTransform; diff --git a/src/Vtk/HEP/MuonTomography/testing/vtkVoxRaytracerTest.cpp b/src/Vtk/HEP/MuonTomography/testing/vtkVoxRaytracerTest.cpp index be4d220..2548ad0 100644 --- a/src/Vtk/HEP/MuonTomography/testing/vtkVoxRaytracerTest.cpp +++ b/src/Vtk/HEP/MuonTomography/testing/vtkVoxRaytracerTest.cpp @@ -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(); } diff --git a/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.cpp b/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.cpp index 2f36157..15f2c07 100644 --- a/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.cpp +++ b/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.cpp @@ -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); diff --git a/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.h b/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.h index 5d0024a..7f53034 100644 --- a/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.h +++ b/src/Vtk/HEP/MuonTomography/vtkVoxRaytracerRepresentation.h @@ -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; diff --git a/src/Vtk/Math/testing/vtkStructuredGridTest.cpp b/src/Vtk/Math/testing/vtkStructuredGridTest.cpp index 7062cea..0e540bd 100644 --- a/src/Vtk/Math/testing/vtkStructuredGridTest.cpp +++ b/src/Vtk/Math/testing/vtkStructuredGridTest.cpp @@ -44,5 +44,5 @@ BOOST_AUTO_TEST_CASE(vtkStructuredGridTest) { viewer.Start(); } - BOOST_CHECK(grid_viewer.GetWidget() != nullptr); + BOOST_CHECK(grid_viewer.GetProp() != nullptr); } diff --git a/src/Vtk/Math/vtkDense.h b/src/Vtk/Math/vtkDense.h new file mode 100644 index 0000000..54a8448 --- /dev/null +++ b/src/Vtk/Math/vtkDense.h @@ -0,0 +1,54 @@ +#ifndef U_VTK_DENSE_H +#define U_VTK_DENSE_H + +#include "Math/Dense.h" +#include + +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 \ No newline at end of file diff --git a/src/Vtk/Math/vtkStructuredGrid.cpp b/src/Vtk/Math/vtkStructuredGrid.cpp index 3cf9898..fc43714 100644 --- a/src/Vtk/Math/vtkStructuredGrid.cpp +++ b/src/Vtk/Math/vtkStructuredGrid.cpp @@ -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 callback = - vtkSmartPointer::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 vmat2 = vtkSmartPointer::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 cube = vtkSmartPointer::New(); - vtkSmartPointer filter = - vtkSmartPointer::New(); - - vtkSmartPointer vmat = vtkSmartPointer::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 mapper = vtkSmartPointer::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 vmat; + Matrix4fToVtk(m_Content->GetWorldMatrix(), vmat); + m_Actor->SetUserMatrix(vmat); this->SetProp(m_Actor); } diff --git a/src/Vtk/Math/vtkStructuredGrid.h b/src/Vtk/Math/vtkStructuredGrid.h index 0921a09..0a7a537 100644 --- a/src/Vtk/Math/vtkStructuredGrid.h +++ b/src/Vtk/Math/vtkStructuredGrid.h @@ -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 t = vtkSmartPointer::New(); - vtkBoxWidget *widget = reinterpret_cast(caller); - widget->GetTransform(t); - grid->SetTransform(t); - } - - private: - uLib::Vtk::vtkStructuredGrid *grid; - }; - vtkActor *m_Actor; - vtkBoxWidget *m_Widget; StructuredGrid *m_Content; vtkTransform *m_Transform; }; diff --git a/src/Vtk/testing/vtkContainerBoxTest.cpp b/src/Vtk/testing/vtkContainerBoxTest.cpp index 5b99c5e..1ef9624 100644 --- a/src/Vtk/testing/vtkContainerBoxTest.cpp +++ b/src/Vtk/testing/vtkContainerBoxTest.cpp @@ -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; diff --git a/src/Vtk/uLibVtkInterface.cxx b/src/Vtk/uLibVtkInterface.cxx index 46f7b07..a8a14a2 100644 --- a/src/Vtk/uLibVtkInterface.cxx +++ b/src/Vtk/uLibVtkInterface.cxx @@ -45,8 +45,9 @@ #include #include +#include #include -#include +#include #include #include #include @@ -82,7 +83,7 @@ class PuppetData { public: PuppetData() : m_Renderers(vtkSmartPointer::New()), - m_Assembly(vtkSmartPointer::New()), + m_Assembly(vtkSmartPointer::New()), m_ShowBoundingBox(false), m_ShowScaleMeasures(false), m_Representation(-1), @@ -99,7 +100,7 @@ public: // members // vtkSmartPointer m_Renderers; - vtkSmartPointer m_Assembly; + vtkSmartPointer m_Assembly; vtkSmartPointer m_OutlineSource; vtkSmartPointer 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; iGetNumberOfItems(); ++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; iGetNumberOfItems(); ++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) { } diff --git a/src/Vtk/uLibVtkInterface.h b/src/Vtk/uLibVtkInterface.h index 4ae43f1..28a37e1 100644 --- a/src/Vtk/uLibVtkInterface.h +++ b/src/Vtk/uLibVtkInterface.h @@ -86,6 +86,8 @@ public: void SetSelected(bool selected = true); bool IsSelected() const; + virtual void Update(); + virtual void ConnectInteractor(class vtkRenderWindowInteractor *interactor); protected: diff --git a/src/Vtk/vtkContainerBox.cpp b/src/Vtk/vtkContainerBox.cpp index 736c081..7511a06 100644 --- a/src/Vtk/vtkContainerBox.cpp +++ b/src/Vtk/vtkContainerBox.cpp @@ -41,21 +41,24 @@ #include #include +#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 vmat = vtkSmartPointer::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 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 cube = vtkSmartPointer::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 line = - // vtkSmartPointer::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 vmat = vtkSmartPointer::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 mapper = vtkSmartPointer::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::New(); mapper->SetInputConnection(axes->GetOutputPort()); mapper->Update(); - m_Pivot->SetUserMatrix(vmat); - m_Pivot->SetMapper(mapper); - - Matrix4f pivotTransform = c->AffineTransform::GetWorldMatrix(); - vtkSmartPointer pmat = vtkSmartPointer::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 vmat; + Matrix4fToVtk(c->GetMatrix(), vmat); + root->SetUserMatrix(vmat); + } } } // namespace Vtk diff --git a/src/Vtk/vtkContainerBox.h b/src/Vtk/vtkContainerBox.h index 103175a..4501c7c 100644 --- a/src/Vtk/vtkContainerBox.h +++ b/src/Vtk/vtkContainerBox.h @@ -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; }; diff --git a/src/Vtk/vtkHandlerWidget.cpp b/src/Vtk/vtkHandlerWidget.cpp index 3ea3d54..7e0757d 100644 --- a/src/Vtk/vtkHandlerWidget.cpp +++ b/src/Vtk/vtkHandlerWidget.cpp @@ -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]); diff --git a/src/Vtk/vtkViewport.cpp b/src/Vtk/vtkViewport.cpp index cf3e59e..ccb1bf7 100644 --- a/src/Vtk/vtkViewport.cpp +++ b/src/Vtk/vtkViewport.cpp @@ -1,7 +1,9 @@ #include "vtkViewport.h" #include +#include #include #include +#include #include #include #include @@ -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 widgetInteractionCallback; + widgetInteractionCallback->SetClientData(this); + widgetInteractionCallback->SetCallback([](vtkObject*, unsigned long, void* clientdata, void*){ + auto* self = static_cast(clientdata); + for (auto* p : self->m_Puppets) { + if (p->IsSelected()) { + p->Update(); + } + } + }); + m_HandlerWidget->AddObserver(vtkCommand::InteractionEvent, widgetInteractionCallback); + // Picking for selection m_Picker = vtkSmartPointer::New(); vtkNew 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; iGetNumberOfItems(); ++i) { if (parts->GetNextProp() == picked) {