refactor: extend Object property system and implement recursive property discovery in Vtk::Puppet archive

This commit is contained in:
AndreaRigoni
2026-04-03 08:54:37 +00:00
parent 6396bdfebf
commit a6a1539663
12 changed files with 459 additions and 272 deletions

View File

@@ -61,8 +61,8 @@ int main(int argc, char** argv) {
vtkTess.AddToViewer(viewer);
// Color them differently
vtkActor::SafeDownCast(vtkBox.GetProp())->GetProperty()->SetColor(0.8, 0.2, 0.2); // Redish box
vtkActor::SafeDownCast(vtkTess.GetProp())->GetProperty()->SetColor(0.2, 0.8, 0.2); // Greenish tess
vtkBox.SetColor(0.8, 0.2, 0.2); // Redish box
vtkTess.SetColor(0.2, 0.8, 0.2); // Greenish tess
// Position tessellated solid away from box
Matrix4f trans = Matrix4f::Identity();

View File

@@ -13,43 +13,104 @@
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkAssembly.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <Geant4/G4VPhysicalVolume.hh>
#include "Vtk/Math/vtkDense.h"
namespace uLib {
namespace Vtk {
vtkBoxSolid::vtkBoxSolid(Geant::BoxSolid *content)
: vtkGeantSolid(content), m_BoxContent(content) {
// Re-run Update for box-specific pipe
: vtkGeantSolid(content), m_BoxContent(content), m_BoxPuppet(nullptr) {
if (m_BoxContent && m_BoxContent->GetObject()) {
m_BoxPuppet = new vtkContainerBox(m_BoxContent->GetObject());
// Use the specialized box puppet's representation as our main prop
this->SetProp(m_BoxPuppet->GetProp());
}
// Connect the model's Updated event to updateTransform to ensure VTK sync
Object::connect(m_BoxContent, &uLib::Object::Updated, this, &vtkBoxSolid::UpdateTransform);
// Initial sync
this->Update();
}
vtkBoxSolid::~vtkBoxSolid() {}
vtkBoxSolid::~vtkBoxSolid() {
if (m_BoxPuppet) {
delete m_BoxPuppet;
}
}
void vtkBoxSolid::Update() {
this->UpdateGeometry();
this->UpdateTransform();
// Ensure base Puppet properties (color, opacity, etc) are applied
this->Puppet::Update();
}
void vtkBoxSolid::SyncFromVtk() {
vtkProp3D *root = vtkProp3D::SafeDownCast(this->GetProp());
if (root && m_BoxContent) {
vtkMatrix4x4 *rootMat = root->GetUserMatrix();
if (rootMat) {
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
m_BoxContent->SetTransform(vtkWorld);
m_BoxContent->Updated();
}
}
}
void vtkBoxSolid::UpdateGeometry() {
if (!m_BoxContent || !m_BoxContent->GetObject()) {
// Fallback to base tessellation if no model object
if (!m_BoxContent || !m_BoxContent->GetObject() || !m_BoxPuppet) {
// Fallback to base tessellation if no model object is available
vtkGeantSolid::UpdateGeometry();
return;
}
// Use the underlying ContainerBox for precise geometry
Vector3f size = m_BoxContent->GetObject()->GetSize();
vtkNew<vtkCubeSource> cube;
cube->SetXLength(size(0));
cube->SetYLength(size(1));
cube->SetZLength(size(2));
cube->Update();
// The vtkContainerBox manages its own geometry update
m_BoxPuppet->Update();
}
vtkPolyData *poly = GetPolyData();
if (poly) {
poly->ShallowCopy(cube->GetOutput());
poly->Modified();
void vtkBoxSolid::UpdateTransform() {
if (!m_BoxContent || !m_BoxPuppet) {
vtkGeantSolid::UpdateTransform();
return;
}
// 1. Sync the inner box TRS (local box properties like size and offset)
m_BoxPuppet->Update();
// 2. Sync the Geant4-level placement (world position/rotation)
vtkProp3D* root = vtkProp3D::SafeDownCast(this->GetProp());
if (root && m_BoxContent->GetPhysical()) {
auto *phys = m_BoxContent->GetPhysical();
G4ThreeVector pos = phys->GetTranslation();
const G4RotationMatrix *rot = phys->GetRotation();
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->Identity();
transform->Translate(pos.x(), pos.y(), pos.z());
if (rot) {
// G4RotationMatrix stores the inverse of the rotation for placement
G4RotationMatrix invRot = rot->inverse();
double elements[16] = {
invRot.xx(), invRot.xy(), invRot.xz(), 0,
invRot.yx(), invRot.yy(), invRot.yz(), 0,
invRot.zx(), invRot.zy(), invRot.zz(), 0,
0, 0, 0, 1
};
vtkSmartPointer<vtkMatrix4x4> mat = vtkSmartPointer<vtkMatrix4x4>::New();
mat->DeepCopy(elements);
transform->Concatenate(mat);
}
// Apply the Geant4 transform on top of the local box's UserMatrix
root->SetUserTransform(transform);
} else if (root) {
root->SetUserTransform(nullptr);
}
}

View File

@@ -26,7 +26,12 @@
#ifndef U_VTKBOXSOLID_H
#define U_VTKBOXSOLID_H
#include "Core/Types.h"
#include "Core/Property.h"
#include "Core/Serializable.h"
#include "vtkGeantSolid.h"
#include "Vtk/Math/vtkContainerBox.h"
namespace uLib {
namespace Vtk {
@@ -35,15 +40,27 @@ namespace Vtk {
* @brief VTK Puppet for visualizing a Geant::BoxSolid.
*/
class vtkBoxSolid : public vtkGeantSolid {
uLibTypeMacro(vtkBoxSolid, uLib::Vtk::vtkGeantSolid)
public:
vtkBoxSolid(Geant::BoxSolid *content);
virtual ~vtkBoxSolid();
virtual void Update() override;
virtual void UpdateGeometry() override;
virtual void UpdateTransform() override;
virtual void SyncFromVtk() override;
template <typename Ar>
void serialize(Ar &ar, const unsigned int version) {
ar & NVP("BoxSolid", *m_BoxContent);
}
protected:
Geant::BoxSolid *m_BoxContent;
vtkContainerBox *m_BoxPuppet;
ULIB_DECLARE_PROPERTIES(vtkBoxSolid)
};
} // namespace Vtk