[Rendering3D] Add callback in OglModel to update visual after dynamic change of position
This PR adds a callback in OglModel, to update the current visual (triggering a call to initVisual()), whenever the m_positions field is changed dynamically.
The first interest of this PR is to add the possibility to change dynamically the underlying mesh of the OglModel (typically with a controller), and see the corresponding changes. The context I'm using this feature is in a scene where I have several mesh files representing the same mesh moving along time. Loading these meshes sequentially along time, using a python controller, is equivalent to impose a displacement to the underlying mesh during the simulation. But visualising this movement requires this additional callback. Unfortunately I can't share the data I'm referring to, and I don't have an example as striking at my disposal.
There are two questions I'd like to discuss:
- Is this callback likely to cause some trouble in existing scenes ?
- Is this behaviour generally desirable ?
By submitting this pull request, I acknowledge that
I have read, understand, and agree SOFA Developer Certificate of Origin (DCO).
Reviewers will merge this pull-request only if
- it builds with SUCCESS for all platforms on the CI.
- it does not generate new warnings.
- it does not generate new unit test failures.
- it does not generate new scene test failures.
- it does not break API compatibility.
- it is more than 1 week old (or has fast-merge label).
I am curious how the update of the "original" positions while simulating, is behaving with a barycentric mapping (which has to compute its bary coefficients from the starting position) ? 🤔
@fredroy This is a very good question and definitely worth investigation.
To me this is related to a systematic problem we have regarding the mix between Data update through DDG or updates using toModel and fromModel.
As far as can think about it is that BarycentricMapping should stop using the to and from model to compute barycentric topologies Maybe it should be refactored to be part of the Data depenency graph by adding few data field. - control_rest_position // The vector of positions that are the control points of the interpolation space. - target_rest_position // The vector of positions that are embeded into interpolation space.
With these two it is clear that a change in the contrl_rest_position or target_rest_position should trigger the recomputation of barycentric coordinates.
It may also trigger the initVisual() when topological cases occur @Camille-K @epernod
From the callback, we can not ensure that we have a OGL context. Using an intermediate boolean
@Camille-K will you test the suggestion? @epernod wanted to be poked here as well to test :)
Sorry for the delay !
First, I have some precisions regarding Fred's remark: with the modification I suggested, I see a critical performance drop in the caduceus scene, going from ~150-200 FPS before the change, to ~25 FPS after. I expect that, indeed, the barycentric mapping accesses the m_positions field of the OGLmodel, consequently causing extensive triggering of the callback at each time step. So the solution I first suggested should be discarded anyway.
@hugtalbot, using the m_restPositions field for the callback doesn't have the same performance issue. However I believe that this field is not used in the rendering process of the OglModel. Or, at least, calling initVisual() after a change of m_restPositions doesn't change the visual. So this solution doesn't solve the initial issue I had.
I tried to look into how the BarycentricMapping works in details, but I'm afraid it is a bit too complexe for me with the time I have at the moment... My idea was to find how the barycentric mapping makes sure that the visual OGLModel is updated at each time step, and mimick this. If someone is familiar with the process ?
In the meantime, regarding the specific scenario I was working on, I'm using another workaround. Instead of dynamically changing the source file of the loader, I'm creating as many loaders as mesh files I have, and I dynamically change the loader I need at a given time during the simulation.