refactor: update transformation system, improve template readability, and reorganize VTK assembly management

This commit is contained in:
AndreaRigoni
2026-03-31 16:04:03 +00:00
parent 22d0041942
commit d4fd2d3914
30 changed files with 568 additions and 501 deletions

View File

@@ -1,73 +0,0 @@
# Transformation Flow and Synchronization System
This document describes how transformations are applied and synchronized between the interactive 3D viewport, the visualization puppets, and the underlying mathematical models within the `uLib` framework.
## Architecture Overview
The system follows a Model-View-Controller (MVC) like pattern where:
- **Model**: `uLib::AffineTransform` (or derived classes like `ContainerBox`).
- **View/Puppet**: `uLib::Vtk::Puppet` (and specialized derivations like `Vtk::Assembly`).
- **Controller/Interaction**: `vtkHandlerWidget` (the transformation gizmo).
---
## 1. Interaction Flow (Gizmo -> Model)
When a user interacts with the `vtkHandlerWidget` (dragging arrows, rings, or cubes), the following chain of events occurs:
```mermaid
sequenceDiagram
participant User
participant HW as vtkHandlerWidget
participant VP as vtkViewport
participant P as vtkPuppet
participant M as uLib Model
User->>HW: Drag handle (MouseMove)
HW->>HW: Calculate Delta Matrix (op)
HW->>HW: Total = StartState * op
HW->>HW: Decompose Total into P, O, S
HW->>P: SetPosition, SetOrientation, SetScale
HW-->>VP: Invoke InteractionEvent
VP->>P: SyncFromVtk()
P->>P: Get local matrix from VTK Prop
P->>M: SetMatrix(matrix)
M-->>M: Update local properties (P, O, S)
M-->>P: Emit Updated signal
P->>P: Puppet::Update()
P->>P: (Redundant sanity write to Prop)
```
### Key Principles:
- **Single Source of Truth**: The `uLib::AffineTransform` is the owner of the transformation state.
- **Internal TRS vs UserMatrix**: We apply transformations directly to VTK's internal `Position`, `Orientation`, and `Scale` properties. This ensures the data is "visible" to VTK actors and simplifies decomposition.
- **Cumulative Bias Avoidance**: The `HandlerWidget` calculates transformations relative to the state at the start of the click, preventing numerical drift during a single drag operation.
---
## 2. Synchronization Loop Resolution
To prevent infinite loops and "double-transformation" artifacts (especially in assemblies), the following protections are in place:
1. **Hierarchy Isolation**: The `Puppet` base class distinguishes between the **Root Property** (which receives the puppet's master transformation) and **Sub-Parts** (which only receive appearance updates like color/visibility). This prevents parts from inheriting the same displacement twice.
2. **Re-entrancy Guards**: Puppets use an `m_InUpdate` flag to prevent a feedback loop where `SyncFromVtk` triggers a Model Update, which then re-triggers the Puppet Update.
3. **Signal Blocking**: In specialized cases (like `vtkAssembly`), `m_BlockUpdate` is used to prevent the model-to-puppet push during a puppet-to-model sync.
---
## 3. Undo System (Ctrl-Z)
### Current Implementation (Delta Chain)
Currently, the system maintains a `m_TransformChain` of delta matrices.
- **Record**: After every drag, a delta matrix ($M_{delta} = M_{end} \cdot M_{start}^{-1}$) is appended to the chain.
- **Undo**: The last delta is removed, and the prop is reconstructed by reapplying the remaining chain from a `BaseMatrix`.
### Planned Improvement (TRS Snapshots)
We are migrating to a `uLib::TRS` snapshot system for Undo.
- **Record**: At the start of a drag, the current `TRS` state of the object is pushed to the `m_UndoStack`.
- **Undo**: The top `TRS` is popped and applied directly to the model.
This approach is more robust because:
- It eliminates matrix multiplication error accumulation.
- It bypasses rotation convention/order issues (Gimbal lock in deltas).
- It returns the object to exactly its previous property values.

21
docs/update_properties.md Normal file
View File

@@ -0,0 +1,21 @@
# Properties and the vtk-gui representation
This is the rationale behind the connection between TRS properties and Puppet Transformation.
The properties from model get propoagated via Object signalling system (the Update signal) to the vtkRepresentation and to the Qt widgets so that the overall transformation of the model reflects into a modification of its representation in vtk and in the gui.
In addition the properties need to be adjusted also from vtk, for example if user uses handlerwidget to change the transformation this is eventually applied to Puppet and Puppet should propagate the transformation change to the vtk representation object (for instance vtkContainerBox) and the latter eventually propagates the change into the model.
the Puppet or the vtk representation wrapper ( vtkContainerBox for instance is the wrapper od ContainerBox ) should not directly show the transformation of the handlerwidget but it should show the transformation of the model once applied so we are always seeing the actual aspect of the model reflected to the vtk representation and not the other way around.
So in syntesis the model is the master and the vtk representation and the gui are the slaves of any modification, but the vtkHandlerWidget is able to apply a transform that should be applied to the model and then the model should propagate the transformation change to the vtk representation and to the gui.
## The Puppet
The puppet is the proxy of the spatial placement of objects in the scene. Puppets should have an internal ContainerBox that is shown in the scene around the content to be able to pick Puppet from vtkViewport using the handler widget. The HandlerWidget moves the Puppet ContainerBox (the red Highlight element whe selected) to reflect the handler current transformation, but the transformation is propagated to the derived Puppet classes like vtkContainerBox.
The vtkHandlerWidget should handle the transformation of the puppet internal ContainerBox. The changes of the ContainerBox will be propagated to the derived classes and eventually to the model.