# Bug in vtkCamera::setUserViewTransform with an inverse vtkTransform

**URL:** https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738
**Category:** Development
**Tags:** bug, code
**Created:** [October 17, 2024, 3:50pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738 "2024-10-17T15:50:56Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![manik](https://discourse.vtk.org/user_avatar/discourse.vtk.org/manik/32/9300_2.png) [@manik](https://discourse.vtk.org/u/manik)
#### Post date: [October 17, 2024, 3:50pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/1 "2024-10-17T15:50:56Z")

</div>

Hi,  
I think I found a bug somewhere between vtkCamera and vtkAbstractTransform/vtkTransform that leads to a deadlock due to a mutex being locked twice.  
I made a minimal example: just use the [vtkCamera example](https://examples.vtk.org/site/Cxx/Visualization/Camera/) and add two lines just after creating the vtkCamera:

```auto
vtkNew<vtkTransform> myViewTransform; // Identity Transform
camera->SetUserViewTransform(vtkTransform::SafeDownCast(myViewTransform->GetInverse())); 

```

The executable freezes before showing the window.

I looked into the code and here is what happens:

- when calling `vtkCamera::SetUserViewTransform`, the `vtkCamera` creates a `vtkCameraCallbackCommand` and adds it as an Observer of the userViewTransform
- When any changes happen to the camera (e.g. `SetPosition`), the camera recomputes its internal transformation by composing userViewTransform with other transformations in **`vtkCamera::ComputeViewTransform()`**
- This in turn calls `userViewTransform->Update()` through a `GetMatrix()` on the concatenated transform
- In `vtkAbstractTransform::Update()`, **UpdateMutex is locked**
- There is here a special case for inverse transforms:

```cpp
// check to see if we are a special 'inverse' transform
  if (this->DependsOnInverse && this->MyInverse->GetMTime() >= this->UpdateTime.GetMTime())
  {
    vtkDebugMacro("Updating transformation from its inverse");
    this->InternalDeepCopy(this->MyInverse);
    this->Inverse();
    vtkDebugMacro("Calling InternalUpdate on the transformation");
    this->InternalUpdate();
  }

```

- `vtkTransform::Inverse` does invert the matrix, but it also calls `this->Modified()`
- `Modified()` evokes a `ModifiedEvent`
- This calls the vtkCameraCallback defined earlier
- In the `Exec()` method of the callback, it calls **`vtkCamera::ComputeViewTransform()`** again while we are still in it
- We are in a loop, and we reach again the **updateMutex.lock()** which blocks forever.

**Possible solution**  
The vtkCamera should disable its callback in the UserViewTransform when running ComputeViewTransform, (e.g. what is done in the destructor)

```cpp
void vtkCamera::ComputeViewTransform()
{
  // main view through the camera
  this->Transform->Identity();
  if (this->UserViewTransform)
  {
    ***this->UserViewTransform->RemoveObserver(this->UserViewTransformCallbackCommand);
    this->Transform->Concatenate(this->UserViewTransform);
  }
  this->Transform->SetupCamera(this->Position, this->FocalPoint, this->ViewUp);
  this->ViewTransform->Identity();
  this->ViewTransform->Concatenate(this->Transform->GetMatrix());
  ***if (this->UserViewTransform){
  *** this->UserViewTransform->AddObserver(
  *** vtkCommand::ModifiedEvent, this->UserViewTransformCallbackCommand);
  ***}
}

```

However there might be other places where the camera updates its transform outside ComputeViewTransform that may trigger the same deadlock.

Any comment or idea ? How should I proceed to get this bug corrected in VTK ?

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 18, 2024, 9:47pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/2 "2024-10-18T21:47:12Z")

</div>

Thanks for your detailed analysis. The official issue page for VTK is [https://gitlab.kitware.com/vtk/vtk/issues](https://gitlab.kitware.com/vtk/vtk/-/issues), but here works too.

The main fault lies with the vtkTransform. A mutex lock around code that calls Modified(), or any method that can trigger callbacks, is guaranteed to eventually cause a deadlock in someone’s application. So rather than patching camera, I’m thinking of a patching the transform so that the Modified() call is deferred until the mutex is unlocked.

However, I must say that I was surprised to see that vtkCamera is observing a ModifiedEvent. We usually design our code to check the ModifiedTime of objects, rather than listen for ModifiedEvent.

Once I have a patch, I’ll report back here.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 21, 2024, 12:02am UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/3 "2024-10-21T00:02:46Z")

</div>

I’ve submitted a transform patch at [gitlab.kitware.com/vtk/vtk/merge\_requests/11574](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/11574). It still has to go through review, so I can’t say exactly when it will be merged.

---

<div class="post-metadata">

### Author: ![manik](https://discourse.vtk.org/user_avatar/discourse.vtk.org/manik/32/9300_2.png) [@manik](https://discourse.vtk.org/u/manik)
#### Post date: [October 22, 2024, 12:31pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/4 "2024-10-22T12:31:48Z")

</div>

Thank you very much ! I will follow the integration of the patch.

---

<div class="post-metadata">

### Author: ![manik](https://discourse.vtk.org/user_avatar/discourse.vtk.org/manik/32/9300_2.png) [@manik](https://discourse.vtk.org/u/manik)
#### Post date: [October 22, 2024, 12:50pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/5 "2024-10-22T12:50:50Z")

</div>

And yes, I was surprised too about the ModifiedEvent and the Observer.  
I think this might be necessary because the userViewTransform might be updated by the Application without triggering a refresh of the camera view. As long as no one moves the camera or sets a Transform, I don’t think the camera will check for the ModifiedTime of the transforms.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 22, 2024, 1:18pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/6 "2024-10-22T13:18:35Z")

</div>

But observing the ModifiedEvent of the transform won’t catch all changes to the transform, either. For instance, if `A = B->GetInverse()`, then changing `B` won’t cause `A` to generate a ModifiedEvent.

As an example of how ModifiedTime can be used properly, consider the UserTransform of vtkProp3D (the base class of vtkActor). For VTK actors, the ModifiedTime of the actor includes the ModifiedTime of the UserTransform, which in turn includes the ModifiedTime of all the other transforms that UserTransform depends upon. So when the vtkRenderer renders the scene, it considers the ModifiedTime of the actor’s transforms.

In comparison, the ModifiedTime of vtkCamera does not consider the ModifiedTime of the UserViewTransform. So it’s the responsibility of the application to call Modified() on the camera whenever the UserViewTransform changes. Trying to automate this with a transform -\> camera callback is not only messy, but it doesn’t work in all situations (see first paragraph above).

I’d be in favor of changing the camera user transforms to work the same way as the actor user transforms, i.e. with ModifiedTime checks to ensure that everything is up-to-date when the render occurs.

---

<div class="post-metadata">

### Author: ![manik](https://discourse.vtk.org/user_avatar/discourse.vtk.org/manik/32/9300_2.png) [@manik](https://discourse.vtk.org/u/manik)
#### Post date: [October 22, 2024, 1:42pm UTC](https://discourse.vtk.org/t/bug-in-vtkcamera-setuserviewtransform-with-an-inverse-vtktransform/14738/7 "2024-10-22T13:42:13Z")

</div>

Thanks for the explanation, especially how it works with Actors; seems that it would be a much better solution.
