Compare commits
1 Commits
fix-proper
...
fix-assemb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
010927714f |
@@ -148,6 +148,7 @@ QVariant ContextModel::data(const QModelIndex& index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
|
||||
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||
if (!obj) return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString typeName = getDemangledName(typeid(*obj));
|
||||
|
||||
@@ -94,8 +94,8 @@ void QViewportPane::setObject(uLib::Object* obj) {
|
||||
|
||||
void QViewportPane::setViewport(QWidget* viewport, const QString& title) {
|
||||
if (m_viewport) {
|
||||
m_viewport->parentWidget()->layout()->removeWidget(m_viewport);
|
||||
delete m_viewport;
|
||||
// Use deleteLater() instead of delete to avoid crashes during repaint cycles
|
||||
m_viewport->deleteLater();
|
||||
}
|
||||
m_viewport = viewport;
|
||||
m_titleLabel->setText(title);
|
||||
@@ -105,21 +105,8 @@ void QViewportPane::setViewport(QWidget* viewport, const QString& title) {
|
||||
mainAreaLayout->insertWidget(0, m_viewport);
|
||||
}
|
||||
|
||||
|
||||
QViewportPane::~QViewportPane() {}
|
||||
|
||||
void QViewportPane::setViewport(QWidget* viewport, const QString& title) {
|
||||
if (m_viewport) {
|
||||
m_layout->removeWidget(m_viewport);
|
||||
delete m_viewport;
|
||||
}
|
||||
m_viewport = viewport;
|
||||
m_titleLabel->setText(title);
|
||||
|
||||
m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_layout->addWidget(m_viewport);
|
||||
}
|
||||
|
||||
void QViewportPane::addVtkViewport() {
|
||||
auto* viewport = new uLib::Vtk::QViewport(this);
|
||||
setViewport(viewport, "VTK Viewport");
|
||||
|
||||
@@ -115,7 +115,7 @@ void ViewportPane::setObject(uLib::Object* obj) {
|
||||
|
||||
void ViewportPane::setViewport(QWidget* viewport, const QString& title) {
|
||||
if (m_viewport) {
|
||||
delete m_viewport;
|
||||
m_viewport->deleteLater();
|
||||
}
|
||||
m_viewport = viewport;
|
||||
m_titleLabel->setText(title);
|
||||
|
||||
37
build.log
37
build.log
@@ -1,36 +1 @@
|
||||
make: Entering directory '/home/rigoni/devel/cmt/ulib/build'
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/VoxImage.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/TriangleMesh.cpp.o
|
||||
[ 30%] Building CXX object src/Core/CMakeFiles/mutomCore.dir/Options.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Dense.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/StructuredGrid.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/VoxRaytracer.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/StructuredData.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Structured2DGrid.cpp.o
|
||||
[ 30%] Building CXX object src/Math/CMakeFiles/mutomMath.dir/Structured4DGrid.cpp.o
|
||||
[ 33%] Linking CXX shared library libmutomCore.so
|
||||
[ 33%] Built target mutomCore
|
||||
[ 36%] Linking CXX shared library libmutomMath.so
|
||||
[ 36%] Built target mutomMath
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkContainerBox.cpp.o
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/uLibVtkInterface.cxx.o
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkStructuredGrid.cpp.o
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkMuonScatter.cxx.o
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/uLibVtkViewer.cpp.o
|
||||
[ 63%] Generating mutomRootDict.cxx, libmutomRootDict_rdict.pcm, libmutomRootDict.rootmap
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkVoxImage.cpp.o
|
||||
[ 63%] Building CXX object src/Vtk/CMakeFiles/mutomVtk.dir/vtkVoxRaytracerRepresentation.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorSkinHit.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorHit.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorMCTrack.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorInfo.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/RootMuonScatter.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorPrimaryVertex.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/muCastorMuDetDIGI.cpp.o
|
||||
[ 90%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/SkinDetectorWriter.cpp.o
|
||||
[ 93%] Building CXX object src/Root/CMakeFiles/mutomRoot.dir/mutomRootDict.cxx.o
|
||||
[ 96%] Linking CXX shared library libmutomVtk.so
|
||||
[ 96%] Built target mutomVtk
|
||||
[100%] Linking CXX shared library libmutomRoot.so
|
||||
[100%] Built target mutomRoot
|
||||
make: Leaving directory '/home/rigoni/devel/cmt/ulib/build'
|
||||
ninja: error: loading 'build.ninja': No such file or directory
|
||||
|
||||
@@ -9,7 +9,7 @@ dependencies:
|
||||
- root
|
||||
- vtk=9.4 # VTK 9.4
|
||||
- pybind11
|
||||
# - boost=1.86.0 # requested by VTK 9.4
|
||||
#- boost=1.86.0 # requested by VTK 9.4
|
||||
- ninja
|
||||
- clang
|
||||
- clangxx
|
||||
|
||||
@@ -46,6 +46,8 @@ public:
|
||||
DataAllocator(size_t size = 0, bool owns_objects = true)
|
||||
: m_Size(size), m_RamData(nullptr), m_VramData(nullptr),
|
||||
m_Device(MemoryDevice::RAM), m_OwnsObjects(owns_objects) {
|
||||
if (m_Size >= (static_cast<size_t>(1) << 60))
|
||||
throw std::invalid_argument("DataAllocator: absurdly large size requested");
|
||||
if (m_Size > 0) {
|
||||
if (m_OwnsObjects)
|
||||
m_RamData = new T[m_Size]();
|
||||
@@ -139,7 +141,7 @@ public:
|
||||
void MoveToRAM() {
|
||||
if (m_Device == MemoryDevice::RAM)
|
||||
return;
|
||||
if (!m_RamData && m_Size > 0) {
|
||||
if (!m_RamData && m_Size > 0 && m_Size < (static_cast<size_t>(1) << 60)) {
|
||||
if (m_OwnsObjects)
|
||||
m_RamData = new T[m_Size]();
|
||||
else
|
||||
@@ -178,7 +180,7 @@ public:
|
||||
T *newRam = nullptr;
|
||||
T *newVram = nullptr;
|
||||
|
||||
if (size > 0) {
|
||||
if (size > 0 && size < (static_cast<size_t>(1) << 60)) {
|
||||
if (m_OwnsObjects)
|
||||
newRam = new T[size]();
|
||||
else
|
||||
|
||||
@@ -208,7 +208,8 @@ void Object::PrintSelf(std::ostream &o) const {
|
||||
|
||||
bool Object::addSignalImpl(SignalBase *sig, GenericMFPtr fptr,
|
||||
const char *name) {
|
||||
ObjectPrivate::Signal s = {fptr, std::string(name), sig};
|
||||
if (!d) return false;
|
||||
ObjectPrivate::Signal s = {fptr, std::string(name ? name : "unnamed"), sig};
|
||||
d->sigv.push_back(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ ObjectsContext::ObjectsContext() : Object() {}
|
||||
ObjectsContext::~ObjectsContext() {}
|
||||
|
||||
void ObjectsContext::AddObject(Object* obj) {
|
||||
if (obj && std::find(m_objects.begin(), m_objects.end(), obj) == m_objects.end()) {
|
||||
if (!obj || obj == this) return;
|
||||
|
||||
if (std::find(m_objects.begin(), m_objects.end(), obj) == m_objects.end()) {
|
||||
m_objects.push_back(obj);
|
||||
// Connect child's update to context's update to trigger re-renders
|
||||
Object::connect(obj, &Object::Updated, this, &Object::Updated);
|
||||
|
||||
@@ -37,27 +37,18 @@ Assembly::Assembly(const Assembly ©)
|
||||
m_GroupSelection(copy.m_GroupSelection) {}
|
||||
|
||||
Assembly::~Assembly() {
|
||||
for (auto const& [obj, conn] : m_ChildConnections) {
|
||||
conn.disconnect();
|
||||
}
|
||||
m_ChildConnections.clear();
|
||||
}
|
||||
|
||||
void Assembly::AddObject(Object *obj) {
|
||||
if (!obj || obj == this) return;
|
||||
|
||||
if (auto *at = dynamic_cast<AffineTransform *>(obj)) {
|
||||
at->SetParent(this);
|
||||
}
|
||||
|
||||
// Base class already handles the list and child->parent update connection
|
||||
ObjectsContext::AddObject(obj);
|
||||
|
||||
// Connect to child updates to recompute AABB
|
||||
m_ChildConnections[obj] = Object::connect(obj, &Object::Updated, [this](){
|
||||
this->ComputeBoundingBox();
|
||||
this->Updated(); // Signal that assembly itself changed (AABB-wise)
|
||||
});
|
||||
|
||||
// Parent -> Child propagation for world matrix updates
|
||||
Object::connect(this, &Object::Updated, obj, &Object::Updated);
|
||||
|
||||
this->ComputeBoundingBox();
|
||||
}
|
||||
|
||||
@@ -67,12 +58,6 @@ void Assembly::RemoveObject(Object *obj) {
|
||||
at->SetParent(nullptr);
|
||||
}
|
||||
|
||||
auto itConn = m_ChildConnections.find(obj);
|
||||
if (itConn != m_ChildConnections.end()) {
|
||||
itConn->second.disconnect();
|
||||
m_ChildConnections.erase(itConn);
|
||||
}
|
||||
|
||||
ObjectsContext::RemoveObject(obj);
|
||||
this->ComputeBoundingBox();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Math/Transform.h"
|
||||
|
||||
namespace uLib {
|
||||
namespace Vtk { class Assembly; }
|
||||
|
||||
/**
|
||||
* @brief Assembly groups geometric objects (ContainerBox, Cylinder, etc.)
|
||||
@@ -46,6 +47,7 @@ namespace uLib {
|
||||
class Assembly : public ObjectsContext, public TRS {
|
||||
public:
|
||||
uLibTypeMacro(Assembly, ObjectsContext, TRS)
|
||||
friend class Vtk::Assembly;
|
||||
|
||||
|
||||
Assembly();
|
||||
@@ -112,7 +114,6 @@ private:
|
||||
bool m_ShowBoundingBox;
|
||||
bool m_GroupSelection;
|
||||
bool m_InUpdated = false;
|
||||
std::map<Object*, Connection> m_ChildConnections;
|
||||
|
||||
ULIB_DECLARE_PROPERTIES(Assembly)
|
||||
};
|
||||
|
||||
@@ -28,33 +28,33 @@ using namespace uLib;
|
||||
int main(int argc, char **argv) {
|
||||
bool interactive = (argc > 1 && std::string(argv[1]) == "-i");
|
||||
|
||||
// ---- 1. Build model objects ----
|
||||
ContainerBox box1;
|
||||
box1.Scale(Vector3f(1_m, 2_m, 0.5_m));
|
||||
box1.SetPosition(Vector3f(0, 0, 0));
|
||||
// ---- 1. Build model objects on the heap (expected by uLib SmartPointer) ----
|
||||
auto* box1 = new ContainerBox();
|
||||
box1->Scale(Vector3f(1, 2, 0.5));
|
||||
// box1->SetPosition(Vector3f(0, 0, 0));
|
||||
|
||||
ContainerBox box2;
|
||||
box2.Scale(Vector3f(0.5_m, 0.5_m, 3_m));
|
||||
box2.SetPosition(Vector3f(2_m, 0, 0));
|
||||
auto* box2 = new ContainerBox();
|
||||
box2->Scale(Vector3f(0.5, 0.5, 3));
|
||||
box2->SetPosition(Vector3f(2, 0, 0));
|
||||
|
||||
Cylinder cyl(0.3_m, 1.5_m, 1);
|
||||
cyl.SetPosition(Vector3f(0, 3_m, 0));
|
||||
auto* cyl = new Cylinder(1, 1.5, 1);
|
||||
cyl->SetPosition(Vector3f(0, 3, 0));
|
||||
|
||||
// ---- 2. Create an Assembly and add objects ----
|
||||
Assembly assembly;
|
||||
assembly.AddObject(&box1);
|
||||
assembly.AddObject(&box2);
|
||||
assembly.AddObject(&cyl);
|
||||
assembly.SetShowBoundingBox(true);
|
||||
auto* assembly = new Assembly();
|
||||
assembly->AddObject(box1);
|
||||
assembly->AddObject(box2);
|
||||
assembly->AddObject(cyl);
|
||||
assembly->SetShowBoundingBox(true);
|
||||
|
||||
// ---- 3. Apply a group transform ----
|
||||
assembly.SetPosition(Vector3f(1_m, 1_m, 0));
|
||||
// assembly->SetPosition(Vector3f(1_m, 1_m, 0));
|
||||
|
||||
// ---- 5. Visualize (create prop3ds to set properties) ----
|
||||
Vtk::Assembly vtkAsm(&assembly);
|
||||
Vtk::Assembly vtkAsm(assembly); // Vtk::Assembly takes ownership of the model wrapper
|
||||
|
||||
Vtk::Viewer viewer;
|
||||
vtkAsm.AddToViewer(viewer); // This triggers prop3d creation via ConnectRenderer which eventually calls Prop3D::GetProp
|
||||
vtkAsm.AddToViewer(viewer);
|
||||
|
||||
// Explicitly update to ensure prop3ds exist and are added to assemblies
|
||||
vtkAsm.Update();
|
||||
@@ -74,16 +74,16 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
};
|
||||
|
||||
setProps(childCtx->GetProp3D(&box1), 1.0, 0.0, 0.0); // Red
|
||||
setProps(childCtx->GetProp3D(&box2), 0.0, 1.0, 0.0); // Green
|
||||
setProps(childCtx->GetProp3D(&cyl), 0.0, 0.0, 1.0); // Blue
|
||||
setProps(childCtx->GetProp3D(box1), 1.0, 0.0, 0.0); // Red
|
||||
setProps(childCtx->GetProp3D(box2), 0.0, 1.0, 0.0); // Green
|
||||
setProps(childCtx->GetProp3D(cyl), 0.0, 0.0, 1.0); // Blue
|
||||
}
|
||||
|
||||
std::cout << "Prop3Ds in viewport: " << viewer.getProp3Ds().size() << " (Expected 4: 1 assembly + 3 children)" << std::endl;
|
||||
|
||||
// ---- 4. Query the bounding box for terminal output ----
|
||||
Vector3f bbMin, bbMax;
|
||||
assembly.GetBoundingBox(bbMin, bbMax);
|
||||
assembly->GetBoundingBox(bbMin, bbMax);
|
||||
std::cout << "Assembly bounding box:" << std::endl;
|
||||
std::cout << " min = " << bbMin.transpose() << std::endl;
|
||||
std::cout << " max = " << bbMax.transpose() << std::endl;
|
||||
|
||||
@@ -45,15 +45,13 @@ Assembly::Assembly(uLib::Assembly *content)
|
||||
|
||||
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();
|
||||
m_VtkAsm->PickableOff();
|
||||
// 1. Setup the internal VTK assembly
|
||||
m_VtkAsm = vtkSmartPointer<::vtkAssembly>::New();
|
||||
m_BBoxActor = vtkSmartPointer<::vtkActor>::New();
|
||||
this->SetProp(m_VtkAsm);
|
||||
|
||||
// 2. Create the bounding-box wireframe actor
|
||||
@@ -64,7 +62,6 @@ void Assembly::InstallPipe() {
|
||||
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
|
||||
@@ -93,14 +90,7 @@ void Assembly::Update() {
|
||||
if (m_InUpdate) return;
|
||||
m_InUpdate = true;
|
||||
|
||||
if (this->m_model && m_VtkAsm) {
|
||||
// Apply world matrix from the assembly content
|
||||
vtkNew<vtkMatrix4x4> m;
|
||||
Matrix4fToVtk(this->m_model->GetMatrix(), m);
|
||||
m_VtkAsm->SetUserMatrix(m);
|
||||
m_VtkAsm->Modified();
|
||||
}
|
||||
|
||||
// Delegate to Prop3D to handle standard transformation application (uses GetContent())
|
||||
this->Prop3D::Update();
|
||||
this->UpdateBoundingBox();
|
||||
if (m_ChildContext)
|
||||
@@ -110,25 +100,29 @@ void Assembly::Update() {
|
||||
|
||||
void Assembly::SyncFromVtk() {
|
||||
if (m_InUpdate) return;
|
||||
if (!this->m_model || !m_VtkAsm) return;
|
||||
|
||||
m_InUpdate = true;
|
||||
|
||||
// VTK -> Model: Update world matrix (accounting for model parents)
|
||||
if (vtkProp3D* proxy = this->GetProxyProp()) {
|
||||
this->m_model->SetWorldMatrix(VtkToMatrix4f(proxy->GetUserMatrix()));
|
||||
this->m_model->FromMatrix(this->m_model->GetMatrix());
|
||||
}
|
||||
|
||||
this->UpdateBoundingBox();
|
||||
|
||||
// Sync the group-level transformation from VTK to the domain model
|
||||
this->Prop3D::SyncFromVtk();
|
||||
|
||||
// Propagate sync to children
|
||||
if (m_ChildContext)
|
||||
m_ChildContext->SyncFromVtk();
|
||||
|
||||
this->m_model->Updated(); // Notify change in model
|
||||
|
||||
|
||||
m_InUpdate = false;
|
||||
}
|
||||
|
||||
|
||||
void Assembly::serialize_display(uLib::Archive::display_properties_archive &ar, const unsigned int version) {
|
||||
// 1. Register base class appearance/transform
|
||||
this->Prop3D::serialize_display(ar, version);
|
||||
|
||||
// 2. Map domain model properties (Bounding Box visibility, etc.)
|
||||
if (this->m_model) {
|
||||
ar & HRP("ShowBoundingBox", m_model->m_ShowBoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
void Assembly::UpdateBoundingBox() {
|
||||
if (!this->m_model || !m_BBoxActor) return;
|
||||
@@ -188,10 +182,6 @@ void Assembly::UpdateBoundingBox() {
|
||||
m_BBoxActor->Modified();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ //
|
||||
ObjectsContext *Assembly::GetChildrenContext() const {
|
||||
return m_ChildContext;
|
||||
}
|
||||
|
||||
} // namespace Vtk
|
||||
} // namespace uLib
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
#include "Math/Assembly.h"
|
||||
#include "Vtk/uLibVtkInterface.h"
|
||||
|
||||
class vtkActor;
|
||||
class vtkAssembly; // VTK library forward declaration (must be before namespace)
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkActor.h>
|
||||
#include <vtkAssembly.h>
|
||||
|
||||
namespace uLib {
|
||||
namespace Vtk {
|
||||
@@ -39,33 +40,36 @@ class Assembly : public Prop3D, public uLib::ObjectWrapper<uLib::Assembly> {
|
||||
public:
|
||||
uLibTypeMacro(Assembly, Prop3D)
|
||||
|
||||
Assembly(uLib::Assembly *content);
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param content Pointer to the domain assembly model.
|
||||
*/
|
||||
explicit Assembly(uLib::Assembly *content);
|
||||
virtual ~Assembly();
|
||||
|
||||
/** @brief Updates the VTK representation from the model (model→VTK). */
|
||||
virtual void Update() override;
|
||||
|
||||
/** @brief Synchronizes the model from the VTK representation (VTK→model). */
|
||||
virtual void SyncFromVtk() override;
|
||||
|
||||
virtual uLib::Object* GetContent() const override { return (uLib::Object*)m_model.get(); }
|
||||
virtual uLib::ObjectsContext* GetChildren() override { return (uLib::ObjectsContext*)m_model.get(); }
|
||||
|
||||
/**
|
||||
* @brief Returns the prop3d managing child objects.
|
||||
*/
|
||||
/** @brief Returns the visualization context for children. */
|
||||
uLib::Vtk::ObjectsContext* GetChildrenContext() const { return m_ChildContext; }
|
||||
|
||||
/** @brief Returns the prop3d managing child objects. */
|
||||
ObjectsContext *GetChildrenContext() const;
|
||||
/** @brief Property serialization for Display Properties Panel. */
|
||||
void serialize_display(Archive::display_properties_archive &ar, const unsigned int version = 0) override;
|
||||
|
||||
private:
|
||||
void UpdateBoundingBox();
|
||||
void InstallPipe();
|
||||
|
||||
ObjectsContext *m_ChildContext;
|
||||
vtkActor *m_BBoxActor;
|
||||
::vtkAssembly *m_VtkAsm; // VTK library assembly — NOT this class
|
||||
bool m_InUpdate; // re-entrancy guard
|
||||
vtkSmartPointer<::vtkAssembly> m_VtkAsm;
|
||||
vtkSmartPointer<::vtkActor> m_BBoxActor;
|
||||
|
||||
uLib::Vtk::ObjectsContext *m_ChildContext;
|
||||
bool m_InUpdate;
|
||||
};
|
||||
|
||||
} // namespace Vtk
|
||||
|
||||
@@ -56,7 +56,9 @@ struct ContainerBoxData {
|
||||
: m_Cube(vtkSmartPointer<vtkActor>::New()),
|
||||
m_Axes(vtkSmartPointer<vtkActor>::New()),
|
||||
m_VtkAsm(vtkSmartPointer<vtkAssembly>::New()) {}
|
||||
~ContainerBoxData() {}
|
||||
~ContainerBoxData() {
|
||||
m_UpdateSignal.disconnect();
|
||||
}
|
||||
};
|
||||
|
||||
ContainerBox::ContainerBox(ContainerBox::Content *content)
|
||||
@@ -93,27 +95,7 @@ void ContainerBox::Update() {
|
||||
this->Prop3D::Update();
|
||||
}
|
||||
|
||||
void ContainerBox::SyncFromVtk() {
|
||||
RecursiveMutex::ScopedLock lock(this->m_UpdateMutex);
|
||||
if (!this->m_model)
|
||||
return;
|
||||
|
||||
vtkProp3D *root = this->GetProxyProp();
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
// VTK -> Model: Extract new world TRS from proxy, which matches the model's
|
||||
// TRS center
|
||||
vtkMatrix4x4 *rootMat = root->GetUserMatrix();
|
||||
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
|
||||
|
||||
// Synchronize TRS property members from the updated local matrix
|
||||
this->m_model->FromMatrix(vtkWorld);
|
||||
|
||||
// Since we modified the model, notify observers, but block the loop back to
|
||||
// VTK ConnectionBlock blocker(d->m_UpdateSignal);
|
||||
this->m_model->Updated();
|
||||
}
|
||||
|
||||
void ContainerBox::InstallPipe() {
|
||||
if (!this->m_model)
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
/**
|
||||
* @brief Synchronizes the model from the VTK representation (VTK→model).
|
||||
*/
|
||||
virtual void SyncFromVtk() override;
|
||||
|
||||
|
||||
virtual uLib::Object *GetContent() const override {
|
||||
return (uLib::Object *)m_model.get();
|
||||
|
||||
@@ -44,8 +44,7 @@ Cylinder::Cylinder(Cylinder::Content *content)
|
||||
}
|
||||
|
||||
Cylinder::~Cylinder() {
|
||||
if (m_Actor) m_Actor->Delete();
|
||||
if (m_VtkAsm) m_VtkAsm->Delete();
|
||||
m_UpdateSignal.disconnect();
|
||||
}
|
||||
|
||||
void Cylinder::Update() {
|
||||
@@ -85,26 +84,13 @@ void Cylinder::Update() {
|
||||
this->Prop3D::Update();
|
||||
}
|
||||
|
||||
void Cylinder::SyncFromVtk() {
|
||||
if (!this->m_model) return;
|
||||
|
||||
vtkProp3D* root = this->GetProxyProp();
|
||||
if (!root) return;
|
||||
|
||||
// VTK -> Model: Extract new world TRS from proxy
|
||||
vtkMatrix4x4* rootMat = root->GetUserMatrix();
|
||||
Matrix4f vtkWorld = VtkToMatrix4f(rootMat);
|
||||
|
||||
// Directly sync model from the world matrix
|
||||
this->m_model->FromMatrix(vtkWorld);
|
||||
this->m_model->Updated();
|
||||
}
|
||||
|
||||
void Cylinder::InstallPipe() {
|
||||
if (!this->m_model)
|
||||
return;
|
||||
|
||||
m_VtkAsm = ::vtkAssembly::New();
|
||||
m_VtkAsm = vtkSmartPointer<::vtkAssembly>::New();
|
||||
this->SetProp(m_VtkAsm);
|
||||
|
||||
vtkNew<vtkCylinderSource> cylinder;
|
||||
@@ -112,7 +98,7 @@ void Cylinder::InstallPipe() {
|
||||
cylinder->SetHeight(1.0);
|
||||
cylinder->SetResolution(32);
|
||||
|
||||
m_Actor = vtkActor::New();
|
||||
m_Actor = vtkSmartPointer<vtkActor>::New();
|
||||
vtkNew<vtkTransform> alignment;
|
||||
m_Actor->SetUserTransform(alignment);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "Math/Cylinder.h"
|
||||
#include "Vtk/uLibVtkInterface.h"
|
||||
#include <vtkActor.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
class vtkAssembly;
|
||||
|
||||
namespace uLib {
|
||||
@@ -53,7 +54,7 @@ public:
|
||||
virtual void Update() override;
|
||||
|
||||
/** Synchronizes the uLib model matrix with the VTK actor specifically for gizmo interactions */
|
||||
virtual void SyncFromVtk() override;
|
||||
|
||||
|
||||
virtual uLib::Object *GetContent() const override {
|
||||
return (uLib::Object *)m_model.get();
|
||||
@@ -63,8 +64,8 @@ protected:
|
||||
/** Sets up the VTK visualization pipeline */
|
||||
virtual void InstallPipe();
|
||||
|
||||
vtkActor *m_Actor;
|
||||
::vtkAssembly *m_VtkAsm;
|
||||
vtkSmartPointer<vtkActor> m_Actor;
|
||||
vtkSmartPointer<::vtkAssembly> m_VtkAsm;
|
||||
uLib::Connection m_UpdateSignal;
|
||||
};
|
||||
|
||||
|
||||
@@ -308,17 +308,7 @@ void VoxImage::serialize_display(uLib::Archive::display_properties_archive & ar,
|
||||
{"MIP", "Composite", "Composite Shaded", "MIP Bone", "MIP Hot", "Additive"});
|
||||
}
|
||||
|
||||
void VoxImage::SyncFromVtk() {
|
||||
if (auto *root = this->GetProxyProp()) {
|
||||
vtkMatrix4x4 *rootMat = root->GetUserMatrix();
|
||||
if (rootMat) {
|
||||
Matrix4f vtkLocal = VtkToMatrix4f(rootMat);
|
||||
// Synchronize TRS from VTK, compensating for local volume offset
|
||||
this->m_model->FromMatrix(vtkLocal); // * this->m_model->GetLocalMatrix().inverse());
|
||||
this->m_model->Updated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VoxImage::Update() {
|
||||
if (auto *root = vtkProp3D::SafeDownCast(this->GetProp())) {
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
void RescaleShaderRange();
|
||||
|
||||
void Update() override;
|
||||
void SyncFromVtk() override;
|
||||
|
||||
void serialize_display(uLib::Archive::display_properties_archive &ar,
|
||||
const unsigned int version = 0) override;
|
||||
|
||||
|
||||
@@ -97,11 +97,24 @@ public:
|
||||
m_HighlightMode(Prop3D::HighlightPlain)
|
||||
{
|
||||
m_Color = Vector3d(-1, -1, -1);
|
||||
m_PrevMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
|
||||
m_PrevMatrix->Identity();
|
||||
}
|
||||
|
||||
~Prop3DData() {
|
||||
// No manual Delete needed for smart pointers
|
||||
|
||||
if (m_Renderers) {
|
||||
m_Renderers->InitTraversal();
|
||||
for (int i = 0; i < m_Renderers->GetNumberOfItems(); ++i) {
|
||||
vtkRenderer* ren = m_Renderers->GetNextItem();
|
||||
if (ren) {
|
||||
if (m_Prop) ren->RemoveViewProp(m_Prop);
|
||||
if (m_OutlineActor) ren->RemoveActor(m_OutlineActor);
|
||||
if (m_CubeAxesActor) ren->RemoveActor(m_CubeAxesActor);
|
||||
if (m_HighlightActor) ren->RemoveActor(m_HighlightActor);
|
||||
}
|
||||
}
|
||||
m_Renderers->RemoveAllItems();
|
||||
}
|
||||
}
|
||||
|
||||
Prop3D *m_Prop3D;
|
||||
@@ -128,6 +141,8 @@ public:
|
||||
|
||||
int m_HighlightMode; // 0: Plain, 1: Corners
|
||||
|
||||
vtkSmartPointer<vtkMatrix4x4> m_PrevMatrix;
|
||||
|
||||
//
|
||||
TRS m_Transform;
|
||||
|
||||
@@ -289,6 +304,7 @@ public:
|
||||
vtkNew<vtkMatrix4x4> vwm;
|
||||
Matrix4fToVtk(tr->GetWorldMatrix(), vwm);
|
||||
m_HighlightActor->SetUserMatrix(vwm);
|
||||
m_PrevMatrix->DeepCopy(vwm);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -620,6 +636,7 @@ void Prop3D::ApplyProp3DTransform(vtkProp3D* prop)
|
||||
Matrix4fToVtk(tr->GetMatrix(), m);
|
||||
prop->SetUserMatrix(m);
|
||||
prop->Modified();
|
||||
pd->m_PrevMatrix->DeepCopy(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,7 +647,18 @@ void Prop3D::SyncFromVtk()
|
||||
if (auto* tr = dynamic_cast<uLib::TRS*>(content)) {
|
||||
if (auto* proxy = this->GetProxyProp()) {
|
||||
if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) {
|
||||
tr->FromMatrix(VtkToMatrix4f(mat));
|
||||
// Calculate Delta: currentMatrix * Inv(m_PrevMatrix)
|
||||
vtkNew<vtkMatrix4x4> invPrev;
|
||||
vtkMatrix4x4::Invert(pd->m_PrevMatrix, invPrev);
|
||||
|
||||
vtkNew<vtkMatrix4x4> delta;
|
||||
vtkMatrix4x4::Multiply4x4(mat, invPrev, delta);
|
||||
|
||||
// Apply delta to world matrix
|
||||
Matrix4f nextWorldMatrix = VtkToMatrix4f(delta) * tr->GetWorldMatrix();
|
||||
tr->SetWorldMatrix(nextWorldMatrix);
|
||||
|
||||
pd->m_PrevMatrix->DeepCopy(mat);
|
||||
content->Updated();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,15 +26,17 @@ ObjectsContext::ObjectsContext(uLib::ObjectsContext *context)
|
||||
: m_Context(context), m_Assembly(::vtkAssembly::New()) {
|
||||
this->SetProp(m_Assembly);
|
||||
if (m_Context) {
|
||||
Object::connect(m_Context, &uLib::ObjectsContext::ObjectAdded, this,
|
||||
m_AddedConnection = Object::connect(m_Context, &uLib::ObjectsContext::ObjectAdded, this,
|
||||
&ObjectsContext::OnObjectAdded);
|
||||
Object::connect(m_Context, &uLib::ObjectsContext::ObjectRemoved, this,
|
||||
m_RemovedConnection = Object::connect(m_Context, &uLib::ObjectsContext::ObjectRemoved, this,
|
||||
&ObjectsContext::OnObjectRemoved);
|
||||
this->Synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
ObjectsContext::~ObjectsContext() {
|
||||
m_AddedConnection.disconnect();
|
||||
m_RemovedConnection.disconnect();
|
||||
for (auto const &[obj, prop3d] : m_Prop3Ds) {
|
||||
delete prop3d;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ private:
|
||||
uLib::ObjectsContext *m_Context;
|
||||
std::map<uLib::Object*, Prop3D*> m_Prop3Ds;
|
||||
vtkAssembly *m_Assembly;
|
||||
uLib::Connection m_AddedConnection;
|
||||
uLib::Connection m_RemovedConnection;
|
||||
};
|
||||
|
||||
} // namespace Vtk
|
||||
|
||||
@@ -104,6 +104,9 @@ QViewport::QViewport(QWidget* parent)
|
||||
|
||||
QViewport::~QViewport()
|
||||
{
|
||||
if (m_VtkWidget && m_VtkWidget->renderWindow()) {
|
||||
m_VtkWidget->renderWindow()->RemoveRenderer(this->GetRenderer());
|
||||
}
|
||||
}
|
||||
|
||||
void QViewport::SetupPipeline()
|
||||
|
||||
Reference in New Issue
Block a user