refactor: unify vtkBoxSolid architecture with Puppet base and update build documentation
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
trigger: always_on
|
trigger: always_on
|
||||||
---
|
---
|
||||||
|
|
||||||
build in build directory using always micromamba "mutom" env.
|
build in build directory using always micromamba "uLib" env.
|
||||||
build with make flag -j$(nproc).
|
build with:
|
||||||
|
make flag -j$(nproc)
|
||||||
|
ninja -C build
|
||||||
@@ -105,6 +105,8 @@ void Solid::SetTransform(Matrix4f transform) {
|
|||||||
m_Physical->SetTranslation(*m_Position);
|
m_Physical->SetTranslation(*m_Position);
|
||||||
m_Physical->SetRotation(m_Rotation);
|
m_Physical->SetRotation(m_Rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "Solid " << GetName() << " position: " << pos << " rotation: " << m << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Solid::SetParent(Solid *parent) {
|
void Solid::SetParent(Solid *parent) {
|
||||||
|
|||||||
@@ -10,9 +10,11 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
#include "vtkBoxSolid.h"
|
#include "vtkBoxSolid.h"
|
||||||
|
#include "Core/Monitor.h"
|
||||||
#include <vtkCubeSource.h>
|
#include <vtkCubeSource.h>
|
||||||
#include <vtkPolyDataMapper.h>
|
#include <vtkPolyDataMapper.h>
|
||||||
#include <vtkActor.h>
|
#include <vtkActor.h>
|
||||||
|
#include <vtkProperty.h>
|
||||||
#include <vtkAssembly.h>
|
#include <vtkAssembly.h>
|
||||||
#include <vtkTransform.h>
|
#include <vtkTransform.h>
|
||||||
#include <vtkMatrix4x4.h>
|
#include <vtkMatrix4x4.h>
|
||||||
@@ -23,95 +25,59 @@ namespace uLib {
|
|||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
vtkBoxSolid::vtkBoxSolid(Geant::BoxSolid *content)
|
vtkBoxSolid::vtkBoxSolid(Geant::BoxSolid *content)
|
||||||
: vtkGeantSolid(content), m_BoxContent(content), m_BoxPuppet(nullptr) {
|
: vtkGeantSolid(content), m_BoxContent(content) {
|
||||||
|
this->InstallPipe();
|
||||||
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
|
// Connect the model's Updated event to updateTransform to ensure VTK sync
|
||||||
Object::connect(m_BoxContent, &uLib::Object::Updated, this, &vtkBoxSolid::UpdateTransform);
|
m_UpdateConnection = Object::connect(m_BoxContent, &uLib::Object::Updated, this, &vtkBoxSolid::Update);
|
||||||
|
|
||||||
// Initial sync
|
// Initial sync
|
||||||
this->Update();
|
this->Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkBoxSolid::~vtkBoxSolid() {
|
vtkBoxSolid::~vtkBoxSolid() {
|
||||||
if (m_BoxPuppet) {
|
|
||||||
delete m_BoxPuppet;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkBoxSolid::Update() {
|
void vtkBoxSolid::Update() {
|
||||||
|
ConnectionBlock blocker(m_UpdateConnection);
|
||||||
this->UpdateGeometry();
|
this->UpdateGeometry();
|
||||||
this->UpdateTransform();
|
// Ensure base Puppet properties (color, opacity, etc) and transform are applied
|
||||||
// Ensure base Puppet properties (color, opacity, etc) are applied
|
|
||||||
this->Puppet::Update();
|
this->Puppet::Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkBoxSolid::SyncFromVtk() {
|
void vtkBoxSolid::SyncFromVtk() {
|
||||||
vtkProp3D *root = vtkProp3D::SafeDownCast(this->GetProp());
|
this->Puppet::SyncFromVtk();
|
||||||
if (root && m_BoxContent) {
|
if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) {
|
||||||
vtkMatrix4x4 *rootMat = root->GetUserMatrix();
|
if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) {
|
||||||
if (rootMat) {
|
m_BoxContent->SetTransform(VtkToMatrix4f(mat));
|
||||||
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
|
}
|
||||||
m_BoxContent->SetTransform(vtkWorld);
|
|
||||||
m_BoxContent->Updated();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkBoxSolid::UpdateGeometry() {
|
void vtkBoxSolid::UpdateGeometry() {
|
||||||
if (!m_BoxContent || !m_BoxContent->GetObject() || !m_BoxPuppet) {
|
// Sync geometry from G4VSolid provided by vtkGeantSolid (tessellation)
|
||||||
// Fallback to base tessellation if no model object is available
|
vtkGeantSolid::UpdateGeometry();
|
||||||
vtkGeantSolid::UpdateGeometry();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The vtkContainerBox manages its own geometry update
|
|
||||||
m_BoxPuppet->Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkBoxSolid::UpdateTransform() {
|
void vtkBoxSolid::UpdateTransform() {
|
||||||
if (!m_BoxContent || !m_BoxPuppet) {
|
// Take transform from Puppet base (which uses GetContent() -> ContainerBox TRS)
|
||||||
vtkGeantSolid::UpdateTransform();
|
this->Puppet::Update();
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
void vtkBoxSolid::serialize_display(uLib::Archive::display_properties_archive &ar,
|
||||||
|
const unsigned int version) {
|
||||||
|
// Expose Geant solid properties and underlying Box/TRS properties
|
||||||
|
this->Puppet::serialize_display(ar, version);
|
||||||
|
if (m_BoxContent) {
|
||||||
|
ar & NVP("Box", *m_BoxContent);
|
||||||
|
if (m_BoxContent->GetObject()) {
|
||||||
|
ar & NVP("Container", *m_BoxContent->GetObject());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Sync the inner box TRS (local box properties like size and offset)
|
void vtkBoxSolid::InstallPipe() {
|
||||||
m_BoxPuppet->Update();
|
vtkGeantSolid::InstallPipe();
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
|
|||||||
@@ -31,7 +31,9 @@
|
|||||||
#include "Core/Serializable.h"
|
#include "Core/Serializable.h"
|
||||||
|
|
||||||
#include "vtkGeantSolid.h"
|
#include "vtkGeantSolid.h"
|
||||||
#include "Vtk/Math/vtkContainerBox.h"
|
|
||||||
|
class vtkCubeSource;
|
||||||
|
class vtkActor;
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
@@ -51,14 +53,23 @@ public:
|
|||||||
virtual void UpdateTransform() override;
|
virtual void UpdateTransform() override;
|
||||||
virtual void SyncFromVtk() override;
|
virtual void SyncFromVtk() override;
|
||||||
|
|
||||||
|
virtual uLib::Object *GetContent() const override {
|
||||||
|
return m_BoxContent ? (::uLib::Object*)m_BoxContent->GetObject() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void serialize_display(uLib::Archive::display_properties_archive &ar,
|
||||||
|
const unsigned int version = 0) override;
|
||||||
|
|
||||||
template <typename Ar>
|
template <typename Ar>
|
||||||
void serialize(Ar &ar, const unsigned int version) {
|
void serialize(Ar &ar, const unsigned int version) {
|
||||||
ar & NVP("BoxSolid", *m_BoxContent);
|
ar & NVP("BoxSolid", *m_BoxContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void InstallPipe() override;
|
||||||
|
|
||||||
Geant::BoxSolid *m_BoxContent;
|
Geant::BoxSolid *m_BoxContent;
|
||||||
vtkContainerBox *m_BoxPuppet;
|
uLib::Connection m_UpdateConnection;
|
||||||
|
|
||||||
ULIB_DECLARE_PROPERTIES(vtkBoxSolid)
|
ULIB_DECLARE_PROPERTIES(vtkBoxSolid)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ void vtkGeantSolid::UpdateGeometry() {
|
|||||||
int nVertices = polyhedron->GetNoVertices();
|
int nVertices = polyhedron->GetNoVertices();
|
||||||
for (int i = 1; i <= nVertices; ++i) {
|
for (int i = 1; i <= nVertices; ++i) {
|
||||||
G4Point3D vtx = polyhedron->GetVertex(i);
|
G4Point3D vtx = polyhedron->GetVertex(i);
|
||||||
|
|
||||||
points->InsertNextPoint(vtx.x(), vtx.y(), vtx.z());
|
points->InsertNextPoint(vtx.x(), vtx.y(), vtx.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ namespace Vtk {
|
|||||||
struct ContainerBoxData;
|
struct ContainerBoxData;
|
||||||
|
|
||||||
class vtkContainerBox : public Puppet, public Polydata {
|
class vtkContainerBox : public Puppet, public Polydata {
|
||||||
|
|
||||||
|
uLibTypeMacro(vtkContainerBox, Puppet, Polydata)
|
||||||
typedef ContainerBox Content;
|
typedef ContainerBox Content;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ void vtkCylinder::Update() {
|
|||||||
|
|
||||||
// Apply Axis alignment
|
// Apply Axis alignment
|
||||||
int axis = m_Content->GetAxis();
|
int axis = m_Content->GetAxis();
|
||||||
if (axis == 0) alignment->RotateZ(-90); // Y -> X
|
if (axis == 0) alignment->RotateZ(-90); // Y -> X
|
||||||
else if (axis == 1) ; // Y -> Y (identity)
|
else if (axis == 1) ; // Y -> Y (identity)
|
||||||
else if (axis == 2) alignment->RotateX(90); // Y -> Z
|
else if (axis == 2) alignment->RotateX(90); // Y -> Z
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,18 +93,10 @@ void vtkCylinder::SyncFromVtk() {
|
|||||||
|
|
||||||
// VTK -> Model: Extract new world TRS from proxy
|
// VTK -> Model: Extract new world TRS from proxy
|
||||||
vtkMatrix4x4* rootMat = root->GetUserMatrix();
|
vtkMatrix4x4* rootMat = root->GetUserMatrix();
|
||||||
if (rootMat) {
|
|
||||||
std::cout << "[vtkCylinder::SyncFromVtk] Read Proxy UserMatrix:" << std::endl;
|
|
||||||
rootMat->Print(std::cout);
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
|
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
|
||||||
|
|
||||||
// Directly sync model from the world matrix
|
// Directly sync model from the world matrix
|
||||||
m_Content->FromMatrix(vtkWorld);
|
m_Content->FromMatrix(vtkWorld);
|
||||||
|
|
||||||
std::cout << "[vtkCylinder::SyncFromVtk] New Model WorldMatrix:" << std::endl << m_Content->GetWorldMatrix() << std::endl;
|
|
||||||
|
|
||||||
m_Content->Updated();
|
m_Content->Updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user