Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Ortographic camera zoom to BoundingBox
#1
Video 
Hi
I have this method to zoom to a BoundingBox:
Code:
    private void Zoom(bool isZoomSelection, BoundingBox? bBox = null)
    {
        if (this.BimScene is null)
        {
            return;
        }

        Threads.ExecuteOnUIThread(() =>
        {
            // BoundingBox can be NaN when there are no models -> Get RootNode BoundingBox instead with the grid
            bBox ??= !isZoomSelection
                ? this.BimScene.GetSceneBoundingBox()
                : this.BimScene.GetSelectionBoundingBox();
            if (bBox.Value.SizeX is float.NaN
                || bBox.Value.SizeY is float.NaN
                || bBox.Value.SizeZ is float.NaN)
            {
                bBox = this.BimScene.RootNode.GetLocalBoundingBox();
            }

            if (Settings.SingleInstance.CameraAnimationDuration > 0)
            {
                var corn = bBox.Value.GetCorners();
                var dist = this.targetPositionCamera.GetFitIntoViewDistanceOrViewWidth(corn, FitIntoViewType.CheckBounds, true, out var targ);
        
                var cameraAnimation = AnimationBuilder.CreateCameraAnimation(this.targetPositionCamera);
                cameraAnimation.EasingFunction = EasingFunctions.QuadraticEaseInOutFunction;
                cameraAnimation.Set(CameraAnimatedProperties.TargetPosition, targ, Settings.SingleInstance.CameraAnimationDuration);
                cameraAnimation.Set(CameraAnimatedProperties.Distance, dist, Settings.SingleInstance.CameraAnimationDuration);

                if (this.currentCameraAnimation is not null)
                {
                    this.currentCameraAnimation.Completed -= this.CameraAnimation_Completed;
                    this.currentCameraAnimation.Stop();
                }

                cameraAnimation.Start();
                this.currentCameraAnimation = cameraAnimation;
                
                this.currentCameraAnimation.Completed += this.CameraAnimation_Completed;
            }
            else
            {
                this.targetPositionCamera.TargetPosition = bBox.Value.GetCenterPosition();
                this.targetPositionCamera.FitIntoView(bBox.Value, false, 1.1f);
            
                this.UpdateCameraPosition();
            }
        }, true);
    }

It works pretty well when in perspective projection, but it does not work for ortographic
I know I must set ViewWidth and AspectRatio to handle that, so, could you please point me in the right direction to calculate the ViewWidth?
#2
As you said, when using the Orthographics camera, you need to change the ViewWidth.

But in your code, when you set up the animation, you always animate the Distance.

You should also use the following code instead:
Code:
var distanceProperty = _targetPositionCamera.ProjectionType == ProjectionTypes.Orthographic
    ? CameraAnimatedProperties.ViewWidth
    : CameraAnimatedProperties.Distance;

cameraAnimation.Set(distanceProperty, dist, _cameraAnimationDuration);

I also see that when you use animation (Settings.SingleInstance.CameraAnimationDuration > 0), then you also animate the TargetPosition to the new position that is calculated from the GetFitIntoViewDistanceOrViewWidth method.

But when you do not use animation, you set TargetPosition to the center position of the bounding box. This can create different results. I would advise you to restructure the code so you would always use the results of the GetFitIntoViewDistanceOrViewWidth method and then create the animation if CameraAnimationDuration > 0 or just set the TargetPosition and Distance / ViewWidth in case of no animation.


Also, if you post the code here, please clean it before posting. For example, the code here has Threads.ExecuteOnUIThread that is irrelevant for this sample. Also it uses some methods that may be also relevant for how the code behaves, but the source is not provided and just clutters the code, for example: BimScene.GetSceneBoundingBox, BimScene.GetSelectionBoundingBox(), this.UpdateCameraPosition(). It is also not clear what happens in this.CameraAnimation_Completed.

When I tried to reproduce the issue, I copied your code to my project, and then I needed to clean the code so it could start. It would be much nicer if you could do that already and post only the code that is relevant to the problem. This would also make the posted code much cleaner for other visitors.

Anyway, after I had cleaned the code and added the code that animates ViewWidth in case of the Orthographic camera, the animation worked.

Here is the cleaned code that I used (added to SharpEngineSceneViewInXaml.xaml.cs sample):
Code:
        private CameraAnimation? _cameraAnimation;
        private float _cameraAnimationDuration = 1000;
        private void Zoom()
        {
            if (_targetPositionCamera == null)
                return;
            var bBox = MainSceneView.Scene.RootNode.GetLocalBoundingBox();
            if (_cameraAnimationDuration > 0)
            {
                var corn = bBox.GetCorners();
                var dist = _targetPositionCamera.GetFitIntoViewDistanceOrViewWidth(corn, FitIntoViewType.CheckBounds, true, out var targ);
       
                var cameraAnimation = AnimationBuilder.CreateCameraAnimation(_targetPositionCamera);
                cameraAnimation.EasingFunction = EasingFunctions.QuadraticEaseInOutFunction;
                cameraAnimation.Set(CameraAnimatedProperties.TargetPosition, targ, _cameraAnimationDuration);

                var distanceProperty = _targetPositionCamera.ProjectionType == ProjectionTypes.Orthographic
                    ? CameraAnimatedProperties.ViewWidth
                    : CameraAnimatedProperties.Distance;

                cameraAnimation.Set(distanceProperty, dist, _cameraAnimationDuration);
                if (_cameraAnimation is not null)
                {
                    //_cameraAnimation.Completed -= this.CameraAnimation_Completed;
                    _cameraAnimation.Stop();
                }
                cameraAnimation.Start();
                _cameraAnimation = cameraAnimation;
               
                //_cameraAnimation.Completed += this.CameraAnimation_Completed;
            }
            else
            {
                _targetPositionCamera.TargetPosition = bBox.GetCenterPosition();
                _targetPositionCamera.FitIntoView(bBox, false, 1.1f);
           
                //this.UpdateCameraPosition();
            }
        }


Node:
I admit that FitIntoView is not perfect—I have spent a lot of time trying to achieve an optimal fit, but I was not successful.
Andrej Benedik
#3
Rainbow 
Thanks for your quick response

You are totally right, I should have clean my code before submitting. I probably didn't pay too much attention thinking that it was self-explanatory

I changed the code and it works perfect now

I also implemented your suggestion to use same logic in both scenario (with or without camera animations)

Thank you very much for your Help Andrej
  


Forum Jump:


Users browsing this thread:
1 Guest(s)