refactor using pimpl and fix test
This commit is contained in:
@@ -103,6 +103,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_WARNING_OPTION}")
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UULIB_SERIALIZATION_ON -Wno-cpp")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -UULIB_SERIALIZATION_ON -Wno-cpp")
|
||||||
|
|
||||||
# CTEST framework
|
# CTEST framework
|
||||||
|
set(CTEST_PROJECT_NAME "uLib")
|
||||||
include(CTest)
|
include(CTest)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public:
|
|||||||
else
|
else
|
||||||
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
}
|
}
|
||||||
|
std::cout << "DataAllocator Constructor: ptr=" << m_RamData << " size=" << m_Size << " own=" << m_OwnsObjects << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataAllocator(const DataAllocator<T> &other)
|
DataAllocator(const DataAllocator<T> &other)
|
||||||
@@ -63,7 +64,12 @@ public:
|
|||||||
m_RamData = new T[m_Size];
|
m_RamData = new T[m_Size];
|
||||||
else
|
else
|
||||||
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
|
||||||
|
if (m_OwnsObjects) {
|
||||||
|
std::copy(other.m_RamData, other.m_RamData + m_Size, m_RamData);
|
||||||
|
} else {
|
||||||
|
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (other.m_VramData) {
|
if (other.m_VramData) {
|
||||||
@@ -73,14 +79,17 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
std::cout << "DataAllocator CopyConstructor: from=" << other.m_RamData << " to=" << m_RamData << " size=" << m_Size << " own=" << m_OwnsObjects << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
~DataAllocator() {
|
~DataAllocator() {
|
||||||
|
std::cout << "DataAllocator Destructor: ptr=" << m_RamData << " size=" << m_Size << " own=" << m_OwnsObjects << std::endl;
|
||||||
if (m_RamData) {
|
if (m_RamData) {
|
||||||
if (m_OwnsObjects)
|
if (m_OwnsObjects)
|
||||||
delete[] m_RamData;
|
delete[] m_RamData;
|
||||||
else
|
else
|
||||||
::operator delete(m_RamData);
|
::operator delete(m_RamData);
|
||||||
|
m_RamData = nullptr;
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (m_VramData) {
|
if (m_VramData) {
|
||||||
@@ -91,6 +100,13 @@ public:
|
|||||||
|
|
||||||
DataAllocator &operator=(const DataAllocator &other) {
|
DataAllocator &operator=(const DataAllocator &other) {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
|
if (m_Size == other.m_Size && m_OwnsObjects != other.m_OwnsObjects) {
|
||||||
|
// Ownership changed but size is same: we must force reallocation
|
||||||
|
// to avoid using the wrong delete operator later.
|
||||||
|
size_t oldSize = m_Size;
|
||||||
|
m_Size = 0;
|
||||||
|
resize(oldSize); // This will free the old buffer with the OLD ownership
|
||||||
|
}
|
||||||
m_OwnsObjects = other.m_OwnsObjects;
|
m_OwnsObjects = other.m_OwnsObjects;
|
||||||
resize(other.m_Size);
|
resize(other.m_Size);
|
||||||
m_Device = other.m_Device;
|
m_Device = other.m_Device;
|
||||||
@@ -101,7 +117,11 @@ public:
|
|||||||
else
|
else
|
||||||
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
m_RamData = static_cast<T *>(::operator new(m_Size * sizeof(T)));
|
||||||
}
|
}
|
||||||
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
if (m_OwnsObjects) {
|
||||||
|
std::copy(other.m_RamData, other.m_RamData + m_Size, m_RamData);
|
||||||
|
} else {
|
||||||
|
std::memcpy(m_RamData, other.m_RamData, m_Size * sizeof(T));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
if (other.m_VramData) {
|
if (other.m_VramData) {
|
||||||
@@ -112,6 +132,7 @@ public:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
std::cout << "DataAllocator AssigmentOp: otherPtr=" << other.m_RamData << " thisPtr=" << m_RamData << " size=" << m_Size << " own=" << m_OwnsObjects << std::endl;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +173,8 @@ public:
|
|||||||
if (m_Size == size)
|
if (m_Size == size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
std::cout << "DataAllocator Resize: from=" << m_Size << " to=" << size << " ptr=" << m_RamData << " own=" << m_OwnsObjects << std::endl;
|
||||||
|
|
||||||
T *newRam = nullptr;
|
T *newRam = nullptr;
|
||||||
T *newVram = nullptr;
|
T *newVram = nullptr;
|
||||||
|
|
||||||
@@ -162,7 +185,11 @@ public:
|
|||||||
newRam = static_cast<T *>(::operator new(size * sizeof(T)));
|
newRam = static_cast<T *>(::operator new(size * sizeof(T)));
|
||||||
|
|
||||||
if (m_RamData) {
|
if (m_RamData) {
|
||||||
std::memcpy(newRam, m_RamData, std::min(m_Size, size) * sizeof(T));
|
if (m_OwnsObjects) {
|
||||||
|
std::copy(m_RamData, m_RamData + std::min(m_Size, size), newRam);
|
||||||
|
} else {
|
||||||
|
std::memcpy(newRam, m_RamData, std::min(m_Size, size) * sizeof(T));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_CUDA
|
#ifdef USE_CUDA
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string m_InstanceName;
|
std::string m_InstanceName;
|
||||||
Vector<Signal> sigv;
|
std::vector<Signal> sigv;
|
||||||
Vector<Slot> slov;
|
std::vector<Slot> slov;
|
||||||
std::vector<PropertyBase*> m_Properties;
|
std::vector<PropertyBase*> m_Properties;
|
||||||
std::vector<PropertyBase*> m_DynamicProperties;
|
std::vector<PropertyBase*> m_DynamicProperties;
|
||||||
bool m_SignalsBlocked;
|
bool m_SignalsBlocked;
|
||||||
@@ -117,15 +117,30 @@ template void Object::serialize(Archive::log_archive &, const unsigned int);
|
|||||||
|
|
||||||
Object::Object() : d(new ObjectPrivate) {
|
Object::Object() : d(new ObjectPrivate) {
|
||||||
d->m_SignalsBlocked = false;
|
d->m_SignalsBlocked = false;
|
||||||
|
std::cout << "Object Constructor: created d=" << d << std::endl;
|
||||||
}
|
}
|
||||||
Object::Object(const Object ©) : d(new ObjectPrivate) {
|
Object::Object(const Object ©) : d(new ObjectPrivate) {
|
||||||
if (copy.d) {
|
if (copy.d) {
|
||||||
d->m_InstanceName = copy.d->m_InstanceName;
|
d->m_InstanceName = copy.d->m_InstanceName;
|
||||||
d->m_SignalsBlocked = copy.d->m_SignalsBlocked;
|
d->m_SignalsBlocked = copy.d->m_SignalsBlocked;
|
||||||
}
|
}
|
||||||
|
std::cout << "Object CopyConstructor: created d=" << d << " from copy.d=" << copy.d << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object& Object::operator=(const Object &other) {
|
||||||
|
// Intentionally does NOT share 'd'. Each Object owns its own ObjectPrivate.
|
||||||
|
// Without this, the compiler-generated operator= would copy the 'd' pointer,
|
||||||
|
// causing two objects to share the same ObjectPrivate. When both are
|
||||||
|
// destroyed, 'd' would be deleted twice, corrupting the heap.
|
||||||
|
if (this != &other && other.d) {
|
||||||
|
d->m_InstanceName = other.d->m_InstanceName;
|
||||||
|
d->m_SignalsBlocked = other.d->m_SignalsBlocked;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::~Object() {
|
Object::~Object() {
|
||||||
|
std::cout << "Object Destructor: deleting d=" << d << " name=" << d->m_InstanceName << std::endl;
|
||||||
for (auto* p : d->m_DynamicProperties) {
|
for (auto* p : d->m_DynamicProperties) {
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
@@ -135,6 +150,7 @@ Object::~Object() {
|
|||||||
void Object::DeepCopy(const Object ©) {
|
void Object::DeepCopy(const Object ©) {
|
||||||
if (this == ©) return;
|
if (this == ©) return;
|
||||||
if (copy.d) d->m_InstanceName = copy.d->m_InstanceName;
|
if (copy.d) d->m_InstanceName = copy.d->m_InstanceName;
|
||||||
|
std::cout << "Object DeepCopy: from d=" << copy.d << " to d=" << d << std::endl;
|
||||||
// Note: signals, slots and properties are intentionally not copied
|
// Note: signals, slots and properties are intentionally not copied
|
||||||
// to maintain instance uniquely and avoid duplicate registrations.
|
// to maintain instance uniquely and avoid duplicate registrations.
|
||||||
this->Updated();
|
this->Updated();
|
||||||
@@ -161,9 +177,8 @@ void Object::LoadConfig(std::istream &is, int version) {
|
|||||||
|
|
||||||
void Object::PrintSelf(std::ostream &o) const {
|
void Object::PrintSelf(std::ostream &o) const {
|
||||||
o << "OBJECT signals: ------------------\n";
|
o << "OBJECT signals: ------------------\n";
|
||||||
Vector<ObjectPrivate::Signal>::Iterator itr;
|
for (const auto& sig : d->sigv) {
|
||||||
for (itr = d->sigv.begin(); itr < d->sigv.end(); itr++) {
|
o << " signal:[ " << sig.sigstr << " ]\n";
|
||||||
o << " signal:[ " << itr->sigstr << " ]\n";
|
|
||||||
}
|
}
|
||||||
o << "--------------------------------------\n\n";
|
o << "--------------------------------------\n\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
|
|
||||||
Object();
|
Object();
|
||||||
Object(const Object ©);
|
Object(const Object ©);
|
||||||
~Object();
|
virtual ~Object();
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "Object"; }
|
virtual const char * GetClassName() const { return "Object"; }
|
||||||
|
|
||||||
@@ -227,10 +227,7 @@ public:
|
|||||||
|
|
||||||
void PrintSelf(std::ostream &o) const;
|
void PrintSelf(std::ostream &o) const;
|
||||||
|
|
||||||
inline const Object &operator=(const Object ©) {
|
Object &operator=(const Object &other);
|
||||||
this->DeepCopy(copy);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool addSignalImpl(SignalBase *sig, GenericMFPtr fptr, const char *name);
|
bool addSignalImpl(SignalBase *sig, GenericMFPtr fptr, const char *name);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "Core/Monitor.h"
|
#include "Core/Monitor.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|||||||
@@ -85,10 +85,11 @@ public:
|
|||||||
* @param copy The ContainerBox instance to copy from.
|
* @param copy The ContainerBox instance to copy from.
|
||||||
*/
|
*/
|
||||||
ContainerBox(const ContainerBox ©)
|
ContainerBox(const ContainerBox ©)
|
||||||
: m_LocalT(this), // BaseClass is Parent of m_LocalTransform
|
: m_LocalT(copy.m_LocalT), // Copy local transform state
|
||||||
AffineTransform(copy),
|
AffineTransform(copy),
|
||||||
p_Size(this, "Size", copy.p_Size),
|
p_Size(this, "Size", copy.p_Size),
|
||||||
p_Origin(this, "Origin", copy.p_Origin) {
|
p_Origin(this, "Origin", copy.p_Origin) {
|
||||||
|
m_LocalT.SetParent(this); // Reset parent to the new object
|
||||||
Object::connect(&p_Size, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncSize);
|
Object::connect(&p_Size, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncSize);
|
||||||
Object::connect(&p_Origin, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncOrigin);
|
Object::connect(&p_Origin, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncOrigin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,20 @@ public:
|
|||||||
|
|
||||||
VoxImage(const Vector3i &size);
|
VoxImage(const Vector3i &size);
|
||||||
|
|
||||||
VoxImage(const VoxImage<T> ©) : BaseClass(copy) {
|
// Use compiler-generated copy constructor and assignment operator
|
||||||
this->m_Data = copy.m_Data;
|
|
||||||
|
VoxImage<T>& operator=(const VoxImage<T>& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
// Copy the base class non-virtual parts (dims, spacing, position, etc.)
|
||||||
|
// WITHOUT going through the virtual SetDims chain (which would call
|
||||||
|
// m_Data.resize() THEN DataAllocator::operator= will resize again → double-free).
|
||||||
|
// Instead, directly copy DataAllocator and update the StructuredGrid state.
|
||||||
|
this->m_Data = other.m_Data;
|
||||||
|
StructuredGrid::SetDims(other.GetDims());
|
||||||
|
this->SetSpacing(other.GetSpacing());
|
||||||
|
this->SetPosition(other.GetPosition());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DataAllocator<T> &Data() { return this->m_Data; }
|
inline DataAllocator<T> &Data() { return this->m_Data; }
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ int main()
|
|||||||
|
|
||||||
// Test 1: Basic identity transformation and cylinder parameters
|
// Test 1: Basic identity transformation and cylinder parameters
|
||||||
{
|
{
|
||||||
Cylinder cyl(2.0, 10.0);
|
Cylinder cyl(2.0, 10.0, 2);
|
||||||
std::cout << "Cyl R=" << cyl.GetRadius() << " H=" << cyl.GetHeight() << std::endl;
|
std::cout << "Cyl R=" << cyl.GetRadius() << " H=" << cyl.GetHeight() << std::endl;
|
||||||
std::cout << "Cyl World Matrix:\n" << cyl.GetWorldMatrix() << std::endl;
|
std::cout << "Cyl World Matrix:\n" << cyl.GetWorldMatrix() << std::endl;
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ int main()
|
|||||||
|
|
||||||
// Test 2: Translation
|
// Test 2: Translation
|
||||||
{
|
{
|
||||||
Cylinder cyl(1.0, 2.0);
|
Cylinder cyl(1.0, 2.0, 2);
|
||||||
cyl.SetPosition(Vector3f(10, 20, 30));
|
cyl.SetPosition(Vector3f(10, 20, 30));
|
||||||
|
|
||||||
// Local base origin (0, 0, 0) -> World (10, 20, 30)
|
// Local base origin (0, 0, 0) -> World (10, 20, 30)
|
||||||
@@ -96,7 +96,7 @@ int main()
|
|||||||
|
|
||||||
// Test 3: Rotation and complex mapping
|
// Test 3: Rotation and complex mapping
|
||||||
{
|
{
|
||||||
Cylinder cyl(5.0, 20.0);
|
Cylinder cyl(5.0, 20.0, 2);
|
||||||
cyl.SetPosition(Vector3f(1.0, 2.0, 3.0));
|
cyl.SetPosition(Vector3f(1.0, 2.0, 3.0));
|
||||||
// Rotate 90 degrees around X: Local Y becomes World Z, Local Z becomes World -Y
|
// Rotate 90 degrees around X: Local Y becomes World Z, Local Z becomes World -Y
|
||||||
cyl.Rotate(M_PI/2.0, Vector3f(1, 0, 0));
|
cyl.Rotate(M_PI/2.0, Vector3f(1, 0, 0));
|
||||||
|
|||||||
@@ -47,18 +47,25 @@
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct ContainerBoxData {
|
||||||
|
vtkActor *m_Cube;
|
||||||
|
vtkActor *m_Axes;
|
||||||
|
|
||||||
|
ContainerBoxData() : m_Cube(vtkActor::New()), m_Axes(vtkActor::New()) {}
|
||||||
|
~ContainerBoxData() {
|
||||||
|
m_Cube->Delete();
|
||||||
|
m_Axes->Delete();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
vtkContainerBox::vtkContainerBox(vtkContainerBox::Content *content)
|
vtkContainerBox::vtkContainerBox(vtkContainerBox::Content *content)
|
||||||
: m_Cube(vtkActor::New()), m_Axes(vtkActor::New()),
|
: d(new ContainerBoxData()), m_Content(content) {
|
||||||
// m_Pivot(vtkActor::New()),
|
|
||||||
m_Content(content) {
|
|
||||||
this->InstallPipe();
|
this->InstallPipe();
|
||||||
Object::connect(m_Content, &Content::Updated, this, &vtkContainerBox::contentUpdate);
|
Object::connect(m_Content, &Content::Updated, this, &vtkContainerBox::contentUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkContainerBox::~vtkContainerBox() {
|
vtkContainerBox::~vtkContainerBox() {
|
||||||
m_Cube->Delete();
|
delete d;
|
||||||
m_Axes->Delete();
|
|
||||||
// m_Pivot->Delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkPolyData *vtkContainerBox::GetPolyData() const {
|
vtkPolyData *vtkContainerBox::GetPolyData() const {
|
||||||
@@ -83,8 +90,8 @@ void vtkContainerBox::contentUpdate() {
|
|||||||
vmat = mat;
|
vmat = mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Cube->SetUserMatrix(nullptr);
|
d->m_Cube->SetUserMatrix(nullptr);
|
||||||
m_Axes->SetUserMatrix(nullptr);
|
d->m_Axes->SetUserMatrix(nullptr);
|
||||||
|
|
||||||
Matrix4f transform = m_Content->GetMatrix();
|
Matrix4f transform = m_Content->GetMatrix();
|
||||||
Matrix4fToVtk(transform, vmat);
|
Matrix4fToVtk(transform, vmat);
|
||||||
@@ -143,9 +150,9 @@ void vtkContainerBox::InstallPipe() {
|
|||||||
cube->SetBounds(0, 1, 0, 1, 0, 1);
|
cube->SetBounds(0, 1, 0, 1, 0, 1);
|
||||||
mapper->SetInputConnection(cube->GetOutputPort());
|
mapper->SetInputConnection(cube->GetOutputPort());
|
||||||
mapper->Update();
|
mapper->Update();
|
||||||
m_Cube->SetMapper(mapper);
|
d->m_Cube->SetMapper(mapper);
|
||||||
m_Cube->GetProperty()->SetRepresentationToWireframe();
|
d->m_Cube->GetProperty()->SetRepresentationToWireframe();
|
||||||
m_Cube->GetProperty()->SetAmbient(0.7);
|
d->m_Cube->GetProperty()->SetAmbient(0.7);
|
||||||
|
|
||||||
// AXES //
|
// AXES //
|
||||||
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
|
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
|
||||||
@@ -153,10 +160,10 @@ void vtkContainerBox::InstallPipe() {
|
|||||||
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||||
mapper->SetInputConnection(axes->GetOutputPort());
|
mapper->SetInputConnection(axes->GetOutputPort());
|
||||||
mapper->Update();
|
mapper->Update();
|
||||||
m_Axes->SetMapper(mapper);
|
d->m_Axes->SetMapper(mapper);
|
||||||
m_Axes->GetProperty()->SetLineWidth(3);
|
d->m_Axes->GetProperty()->SetLineWidth(3);
|
||||||
m_Axes->GetProperty()->SetAmbient(0.4);
|
d->m_Axes->GetProperty()->SetAmbient(0.4);
|
||||||
m_Axes->GetProperty()->SetSpecular(0);
|
d->m_Axes->GetProperty()->SetSpecular(0);
|
||||||
|
|
||||||
// PIVOT //
|
// PIVOT //
|
||||||
axes = vtkSmartPointer<vtkAxes>::New();
|
axes = vtkSmartPointer<vtkAxes>::New();
|
||||||
@@ -165,8 +172,8 @@ void vtkContainerBox::InstallPipe() {
|
|||||||
mapper->SetInputConnection(axes->GetOutputPort());
|
mapper->SetInputConnection(axes->GetOutputPort());
|
||||||
mapper->Update();
|
mapper->Update();
|
||||||
|
|
||||||
this->SetProp(m_Cube);
|
this->SetProp(d->m_Cube);
|
||||||
this->SetProp(m_Axes);
|
this->SetProp(d->m_Axes);
|
||||||
|
|
||||||
vtkProp3D* root = vtkProp3D::SafeDownCast(this->GetProp());
|
vtkProp3D* root = vtkProp3D::SafeDownCast(this->GetProp());
|
||||||
if (root) {
|
if (root) {
|
||||||
|
|||||||
@@ -29,12 +29,15 @@
|
|||||||
#include "Math/ContainerBox.h"
|
#include "Math/ContainerBox.h"
|
||||||
#include "uLibVtkInterface.h"
|
#include "uLibVtkInterface.h"
|
||||||
#include "vtkPolydata.h"
|
#include "vtkPolydata.h"
|
||||||
#include <vtkActor.h>
|
|
||||||
#include <boost/signals2/connection.hpp>
|
#include <boost/signals2/connection.hpp>
|
||||||
|
|
||||||
|
class vtkActor;
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct ContainerBoxData;
|
||||||
|
|
||||||
class vtkContainerBox : public Puppet, public Polydata {
|
class vtkContainerBox : public Puppet, public Polydata {
|
||||||
typedef ContainerBox Content;
|
typedef ContainerBox Content;
|
||||||
|
|
||||||
@@ -51,13 +54,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void InstallPipe();
|
virtual void InstallPipe();
|
||||||
|
|
||||||
vtkActor *m_Cube;
|
struct ContainerBoxData *d;
|
||||||
vtkActor *m_Axes;
|
Content *m_Content;
|
||||||
// vtkActor *m_Pivot;
|
bool m_BlockUpdate = false;
|
||||||
|
|
||||||
Content *m_Content;
|
|
||||||
bool m_BlockUpdate = false;
|
|
||||||
// boost::signals2::connection m_Connection;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
|
|||||||
@@ -67,25 +67,33 @@ vtkStandardNewMacro(vtkInteractorStyleNoSpin);
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct ViewerData {
|
||||||
|
vtkRenderWindow *m_RenderWindow;
|
||||||
|
vtkSmartPointer<vtkButtonWidget> m_GridButton;
|
||||||
|
|
||||||
|
ViewerData() : m_RenderWindow(vtkRenderWindow::New()) {}
|
||||||
|
~ViewerData() { m_RenderWindow->Delete(); }
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
///// VTK VIEWER //////////////////////////////////////////////////////////////
|
///// VTK VIEWER //////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Viewer::Viewer()
|
Viewer::Viewer()
|
||||||
: Viewport(), m_RenderWindow(vtkRenderWindow::New()) {
|
: Viewport(), d(new ViewerData()) {
|
||||||
InstallPipe();
|
InstallPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
Viewer::~Viewer() {
|
Viewer::~Viewer() {
|
||||||
UninstallPipe();
|
UninstallPipe();
|
||||||
m_RenderWindow->Delete();
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::InstallPipe() {
|
void Viewer::InstallPipe() {
|
||||||
m_RenderWindow->AddRenderer(m_Renderer);
|
d->m_RenderWindow->AddRenderer(this->GetRenderer());
|
||||||
m_RenderWindow->SetSize(600,600);
|
d->m_RenderWindow->SetSize(600,600);
|
||||||
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
|
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
|
||||||
vtkSmartPointer<vtkRenderWindowInteractor>::New();
|
vtkSmartPointer<vtkRenderWindowInteractor>::New();
|
||||||
renderWindowInteractor->SetRenderWindow(m_RenderWindow);
|
renderWindowInteractor->SetRenderWindow(d->m_RenderWindow);
|
||||||
|
|
||||||
// Common setup
|
// Common setup
|
||||||
Viewport::SetupPipeline(renderWindowInteractor);
|
Viewport::SetupPipeline(renderWindowInteractor);
|
||||||
@@ -99,21 +107,21 @@ void Viewer::InstallPipe() {
|
|||||||
renderWindowInteractor->SetInteractorStyle(style);
|
renderWindowInteractor->SetInteractorStyle(style);
|
||||||
|
|
||||||
// Must be rendered here in Vtk-6.0 or seg-fault //
|
// Must be rendered here in Vtk-6.0 or seg-fault //
|
||||||
m_RenderWindow->Render();
|
d->m_RenderWindow->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::UninstallPipe() {
|
void Viewer::UninstallPipe() {
|
||||||
if (m_Renderer) {
|
if (GetRenderer()) {
|
||||||
m_Renderer->RemoveAllViewProps();
|
GetRenderer()->RemoveAllViewProps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::Render() {
|
void Viewer::Render() {
|
||||||
if (m_RenderWindow)
|
if (d->m_RenderWindow)
|
||||||
m_RenderWindow->Render();
|
d->m_RenderWindow->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkSmartPointer<vtkCameraOrientationWidget>
|
vtkCameraOrientationWidget *
|
||||||
Viewer::MakeCameraOrientationWidget(vtkRenderWindowInteractor *interactor,
|
Viewer::MakeCameraOrientationWidget(vtkRenderWindowInteractor *interactor,
|
||||||
vtkRenderer *renderer) {
|
vtkRenderer *renderer) {
|
||||||
vtkSmartPointer<vtkCameraOrientationWidget> widget =
|
vtkSmartPointer<vtkCameraOrientationWidget> widget =
|
||||||
@@ -125,7 +133,7 @@ Viewer::MakeCameraOrientationWidget(vtkRenderWindowInteractor *interactor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::SetupGridButton() {
|
void Viewer::SetupGridButton() {
|
||||||
if (!m_RenderWindow || !m_RenderWindow->GetInteractor()) return;
|
if (!d->m_RenderWindow || !d->m_RenderWindow->GetInteractor()) return;
|
||||||
|
|
||||||
// Create procedural textures for the button using canvas
|
// Create procedural textures for the button using canvas
|
||||||
vtkNew<vtkImageCanvasSource2D> canvas;
|
vtkNew<vtkImageCanvasSource2D> canvas;
|
||||||
@@ -158,9 +166,9 @@ void Viewer::SetupGridButton() {
|
|||||||
rep->SetButtonTexture(0, imgOff);
|
rep->SetButtonTexture(0, imgOff);
|
||||||
rep->SetButtonTexture(1, imgOn);
|
rep->SetButtonTexture(1, imgOn);
|
||||||
|
|
||||||
m_GridButton = vtkSmartPointer<vtkButtonWidget>::New();
|
d->m_GridButton = vtkSmartPointer<vtkButtonWidget>::New();
|
||||||
m_GridButton->SetInteractor(m_RenderWindow->GetInteractor());
|
d->m_GridButton->SetInteractor(d->m_RenderWindow->GetInteractor());
|
||||||
m_GridButton->SetRepresentation(rep);
|
d->m_GridButton->SetRepresentation(rep);
|
||||||
|
|
||||||
// Position it initially
|
// Position it initially
|
||||||
UpdateGridButtonPosition();
|
UpdateGridButtonPosition();
|
||||||
@@ -172,7 +180,7 @@ void Viewer::SetupGridButton() {
|
|||||||
auto* v = static_cast<Viewer*>(clientdata);
|
auto* v = static_cast<Viewer*>(clientdata);
|
||||||
v->UpdateGridButtonPosition();
|
v->UpdateGridButtonPosition();
|
||||||
});
|
});
|
||||||
m_RenderWindow->AddObserver(vtkCommand::ModifiedEvent, resizeCallback);
|
d->m_RenderWindow->AddObserver(vtkCommand::ModifiedEvent, resizeCallback);
|
||||||
|
|
||||||
// Callback for state change
|
// Callback for state change
|
||||||
vtkNew<vtkCallbackCommand> stateCallback;
|
vtkNew<vtkCallbackCommand> stateCallback;
|
||||||
@@ -184,19 +192,19 @@ void Viewer::SetupGridButton() {
|
|||||||
v->SetGridVisible(r->GetState() == 1);
|
v->SetGridVisible(r->GetState() == 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_GridButton->AddObserver(vtkCommand::StateChangedEvent, stateCallback);
|
d->m_GridButton->AddObserver(vtkCommand::StateChangedEvent, stateCallback);
|
||||||
m_GridButton->On();
|
d->m_GridButton->On();
|
||||||
|
|
||||||
// Set initial state
|
// Set initial state
|
||||||
rep->SetState(GetGridVisible() ? 1 : 0);
|
rep->SetState(GetGridVisible() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::UpdateGridButtonPosition() {
|
void Viewer::UpdateGridButtonPosition() {
|
||||||
if (!m_GridButton || !m_RenderWindow) return;
|
if (!d->m_GridButton || !d->m_RenderWindow) return;
|
||||||
auto* rep = vtkTexturedButtonRepresentation2D::SafeDownCast(m_GridButton->GetRepresentation());
|
auto* rep = vtkTexturedButtonRepresentation2D::SafeDownCast(d->m_GridButton->GetRepresentation());
|
||||||
if (!rep) return;
|
if (!rep) return;
|
||||||
|
|
||||||
int *sz = m_RenderWindow->GetSize();
|
int *sz = d->m_RenderWindow->GetSize();
|
||||||
if (sz[0] == 0 || sz[1] == 0) return; // Window not yet sized or hidden
|
if (sz[0] == 0 || sz[1] == 0) return; // Window not yet sized or hidden
|
||||||
|
|
||||||
int margin_rigth = 23;
|
int margin_rigth = 23;
|
||||||
@@ -207,12 +215,12 @@ void Viewer::UpdateGridButtonPosition() {
|
|||||||
rep->PlaceWidget(bds);
|
rep->PlaceWidget(bds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewer::Start() { m_RenderWindow->GetInteractor()->Start(); }
|
void Viewer::Start() { d->m_RenderWindow->GetInteractor()->Start(); }
|
||||||
|
|
||||||
vtkRenderWindow *Viewer::GetRenderWindow() { return m_RenderWindow; }
|
vtkRenderWindow *Viewer::GetRenderWindow() { return d->m_RenderWindow; }
|
||||||
|
|
||||||
vtkRenderWindowInteractor *Viewer::GetInteractor() {
|
vtkRenderWindowInteractor *Viewer::GetInteractor() {
|
||||||
return m_RenderWindow->GetInteractor();
|
return d->m_RenderWindow->GetInteractor();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
|
|||||||
@@ -1,44 +1,17 @@
|
|||||||
/*//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 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 >
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 3.0 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
#ifndef ULIBVTKVIEWER_H
|
#ifndef ULIBVTKVIEWER_H
|
||||||
#define ULIBVTKVIEWER_H
|
#define ULIBVTKVIEWER_H
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "vtkViewport.h"
|
#include "vtkViewport.h"
|
||||||
|
|
||||||
|
class vtkRenderWindow;
|
||||||
|
class vtkRenderWindowInteractor;
|
||||||
|
class vtkRenderer;
|
||||||
|
class vtkCameraOrientationWidget;
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
// template <class T> class Tie {
|
struct ViewerData;
|
||||||
// public:
|
|
||||||
// void DoAction() {
|
|
||||||
// std::cout << "Tie::DoAction -> generic Tie does nothing\n";
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
class Viewer : public Viewport {
|
class Viewer : public Viewport {
|
||||||
|
|
||||||
@@ -49,9 +22,9 @@ public:
|
|||||||
// Render scene
|
// Render scene
|
||||||
virtual void Render() override;
|
virtual void Render() override;
|
||||||
|
|
||||||
static vtkSmartPointer<vtkCameraOrientationWidget>
|
static vtkCameraOrientationWidget *
|
||||||
MakeCameraOrientationWidget(vtkRenderWindowInteractor *interactor,
|
MakeCameraOrientationWidget(vtkRenderWindowInteractor *interactor,
|
||||||
vtkRenderer *renderer);
|
vtkRenderer *renderer);
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
|
|
||||||
@@ -65,15 +38,9 @@ private:
|
|||||||
void SetupGridButton();
|
void SetupGridButton();
|
||||||
void UpdateGridButtonPosition();
|
void UpdateGridButtonPosition();
|
||||||
|
|
||||||
vtkRenderWindow *m_RenderWindow;
|
struct ViewerData *d;
|
||||||
vtkSmartPointer<class vtkButtonWidget> m_GridButton;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// template <> class Tie<Viewer> {
|
|
||||||
// public:
|
|
||||||
// void DoAction() { std::cout << " VIEWER TIE !!! \n"; }
|
|
||||||
// };
|
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "vtkHandlerWidget.h"
|
#include "vtkHandlerWidget.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <vtkActor.h>
|
||||||
#include <vtkArcSource.h>
|
#include <vtkArcSource.h>
|
||||||
#include <vtkArrowSource.h>
|
#include <vtkArrowSource.h>
|
||||||
#include <vtkCallbackCommand.h>
|
#include <vtkCallbackCommand.h>
|
||||||
@@ -51,32 +52,60 @@
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct HandlerWidgetData {
|
||||||
|
vtkSmartPointer<::vtkRenderer> m_OverlayRenderer;
|
||||||
|
::vtkProp *m_HighlightedProp;
|
||||||
|
|
||||||
|
// Visual components //
|
||||||
|
vtkSmartPointer<::vtkActor> m_AxesX, m_AxesY, m_AxesZ; // Arrows
|
||||||
|
vtkSmartPointer<::vtkActor> m_RotX, m_RotY, m_RotZ; // Rings
|
||||||
|
vtkSmartPointer<::vtkActor> m_RotCam; // Camera ring
|
||||||
|
vtkSmartPointer<::vtkActor> m_ScaleX, m_ScaleY, m_ScaleZ; // Cubes
|
||||||
|
|
||||||
|
vtkSmartPointer<::vtkPlane> m_ClipPlane;
|
||||||
|
|
||||||
|
vtkSmartPointer<::vtkCellPicker> m_Picker;
|
||||||
|
vtkSmartPointer<::vtkTransform> m_InitialTransform;
|
||||||
|
|
||||||
|
std::vector<vtkSmartPointer<::vtkTransform>> m_TransformChain;
|
||||||
|
vtkSmartPointer<::vtkMatrix4x4> m_BaseMatrix;
|
||||||
|
|
||||||
|
HandlerWidgetData() {
|
||||||
|
m_Picker = vtkSmartPointer<::vtkCellPicker>::New();
|
||||||
|
m_InitialTransform = vtkSmartPointer<::vtkTransform>::New();
|
||||||
|
m_ClipPlane = vtkSmartPointer<::vtkPlane>::New();
|
||||||
|
m_OverlayRenderer = vtkSmartPointer<::vtkRenderer>::New();
|
||||||
|
m_BaseMatrix = vtkSmartPointer<::vtkMatrix4x4>::New();
|
||||||
|
m_HighlightedProp = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
vtkStandardNewMacro(vtkHandlerWidget);
|
vtkStandardNewMacro(vtkHandlerWidget);
|
||||||
|
|
||||||
vtkHandlerWidget::vtkHandlerWidget() {
|
vtkHandlerWidget::vtkHandlerWidget() : d(new HandlerWidgetData()) {
|
||||||
this->Interaction = IDLE;
|
this->Interaction = IDLE;
|
||||||
this->m_Picker = vtkSmartPointer<::vtkCellPicker>::New();
|
d->m_Picker->SetTolerance(0.01); // Increased tolerance for thin gizmos
|
||||||
this->m_Picker->SetTolerance(0.01); // Increased tolerance for thin gizmos
|
|
||||||
this->m_InitialTransform = vtkSmartPointer<::vtkTransform>::New();
|
|
||||||
this->EventCallbackCommand->SetCallback(vtkHandlerWidget::ProcessEvents);
|
this->EventCallbackCommand->SetCallback(vtkHandlerWidget::ProcessEvents);
|
||||||
this->EventCallbackCommand->SetClientData(this);
|
this->EventCallbackCommand->SetClientData(this);
|
||||||
this->m_Frame = LOCAL;
|
this->m_Frame = LOCAL;
|
||||||
this->m_HighlightedProp = nullptr;
|
d->m_OverlayRenderer->SetLayer(1);
|
||||||
this->m_ClipPlane = vtkSmartPointer<::vtkPlane>::New();
|
d->m_OverlayRenderer->EraseOff();
|
||||||
this->m_OverlayRenderer = vtkSmartPointer<::vtkRenderer>::New();
|
d->m_OverlayRenderer->InteractiveOff();
|
||||||
this->m_OverlayRenderer->SetLayer(1);
|
|
||||||
this->m_OverlayRenderer->EraseOff();
|
|
||||||
this->m_OverlayRenderer->InteractiveOff();
|
|
||||||
this->Priority = 50.0; // Higher priority to beat camera style
|
this->Priority = 50.0; // Higher priority to beat camera style
|
||||||
this->m_TranslationEnabled = true;
|
this->m_TranslationEnabled = true;
|
||||||
this->m_RotationEnabled = true;
|
this->m_RotationEnabled = true;
|
||||||
this->m_ScalingEnabled = true;
|
this->m_ScalingEnabled = true;
|
||||||
this->m_BaseMatrix = vtkSmartPointer<::vtkMatrix4x4>::New();
|
d->m_BaseMatrix->Identity();
|
||||||
this->m_BaseMatrix->Identity();
|
|
||||||
this->CreateGizmos();
|
this->CreateGizmos();
|
||||||
}
|
}
|
||||||
|
|
||||||
vtkHandlerWidget::~vtkHandlerWidget() {}
|
vtkHandlerWidget::~vtkHandlerWidget() {
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
::vtkRenderer *vtkHandlerWidget::GetOverlayRenderer() {
|
||||||
|
return d->m_OverlayRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
void vtkHandlerWidget::SetProp3D(::vtkProp3D *prop) {
|
void vtkHandlerWidget::SetProp3D(::vtkProp3D *prop) {
|
||||||
if (this->Prop3D == prop) {
|
if (this->Prop3D == prop) {
|
||||||
@@ -84,13 +113,13 @@ void vtkHandlerWidget::SetProp3D(::vtkProp3D *prop) {
|
|||||||
}
|
}
|
||||||
this->Prop3D = prop;
|
this->Prop3D = prop;
|
||||||
if (this->Prop3D) {
|
if (this->Prop3D) {
|
||||||
// Initialize m_BaseMatrix from the object's current matrix
|
// Initialize d->m_BaseMatrix from the object's current matrix
|
||||||
if (this->Prop3D->GetUserMatrix()) {
|
if (this->Prop3D->GetUserMatrix()) {
|
||||||
this->m_BaseMatrix->DeepCopy(this->Prop3D->GetUserMatrix());
|
this->d->m_BaseMatrix->DeepCopy(this->Prop3D->GetUserMatrix());
|
||||||
} else {
|
} else {
|
||||||
this->m_BaseMatrix->Identity();
|
this->d->m_BaseMatrix->Identity();
|
||||||
}
|
}
|
||||||
this->m_TransformChain.clear(); // Clear any previous transform chain
|
this->d->m_TransformChain.clear(); // Clear any previous transform chain
|
||||||
this->UpdateGizmoPosition();
|
this->UpdateGizmoPosition();
|
||||||
}
|
}
|
||||||
this->Modified();
|
this->Modified();
|
||||||
@@ -141,20 +170,20 @@ void vtkHandlerWidget::SetEnabled(int enabling) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sync Viewport and Camera
|
// Sync Viewport and Camera
|
||||||
this->m_OverlayRenderer->SetViewport(this->CurrentRenderer->GetViewport());
|
this->d->m_OverlayRenderer->SetViewport(this->CurrentRenderer->GetViewport());
|
||||||
this->m_OverlayRenderer->SetActiveCamera(this->CurrentRenderer->GetActiveCamera());
|
this->d->m_OverlayRenderer->SetActiveCamera(this->CurrentRenderer->GetActiveCamera());
|
||||||
win->AddRenderer(this->m_OverlayRenderer);
|
win->AddRenderer(this->d->m_OverlayRenderer);
|
||||||
|
|
||||||
this->m_OverlayRenderer->AddActor(m_AxesX);
|
this->d->m_OverlayRenderer->AddActor(d->m_AxesX);
|
||||||
this->m_OverlayRenderer->AddActor(m_AxesY);
|
this->d->m_OverlayRenderer->AddActor(d->m_AxesY);
|
||||||
this->m_OverlayRenderer->AddActor(m_AxesZ);
|
this->d->m_OverlayRenderer->AddActor(d->m_AxesZ);
|
||||||
this->m_OverlayRenderer->AddActor(m_RotX);
|
this->d->m_OverlayRenderer->AddActor(d->m_RotX);
|
||||||
this->m_OverlayRenderer->AddActor(m_RotY);
|
this->d->m_OverlayRenderer->AddActor(d->m_RotY);
|
||||||
this->m_OverlayRenderer->AddActor(m_RotZ);
|
this->d->m_OverlayRenderer->AddActor(d->m_RotZ);
|
||||||
this->m_OverlayRenderer->AddActor(m_RotCam);
|
this->d->m_OverlayRenderer->AddActor(d->m_RotCam);
|
||||||
this->m_OverlayRenderer->AddActor(m_ScaleX);
|
this->d->m_OverlayRenderer->AddActor(d->m_ScaleX);
|
||||||
this->m_OverlayRenderer->AddActor(m_ScaleY);
|
this->d->m_OverlayRenderer->AddActor(d->m_ScaleY);
|
||||||
this->m_OverlayRenderer->AddActor(m_ScaleZ);
|
this->d->m_OverlayRenderer->AddActor(d->m_ScaleZ);
|
||||||
|
|
||||||
this->UpdateVisibility();
|
this->UpdateVisibility();
|
||||||
|
|
||||||
@@ -167,9 +196,9 @@ void vtkHandlerWidget::SetEnabled(int enabling) {
|
|||||||
this->Highlight(nullptr);
|
this->Highlight(nullptr);
|
||||||
this->Interactor->RemoveObserver(this->EventCallbackCommand);
|
this->Interactor->RemoveObserver(this->EventCallbackCommand);
|
||||||
if (this->Interactor->GetRenderWindow()) {
|
if (this->Interactor->GetRenderWindow()) {
|
||||||
this->Interactor->GetRenderWindow()->RemoveRenderer(this->m_OverlayRenderer);
|
this->Interactor->GetRenderWindow()->RemoveRenderer(this->d->m_OverlayRenderer);
|
||||||
}
|
}
|
||||||
this->m_OverlayRenderer->RemoveAllViewProps();
|
this->d->m_OverlayRenderer->RemoveAllViewProps();
|
||||||
this->InvokeEvent(::vtkCommand::DisableEvent, nullptr);
|
this->InvokeEvent(::vtkCommand::DisableEvent, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,15 +243,15 @@ void vtkHandlerWidget::OnKeyPress() {
|
|||||||
bool ctrl = (this->Interactor->GetControlKey() != 0);
|
bool ctrl = (this->Interactor->GetControlKey() != 0);
|
||||||
|
|
||||||
if (ctrl && key == "z") {
|
if (ctrl && key == "z") {
|
||||||
if (!this->m_TransformChain.empty()) {
|
if (!this->d->m_TransformChain.empty()) {
|
||||||
std::cout << "Undoing last transform action..." << std::endl;
|
std::cout << "Undoing last transform action..." << std::endl;
|
||||||
this->m_TransformChain.pop_back();
|
this->d->m_TransformChain.pop_back();
|
||||||
|
|
||||||
// Update object from chain
|
// Update object from chain
|
||||||
vtkNew<vtkTransform> total;
|
vtkNew<vtkTransform> total;
|
||||||
total->PostMultiply();
|
total->PostMultiply();
|
||||||
total->SetMatrix(this->m_BaseMatrix.GetPointer());
|
total->SetMatrix(this->d->m_BaseMatrix.GetPointer());
|
||||||
for (auto& t : m_TransformChain) {
|
for (auto& t : d->m_TransformChain) {
|
||||||
total->Concatenate(t);
|
total->Concatenate(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,33 +274,33 @@ void vtkHandlerWidget::OnLeftButtonDown() {
|
|||||||
this->CurrentRenderer = this->Interactor->FindPokedRenderer(X, Y);
|
this->CurrentRenderer = this->Interactor->FindPokedRenderer(X, Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_Picker->Pick(X, Y, 0.0, this->m_OverlayRenderer);
|
this->d->m_Picker->Pick(X, Y, 0.0, this->d->m_OverlayRenderer);
|
||||||
::vtkProp *prop = this->m_Picker->GetViewProp();
|
::vtkProp *prop = this->d->m_Picker->GetViewProp();
|
||||||
this->m_Picker->GetPickPosition(this->m_StartPickPosition);
|
this->d->m_Picker->GetPickPosition(this->m_StartPickPosition);
|
||||||
|
|
||||||
if (!prop)
|
if (!prop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this->Interaction = IDLE;
|
this->Interaction = IDLE;
|
||||||
if (prop == m_AxesX)
|
if (prop == d->m_AxesX)
|
||||||
this->Interaction = TRANS_X;
|
this->Interaction = TRANS_X;
|
||||||
else if (prop == m_AxesY)
|
else if (prop == d->m_AxesY)
|
||||||
this->Interaction = TRANS_Y;
|
this->Interaction = TRANS_Y;
|
||||||
else if (prop == m_AxesZ)
|
else if (prop == d->m_AxesZ)
|
||||||
this->Interaction = TRANS_Z;
|
this->Interaction = TRANS_Z;
|
||||||
else if (prop == m_RotX)
|
else if (prop == d->m_RotX)
|
||||||
this->Interaction = ROT_X;
|
this->Interaction = ROT_X;
|
||||||
else if (prop == m_RotY)
|
else if (prop == d->m_RotY)
|
||||||
this->Interaction = ROT_Y;
|
this->Interaction = ROT_Y;
|
||||||
else if (prop == m_RotZ)
|
else if (prop == d->m_RotZ)
|
||||||
this->Interaction = ROT_Z;
|
this->Interaction = ROT_Z;
|
||||||
else if (prop == m_ScaleX)
|
else if (prop == d->m_ScaleX)
|
||||||
this->Interaction = SCALE_X;
|
this->Interaction = SCALE_X;
|
||||||
else if (prop == m_ScaleY)
|
else if (prop == d->m_ScaleY)
|
||||||
this->Interaction = SCALE_Y;
|
this->Interaction = SCALE_Y;
|
||||||
else if (prop == m_ScaleZ)
|
else if (prop == d->m_ScaleZ)
|
||||||
this->Interaction = SCALE_Z;
|
this->Interaction = SCALE_Z;
|
||||||
else if (prop == m_RotCam)
|
else if (prop == d->m_RotCam)
|
||||||
this->Interaction = ROT_CAM;
|
this->Interaction = ROT_CAM;
|
||||||
|
|
||||||
if (this->Interaction != IDLE) {
|
if (this->Interaction != IDLE) {
|
||||||
@@ -285,14 +314,14 @@ void vtkHandlerWidget::OnLeftButtonDown() {
|
|||||||
|
|
||||||
// If the chain is empty, initialize base from current state?
|
// If the chain is empty, initialize base from current state?
|
||||||
// Actually, if we just started selecting this object, we should have initialized BaseMatrix.
|
// Actually, if we just started selecting this object, we should have initialized BaseMatrix.
|
||||||
// For now, let's keep m_InitialTransform as the state BEFORE this drag
|
// For now, let's keep d->m_InitialTransform as the state BEFORE this drag
|
||||||
vtkNew<vtkTransform> current;
|
vtkNew<vtkTransform> current;
|
||||||
current->PostMultiply();
|
current->PostMultiply();
|
||||||
current->SetMatrix(this->m_BaseMatrix.GetPointer());
|
current->SetMatrix(this->d->m_BaseMatrix.GetPointer());
|
||||||
for (auto& t : m_TransformChain) {
|
for (auto& t : d->m_TransformChain) {
|
||||||
current->Concatenate(t);
|
current->Concatenate(t);
|
||||||
}
|
}
|
||||||
this->m_InitialTransform->SetMatrix(current->GetMatrix());
|
this->d->m_InitialTransform->SetMatrix(current->GetMatrix());
|
||||||
}
|
}
|
||||||
this->EventCallbackCommand->SetAbortFlag(1);
|
this->EventCallbackCommand->SetAbortFlag(1);
|
||||||
this->InvokeEvent(::vtkCommand::StartInteractionEvent, nullptr);
|
this->InvokeEvent(::vtkCommand::StartInteractionEvent, nullptr);
|
||||||
@@ -310,10 +339,10 @@ void vtkHandlerWidget::OnLeftButtonUp() {
|
|||||||
|
|
||||||
// We need to re-calculate the final 'op' to store it
|
// We need to re-calculate the final 'op' to store it
|
||||||
// Actually, we could have stored it in OnMouseMove, but let's re-calculate or
|
// Actually, we could have stored it in OnMouseMove, but let's re-calculate or
|
||||||
// just capture the delta between m_InitialTransform and current UserMatrix.
|
// just capture the delta between d->m_InitialTransform and current UserMatrix.
|
||||||
if (this->Prop3D && this->Prop3D->GetUserMatrix()) {
|
if (this->Prop3D && this->Prop3D->GetUserMatrix()) {
|
||||||
vtkNew<vtkMatrix4x4> inv;
|
vtkNew<vtkMatrix4x4> inv;
|
||||||
vtkMatrix4x4::Invert(this->m_InitialTransform->GetMatrix(), inv);
|
vtkMatrix4x4::Invert(this->d->m_InitialTransform->GetMatrix(), inv);
|
||||||
|
|
||||||
vtkNew<vtkMatrix4x4> final_op_mat;
|
vtkNew<vtkMatrix4x4> final_op_mat;
|
||||||
vtkMatrix4x4::Multiply4x4(this->Prop3D->GetUserMatrix(), inv, final_op_mat);
|
vtkMatrix4x4::Multiply4x4(this->Prop3D->GetUserMatrix(), inv, final_op_mat);
|
||||||
@@ -321,8 +350,8 @@ void vtkHandlerWidget::OnLeftButtonUp() {
|
|||||||
vtkNew<vtkTransform> final_op;
|
vtkNew<vtkTransform> final_op;
|
||||||
final_op->SetMatrix(final_op_mat);
|
final_op->SetMatrix(final_op_mat);
|
||||||
|
|
||||||
this->m_TransformChain.push_back(final_op);
|
this->d->m_TransformChain.push_back(final_op);
|
||||||
std::cout << "Action finalized. Chain size: " << this->m_TransformChain.size() << std::endl;
|
std::cout << "Action finalized. Chain size: " << this->d->m_TransformChain.size() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->Interaction = IDLE;
|
this->Interaction = IDLE;
|
||||||
@@ -339,8 +368,8 @@ void vtkHandlerWidget::OnMouseMove() {
|
|||||||
int Y = this->Interactor->GetEventPosition()[1];
|
int Y = this->Interactor->GetEventPosition()[1];
|
||||||
|
|
||||||
if (this->Interaction == IDLE) {
|
if (this->Interaction == IDLE) {
|
||||||
this->m_Picker->Pick(X, Y, 0.0, this->m_OverlayRenderer);
|
this->d->m_Picker->Pick(X, Y, 0.0, this->d->m_OverlayRenderer);
|
||||||
::vtkProp *prop = this->m_Picker->GetViewProp();
|
::vtkProp *prop = this->d->m_Picker->GetViewProp();
|
||||||
this->Highlight(prop);
|
this->Highlight(prop);
|
||||||
this->UpdateGizmoPosition(); // Ensure camera adjustments happen
|
this->UpdateGizmoPosition(); // Ensure camera adjustments happen
|
||||||
return;
|
return;
|
||||||
@@ -353,7 +382,7 @@ void vtkHandlerWidget::OnMouseMove() {
|
|||||||
// std::cout << "Interaction " << this->Interaction << " dx=" << dx << " dy=" << dy << std::endl;
|
// std::cout << "Interaction " << this->Interaction << " dx=" << dx << " dy=" << dy << std::endl;
|
||||||
|
|
||||||
// Get current gizmo properties from its actors
|
// Get current gizmo properties from its actors
|
||||||
vtkMatrix4x4 *gizmo_mat = m_AxesX->GetUserMatrix();
|
vtkMatrix4x4 *gizmo_mat = d->m_AxesX->GetUserMatrix();
|
||||||
if (!gizmo_mat)
|
if (!gizmo_mat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -542,7 +571,7 @@ void vtkHandlerWidget::OnMouseMove() {
|
|||||||
// Total transform = Base * Chain * Interaction
|
// Total transform = Base * Chain * Interaction
|
||||||
vtkNew<vtkTransform> total;
|
vtkNew<vtkTransform> total;
|
||||||
total->PostMultiply();
|
total->PostMultiply();
|
||||||
total->SetMatrix(this->m_InitialTransform->GetMatrix()); // m_InitialTransform is already Base*Chain
|
total->SetMatrix(this->d->m_InitialTransform->GetMatrix()); // d->m_InitialTransform is already Base*Chain
|
||||||
total->Concatenate(op);
|
total->Concatenate(op);
|
||||||
|
|
||||||
vtkMatrix4x4* targetMat = this->Prop3D->GetUserMatrix();
|
vtkMatrix4x4* targetMat = this->Prop3D->GetUserMatrix();
|
||||||
@@ -588,41 +617,41 @@ void vtkHandlerWidget::SetScalingEnabled(bool enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vtkHandlerWidget::UpdateVisibility() {
|
void vtkHandlerWidget::UpdateVisibility() {
|
||||||
if (!m_AxesX) return;
|
if (!d->m_AxesX) return;
|
||||||
|
|
||||||
m_AxesX->SetVisibility(m_TranslationEnabled);
|
d->m_AxesX->SetVisibility(m_TranslationEnabled);
|
||||||
m_AxesY->SetVisibility(m_TranslationEnabled);
|
d->m_AxesY->SetVisibility(m_TranslationEnabled);
|
||||||
m_AxesZ->SetVisibility(m_TranslationEnabled);
|
d->m_AxesZ->SetVisibility(m_TranslationEnabled);
|
||||||
|
|
||||||
m_RotX->SetVisibility(m_RotationEnabled);
|
d->m_RotX->SetVisibility(m_RotationEnabled);
|
||||||
m_RotY->SetVisibility(m_RotationEnabled);
|
d->m_RotY->SetVisibility(m_RotationEnabled);
|
||||||
m_RotZ->SetVisibility(m_RotationEnabled);
|
d->m_RotZ->SetVisibility(m_RotationEnabled);
|
||||||
m_RotCam->SetVisibility(m_RotationEnabled);
|
d->m_RotCam->SetVisibility(m_RotationEnabled);
|
||||||
|
|
||||||
m_ScaleX->SetVisibility(m_ScalingEnabled);
|
d->m_ScaleX->SetVisibility(m_ScalingEnabled);
|
||||||
m_ScaleY->SetVisibility(m_ScalingEnabled);
|
d->m_ScaleY->SetVisibility(m_ScalingEnabled);
|
||||||
m_ScaleZ->SetVisibility(m_ScalingEnabled);
|
d->m_ScaleZ->SetVisibility(m_ScalingEnabled);
|
||||||
|
|
||||||
// Update picker list
|
// Update picker list
|
||||||
if (m_Picker) {
|
if (d->m_Picker) {
|
||||||
m_Picker->InitializePickList();
|
d->m_Picker->InitializePickList();
|
||||||
if (m_TranslationEnabled) {
|
if (m_TranslationEnabled) {
|
||||||
m_Picker->AddPickList(m_AxesX);
|
d->m_Picker->AddPickList(d->m_AxesX);
|
||||||
m_Picker->AddPickList(m_AxesY);
|
d->m_Picker->AddPickList(d->m_AxesY);
|
||||||
m_Picker->AddPickList(m_AxesZ);
|
d->m_Picker->AddPickList(d->m_AxesZ);
|
||||||
}
|
}
|
||||||
if (m_RotationEnabled) {
|
if (m_RotationEnabled) {
|
||||||
m_Picker->AddPickList(m_RotX);
|
d->m_Picker->AddPickList(d->m_RotX);
|
||||||
m_Picker->AddPickList(m_RotY);
|
d->m_Picker->AddPickList(d->m_RotY);
|
||||||
m_Picker->AddPickList(m_RotZ);
|
d->m_Picker->AddPickList(d->m_RotZ);
|
||||||
m_Picker->AddPickList(m_RotCam);
|
d->m_Picker->AddPickList(d->m_RotCam);
|
||||||
}
|
}
|
||||||
if (m_ScalingEnabled) {
|
if (m_ScalingEnabled) {
|
||||||
m_Picker->AddPickList(m_ScaleX);
|
d->m_Picker->AddPickList(d->m_ScaleX);
|
||||||
m_Picker->AddPickList(m_ScaleY);
|
d->m_Picker->AddPickList(d->m_ScaleY);
|
||||||
m_Picker->AddPickList(m_ScaleZ);
|
d->m_Picker->AddPickList(d->m_ScaleZ);
|
||||||
}
|
}
|
||||||
m_Picker->PickFromListOn();
|
d->m_Picker->PickFromListOn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +705,7 @@ void vtkHandlerWidget::CreateGizmos() {
|
|||||||
|
|
||||||
auto mapper = vtkSmartPointer<::vtkPolyDataMapper>::New();
|
auto mapper = vtkSmartPointer<::vtkPolyDataMapper>::New();
|
||||||
mapper->SetInputConnection(circle->GetOutputPort());
|
mapper->SetInputConnection(circle->GetOutputPort());
|
||||||
mapper->AddClippingPlane(this->m_ClipPlane);
|
mapper->AddClippingPlane(this->d->m_ClipPlane);
|
||||||
|
|
||||||
auto actor = vtkSmartPointer<::vtkActor>::New();
|
auto actor = vtkSmartPointer<::vtkActor>::New();
|
||||||
actor->SetMapper(mapper);
|
actor->SetMapper(mapper);
|
||||||
@@ -690,15 +719,15 @@ void vtkHandlerWidget::CreateGizmos() {
|
|||||||
blue[] = {0.0, 0.0, 1.0}, white[] = {1.0, 1.0, 1.0};
|
blue[] = {0.0, 0.0, 1.0}, white[] = {1.0, 1.0, 1.0};
|
||||||
|
|
||||||
double x[] = {1, 0, 0}, y[] = {0, 1, 0}, z[] = {0, 0, 1};
|
double x[] = {1, 0, 0}, y[] = {0, 1, 0}, z[] = {0, 0, 1};
|
||||||
m_AxesX = create_arrow(x, red);
|
d->m_AxesX = create_arrow(x, red);
|
||||||
m_AxesY = create_arrow(y, green);
|
d->m_AxesY = create_arrow(y, green);
|
||||||
m_AxesZ = create_arrow(z, blue);
|
d->m_AxesZ = create_arrow(z, blue);
|
||||||
|
|
||||||
m_RotX = create_ring(0, red);
|
d->m_RotX = create_ring(0, red);
|
||||||
m_RotY = create_ring(1, green);
|
d->m_RotY = create_ring(1, green);
|
||||||
m_RotZ = create_ring(2, blue);
|
d->m_RotZ = create_ring(2, blue);
|
||||||
|
|
||||||
m_RotCam = vtkSmartPointer<::vtkActor>::New();
|
d->m_RotCam = vtkSmartPointer<::vtkActor>::New();
|
||||||
{
|
{
|
||||||
auto circle = vtkSmartPointer<::vtkRegularPolygonSource>::New();
|
auto circle = vtkSmartPointer<::vtkRegularPolygonSource>::New();
|
||||||
circle->SetNumberOfSides(64);
|
circle->SetNumberOfSides(64);
|
||||||
@@ -708,10 +737,10 @@ void vtkHandlerWidget::CreateGizmos() {
|
|||||||
circle->GeneratePolylineOn();
|
circle->GeneratePolylineOn();
|
||||||
auto mapper = vtkSmartPointer<::vtkPolyDataMapper>::New();
|
auto mapper = vtkSmartPointer<::vtkPolyDataMapper>::New();
|
||||||
mapper->SetInputConnection(circle->GetOutputPort());
|
mapper->SetInputConnection(circle->GetOutputPort());
|
||||||
m_RotCam->SetMapper(mapper);
|
d->m_RotCam->SetMapper(mapper);
|
||||||
m_RotCam->GetProperty()->SetColor(white);
|
d->m_RotCam->GetProperty()->SetColor(white);
|
||||||
m_RotCam->GetProperty()->SetLineWidth(2);
|
d->m_RotCam->GetProperty()->SetLineWidth(2);
|
||||||
m_RotCam->GetProperty()->SetLighting(0);
|
d->m_RotCam->GetProperty()->SetLighting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto create_cube = [](double pos[3], double color[3]) {
|
auto create_cube = [](double pos[3], double color[3]) {
|
||||||
@@ -730,23 +759,23 @@ void vtkHandlerWidget::CreateGizmos() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
double px[] = {1.2, 0, 0}, py[] = {0, 1.2, 0}, pz[] = {0, 0, 1.2};
|
double px[] = {1.2, 0, 0}, py[] = {0, 1.2, 0}, pz[] = {0, 0, 1.2};
|
||||||
m_ScaleX = create_cube(px, red);
|
d->m_ScaleX = create_cube(px, red);
|
||||||
m_ScaleY = create_cube(py, green);
|
d->m_ScaleY = create_cube(py, green);
|
||||||
m_ScaleZ = create_cube(pz, blue);
|
d->m_ScaleZ = create_cube(pz, blue);
|
||||||
|
|
||||||
// Configure picker to only see gizmo actors (Pick-Through)
|
// Configure picker to only see gizmo actors (Pick-Through)
|
||||||
m_Picker->InitializePickList();
|
d->m_Picker->InitializePickList();
|
||||||
m_Picker->AddPickList(m_AxesX);
|
d->m_Picker->AddPickList(d->m_AxesX);
|
||||||
m_Picker->AddPickList(m_AxesY);
|
d->m_Picker->AddPickList(d->m_AxesY);
|
||||||
m_Picker->AddPickList(m_AxesZ);
|
d->m_Picker->AddPickList(d->m_AxesZ);
|
||||||
m_Picker->AddPickList(m_RotX);
|
d->m_Picker->AddPickList(d->m_RotX);
|
||||||
m_Picker->AddPickList(m_RotY);
|
d->m_Picker->AddPickList(d->m_RotY);
|
||||||
m_Picker->AddPickList(m_RotZ);
|
d->m_Picker->AddPickList(d->m_RotZ);
|
||||||
m_Picker->AddPickList(m_RotCam);
|
d->m_Picker->AddPickList(d->m_RotCam);
|
||||||
m_Picker->AddPickList(m_ScaleX);
|
d->m_Picker->AddPickList(d->m_ScaleX);
|
||||||
m_Picker->AddPickList(m_ScaleY);
|
d->m_Picker->AddPickList(d->m_ScaleY);
|
||||||
m_Picker->AddPickList(m_ScaleZ);
|
d->m_Picker->AddPickList(d->m_ScaleZ);
|
||||||
m_Picker->PickFromListOn();
|
d->m_Picker->PickFromListOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkHandlerWidget::UpdateGizmoPosition() {
|
void vtkHandlerWidget::UpdateGizmoPosition() {
|
||||||
@@ -843,24 +872,24 @@ void vtkHandlerWidget::UpdateGizmoPosition() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_AxesX->SetUserMatrix(mat_gizmo);
|
d->m_AxesX->SetUserMatrix(mat_gizmo);
|
||||||
m_AxesY->SetUserMatrix(mat_gizmo);
|
d->m_AxesY->SetUserMatrix(mat_gizmo);
|
||||||
m_AxesZ->SetUserMatrix(mat_gizmo);
|
d->m_AxesZ->SetUserMatrix(mat_gizmo);
|
||||||
m_RotX->SetUserMatrix(mat_gizmo);
|
d->m_RotX->SetUserMatrix(mat_gizmo);
|
||||||
m_RotY->SetUserMatrix(mat_gizmo);
|
d->m_RotY->SetUserMatrix(mat_gizmo);
|
||||||
m_RotZ->SetUserMatrix(mat_gizmo);
|
d->m_RotZ->SetUserMatrix(mat_gizmo);
|
||||||
m_ScaleX->SetUserMatrix(mat_gizmo);
|
d->m_ScaleX->SetUserMatrix(mat_gizmo);
|
||||||
m_ScaleY->SetUserMatrix(mat_gizmo);
|
d->m_ScaleY->SetUserMatrix(mat_gizmo);
|
||||||
m_ScaleZ->SetUserMatrix(mat_gizmo);
|
d->m_ScaleZ->SetUserMatrix(mat_gizmo);
|
||||||
|
|
||||||
// Sync Overlay Renderer with Main Renderer
|
// Sync Overlay Renderer with Main Renderer
|
||||||
if (this->CurrentRenderer && this->m_OverlayRenderer) {
|
if (this->CurrentRenderer && this->d->m_OverlayRenderer) {
|
||||||
this->m_OverlayRenderer->SetViewport(this->CurrentRenderer->GetViewport());
|
this->d->m_OverlayRenderer->SetViewport(this->CurrentRenderer->GetViewport());
|
||||||
this->m_OverlayRenderer->SetAspect(this->CurrentRenderer->GetAspect());
|
this->d->m_OverlayRenderer->SetAspect(this->CurrentRenderer->GetAspect());
|
||||||
this->m_OverlayRenderer->ComputeAspect();
|
this->d->m_OverlayRenderer->ComputeAspect();
|
||||||
|
|
||||||
if (this->m_OverlayRenderer->GetActiveCamera() != this->CurrentRenderer->GetActiveCamera()) {
|
if (this->d->m_OverlayRenderer->GetActiveCamera() != this->CurrentRenderer->GetActiveCamera()) {
|
||||||
this->m_OverlayRenderer->SetActiveCamera(this->CurrentRenderer->GetActiveCamera());
|
this->d->m_OverlayRenderer->SetActiveCamera(this->CurrentRenderer->GetActiveCamera());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -890,36 +919,36 @@ void vtkHandlerWidget::UpdateGizmoPosition() {
|
|||||||
}
|
}
|
||||||
tcam->Translate(mat_gizmo->GetElement(0, 3), mat_gizmo->GetElement(1, 3),
|
tcam->Translate(mat_gizmo->GetElement(0, 3), mat_gizmo->GetElement(1, 3),
|
||||||
mat_gizmo->GetElement(2, 3));
|
mat_gizmo->GetElement(2, 3));
|
||||||
m_RotCam->SetUserMatrix(tcam->GetMatrix());
|
d->m_RotCam->SetUserMatrix(tcam->GetMatrix());
|
||||||
|
|
||||||
// Update clipping plane for axes rings
|
// Update clipping plane for axes rings
|
||||||
this->m_ClipPlane->SetOrigin(mat_gizmo->GetElement(0, 3),
|
this->d->m_ClipPlane->SetOrigin(mat_gizmo->GetElement(0, 3),
|
||||||
mat_gizmo->GetElement(1, 3),
|
mat_gizmo->GetElement(1, 3),
|
||||||
mat_gizmo->GetElement(2, 3));
|
mat_gizmo->GetElement(2, 3));
|
||||||
this->m_ClipPlane->SetNormal(dir);
|
this->d->m_ClipPlane->SetNormal(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vtkHandlerWidget::Highlight(::vtkProp *prop) {
|
void vtkHandlerWidget::Highlight(::vtkProp *prop) {
|
||||||
if (this->m_HighlightedProp == prop)
|
if (this->d->m_HighlightedProp == prop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Restore previous
|
// Restore previous
|
||||||
if (this->m_HighlightedProp) {
|
if (this->d->m_HighlightedProp) {
|
||||||
::vtkActor *actor = ::vtkActor::SafeDownCast(this->m_HighlightedProp);
|
::vtkActor *actor = ::vtkActor::SafeDownCast(this->d->m_HighlightedProp);
|
||||||
if (actor) {
|
if (actor) {
|
||||||
actor->GetProperty()->SetColor(m_OriginalColor);
|
actor->GetProperty()->SetColor(m_OriginalColor);
|
||||||
actor->GetProperty()->SetLineWidth(3);
|
actor->GetProperty()->SetLineWidth(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_HighlightedProp = nullptr;
|
this->d->m_HighlightedProp = nullptr;
|
||||||
|
|
||||||
// Highlight new if it belongs to us
|
// Highlight new if it belongs to us
|
||||||
if (prop == m_AxesX || prop == m_AxesY || prop == m_AxesZ || prop == m_RotX ||
|
if (prop == d->m_AxesX || prop == d->m_AxesY || prop == d->m_AxesZ || prop == d->m_RotX ||
|
||||||
prop == m_RotY || prop == m_RotZ || prop == m_RotCam || prop == m_ScaleX ||
|
prop == d->m_RotY || prop == d->m_RotZ || prop == d->m_RotCam || prop == d->m_ScaleX ||
|
||||||
prop == m_ScaleY || prop == m_ScaleZ) {
|
prop == d->m_ScaleY || prop == d->m_ScaleZ) {
|
||||||
this->m_HighlightedProp = prop;
|
this->d->m_HighlightedProp = prop;
|
||||||
::vtkActor *actor = ::vtkActor::SafeDownCast(prop);
|
::vtkActor *actor = ::vtkActor::SafeDownCast(prop);
|
||||||
if (actor) {
|
if (actor) {
|
||||||
actor->GetProperty()->GetColor(m_OriginalColor);
|
actor->GetProperty()->GetColor(m_OriginalColor);
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ public:
|
|||||||
void SetReferenceFrame(ReferenceFrame frame);
|
void SetReferenceFrame(ReferenceFrame frame);
|
||||||
ReferenceFrame GetReferenceFrame() const { return this->m_Frame; }
|
ReferenceFrame GetReferenceFrame() const { return this->m_Frame; }
|
||||||
|
|
||||||
|
struct HandlerWidgetData *d;
|
||||||
|
|
||||||
using ::vtk3DWidget::PlaceWidget;
|
using ::vtk3DWidget::PlaceWidget;
|
||||||
virtual void PlaceWidget(double bounds[6]) override;
|
virtual void PlaceWidget(double bounds[6]) override;
|
||||||
virtual void PlaceWidget() override;
|
virtual void PlaceWidget() override;
|
||||||
@@ -101,7 +103,7 @@ public:
|
|||||||
void SetTransform(::vtkTransform *t);
|
void SetTransform(::vtkTransform *t);
|
||||||
void GetTransform(::vtkTransform *t);
|
void GetTransform(::vtkTransform *t);
|
||||||
|
|
||||||
::vtkRenderer *GetOverlayRenderer() { return this->m_OverlayRenderer; }
|
::vtkRenderer *GetOverlayRenderer();
|
||||||
|
|
||||||
void SetTranslationEnabled(bool enabled);
|
void SetTranslationEnabled(bool enabled);
|
||||||
bool GetTranslationEnabled() const { return m_TranslationEnabled; }
|
bool GetTranslationEnabled() const { return m_TranslationEnabled; }
|
||||||
@@ -116,32 +118,16 @@ protected:
|
|||||||
void Highlight(::vtkProp *prop);
|
void Highlight(::vtkProp *prop);
|
||||||
void UpdateVisibility();
|
void UpdateVisibility();
|
||||||
|
|
||||||
vtkSmartPointer<::vtkRenderer> m_OverlayRenderer;
|
|
||||||
ReferenceFrame m_Frame;
|
ReferenceFrame m_Frame;
|
||||||
bool m_TranslationEnabled;
|
bool m_TranslationEnabled;
|
||||||
bool m_RotationEnabled;
|
bool m_RotationEnabled;
|
||||||
bool m_ScalingEnabled;
|
bool m_ScalingEnabled;
|
||||||
|
|
||||||
int Interaction;
|
int Interaction;
|
||||||
::vtkProp *m_HighlightedProp;
|
|
||||||
double m_OriginalColor[3];
|
double m_OriginalColor[3];
|
||||||
|
|
||||||
// Visual components //
|
|
||||||
vtkSmartPointer<::vtkActor> m_AxesX, m_AxesY, m_AxesZ; // Arrows
|
|
||||||
vtkSmartPointer<::vtkActor> m_RotX, m_RotY, m_RotZ; // Rings
|
|
||||||
vtkSmartPointer<::vtkActor> m_RotCam; // Camera ring
|
|
||||||
vtkSmartPointer<::vtkActor> m_ScaleX, m_ScaleY, m_ScaleZ; // Cubes
|
|
||||||
|
|
||||||
vtkSmartPointer<::vtkPlane> m_ClipPlane;
|
|
||||||
|
|
||||||
vtkSmartPointer<::vtkCellPicker> m_Picker;
|
|
||||||
|
|
||||||
double StartEventPosition[2];
|
double StartEventPosition[2];
|
||||||
double m_StartPickPosition[3];
|
double m_StartPickPosition[3];
|
||||||
vtkSmartPointer<::vtkTransform> m_InitialTransform;
|
|
||||||
|
|
||||||
std::vector<vtkSmartPointer<::vtkTransform>> m_TransformChain;
|
|
||||||
vtkSmartPointer<::vtkMatrix4x4> m_BaseMatrix;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void SetProp3D(::vtkProp3D *prop) override;
|
virtual void SetProp3D(::vtkProp3D *prop) override;
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ QViewport::~QViewport()
|
|||||||
void QViewport::SetupPipeline()
|
void QViewport::SetupPipeline()
|
||||||
{
|
{
|
||||||
// Add our renderer to the QVTKOpenGLNativeWidget's render window
|
// Add our renderer to the QVTKOpenGLNativeWidget's render window
|
||||||
vtkRenderWindow* rw = m_VtkWidget->renderWindow();
|
::vtkRenderWindow* rw = m_VtkWidget->renderWindow();
|
||||||
rw->AddRenderer(m_Renderer);
|
rw->AddRenderer(this->GetRenderer());
|
||||||
|
|
||||||
// Common setup
|
// Common setup
|
||||||
Viewport::SetupPipeline(rw->GetInteractor());
|
Viewport::SetupPipeline(rw->GetInteractor());
|
||||||
|
|||||||
@@ -8,13 +8,20 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vtkInteractorStyleTrackballCamera.h>
|
#include <vtkInteractorStyleTrackballCamera.h>
|
||||||
#include <vtkObjectFactory.h>
|
#include <vtkObjectFactory.h>
|
||||||
|
#include <vtkAxesActor.h>
|
||||||
|
#include <vtkRenderer.h>
|
||||||
#include <vtkRenderWindow.h>
|
#include <vtkRenderWindow.h>
|
||||||
#include <vtkRenderWindowInteractor.h>
|
#include <vtkRenderWindowInteractor.h>
|
||||||
#include <vtkNew.h>
|
#include <vtkCornerAnnotation.h>
|
||||||
|
#include <vtkOrientationMarkerWidget.h>
|
||||||
|
#include <vtkCameraOrientationWidget.h>
|
||||||
|
#include <vtkPlaneSource.h>
|
||||||
|
#include <vtkActor.h>
|
||||||
|
#include <vtkAxes.h>
|
||||||
|
#include <vtkNamedColors.h>
|
||||||
|
#include <vtkCellPicker.h>
|
||||||
#include <vtkTextProperty.h>
|
#include <vtkTextProperty.h>
|
||||||
|
|
||||||
#include <vtkPolyDataMapper.h>
|
#include <vtkPolyDataMapper.h>
|
||||||
|
|
||||||
#include <vtkProperty.h>
|
#include <vtkProperty.h>
|
||||||
#include <vtkCallbackCommand.h>
|
#include <vtkCallbackCommand.h>
|
||||||
#include <vtkMath.h>
|
#include <vtkMath.h>
|
||||||
@@ -25,23 +32,50 @@
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct ViewportData {
|
||||||
|
vtkSmartPointer<vtkRenderer> m_Renderer;
|
||||||
|
vtkSmartPointer<vtkCornerAnnotation> m_Annotation;
|
||||||
|
vtkSmartPointer<vtkOrientationMarkerWidget> m_Marker;
|
||||||
|
vtkSmartPointer<vtkCameraOrientationWidget> m_CameraWidget;
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkPlaneSource> m_GridSource;
|
||||||
|
vtkSmartPointer<vtkActor> m_GridActor;
|
||||||
|
vtkSmartPointer<vtkAxes> m_OriginAxes;
|
||||||
|
vtkSmartPointer<vtkActor> m_OriginAxesActor;
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkNamedColors> m_Colors;
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkHandlerWidget> m_HandlerWidget;
|
||||||
|
vtkSmartPointer<vtkCellPicker> m_Picker;
|
||||||
|
vtkSmartPointer<vtkCallbackCommand> m_KeyCallback;
|
||||||
|
|
||||||
|
ViewportData()
|
||||||
|
: m_Renderer(vtkSmartPointer<vtkRenderer>::New())
|
||||||
|
, m_Annotation(vtkSmartPointer<vtkCornerAnnotation>::New())
|
||||||
|
, m_Marker(vtkSmartPointer<vtkOrientationMarkerWidget>::New())
|
||||||
|
, m_CameraWidget(nullptr)
|
||||||
|
, m_Colors(vtkSmartPointer<vtkNamedColors>::New())
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
Viewport::Viewport()
|
Viewport::Viewport()
|
||||||
: m_Renderer(vtkSmartPointer<vtkRenderer>::New())
|
: d(new ViewportData())
|
||||||
, m_Annotation(vtkSmartPointer<vtkCornerAnnotation>::New())
|
|
||||||
, m_Marker(vtkSmartPointer<vtkOrientationMarkerWidget>::New())
|
|
||||||
, m_CameraWidget(nullptr)
|
|
||||||
, m_Colors(vtkSmartPointer<vtkNamedColors>::New())
|
|
||||||
, m_GridAxis(Y)
|
, m_GridAxis(Y)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Viewport::~Viewport()
|
Viewport::~Viewport()
|
||||||
{
|
{
|
||||||
if (m_Renderer) {
|
if (d->m_Renderer) {
|
||||||
m_Renderer->RemoveAllViewProps();
|
d->m_Renderer->RemoveAllViewProps();
|
||||||
}
|
}
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vtkRenderer* Viewport::GetRenderer() { return d->m_Renderer; }
|
||||||
|
vtkCornerAnnotation* Viewport::GetAnnotation() { return d->m_Annotation; }
|
||||||
|
vtkCameraOrientationWidget* Viewport::GetCameraWidget() { return d->m_CameraWidget; }
|
||||||
|
|
||||||
void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
||||||
{
|
{
|
||||||
if (!iren) return;
|
if (!iren) return;
|
||||||
@@ -51,49 +85,49 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
iren->SetInteractorStyle(style);
|
iren->SetInteractorStyle(style);
|
||||||
|
|
||||||
// Corner annotation
|
// Corner annotation
|
||||||
m_Annotation->GetTextProperty()->SetColor(1, 1, 1);
|
d->m_Annotation->GetTextProperty()->SetColor(1, 1, 1);
|
||||||
m_Annotation->GetTextProperty()->SetFontFamilyToArial();
|
d->m_Annotation->GetTextProperty()->SetFontFamilyToArial();
|
||||||
m_Annotation->GetTextProperty()->SetOpacity(0.5);
|
d->m_Annotation->GetTextProperty()->SetOpacity(0.5);
|
||||||
m_Annotation->SetMaximumFontSize(10);
|
d->m_Annotation->SetMaximumFontSize(10);
|
||||||
m_Annotation->SetText(0, "uLib VTK viewer.");
|
d->m_Annotation->SetText(0, "uLib VTK viewer.");
|
||||||
m_Renderer->AddViewProp(m_Annotation);
|
d->m_Renderer->AddViewProp(d->m_Annotation);
|
||||||
|
|
||||||
// right corner annotation
|
// right corner annotation
|
||||||
m_Annotation->SetText(1, "Grid: -");
|
d->m_Annotation->SetText(1, "Grid: -");
|
||||||
|
|
||||||
// Orientation axes marker (bottom-left corner)
|
// Orientation axes marker (bottom-left corner)
|
||||||
vtkNew<vtkAxesActor> axes;
|
vtkNew<vtkAxesActor> axes;
|
||||||
m_Marker->SetInteractor(iren);
|
d->m_Marker->SetInteractor(iren);
|
||||||
m_Marker->SetOrientationMarker(axes);
|
d->m_Marker->SetOrientationMarker(axes);
|
||||||
m_Marker->SetViewport(0.0, 0.0, 0.2, 0.2);
|
d->m_Marker->SetViewport(0.0, 0.0, 0.2, 0.2);
|
||||||
m_Marker->SetEnabled(true);
|
d->m_Marker->SetEnabled(true);
|
||||||
m_Marker->InteractiveOff();
|
d->m_Marker->InteractiveOff();
|
||||||
|
|
||||||
// Grid Plane centered at (0,0,0)
|
// Grid Plane centered at (0,0,0)
|
||||||
m_GridSource = vtkSmartPointer<vtkPlaneSource>::New();
|
d->m_GridSource = vtkSmartPointer<vtkPlaneSource>::New();
|
||||||
m_GridActor = vtkSmartPointer<vtkActor>::New();
|
d->m_GridActor = vtkSmartPointer<vtkActor>::New();
|
||||||
vtkNew<vtkPolyDataMapper> gridMapper;
|
vtkNew<vtkPolyDataMapper> gridMapper;
|
||||||
gridMapper->SetInputConnection(m_GridSource->GetOutputPort());
|
gridMapper->SetInputConnection(d->m_GridSource->GetOutputPort());
|
||||||
|
|
||||||
m_GridActor->SetMapper(gridMapper);
|
d->m_GridActor->SetMapper(gridMapper);
|
||||||
m_GridActor->GetProperty()->SetRepresentationToWireframe();
|
d->m_GridActor->GetProperty()->SetRepresentationToWireframe();
|
||||||
m_GridActor->GetProperty()->SetColor(0.4, 0.4, 0.4);
|
d->m_GridActor->GetProperty()->SetColor(0.4, 0.4, 0.4);
|
||||||
m_GridActor->GetProperty()->SetLighting(0);
|
d->m_GridActor->GetProperty()->SetLighting(0);
|
||||||
m_GridActor->GetProperty()->SetOpacity(0.5);
|
d->m_GridActor->GetProperty()->SetOpacity(0.5);
|
||||||
m_GridActor->PickableOff();
|
d->m_GridActor->PickableOff();
|
||||||
m_Renderer->AddActor(m_GridActor);
|
d->m_Renderer->AddActor(d->m_GridActor);
|
||||||
|
|
||||||
// Global Origin Axes
|
// Global Origin Axes
|
||||||
m_OriginAxes = vtkSmartPointer<vtkAxes>::New();
|
d->m_OriginAxes = vtkSmartPointer<vtkAxes>::New();
|
||||||
m_OriginAxes->SetScaleFactor(1.0); // will be updated
|
d->m_OriginAxes->SetScaleFactor(1.0); // will be updated
|
||||||
|
|
||||||
vtkNew<vtkPolyDataMapper> axesMapper;
|
vtkNew<vtkPolyDataMapper> axesMapper;
|
||||||
axesMapper->SetInputConnection(m_OriginAxes->GetOutputPort());
|
axesMapper->SetInputConnection(d->m_OriginAxes->GetOutputPort());
|
||||||
|
|
||||||
m_OriginAxesActor = vtkSmartPointer<vtkActor>::New();
|
d->m_OriginAxesActor = vtkSmartPointer<vtkActor>::New();
|
||||||
m_OriginAxesActor->SetMapper(axesMapper);
|
d->m_OriginAxesActor->SetMapper(axesMapper);
|
||||||
m_OriginAxesActor->PickableOff();
|
d->m_OriginAxesActor->PickableOff();
|
||||||
m_Renderer->AddActor(m_OriginAxesActor);
|
d->m_Renderer->AddActor(d->m_OriginAxesActor);
|
||||||
|
|
||||||
UpdateGrid();
|
UpdateGrid();
|
||||||
|
|
||||||
@@ -104,31 +138,31 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
static_cast<Viewport*>(clientdata)->UpdateGrid();
|
static_cast<Viewport*>(clientdata)->UpdateGrid();
|
||||||
});
|
});
|
||||||
iren->AddObserver(vtkCommand::InteractionEvent, interactionCallback);
|
iren->AddObserver(vtkCommand::InteractionEvent, interactionCallback);
|
||||||
m_Renderer->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent, interactionCallback);
|
d->m_Renderer->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent, interactionCallback);
|
||||||
|
|
||||||
|
|
||||||
// Camera-orientation widget (VTK >= 9)
|
// Camera-orientation widget (VTK >= 9)
|
||||||
#if VTK_MAJOR_VERSION >= 9
|
#if VTK_MAJOR_VERSION >= 9
|
||||||
m_CameraWidget = vtkSmartPointer<vtkCameraOrientationWidget>::New();
|
d->m_CameraWidget = vtkSmartPointer<vtkCameraOrientationWidget>::New();
|
||||||
m_CameraWidget->SetParentRenderer(m_Renderer);
|
d->m_CameraWidget->SetParentRenderer(d->m_Renderer);
|
||||||
m_CameraWidget->SetInteractor(iren);
|
d->m_CameraWidget->SetInteractor(iren);
|
||||||
m_CameraWidget->On();
|
d->m_CameraWidget->On();
|
||||||
#endif
|
#endif
|
||||||
m_Renderer->SetBackground(0.15, 0.15, 0.15);
|
d->m_Renderer->SetBackground(0.15, 0.15, 0.15);
|
||||||
m_Renderer->ResetCamera();
|
d->m_Renderer->ResetCamera();
|
||||||
|
|
||||||
// Setup layering for overimposed rendering
|
// Setup layering for overimposed rendering
|
||||||
if (iren->GetRenderWindow()) {
|
if (iren->GetRenderWindow()) {
|
||||||
iren->GetRenderWindow()->SetNumberOfLayers(2);
|
iren->GetRenderWindow()->SetNumberOfLayers(2);
|
||||||
m_Renderer->SetLayer(0);
|
d->m_Renderer->SetLayer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Handler Widget
|
// Setup Handler Widget
|
||||||
m_HandlerWidget = vtkSmartPointer<vtkHandlerWidget>::New();
|
d->m_HandlerWidget = vtkSmartPointer<vtkHandlerWidget>::New();
|
||||||
m_HandlerWidget->SetInteractor(iren);
|
d->m_HandlerWidget->SetInteractor(iren);
|
||||||
m_HandlerWidget->SetCurrentRenderer(m_Renderer);
|
d->m_HandlerWidget->SetCurrentRenderer(d->m_Renderer);
|
||||||
if (m_HandlerWidget->GetOverlayRenderer()) {
|
if (d->m_HandlerWidget->GetOverlayRenderer()) {
|
||||||
m_HandlerWidget->GetOverlayRenderer()->SetLayer(1);
|
d->m_HandlerWidget->GetOverlayRenderer()->SetLayer(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Observe InteractionEvent to update the selected puppet when the widget moves it
|
// Observe InteractionEvent to update the selected puppet when the widget moves it
|
||||||
@@ -142,10 +176,10 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_HandlerWidget->AddObserver(vtkCommand::InteractionEvent, widgetInteractionCallback);
|
d->m_HandlerWidget->AddObserver(vtkCommand::InteractionEvent, widgetInteractionCallback);
|
||||||
|
|
||||||
// Picking for selection
|
// Picking for selection
|
||||||
m_Picker = vtkSmartPointer<vtkCellPicker>::New();
|
d->m_Picker = vtkSmartPointer<vtkCellPicker>::New();
|
||||||
vtkNew<vtkCallbackCommand> clickCallback;
|
vtkNew<vtkCallbackCommand> clickCallback;
|
||||||
clickCallback->SetClientData(this);
|
clickCallback->SetClientData(this);
|
||||||
clickCallback->SetCallback([](vtkObject* caller, unsigned long, void* clientdata, void*){
|
clickCallback->SetCallback([](vtkObject* caller, unsigned long, void* clientdata, void*){
|
||||||
@@ -153,8 +187,8 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
auto* self = static_cast<Viewport*>(clientdata);
|
auto* self = static_cast<Viewport*>(clientdata);
|
||||||
|
|
||||||
int* pos = iren->GetEventPosition();
|
int* pos = iren->GetEventPosition();
|
||||||
self->m_Picker->Pick(pos[0], pos[1], 0, self->m_Renderer);
|
self->d->m_Picker->Pick(pos[0], pos[1], 0, self->d->m_Renderer);
|
||||||
vtkProp* picked = self->m_Picker->GetViewProp();
|
vtkProp* picked = self->d->m_Picker->GetViewProp();
|
||||||
|
|
||||||
Puppet* target = nullptr;
|
Puppet* target = nullptr;
|
||||||
if (picked) {
|
if (picked) {
|
||||||
@@ -190,59 +224,59 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
iren->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
|
iren->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);
|
||||||
|
|
||||||
// Keyboard events for widget coordinate frame
|
// Keyboard events for widget coordinate frame
|
||||||
m_KeyCallback = vtkSmartPointer<vtkCallbackCommand>::New();
|
d->m_KeyCallback = vtkSmartPointer<vtkCallbackCommand>::New();
|
||||||
m_KeyCallback->SetClientData(this);
|
d->m_KeyCallback->SetClientData(this);
|
||||||
m_KeyCallback->SetCallback([](vtkObject* caller, unsigned long event, void* clientdata, void*){
|
d->m_KeyCallback->SetCallback([](vtkObject* caller, unsigned long event, void* clientdata, void*){
|
||||||
auto* iren = static_cast<vtkRenderWindowInteractor*>(caller);
|
auto* iren = static_cast<vtkRenderWindowInteractor*>(caller);
|
||||||
auto* self = static_cast<Viewport*>(clientdata);
|
auto* self = static_cast<Viewport*>(clientdata);
|
||||||
|
|
||||||
std::string key = iren->GetKeySym();
|
std::string key = iren->GetKeySym();
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
if (self->m_HandlerWidget && self->m_HandlerWidget->GetEnabled()) {
|
if (self->d->m_HandlerWidget && self->d->m_HandlerWidget->GetEnabled()) {
|
||||||
if (key == "l") {
|
if (key == "l") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::LOCAL);
|
self->d->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::LOCAL);
|
||||||
std::cout << "Widget Frame: LOCAL" << std::endl;
|
std::cout << "Widget Frame: LOCAL" << std::endl;
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "g") {
|
else if (key == "g") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::GLOBAL);
|
self->d->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::GLOBAL);
|
||||||
std::cout << "Widget Frame: GLOBAL" << std::endl;
|
std::cout << "Widget Frame: GLOBAL" << std::endl;
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "c") {
|
else if (key == "c") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER);
|
self->d->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER);
|
||||||
std::cout << "Widget Frame: CENTER" << std::endl;
|
std::cout << "Widget Frame: CENTER" << std::endl;
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "k") {
|
else if (key == "k") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER_LOCAL);
|
self->d->m_HandlerWidget->SetReferenceFrame(vtkHandlerWidget::CENTER_LOCAL);
|
||||||
std::cout << "Widget Frame: CENTER_LOCAL" << std::endl;
|
std::cout << "Widget Frame: CENTER_LOCAL" << std::endl;
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "1") {
|
else if (key == "1") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetTranslationEnabled(!self->m_HandlerWidget->GetTranslationEnabled());
|
self->d->m_HandlerWidget->SetTranslationEnabled(!self->d->m_HandlerWidget->GetTranslationEnabled());
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "2") {
|
else if (key == "2") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetRotationEnabled(!self->m_HandlerWidget->GetRotationEnabled());
|
self->d->m_HandlerWidget->SetRotationEnabled(!self->d->m_HandlerWidget->GetRotationEnabled());
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
else if (key == "3") {
|
else if (key == "3") {
|
||||||
if (event == vtkCommand::KeyPressEvent) {
|
if (event == vtkCommand::KeyPressEvent) {
|
||||||
self->m_HandlerWidget->SetScalingEnabled(!self->m_HandlerWidget->GetScalingEnabled());
|
self->d->m_HandlerWidget->SetScalingEnabled(!self->d->m_HandlerWidget->GetScalingEnabled());
|
||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
@@ -256,12 +290,12 @@ void Viewport::SetupPipeline(vtkRenderWindowInteractor* iren)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (handled) {
|
if (handled) {
|
||||||
self->m_KeyCallback->SetAbortFlag(1);
|
self->d->m_KeyCallback->SetAbortFlag(1);
|
||||||
iren->Render();
|
iren->Render();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
iren->AddObserver(vtkCommand::KeyPressEvent, m_KeyCallback, 1.0);
|
iren->AddObserver(vtkCommand::KeyPressEvent, d->m_KeyCallback, 1.0);
|
||||||
iren->AddObserver(vtkCommand::CharEvent, m_KeyCallback, 1.0);
|
iren->AddObserver(vtkCommand::CharEvent, d->m_KeyCallback, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::Reset()
|
void Viewport::Reset()
|
||||||
@@ -272,15 +306,15 @@ void Viewport::Reset()
|
|||||||
|
|
||||||
void Viewport::ZoomAuto()
|
void Viewport::ZoomAuto()
|
||||||
{
|
{
|
||||||
if (m_Renderer) {
|
if (d->m_Renderer) {
|
||||||
m_Renderer->ResetCameraClippingRange();
|
d->m_Renderer->ResetCameraClippingRange();
|
||||||
m_Renderer->ResetCamera();
|
d->m_Renderer->ResetCamera();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::ZoomSelected()
|
void Viewport::ZoomSelected()
|
||||||
{
|
{
|
||||||
if (!m_Renderer) return;
|
if (!d->m_Renderer) return;
|
||||||
|
|
||||||
Puppet* selected = nullptr;
|
Puppet* selected = nullptr;
|
||||||
for (auto* p : m_Puppets) {
|
for (auto* p : m_Puppets) {
|
||||||
@@ -316,15 +350,15 @@ void Viewport::ZoomSelected()
|
|||||||
newBounds[2*i+1] = center[i] + 2.5 * current_h;
|
newBounds[2*i+1] = center[i] + 2.5 * current_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Renderer->ResetCamera(newBounds);
|
d->m_Renderer->ResetCamera(newBounds);
|
||||||
m_Renderer->ResetCameraClippingRange();
|
d->m_Renderer->ResetCameraClippingRange();
|
||||||
this->Render();
|
this->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::AddPuppet(Puppet& prop)
|
void Viewport::AddPuppet(Puppet& prop)
|
||||||
{
|
{
|
||||||
m_Puppets.push_back(&prop);
|
m_Puppets.push_back(&prop);
|
||||||
prop.ConnectRenderer(m_Renderer);
|
prop.ConnectRenderer(d->m_Renderer);
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +367,7 @@ void Viewport::RemovePuppet(Puppet& prop)
|
|||||||
if (prop.IsSelected()) SelectPuppet(nullptr);
|
if (prop.IsSelected()) SelectPuppet(nullptr);
|
||||||
auto it = std::find(m_Puppets.begin(), m_Puppets.end(), &prop);
|
auto it = std::find(m_Puppets.begin(), m_Puppets.end(), &prop);
|
||||||
if (it != m_Puppets.end()) m_Puppets.erase(it);
|
if (it != m_Puppets.end()) m_Puppets.erase(it);
|
||||||
prop.DisconnectRenderer(m_Renderer);
|
prop.DisconnectRenderer(d->m_Renderer);
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,17 +377,17 @@ void Viewport::SelectPuppet(Puppet* prop)
|
|||||||
p->SetSelected(p == prop);
|
p->SetSelected(p == prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_HandlerWidget) {
|
if (d->m_HandlerWidget) {
|
||||||
if (prop) {
|
if (prop) {
|
||||||
vtkProp3D* prop3d = vtkProp3D::SafeDownCast(prop->GetProp());
|
vtkProp3D* prop3d = vtkProp3D::SafeDownCast(prop->GetProp());
|
||||||
if (prop3d) {
|
if (prop3d) {
|
||||||
m_HandlerWidget->SetProp3D(prop3d);
|
d->m_HandlerWidget->SetProp3D(prop3d);
|
||||||
m_HandlerWidget->SetEnabled(1);
|
d->m_HandlerWidget->SetEnabled(1);
|
||||||
m_HandlerWidget->PlaceWidget(prop3d->GetBounds());
|
d->m_HandlerWidget->PlaceWidget(prop3d->GetBounds());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_HandlerWidget->SetEnabled(0);
|
d->m_HandlerWidget->SetEnabled(0);
|
||||||
m_HandlerWidget->SetProp3D(nullptr);
|
d->m_HandlerWidget->SetProp3D(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,16 +396,16 @@ void Viewport::SelectPuppet(Puppet* prop)
|
|||||||
|
|
||||||
void Viewport::SetGridVisible(bool visible)
|
void Viewport::SetGridVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (m_GridActor) {
|
if (d->m_GridActor) {
|
||||||
m_GridActor->SetVisibility(visible);
|
d->m_GridActor->SetVisibility(visible);
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Viewport::GetGridVisible() const
|
bool Viewport::GetGridVisible() const
|
||||||
{
|
{
|
||||||
if (m_GridActor) {
|
if (d->m_GridActor) {
|
||||||
return m_GridActor->GetVisibility() != 0;
|
return d->m_GridActor->GetVisibility() != 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -385,26 +419,26 @@ void Viewport::SetGridAxis(Axis axis)
|
|||||||
|
|
||||||
void Viewport::addProp(vtkProp* prop)
|
void Viewport::addProp(vtkProp* prop)
|
||||||
{
|
{
|
||||||
if (m_Renderer) {
|
if (d->m_Renderer) {
|
||||||
m_Renderer->AddActor(prop);
|
d->m_Renderer->AddActor(prop);
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::RemoveProp(vtkProp* prop)
|
void Viewport::RemoveProp(vtkProp* prop)
|
||||||
{
|
{
|
||||||
if (m_Renderer) {
|
if (d->m_Renderer) {
|
||||||
m_Renderer->RemoveViewProp(prop);
|
d->m_Renderer->RemoveViewProp(prop);
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Viewport::UpdateGrid()
|
void Viewport::UpdateGrid()
|
||||||
{
|
{
|
||||||
if (!m_Renderer || !m_GridSource) return;
|
if (!d->m_Renderer || !d->m_GridSource) return;
|
||||||
if (m_GridActor && !m_GridActor->GetVisibility()) return;
|
if (d->m_GridActor && !d->m_GridActor->GetVisibility()) return;
|
||||||
|
|
||||||
vtkCamera* camera = m_Renderer->GetActiveCamera();
|
vtkCamera* camera = d->m_Renderer->GetActiveCamera();
|
||||||
if (!camera) return;
|
if (!camera) return;
|
||||||
|
|
||||||
// Determine the "scale" of the view (how many units are visible vertically)
|
// Determine the "scale" of the view (how many units are visible vertically)
|
||||||
@@ -425,6 +459,9 @@ void Viewport::UpdateGrid()
|
|||||||
double log10Spacing = std::floor(std::log10(viewHeight / 5.0));
|
double log10Spacing = std::floor(std::log10(viewHeight / 5.0));
|
||||||
double spacing = std::pow(10.0, log10Spacing);
|
double spacing = std::pow(10.0, log10Spacing);
|
||||||
|
|
||||||
|
// Spacing should be at least 1mm
|
||||||
|
if (spacing < 1.0) spacing = 1.0;
|
||||||
|
|
||||||
// Get current focal point to center the grid near what we're looking at
|
// Get current focal point to center the grid near what we're looking at
|
||||||
double focalPoint[3];
|
double focalPoint[3];
|
||||||
camera->GetFocalPoint(focalPoint);
|
camera->GetFocalPoint(focalPoint);
|
||||||
@@ -455,31 +492,28 @@ void Viewport::UpdateGrid()
|
|||||||
p1[idxH] = maxH; p1[idxV] = minV; p1[idxN] = centerN;
|
p1[idxH] = maxH; p1[idxV] = minV; p1[idxN] = centerN;
|
||||||
p2[idxH] = minH; p2[idxV] = maxV; p2[idxN] = centerN;
|
p2[idxH] = minH; p2[idxV] = maxV; p2[idxN] = centerN;
|
||||||
|
|
||||||
m_GridSource->SetOrigin(origin);
|
d->m_GridSource->SetOrigin(origin);
|
||||||
m_GridSource->SetPoint1(p1);
|
d->m_GridSource->SetPoint1(p1);
|
||||||
m_GridSource->SetPoint2(p2);
|
d->m_GridSource->SetPoint2(p2);
|
||||||
m_GridSource->SetXResolution(numLines);
|
d->m_GridSource->SetXResolution(numLines);
|
||||||
m_GridSource->SetYResolution(numLines);
|
d->m_GridSource->SetYResolution(numLines);
|
||||||
m_GridSource->Update();
|
d->m_GridSource->Update();
|
||||||
|
|
||||||
if (m_OriginAxes) {
|
if (d->m_OriginAxes) {
|
||||||
m_OriginAxes->SetScaleFactor(spacing);
|
d->m_OriginAxes->SetScaleFactor(spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update annotation for grid size
|
// Update annotation for grid size
|
||||||
char gridLabel[32];
|
char gridLabel[32];
|
||||||
if (spacing >= 1000.0) {
|
if (spacing >= 1000.0) {
|
||||||
sprintf(gridLabel, "Grid: %.0f m", spacing / 1000.0);
|
sprintf(gridLabel, "Grid: %.1f m", spacing / 1000.0);
|
||||||
} else if (spacing >= 10.0) {
|
} else if (spacing >= 10.0) {
|
||||||
sprintf(gridLabel, "Grid: %.0f cm", spacing / 10.0);
|
sprintf(gridLabel, "Grid: %.1f cm", spacing / 10.0);
|
||||||
} else {
|
} else {
|
||||||
sprintf(gridLabel, "Grid: %.0f mm", spacing);
|
sprintf(gridLabel, "Grid: %.0f mm", spacing);
|
||||||
}
|
}
|
||||||
m_Annotation->SetText(1, gridLabel);
|
d->m_Annotation->SetText(1, gridLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
|
|||||||
@@ -2,23 +2,19 @@
|
|||||||
#define ULIB_VTK_VIEWPORT_H
|
#define ULIB_VTK_VIEWPORT_H
|
||||||
|
|
||||||
#include "uLibVtkInterface.h"
|
#include "uLibVtkInterface.h"
|
||||||
#include <vtkCornerAnnotation.h>
|
|
||||||
#include <vtkOrientationMarkerWidget.h>
|
|
||||||
#include <vtkRenderer.h>
|
|
||||||
#include <vtkSmartPointer.h>
|
|
||||||
#include <vtkVersion.h>
|
|
||||||
#include <vtkRenderer.h>
|
|
||||||
#include <vtkCornerAnnotation.h>
|
|
||||||
#include <vtkOrientationMarkerWidget.h>
|
|
||||||
#include <vtkCameraOrientationWidget.h>
|
|
||||||
#include <vtkNamedColors.h>
|
|
||||||
#include <vtkAxes.h>
|
|
||||||
#include <vtkAxesActor.h>
|
|
||||||
#include <vtkPlaneSource.h>
|
|
||||||
#include <vtkActor.h>
|
|
||||||
#include <vtkCellPicker.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// VTK classes are in the global namespace
|
||||||
|
class vtkRenderer;
|
||||||
|
class vtkCornerAnnotation;
|
||||||
|
class vtkOrientationMarkerWidget;
|
||||||
|
class vtkCameraOrientationWidget;
|
||||||
|
class vtkPlaneSource;
|
||||||
|
class vtkActor;
|
||||||
|
class vtkAxes;
|
||||||
|
class vtkNamedColors;
|
||||||
|
class vtkCellPicker;
|
||||||
|
class vtkCallbackCommand;
|
||||||
class vtkProp;
|
class vtkProp;
|
||||||
class vtk3DWidget;
|
class vtk3DWidget;
|
||||||
class vtkRenderWindow;
|
class vtkRenderWindow;
|
||||||
@@ -28,6 +24,7 @@ class vtkCamera;
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Vtk {
|
namespace Vtk {
|
||||||
|
|
||||||
|
struct ViewportData;
|
||||||
class vtkHandlerWidget;
|
class vtkHandlerWidget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,11 +53,11 @@ public:
|
|||||||
void AddWidget(vtk3DWidget *widget);
|
void AddWidget(vtk3DWidget *widget);
|
||||||
|
|
||||||
// Direct access to VTK internals
|
// Direct access to VTK internals
|
||||||
vtkRenderer* GetRenderer() { return m_Renderer; }
|
vtkRenderer* GetRenderer();
|
||||||
virtual vtkRenderWindow* GetRenderWindow() = 0;
|
virtual vtkRenderWindow* GetRenderWindow() = 0;
|
||||||
virtual vtkRenderWindowInteractor* GetInteractor() = 0;
|
virtual vtkRenderWindowInteractor* GetInteractor() = 0;
|
||||||
vtkCornerAnnotation* GetAnnotation() { return m_Annotation; }
|
vtkCornerAnnotation* GetAnnotation();
|
||||||
vtkCameraOrientationWidget* GetCameraWidget(){ return m_CameraWidget; }
|
vtkCameraOrientationWidget* GetCameraWidget();
|
||||||
const std::vector<Puppet*>& getPuppets() const { return m_Puppets; }
|
const std::vector<Puppet*>& getPuppets() const { return m_Puppets; }
|
||||||
|
|
||||||
// Grid control
|
// Grid control
|
||||||
@@ -76,23 +73,9 @@ protected:
|
|||||||
|
|
||||||
void UpdateGrid();
|
void UpdateGrid();
|
||||||
|
|
||||||
vtkSmartPointer<vtkRenderer> m_Renderer;
|
struct ViewportData *d;
|
||||||
vtkSmartPointer<vtkCornerAnnotation> m_Annotation;
|
|
||||||
vtkSmartPointer<vtkOrientationMarkerWidget> m_Marker;
|
|
||||||
vtkSmartPointer<vtkCameraOrientationWidget> m_CameraWidget;
|
|
||||||
|
|
||||||
vtkSmartPointer<vtkPlaneSource> m_GridSource;
|
|
||||||
vtkSmartPointer<vtkActor> m_GridActor;
|
|
||||||
vtkSmartPointer<vtkAxes> m_OriginAxes;
|
|
||||||
vtkSmartPointer<vtkActor> m_OriginAxesActor;
|
|
||||||
|
|
||||||
vtkSmartPointer<vtkNamedColors> m_Colors;
|
|
||||||
|
|
||||||
Axis m_GridAxis;
|
Axis m_GridAxis;
|
||||||
vtkSmartPointer<vtkHandlerWidget> m_HandlerWidget;
|
|
||||||
std::vector<Puppet*> m_Puppets;
|
std::vector<Puppet*> m_Puppets;
|
||||||
vtkSmartPointer<vtkCellPicker> m_Picker;
|
|
||||||
vtkSmartPointer<vtkCallbackCommand> m_KeyCallback;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
|
|||||||
Reference in New Issue
Block a user