ZoomPanel + 3D
#1
Can I use a ZoomPanel and it's functionality in a 3D view?  

Most of the time I am looking for using the zoom box while in a 3D view that is emulating a 2D view (i.e Top-Down for PlanView).  However, it might be convenient to be able to use it in a "real" 3D view (isometric) but I would want to prevent any rotation while doing this.  

I need to give my users the ability to have a "zoom-box" and I'm hoping that ZoomPanel is my solution. It has all of the UI that I'm looking for with panning, zoombox, zoomin, zoomout, "home" - 1:1, and mini-map.
#2
This is an interesting idea.

I have tried it and this may actually work for the Orthographics camera and when the view is parallel with coordinate axis - for example top-down view. You would also need a button on UI that would enable such navigation - in this mode the 3D rotation would be disabled.

You can try this with the following XAML and cs:

XAML:
Code:
<Window x:Class="WpfApplication16.DXEngineWithZoomPanel"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:cameras="clr-namespace:Ab3d.Cameras;assembly=Ab3d.PowerToys"
     xmlns:ab3d="clr-namespace:Ab3d.Controls;assembly=Ab3d.PowerToys"  
     xmlns:visuals="clr-namespace:Ab3d.Visuals;assembly=Ab3d.PowerToys"
     xmlns:dxControls="clr-namespace:Ab3d.DirectX.Controls;assembly=Ab3d.DXEngine.Wpf"
     xmlns:controls="clr-namespace:Ab2d.Controls;assembly=Ab2d.Controls.ZoomPanel"
     Title="StandardXaml"
     mc:Ignorable="d"
     d:DesignHeight="400" d:DesignWidth="800">

   <Grid Name="RootGrid">
       <Border Name="ViewportBorder" Background="Transparent">

           <dxControls:DXViewportView Name="MainDXViewportView" PresentationType="DirectXImage">

               <Viewport3D Name="MainViewport">
                   <visuals:WireGridVisual3D CenterPosition="0 0 0" Size="100 100" WidthCellsCount="5" HeightCellsCount="5" LineColor="#555555" LineThickness="2"/>

                   <visuals:BoxVisual3D x:Name="Box1Visual3D" CenterPosition="0 10 0" Size="50 20 50" Material="Gold" />
               </Viewport3D>

           </dxControls:DXViewportView>
       </Border>

       <cameras:TargetPositionCamera Name="Camera1"
                                     TargetPosition="0 0 0"
                                     Heading="0" Attitude="-90" Bank="0"
                                     Distance="400"
                                     CameraWidth="1000"
                                     ShowCameraLight="Always"
                                     CameraType="OrthographicCamera"
                                     TargetViewport3D="{Binding ElementName=MainViewport}"/>

       <ab3d:MouseCameraController Name="MouseCameraController1"
                                   RotateCameraConditions="LeftMouseButtonPressed"
                                   MoveCameraConditions="LeftMouseButtonPressed, ControlKey"
                                   EventsSourceElement="{Binding ElementName=ViewportBorder}"
                                   TargetCamera="{Binding ElementName=Camera1}" />


       <controls:ZoomPanel x:Name="ZoomPanel1" ZoomMode="ZoomIn" IsHitTestVisible="{Binding ElementName=IsZoomPanelEnabledCheckBox, Path=IsChecked}">
           <Canvas Name="ZoomPanelCanvas" Width="100" Height="100" />
       </controls:ZoomPanel>

       <StackPanel VerticalAlignment="Top" HorizontalAlignment="Right" Orientation="Vertical">
           <controls:ZoomController TargetZoomPanel="{Binding ElementName=ZoomPanel1}"/>
           <CheckBox Name="IsZoomPanelEnabledCheckBox" Content="IsZoomPanelEnabled" IsChecked="True" />
       </StackPanel>

       <controls:ZoomPanelNavigator MinZoomFactor="0.1" MaxZoomFactor="5"
                                    VerticalAlignment="Top" HorizontalAlignment="Left" Height="200"
                                    TargetZoomPanel="{Binding ElementName=ZoomPanel1}"/>
       
       
       <Border VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="5" BorderBrush="Black" BorderThickness="1">
           <StackPanel Orientation="Vertical">
               <TextBlock Text="MiniMap:" />
               <!-- To display an image in MiniMap set the MapImageElement property to an Image -->
               <controls:ZoomPanelMiniMap TargetZoomPanel="{Binding ElementName=ZoomPanel1}" />
           </StackPanel>
       </Border>
   </Grid>
</Window>
cs:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using Ab2d.Controls;

namespace WpfApplication16
{
   /// <summary>
   /// Interaction logic for DXEngineWithZoomPanel.xaml
   /// </summary>
   public partial class DXEngineWithZoomPanel : Window
   {
       private double _initialWidth;
       private double _initialHeight;

       public DXEngineWithZoomPanel()
       {
           InitializeComponent();

           _initialWidth = 1000; // Width at 1:1 view (Viewbox.Width == 1)
           Camera1.CameraWidth = _initialWidth;


           this.Loaded += delegate (object sender, RoutedEventArgs args)
           {
               ZoomPanelCanvas.Width = this.ActualWidth;
               ZoomPanelCanvas.Height = this.ActualHeight;

               _initialHeight = _initialWidth * this.ActualHeight / this.ActualWidth;

               ZoomPanel1.ZoomFactor = 2;
           };

           ZoomPanel1.ViewboxChanged += delegate(object sender, ViewboxChangedRoutedEventArgs e)
           {
               Camera1.CameraWidth = _initialWidth * e.NewViewboxValue.Width;

               double centerX = e.NewViewboxValue.X + (e.NewViewboxValue.Width * 0.5);
               double centerY = e.NewViewboxValue.Y + (e.NewViewboxValue.Height * 0.5);

               Camera1.TargetPosition = new Point3D((centerX - 0.5) * _initialWidth, 0, (centerY - 0.5) * _initialHeight);
           };
       }
   }
}

Note that when ZoomPanel is enabled (IsHitTestVisible is set to true), it will get all mouse events and MouseCameraController will not get any (so 3D rotation will be disabled).
If you would also like to have animated zooming, you would need to subscribe to ZoomFactor DepandencyProperty changes.


Also note that I do not have time to test this solution fully so use with caution.
Andrej Benedik
#3
Do you think it would work if I have an orientation that is NOT on an axis but I'm using a orthographic camera .... that I could treat the ZoomPanel normally but then apply the camera transformation to the newly calculated position for the camera. ???

I think this would assume that the ZoomPanel viewbox is oriented to the camera and not the world coordinates.
#4
I got the Zoombox working for a plane within 3D.  In my case I'm cutting a cross-section of data then decorating it with a cross-section grid.  The cross-section lines are actually in 3D within the data space.  This allows the user to view it all in 3D and zoom into it if they wish in order to put it all in context with the bigger picture of the data.  However in the Cross-section view I only show the cross-section data and decoration.

I solved the problem by calculating the Zoombox center as if the viewbox was in the XY plane at the origin then applying a 3D rotation and translation to move the camera to the actual cross-section data.  In my case I do not allow the user to do a rotation within the Cross-section view.
#5
Great!

Thank you for sharing this.
Andrej Benedik
  


Forum Jump:


Users browsing this thread:
1 Guest(s)