Camera FitIntoView is slow (200 ms)
#1
Using Ab3d PowerToys WPF (not DXEngine - yet) 9.3.7619
It is taking ~200 ms calling Camera.FitIntoView.
I need it to be much faster.

Simple code:
var area = new BoxVisual3D
{
  CenterPosition = new Point3D(357, 292, -270),
  Size = new Size3D(20, 20, 20)
};
var list = new List<Visual3D> {area};                        
MainCamera.FitIntoView();

//Using {Ab3d.Cameras.TargetPositionCamera}

I have tried using logic to restrict the number of calls - limited success.
The time is slightly longer between a 2D front view and a 3D view.

  • Is there anything simple I can do to improve this time?
  • Would there be much difference in the time if I embedded the WPF inside DxEngine? or somehow used a DXEngine Camera converting it to a WPF Camera using relevant function?
  • Will the latest version make any difference? (I'll try this anyway shortly)
Nigel
#2
FitIntoView method has multiple arguments that can control how the method works.

By default its fitIntoViewType is set to CheckAllPositions. When the scene has models with many positions it can take quite long to check all positions.

To make the method work faster, can set the fitIntoViewType to CheckBounds - this will check only bouding boxes of each Model3D.

There are also some other overloads of FitIntoView - for example one takes a IList<Visual3D> visuals so you can specify on which Visual3D objects you want to do the check.
Andrej Benedik
#3
(03-10-2021, 11:58 AM)abenedik Wrote: FitIntoView method has multiple arguments that can control how the method works.

By default its fitIntoViewType is set to CheckAllPositions. When the scene has models with many positions it can take quite long to check all positions.

To make the method work faster, can set the fitIntoViewType to CheckBounds - this will check only bouding boxes of each Model3D.

There are also some other overloads of FitIntoView - for example one takes a IList<Visual3D> visuals so you can specify on which Visual3D objects you want to do the check.

Thank you for the reply. We are aware of the params that can be used. We found that CheckBounds did not make much difference to the timing. Supplying the List is what we are currently doing - the coding example I included is for just a box.
#4
I have analyzed the code in FitIntoView and optimized the slowest part of the code so that this is now around 50% faster. 

But even without the optimization, this should not take so long as in your case.

After some additional checks, I see that the probable reason for a long time is that the FitIntoView code also calls Ab3d.Utilities.LinesUpdater.Instance.Refresh() method. In case when no DXEngine is used, this method regenerated all 3D lines - regenerates the geometry for all 3D lines. This can take quite some time when there are a lot of 3D lines in the scene. This call is needed to update the lines before the FitIntoView is called.

If you would use Ab3d.DXEngine than LinesUpdater.Instance.Refresh call would be a no-op. Also, rendering 3D lines is greatly accelerated and does not require costly geometry build on the CPU - you can render millions of 3D lines and still have high FPS (on a modern GPU).

To avoid calling LinesUpdater.Instance.Refresh method, you can also call camera.GetFitIntoViewDistanceOrCameraWidth (this is also called inside FitIntoView method) and the set the camera's Distance / CameraWidth based on the result of this method. But this will just postone the regeneration of lines.
Andrej Benedik
#5
(03-12-2021, 12:53 PM)abenedik Wrote: I have analyzed the code in FitIntoView and optimized the slowest part of the code so that this is now around 50% faster. 

But even without the optimization, this should not take so long as in your case.

After some additional checks, I see that the probable reason for a long time is that the FitIntoView code also calls Ab3d.Utilities.LinesUpdater.Instance.Refresh() method. In case when no DXEngine is used, this method regenerated all 3D lines - regenerates the geometry for all 3D lines. This can take quite some time when there are a lot of 3D lines in the scene. This call is needed to update the lines before the FitIntoView is called.

If you would use Ab3d.DXEngine than LinesUpdater.Instance.Refresh call would be a no-op. Also, rendering 3D lines is greatly accelerated and does not require costly geometry build on the CPU - you can render millions of 3D lines and still have high FPS (on a modern GPU).

To avoid calling LinesUpdater.Instance.Refresh method, you can also call camera.GetFitIntoViewDistanceOrCameraWidth (this is also called inside FitIntoView method) and the set the camera's Distance / CameraWidth based on the result of this method. But this will just postone the regeneration of lines.

A 50% improvement will be good for us. We have not moved over to DXEngine yet.
We are already making use of GetFitIntoViewDistanceOrCameraWidth(), and as an optimisation we only call FitIntoView when the distance or position has substantially changed.

Thanks for investigating
Nigel
  


Forum Jump:


Users browsing this thread:
1 Guest(s)