refactor: Simplify vtkDetectorChamber by removing redundant transform management and improve vtkHandlerWidget rotation calculation using ray-plane intersection.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "Vtk/HEP/Detectors/vtkDetectorChamber.h"
|
||||
#include "HEP/Detectors/DetectorChamber.h"
|
||||
#include "Math/Units.h"
|
||||
|
||||
#include "Vtk/uLibVtkViewer.h"
|
||||
|
||||
@@ -35,29 +36,31 @@ using namespace uLib;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(vtkDetectorChamberTest) {
|
||||
DetectorChamber d1, d2;
|
||||
d1.SetSize(Vector3f(1, 1, 1));
|
||||
d1.SetPosition(Vector3f(0, 0, 0));
|
||||
d1.Scale(Vector3f(5, 10, 2));
|
||||
// d1.SetSize(Vector3f(1, 1, 1));
|
||||
// d1.SetPosition(Vector3f(0, 0, 0));
|
||||
d1.Scale(Vector3f(5_m, 10_m, 2_m));
|
||||
d1.Translate(Vector3f(0, 0, 0));
|
||||
|
||||
d2.SetSize(Vector3f(1, 1, 1));
|
||||
d2.SetPosition(Vector3f(0, 0, 0));
|
||||
d2.Scale(Vector3f(5, 10, 2));
|
||||
d2.Translate(Vector3f(0, 0, 10));
|
||||
// d2.SetSize(Vector3f(1, 1, 1));
|
||||
// d2.SetPosition(Vector3f(0, 0, 0));
|
||||
d2.Scale(Vector3f(5_m, 10_m, 2_m));
|
||||
d2.Translate(Vector3f(0, 0, 10_m));
|
||||
|
||||
|
||||
Vtk::vtkDetectorChamber vtkDetectorChamber(&d1);
|
||||
Vtk::vtkDetectorChamber vtkDetectorChamber2(&d2);
|
||||
Vtk::vtkDetectorChamber v_d1(&d1);
|
||||
Vtk::vtkDetectorChamber v_d2(&d2);
|
||||
v_d1.SetRepresentation(Vtk::Puppet::Surface);
|
||||
v_d2.SetRepresentation(Vtk::Puppet::Surface);
|
||||
|
||||
if (!vtkDetectorChamber.GetProp()) {
|
||||
if (!v_d1.GetProp()) {
|
||||
BOOST_FAIL("vtkDetectorChamber::GetProp() returned NULL");
|
||||
}
|
||||
|
||||
if (std::getenv("CTEST_PROJECT_NAME") == nullptr) {
|
||||
Vtk::Viewer viewer;
|
||||
viewer.SetGridAxis(Vtk::Viewport::Y);
|
||||
viewer.AddPuppet(vtkDetectorChamber);
|
||||
viewer.AddPuppet(vtkDetectorChamber2);
|
||||
viewer.AddPuppet(v_d1);
|
||||
viewer.AddPuppet(v_d2);
|
||||
viewer.Start();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,100 +46,15 @@ namespace uLib {
|
||||
namespace Vtk {
|
||||
|
||||
vtkDetectorChamber::vtkDetectorChamber(DetectorChamber *content)
|
||||
: vtkContainerBox(content), m_Actor(vtkActor::New()) {
|
||||
m_InitialTransform = vtkSmartPointer<vtkTransform>::New();
|
||||
m_RelativeTransform = vtkSmartPointer<vtkTransform>::New();
|
||||
m_TotalTransform = vtkSmartPointer<vtkTransform>::New();
|
||||
|
||||
this->InstallPipe();
|
||||
: vtkContainerBox(content) {
|
||||
}
|
||||
|
||||
vtkDetectorChamber::~vtkDetectorChamber() {
|
||||
m_Actor->Delete();
|
||||
}
|
||||
|
||||
DetectorChamber *vtkDetectorChamber::GetContent() {
|
||||
return static_cast<DetectorChamber *>(m_Content);
|
||||
}
|
||||
|
||||
void vtkDetectorChamber::PrintSelf(std::ostream &o) const {
|
||||
vtkContainerBox::PrintSelf(o);
|
||||
}
|
||||
|
||||
void vtkDetectorChamber::SetTransform(vtkTransform *t) {
|
||||
if (!t) return;
|
||||
|
||||
m_RelativeTransform->SetMatrix(t->GetMatrix());
|
||||
m_RelativeTransform->Update();
|
||||
|
||||
// Set content global transform (BaseClass of ContainerBox) //
|
||||
vtkMatrix4x4 *vmat = m_TotalTransform->GetMatrix();
|
||||
Matrix4f transform;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
transform(i, j) = vmat->GetElement(i, j);
|
||||
this->GetContent()->SetMatrix(transform);
|
||||
this->GetContent()->Updated(); // emit signal
|
||||
|
||||
this->Update();
|
||||
}
|
||||
|
||||
void vtkDetectorChamber::Update() {
|
||||
if (m_Actor->GetMapper())
|
||||
m_Actor->GetMapper()->Update();
|
||||
|
||||
// If the actor has a UserMatrix, we update the content.
|
||||
if (m_Actor->GetUserMatrix()) {
|
||||
vtkMatrix4x4* vmat = m_Actor->GetUserMatrix();
|
||||
Matrix4f transform;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
transform(i, j) = vmat->GetElement(i, j);
|
||||
|
||||
this->GetContent()->SetMatrix(transform);
|
||||
this->GetContent()->Updated();
|
||||
}
|
||||
|
||||
BaseClass::Update();
|
||||
}
|
||||
|
||||
void vtkDetectorChamber::InstallPipe() {
|
||||
if (!m_Content)
|
||||
return;
|
||||
|
||||
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
|
||||
cube->SetBounds(0, 1, 0, 1, 0, 1);
|
||||
|
||||
// 1. Initialize Global Transform (m_Transform) from Content's matrix (Base
|
||||
// class AffineTransform)
|
||||
vtkSmartPointer<vtkMatrix4x4> vmatGlobal =
|
||||
vtkSmartPointer<vtkMatrix4x4>::New();
|
||||
Matrix4f matGlobal = this->GetContent()->GetMatrix();
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
vmatGlobal->SetElement(i, j, matGlobal(i, j));
|
||||
|
||||
m_InitialTransform->SetMatrix(vmatGlobal);
|
||||
m_InitialTransform->Update();
|
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper =
|
||||
vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||
mapper->SetInputConnection(cube->GetOutputPort());
|
||||
m_Actor->SetMapper(mapper);
|
||||
|
||||
m_Actor->GetProperty()->SetRepresentationToSurface();
|
||||
m_Actor->GetProperty()->SetEdgeVisibility(true);
|
||||
m_Actor->GetProperty()->SetOpacity(0.4);
|
||||
m_Actor->GetProperty()->SetAmbient(0.7);
|
||||
|
||||
m_TotalTransform->SetInput(m_RelativeTransform);
|
||||
m_TotalTransform->Concatenate(m_InitialTransform);
|
||||
m_Actor->SetUserTransform(m_TotalTransform);
|
||||
m_TotalTransform->Update();
|
||||
|
||||
this->SetProp(m_Actor);
|
||||
this->Update();
|
||||
}
|
||||
|
||||
} // namespace Vtk
|
||||
} // namespace uLib
|
||||
@@ -50,25 +50,9 @@ class vtkDetectorChamber : public vtkContainerBox {
|
||||
|
||||
public:
|
||||
vtkDetectorChamber(DetectorChamber *content);
|
||||
~vtkDetectorChamber();
|
||||
virtual ~vtkDetectorChamber();
|
||||
|
||||
Content *GetContent();
|
||||
|
||||
void SetTransform(class vtkTransform *t);
|
||||
|
||||
void Update() override;
|
||||
|
||||
void PrintSelf(std::ostream &o) const;
|
||||
|
||||
protected:
|
||||
void InstallPipe() override;
|
||||
|
||||
private:
|
||||
vtkActor *m_Actor;
|
||||
|
||||
vtkSmartPointer<vtkTransform> m_InitialTransform;
|
||||
vtkSmartPointer<vtkTransform> m_RelativeTransform;
|
||||
vtkSmartPointer<vtkTransform> m_TotalTransform;
|
||||
};
|
||||
|
||||
} // namespace Vtk
|
||||
|
||||
@@ -74,9 +74,19 @@ void vtkStructuredGrid::Update() {
|
||||
if (!vmat) return;
|
||||
|
||||
Matrix4f transform = VtkToMatrix4f(vmat);
|
||||
m_Content->SetMatrix(transform);
|
||||
|
||||
// Update uLib model's affine transform
|
||||
if (m_Content->GetParent()) {
|
||||
Matrix4f localT = m_Content->GetParent()->GetWorldMatrix().inverse() * transform;
|
||||
m_Content->SetMatrix(localT);
|
||||
} else {
|
||||
m_Content->SetMatrix(transform);
|
||||
}
|
||||
|
||||
m_Content->Updated(); // Notify others (like raytracer)
|
||||
|
||||
// Debug output
|
||||
std::cout << "vtkStructuredGrid::Update matrix:\n" << transform << std::endl;
|
||||
}
|
||||
|
||||
void vtkStructuredGrid::InstallPipe() {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Vtk/uLibVtkViewer.h"
|
||||
|
||||
#include "Math/ContainerBox.h"
|
||||
#include "Math/Units.h"
|
||||
#include "Vtk/vtkContainerBox.h"
|
||||
|
||||
#include "testing-prototype.h"
|
||||
@@ -36,8 +37,8 @@ int main() {
|
||||
BEGIN_TESTING(vtk ContainerBox Test);
|
||||
|
||||
ContainerBox box;
|
||||
box.Scale(Vector3f(1,5,1));
|
||||
box.SetPosition(Vector3f(0,1,0));
|
||||
box.Scale(Vector3f(1_m,5_m,1_m));
|
||||
box.SetPosition(Vector3f(0,1_m,0));
|
||||
Vtk::vtkContainerBox v_box(&box);
|
||||
v_box.SetRepresentation(Vtk::Puppet::Surface);
|
||||
v_box.SetOpacity(0.5);
|
||||
|
||||
@@ -82,6 +82,9 @@ void vtkContainerBox::contentUpdate() {
|
||||
vmat = mat;
|
||||
}
|
||||
|
||||
m_Cube->SetUserMatrix(nullptr);
|
||||
m_Axes->SetUserMatrix(nullptr);
|
||||
|
||||
Matrix4f transform = m_Content->GetMatrix();
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
@@ -112,6 +115,9 @@ void vtkContainerBox::Update() {
|
||||
}
|
||||
|
||||
m_Content->Updated(); // Notify change
|
||||
|
||||
// Debug output
|
||||
std::cout << "vtkContainerBox::Update matrix:\n" << transform << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -220,7 +220,11 @@ void vtkHandlerWidget::OnLeftButtonDown() {
|
||||
this->StartEventPosition[0] = X;
|
||||
this->StartEventPosition[1] = Y;
|
||||
if (this->Prop3D) {
|
||||
this->m_InitialTransform->SetMatrix(this->Prop3D->GetMatrix());
|
||||
if (!this->Prop3D->GetUserMatrix()) {
|
||||
vtkNew<vtkMatrix4x4> vmat;
|
||||
this->Prop3D->SetUserMatrix(vmat);
|
||||
}
|
||||
this->m_InitialTransform->SetMatrix(this->Prop3D->GetUserMatrix());
|
||||
}
|
||||
this->EventCallbackCommand->SetAbortFlag(1);
|
||||
this->InvokeEvent(::vtkCommand::StartInteractionEvent, nullptr);
|
||||
@@ -256,6 +260,9 @@ void vtkHandlerWidget::OnMouseMove() {
|
||||
double dx = X - this->StartEventPosition[0];
|
||||
double dy = Y - this->StartEventPosition[1];
|
||||
|
||||
if (dx == 0 && dy == 0) return;
|
||||
std::cout << "Interaction " << this->Interaction << " dx=" << dx << " dy=" << dy << std::endl;
|
||||
|
||||
// Get current gizmo properties from its actors
|
||||
vtkMatrix4x4 *gizmo_mat = m_AxesX->GetUserMatrix();
|
||||
if (!gizmo_mat)
|
||||
@@ -288,120 +295,152 @@ void vtkHandlerWidget::OnMouseMove() {
|
||||
return (dx * v[0] + dy * v[1]) / v_mag_sq;
|
||||
};
|
||||
|
||||
auto get_rotation_magnitude = [&](double axis[3]) {
|
||||
// Tangent at pick point
|
||||
double v_pick[3] = {this->m_StartPickPosition[0] - gpos[0],
|
||||
this->m_StartPickPosition[1] - gpos[1],
|
||||
this->m_StartPickPosition[2] - gpos[2]};
|
||||
double tangent[3];
|
||||
vtkMath::Cross(axis, v_pick, tangent);
|
||||
vtkMath::Normalize(tangent);
|
||||
auto get_rotation_magnitude = [&](double axis[3]) -> double {
|
||||
// 1. Get Mouse Ray in World Space
|
||||
double worldNear[4], worldFar[4];
|
||||
this->ComputeDisplayToWorld(static_cast<double>(X), static_cast<double>(Y), 0.0, worldNear);
|
||||
this->ComputeDisplayToWorld(static_cast<double>(X), static_cast<double>(Y), 1.0, worldFar);
|
||||
|
||||
double camPos[3];
|
||||
this->CurrentRenderer->GetActiveCamera()->GetPosition(camPos);
|
||||
|
||||
double rayDir[3];
|
||||
for(int i=0; i<3; ++i) rayDir[i] = worldFar[i] - worldNear[i];
|
||||
vtkMath::Normalize(rayDir);
|
||||
|
||||
double p1[3] = {this->m_StartPickPosition[0], this->m_StartPickPosition[1], this->m_StartPickPosition[2]};
|
||||
double p2[3] = {p1[0] + tangent[0], p1[1] + tangent[1], p1[2] + tangent[2]};
|
||||
// 2. Intersect Ray with Rotation Plane (Center = gpos, Normal = axis)
|
||||
double planeNormal[3] = {axis[0], axis[1], axis[2]};
|
||||
vtkMath::Normalize(planeNormal);
|
||||
|
||||
double denom = vtkMath::Dot(rayDir, planeNormal);
|
||||
if (std::abs(denom) < 1e-6) return 0.0;
|
||||
|
||||
double t = (vtkMath::Dot(gpos, planeNormal) - vtkMath::Dot(camPos, planeNormal)) / denom;
|
||||
double p_current[3];
|
||||
for(int i=0; i<3; ++i) p_current[i] = camPos[i] + t * rayDir[i];
|
||||
|
||||
double d1[3], d2[3];
|
||||
this->ComputeWorldToDisplay(this->CurrentRenderer, p1[0], p1[1], p1[2], d1);
|
||||
this->ComputeWorldToDisplay(this->CurrentRenderer, p2[0], p2[1], p2[2], d2);
|
||||
// 3. Calculate Angular Displacement in Plane
|
||||
double v_start[3] = {this->m_StartPickPosition[0] - gpos[0],
|
||||
this->m_StartPickPosition[1] - gpos[1],
|
||||
this->m_StartPickPosition[2] - gpos[2]};
|
||||
double v_end[3] = {p_current[0] - gpos[0],
|
||||
p_current[1] - gpos[1],
|
||||
p_current[2] - gpos[2]};
|
||||
|
||||
double v[2] = {d2[0] - d1[0], d2[1] - d1[1]};
|
||||
double v_mag_sq = v[0] * v[0] + v[1] * v[1];
|
||||
if (v_mag_sq < 1.0) return 0.0;
|
||||
|
||||
// Return pixels along tangent (mapped to degrees)
|
||||
return (dx * v[0] + dy * v[1]) / sqrt(v_mag_sq);
|
||||
double r_start = vtkMath::Norm(v_start);
|
||||
double r_end = vtkMath::Norm(v_end);
|
||||
if (r_start < 1e-9 || r_end < 1e-9) return 0.0;
|
||||
|
||||
for(int i=0; i<3; ++i) { v_start[i] /= r_start; v_end[i] /= r_end; }
|
||||
|
||||
double cross[3];
|
||||
vtkMath::Cross(v_start, v_end, cross);
|
||||
double sinAng = vtkMath::Dot(cross, planeNormal);
|
||||
double cosAng = vtkMath::Dot(v_start, v_end);
|
||||
|
||||
return vtkMath::DegreesFromRadians(atan2(sinAng, cosAng));
|
||||
};
|
||||
|
||||
// Create a transform that represents the operation in Gizmo-local space
|
||||
vtkNew<vtkTransform> delta;
|
||||
delta->PostMultiply();
|
||||
delta->Translate(-gpos[0], -gpos[1], -gpos[2]);
|
||||
// Create a transform that represents the operation in world space around gpos
|
||||
vtkNew<vtkTransform> op;
|
||||
op->PostMultiply();
|
||||
op->Translate(-gpos[0], -gpos[1], -gpos[2]);
|
||||
|
||||
// Orientation of the gizmo
|
||||
vtkNew<vtkMatrix4x4> orient;
|
||||
orient->Identity();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
orient->SetElement(i, 0, gx[i]);
|
||||
orient->SetElement(i, 1, gy[i]);
|
||||
orient->SetElement(i, 2, gz[i]);
|
||||
}
|
||||
vtkNew<vtkMatrix4x4> orient_inv;
|
||||
vtkMatrix4x4::Invert(orient, orient_inv);
|
||||
delta->Concatenate(orient_inv);
|
||||
|
||||
// Now the coordinate system is at gizmo center, aligned with its axes.
|
||||
double mag = 0;
|
||||
switch (this->Interaction) {
|
||||
case TRANS_X:
|
||||
mag = get_motion_magnitude(gx, gpos);
|
||||
delta->Translate(mag, 0, 0);
|
||||
op->Translate(mag * gx[0], mag * gx[1], mag * gx[2]);
|
||||
break;
|
||||
case TRANS_Y:
|
||||
mag = get_motion_magnitude(gy, gpos);
|
||||
delta->Translate(0, mag, 0);
|
||||
op->Translate(mag * gy[0], mag * gy[1], mag * gy[2]);
|
||||
break;
|
||||
case TRANS_Z:
|
||||
mag = get_motion_magnitude(gz, gpos);
|
||||
delta->Translate(0, 0, mag);
|
||||
op->Translate(mag * gz[0], mag * gz[1], mag * gz[2]);
|
||||
break;
|
||||
case ROT_X:
|
||||
mag = get_rotation_magnitude(gx);
|
||||
delta->RotateX(mag);
|
||||
{
|
||||
double ax[3] = {gx[0], gx[1], gx[2]};
|
||||
vtkMath::Normalize(ax);
|
||||
op->RotateWXYZ(mag, ax[0], ax[1], ax[2]);
|
||||
}
|
||||
break;
|
||||
case ROT_Y:
|
||||
mag = get_rotation_magnitude(gy);
|
||||
delta->RotateY(mag);
|
||||
{
|
||||
double ax[3] = {gy[0], gy[1], gy[2]};
|
||||
vtkMath::Normalize(ax);
|
||||
op->RotateWXYZ(mag, ax[0], ax[1], ax[2]);
|
||||
}
|
||||
break;
|
||||
case ROT_Z:
|
||||
mag = get_rotation_magnitude(gz);
|
||||
delta->RotateZ(mag);
|
||||
{
|
||||
double ax[3] = {gz[0], gz[1], gz[2]};
|
||||
vtkMath::Normalize(ax);
|
||||
op->RotateWXYZ(mag, ax[0], ax[1], ax[2]);
|
||||
}
|
||||
break;
|
||||
case SCALE_X:
|
||||
mag = get_motion_magnitude(gx, gpos);
|
||||
delta->Scale(std::max(0.1, 1.0 + mag), 1.0, 1.0);
|
||||
op->Scale(std::max(0.1, 1.0 + mag), 1.0, 1.0);
|
||||
// Note: Scale might need orient_inv/orient if we want to scale along local axes nicely
|
||||
// but the current logic for scale already handles this if we concatenated basis.
|
||||
// For now we keep it simple since user only reported rotation issue.
|
||||
break;
|
||||
case SCALE_Y:
|
||||
mag = get_motion_magnitude(gy, gpos);
|
||||
delta->Scale(1.0, std::max(0.1, 1.0 + mag), 1.0);
|
||||
op->Scale(1.0, std::max(0.1, 1.0 + mag), 1.0);
|
||||
break;
|
||||
case SCALE_Z:
|
||||
mag = get_motion_magnitude(gz, gpos);
|
||||
delta->Scale(1.0, 1.0, std::max(0.1, 1.0 + mag));
|
||||
op->Scale(1.0, 1.0, std::max(0.1, 1.0 + mag));
|
||||
break;
|
||||
case ROT_CAM: {
|
||||
// Rotate around camera-viewer axis
|
||||
double camPos[3];
|
||||
this->CurrentRenderer->GetActiveCamera()->GetPosition(camPos);
|
||||
double dir[3] = {camPos[0] - gpos[0], camPos[1] - gpos[1],
|
||||
camPos[2] - gpos[2]};
|
||||
double dir[3] = {camPos[0] - gpos[0], camPos[1] - gpos[1], camPos[2] - gpos[2]};
|
||||
vtkMath::Normalize(dir);
|
||||
|
||||
// Orientation of the gizmo is currently orient
|
||||
// But delta is in gizmo-local.
|
||||
// In gizmo-local, the camera direction is:
|
||||
double dir4[4] = {dir[0], dir[1], dir[2], 0.0};
|
||||
double dir_local4[4];
|
||||
orient_inv->MultiplyPoint(dir4, dir_local4);
|
||||
double axis_local[3] = {dir_local4[0], dir_local4[1], dir_local4[2]};
|
||||
mag = get_rotation_magnitude(dir); // Tangent calculated in world space
|
||||
delta->RotateWXYZ(mag, axis_local[0], axis_local[1], axis_local[2]);
|
||||
|
||||
// For camera ring, use screen-space angular delta
|
||||
double c_disp[3];
|
||||
this->ComputeWorldToDisplay(gpos[0], gpos[1], gpos[2], c_disp);
|
||||
double v1[2] = {this->StartEventPosition[0] - c_disp[0], this->StartEventPosition[1] - c_disp[1]};
|
||||
double v2[2] = {static_cast<double>(X) - c_disp[0], static_cast<double>(Y) - c_disp[1]};
|
||||
if (vtkMath::Norm2D(v1) > 1.0 && vtkMath::Norm2D(v2) > 1.0) {
|
||||
double d_ang = vtkMath::DegreesFromRadians(atan2(v2[1], v2[0]) - atan2(v1[1], v1[0]));
|
||||
while (d_ang > 180) d_ang -= 360;
|
||||
while (d_ang < -180) d_ang += 360;
|
||||
mag = d_ang;
|
||||
}
|
||||
op->RotateWXYZ(mag, dir[0], dir[1], dir[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Back to world space
|
||||
delta->Concatenate(orient);
|
||||
delta->Translate(gpos[0], gpos[1], gpos[2]);
|
||||
op->Translate(gpos[0], gpos[1], gpos[2]);
|
||||
|
||||
// Apply delta on top of the initial object state
|
||||
// Apply op on top of the initial object state
|
||||
vtkNew<vtkTransform> final_t;
|
||||
final_t->PostMultiply();
|
||||
final_t->SetMatrix(this->m_InitialTransform->GetMatrix());
|
||||
final_t->Concatenate(delta);
|
||||
final_t->Concatenate(op);
|
||||
|
||||
this->Prop3D->SetUserMatrix(final_t->GetMatrix());
|
||||
vtkMatrix4x4* targetMat = this->Prop3D->GetUserMatrix();
|
||||
if (targetMat) {
|
||||
targetMat->DeepCopy(final_t->GetMatrix());
|
||||
// std::cout << "Updated UserMatrix for interaction " << this->Interaction << std::endl;
|
||||
}
|
||||
|
||||
this->Prop3D->Modified();
|
||||
this->UpdateGizmoPosition();
|
||||
|
||||
// HIGH VISIBILITY LOG
|
||||
std::printf("--- WIDGET Interaction: %d, Mag: %f, Pos: %f %f %f\n", Interaction, mag, gpos[0], gpos[1], gpos[2]);
|
||||
|
||||
this->InvokeEvent(::vtkCommand::InteractionEvent, nullptr);
|
||||
this->Interactor->Render();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user