refactor: update transformation system, improve template readability, and reorganize VTK assembly management
This commit is contained in:
@@ -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
21
docs/update_properties.md
Normal 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.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user