211 lines
6.1 KiB
C++
211 lines
6.1 KiB
C++
/*//////////////////////////////////////////////////////////////////////////////
|
|
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
|
|
All rights reserved
|
|
|
|
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
|
|
|
|
//////////////////////////////////////////////////////////////////////////////*/
|
|
|
|
#include "vtkAssembly.h" // uLib::Vtk::Assembly
|
|
#include "Vtk/vtkObjectsContext.h"
|
|
#include "Math/vtkDense.h"
|
|
|
|
#include <vtkAssembly.h> // VTK library ::vtkAssembly
|
|
#include <vtkActor.h>
|
|
#include <vtkCubeSource.h>
|
|
#include <vtkPolyDataMapper.h>
|
|
#include <vtkProperty.h>
|
|
#include <vtkMatrix4x4.h>
|
|
#include <vtkPropCollection.h>
|
|
#include <vtkNew.h>
|
|
#include <vtkProp3D.h>
|
|
#include <vtkPoints.h>
|
|
#include <vtkCellArray.h>
|
|
#include <vtkPolyData.h>
|
|
|
|
namespace uLib {
|
|
namespace Vtk {
|
|
|
|
// ------------------------------------------------------------------ //
|
|
Assembly::Assembly(uLib::Assembly *content)
|
|
: m_Content(content),
|
|
m_ChildContext(nullptr),
|
|
m_BBoxActor(nullptr),
|
|
m_VtkAsm(nullptr),
|
|
m_InUpdate(false),
|
|
m_BlockUpdate(false) {
|
|
this->InstallPipe();
|
|
if (m_Content) {
|
|
Object::connect(m_Content, &uLib::Assembly::Updated,
|
|
this, &Assembly::contentUpdate);
|
|
}
|
|
}
|
|
|
|
Assembly::~Assembly() {
|
|
delete m_ChildContext;
|
|
if (m_BBoxActor) m_BBoxActor->Delete();
|
|
if (m_VtkAsm) m_VtkAsm->Delete();
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
void Assembly::InstallPipe() {
|
|
// 1. Create the VTK library assembly that groups everything
|
|
m_VtkAsm = ::vtkAssembly::New();
|
|
this->SetProp(m_VtkAsm);
|
|
|
|
// 2. Create the bounding-box wireframe actor
|
|
vtkNew<vtkCubeSource> cube;
|
|
cube->SetBounds(0, 1, 0, 1, 0, 1);
|
|
cube->Update();
|
|
|
|
vtkNew<vtkPolyDataMapper> mapper;
|
|
mapper->SetInputConnection(cube->GetOutputPort());
|
|
|
|
m_BBoxActor = vtkActor::New();
|
|
m_BBoxActor->SetMapper(mapper);
|
|
m_BBoxActor->GetProperty()->SetRepresentationToWireframe();
|
|
m_BBoxActor->GetProperty()->SetColor(1.0, 0.85, 0.0); // gold wireframe
|
|
m_BBoxActor->GetProperty()->SetLineWidth(1.5);
|
|
m_BBoxActor->GetProperty()->SetOpacity(0.6);
|
|
m_BBoxActor->SetVisibility(m_Content ? m_Content->GetShowBoundingBox() : false);
|
|
|
|
m_VtkAsm->AddPart(m_BBoxActor);
|
|
|
|
// 3. Build a child-objects context (auto-creates puppets for each child)
|
|
if (m_Content) {
|
|
m_ChildContext = new vtkObjectsContext(m_Content);
|
|
// The vtkObjectsContext's own prop is already a ::vtkAssembly;
|
|
// nest it inside ours so everything moves together.
|
|
if (auto *childProp = vtkProp3D::SafeDownCast(m_ChildContext->GetProp()))
|
|
m_VtkAsm->AddPart(childProp);
|
|
}
|
|
|
|
// 4. Apply initial transform
|
|
this->UpdateTransform();
|
|
this->UpdateBoundingBox();
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
void Assembly::contentUpdate() {
|
|
if (m_InUpdate) return;
|
|
m_InUpdate = true;
|
|
|
|
this->UpdateTransform();
|
|
this->UpdateBoundingBox();
|
|
if (m_ChildContext)
|
|
m_ChildContext->Update();
|
|
|
|
m_BlockUpdate = true;
|
|
Puppet::Update();
|
|
m_InUpdate = false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
void Assembly::Update() {
|
|
if (m_InUpdate) return;
|
|
if (!m_Content || !m_VtkAsm) return;
|
|
|
|
if (m_BlockUpdate) {
|
|
m_BlockUpdate = false;
|
|
return;
|
|
}
|
|
|
|
m_InUpdate = true;
|
|
|
|
// Pull VTK transform back into the uLib model
|
|
vtkMatrix4x4* vmat = m_VtkAsm->GetUserMatrix();
|
|
if (vmat) {
|
|
Matrix4f transform = VtkToMatrix4f(vmat);
|
|
m_Content->SetMatrix(transform);
|
|
}
|
|
|
|
this->UpdateBoundingBox();
|
|
if (m_ChildContext)
|
|
m_ChildContext->Update();
|
|
|
|
m_Content->Updated(); // Notify change in model
|
|
|
|
m_InUpdate = false;
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
void Assembly::UpdateTransform() {
|
|
if (!m_Content || !m_VtkAsm) return;
|
|
|
|
Matrix4f mat = m_Content->GetMatrix();
|
|
vtkNew<vtkMatrix4x4> vmat;
|
|
Matrix4fToVtk(mat, vmat);
|
|
m_VtkAsm->SetUserMatrix(vmat);
|
|
m_VtkAsm->Modified();
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
void Assembly::UpdateBoundingBox() {
|
|
if (!m_Content || !m_BBoxActor) return;
|
|
|
|
m_BBoxActor->SetVisibility(m_Content->GetShowBoundingBox());
|
|
|
|
Vector3f bbMin, bbMax;
|
|
m_Content->GetBoundingBox(bbMin, bbMax);
|
|
|
|
// Avoid degenerate boxes
|
|
Vector3f size = bbMax - bbMin;
|
|
if (size.norm() < 1e-6f) return;
|
|
|
|
// Rebuild the corner segments to match the AABB
|
|
vtkNew<vtkPoints> points;
|
|
vtkNew<vtkCellArray> lines;
|
|
|
|
float bounds[2][3] = {
|
|
{bbMin(0), bbMin(1), bbMin(2)},
|
|
{bbMax(0), bbMax(1), bbMax(2)}
|
|
};
|
|
|
|
// Corner segment length: 10% of dimension
|
|
float len[3] = {
|
|
(bbMax(0) - bbMin(0)) * 0.1f,
|
|
(bbMax(1) - bbMin(1)) * 0.1f,
|
|
(bbMax(2) - bbMin(2)) * 0.1f
|
|
};
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
float p[3];
|
|
p[0] = bounds[(i & 1) ? 1 : 0][0];
|
|
p[1] = bounds[(i & 2) ? 1 : 0][1];
|
|
p[2] = bounds[(i & 4) ? 1 : 0][2];
|
|
|
|
for (int axis = 0; axis < 3; ++axis) {
|
|
float p2[3] = {p[0], p[1], p[2]};
|
|
float delta = (i & (1 << axis)) ? -len[axis] : len[axis];
|
|
p2[axis] += delta;
|
|
|
|
vtkIdType id1 = points->InsertNextPoint(p);
|
|
vtkIdType id2 = points->InsertNextPoint(p2);
|
|
lines->InsertNextCell(2);
|
|
lines->InsertCellPoint(id1);
|
|
lines->InsertCellPoint(id2);
|
|
}
|
|
}
|
|
|
|
vtkNew<vtkPolyData> poly;
|
|
poly->SetPoints(points);
|
|
poly->SetLines(lines);
|
|
|
|
vtkNew<vtkPolyDataMapper> mapper;
|
|
mapper->SetInputData(poly);
|
|
|
|
m_BBoxActor->SetMapper(mapper);
|
|
m_BBoxActor->Modified();
|
|
}
|
|
|
|
// ------------------------------------------------------------------ //
|
|
vtkObjectsContext *Assembly::GetChildrenContext() const {
|
|
return m_ChildContext;
|
|
}
|
|
|
|
} // namespace Vtk
|
|
} // namespace uLib
|