FitIntoView() crashes when called from Page.Loaded
Hi. In my Page.Loaded handler, I create my visual objects and then add them to the viewport. I then want to adjust the camera so that the objects are centered on the screen and fit to the view. If I call Camera.FitIntoView(), inside the Page.Loaded handler, then it crashes with a NullReference Exception.

Camera.FitIntoView() works fine elsewhere in the code. I have connected it to a double click event on the screen.


I have tried to reproduce the problem and was not able to do that.

I used the following xaml (as simple as possible):
<Grid Name="RootGrid">
        <Viewport3D Name="MainViewport" />
        <cameras:TargetPositionCamera Name="Camera1"
                                      TargetPosition="0 0 0"
                                      Heading="30" Attitude="-20" Bank="0" />

and the following code behind:
this.Loaded += delegate (object sender, RoutedEventArgs args)
                var boxVisual3D = new Ab3d.Visuals.BoxVisual3D()
                    CenterPosition = new Point3D(0, 0, 0),
                    Size = new Size3D(100, 40, 80),
                    Material = new DiffuseMaterial(Brushes.Green)



This did not throw any exception.
I have also tried to replace the BoxVisual3D with wireframe object and still it worked.

I have also checked the code for FitIntoView and did not find a possible cause of NullReferenceException there.

Could you please post the full stack trace for the exception (you can also send it by email).

The simple code above does not work well - because the TargetViewport3D property is not set in the TargetPositionCamera, the Camera is not correctly initialized at the time of the FitIntoView call - therefore the camera is not adjusted correctly. To fix that I advice to set the TargetViewport3D:
<cameras:TargetPositionCamera Name="Camera1"
                                      TargetPosition="0 0 0"
                                      Heading="30" Attitude="-20" Bank="0"
                                      TargetViewport3D="{Binding ElementName=MainViewport}"/>

It is also possible to call Camera1.Refresh() method before FitIntoView - this will search the visual tree and automatically find the Viewport3D (without setting TargetViewport3D). Because this will be done before the FitIntoView call, the FitIntoView will correctly adjust the camera. I will improve that in the next version.
Andrej Benedik
I have been experimenting with the toolkit by making mods to the SphereVisual3DSample code in the Ab3d.DXEngine.Wpf.Samples project. I will send you my code changes separately. After reading your response, I discovered that the app will not crash if I first call Camera1.Refresh().

Now, the issue that I have is that FitToView in Loaded does not do the same thing as FitToView called later.
Thank you for your sample code.

It really helped to reproduce the problems.

I have fixed the problems and will send you a link to the pre-release version in a private message.

You can also use the current version and use the following workaround:

before calling FitIntoView you need to "set the MainViewport's ActualWidth and ActualHeight" - this is done with first setting Width and Height and then calling Measure and Arrange:

MainViewport.Width = MainDXViewportView.ActualWidth;
MainViewport.Height = MainDXViewportView.ActualHeight;

MainViewport.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
MainViewport.Arrange(new Rect(0, 0, MainViewport.Width, MainViewport.Height));

The problem was that FitIntoView needs aspect ration of the viewport - it used Viewport3D'sActualWidth and ActualHeight. But when Viewport3D is inside DXEngine it is not actually visible - therefore the ActualWidth and ActualHeight are not set when your code is inside Loaded event. Later the DXEngine sets the Width and Height of Viewport3D (actually executed the code above) and therefore the FitIntoView gives you correct results when you call it from double click event.
Andrej Benedik
Thank you.

Forum Jump:

Users browsing this thread:
1 Guest(s)