• WPF Viewport3D 解决透视模式时窗体模糊


    最近折腾Viewport3D玩,遇到了一些诡异的问题,研究一下略有心得,特此和大家分享~

    三维图形概述:

    概要

    三维坐标系

     
           二维图形的 WPF 坐标系将原点定位在呈现区域(通常是屏幕)的左上角。 在二维系统中,x 轴上的正值朝右,y 轴上的正值朝下。 但是,在三维坐标系中,原点位于呈现区域的中心,x 轴上的正值朝右,但是 y 轴上的正值朝上,z 轴上的正值从原点向外朝向观察者。

    照相机

     

    透视投影和正投影
     

    关于TextureCoordinates(纹理坐标):

     
    <MeshGeometry3D Positions="-250,-150,0 250,-150,0 250,150,0 -250,150,0"
    
                    TextureCoordinates="0,1 1,1 1,0 0,0"
    
                    TriangleIndices="0,1,2 0,2,3" />
     
    上面这段MeshGeometry3D(用于生成3-D形状的三角形基元)对照图2三维坐标系会发现是个从左下角逆时针绘制的矩形。如果要将一个窗体UserControl纹理应用到Viewport2DVisual3D上,我们就需要合理的设置TextureCoordinates(纹理坐标)。对照图1二维坐标系,纹理坐标同样是由左下开始绘制的矩形。这样设置,纹理就可以显示正常了。
     
    关于视角和距离的关系:
      
     
    含义:
    说明
    A 视点
       
    线 说明
    BC 查看的目标宽度
    bc 展示的视窗宽度
    AD 视点到查看目标的距离
    ad 视点到视窗的距离
       
    角度 说明
    cAb 视角(FieldOfView)
       
    结论:
    BD/bd=AD/Ad
     
    我们如果想看到一个原样大小的窗体,就需要设置我的角cAb为90。同时设置AD长度为查看目标的一半宽度。
     
     
     
     
    好不容易设置好Viewport3D,将UserControl作为窗体的查看对象,却发现虽然窗体大小一致,但是显示出的UserControl字体和控件却很模糊。当我们以3D模型渲染窗体时,WPF应该做了性能优化,然而我并不清楚如何开启高清模式= =。
    怎么解决这个问题呢?我试了好久,发现并没有比较简单快捷的解决方法。没办法,只能采取一些小技巧来解决啦。
     
    具体思路:
    第一步:窗体呈现时,将UserControl实例化后直接呈现到页面最前端的展示面板上,此时Viewport3D内容为空。
    第二部:触发页面翻转动画时,将最前的展示面板置空,UserControl实例剪切到Viewport3D里面。
    第三步:动画执行完毕后再从Viewport3D里面将UserControl剪切到页面最前端的展示面板中。
     
     示例代码:
    复制代码
    <Window x:Class="App3DWindow.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:app3DWindow="clr-namespace:App3DWindow"
            xmlns:asyncDelegate="clr-namespace:AsyncDelegate"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            Title="MainWindow"
            Width="500"
            Height="310"
            AllowsTransparency="True"
            Background="Transparent"
            Loaded="MainWindow_OnLoaded"
            WindowStyle="None"
            WindowStartupLocation="CenterScreen"
            mc:Ignorable="d">
        <Window.Resources>
            <Storyboard x:Key="Turn2ConfigViewStoryboard">
                <Rotation3DAnimationUsingKeyFrames Storyboard.TargetName="containerUIElement3D" Storyboard.TargetProperty="(Visual3D.Transform).(Transform3DGroup.Children)[2].(RotateTransform3D.Rotation)">
                    <EasingRotation3DKeyFrame KeyTime="0:0:2">
                        <EasingRotation3DKeyFrame.EasingFunction>
                            <QuinticEase EasingMode="EaseOut" />
                        </EasingRotation3DKeyFrame.EasingFunction>
                        <EasingRotation3DKeyFrame.Value>
                            <AxisAngleRotation3D Angle="180" Axis="0,1,0" />
                        </EasingRotation3DKeyFrame.Value>
                    </EasingRotation3DKeyFrame>
                </Rotation3DAnimationUsingKeyFrames>
            </Storyboard>
            <Storyboard x:Key="Turn2DownloadViewStoryboard">
                <Rotation3DAnimationUsingKeyFrames Storyboard.TargetName="containerUIElement3D" Storyboard.TargetProperty="(Visual3D.Transform).(Transform3DGroup.Children)[2].(RotateTransform3D.Rotation)">
                    <EasingRotation3DKeyFrame KeyTime="0:0:2">
                        <EasingRotation3DKeyFrame.EasingFunction>
                            <QuinticEase EasingMode="EaseOut" />
                        </EasingRotation3DKeyFrame.EasingFunction>
                        <EasingRotation3DKeyFrame.Value>
                            <AxisAngleRotation3D Angle="360" Axis="0,1,0" />
                        </EasingRotation3DKeyFrame.Value>
                    </EasingRotation3DKeyFrame>
                </Rotation3DAnimationUsingKeyFrames>
            </Storyboard>
            <!--  相机  -->
            <PerspectiveCamera x:Key="PerspectiveCamera"
                               FieldOfView="90"
                               LookDirection="0,0,-1"
                               NearPlaneDistance="1"
                               Position="0,0,250"
                               UpDirection="0,1,0" />
     
            <OrthographicCamera x:Key="OrthographicCamera"
                                Width="500"
                                LookDirection="0,0,-1"
                                Position="0,0,250"
                                UpDirection="0,1,0" />
        </Window.Resources>
        <Grid Background="Transparent">
            <Viewport3D Margin="0">
                <Viewport3D.Camera>
                    <!--  相机  -->
                    <PerspectiveCamera x:Name="PerspectiveCamera"
                                       FieldOfView="90"
                                       LookDirection="0,0,-1"
                                       NearPlaneDistance="1"
                                       Position="0,0,250"
                                       UpDirection="0,1,0" />
                </Viewport3D.Camera>
                <Viewport3D.Children>
                    <ContainerUIElement3D x:Name="containerUIElement3D">
                        <ContainerUIElement3D.Transform>
                            <Transform3DGroup>
                                <TranslateTransform3D OffsetX="0"
                                                      OffsetY="0"
                                                      OffsetZ="0" />
                                <ScaleTransform3D ScaleX="1"
                                                  ScaleY="1"
                                                  ScaleZ="1" />
                                <RotateTransform3D d:EulerAngles="0,0,0">
                                    <RotateTransform3D.Rotation>
                                        <AxisAngleRotation3D Angle="0" Axis="0,1,0" />
                                    </RotateTransform3D.Rotation>
                                </RotateTransform3D>
                                <TranslateTransform3D OffsetX="0"
                                                      OffsetY="0"
                                                      OffsetZ="0" />
                                <TranslateTransform3D OffsetX="0"
                                                      OffsetY="0"
                                                      OffsetZ="0" />
                            </Transform3DGroup>
                        </ContainerUIElement3D.Transform>
     
                        <!--  正面视角  -->
                        <Viewport2DVisual3D x:Name="FrontViewport2DVisual3D">
                            <Viewport2DVisual3D.Transform>
                                <Transform3DGroup>
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                    <ScaleTransform3D ScaleX="1"
                                                      ScaleY="1"
                                                      ScaleZ="1" />
                                    <RotateTransform3D d:EulerAngles="0,0,0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="0" Axis="0,0,0" />
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                </Transform3DGroup>
                            </Viewport2DVisual3D.Transform>
                            <Viewport2DVisual3D.Geometry>
                                <MeshGeometry3D Positions="-250,-150,0 250,-150,0 250,150,0 -250,150,0"
                                                TextureCoordinates="0,1 1,1 1,0 0,0"
                                                TriangleIndices="0,1,2 0,2,3" />
                            </Viewport2DVisual3D.Geometry>
                            <Viewport2DVisual3D.Material>
                                <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
                            </Viewport2DVisual3D.Material>
                            <Viewport2DVisual3D.Visual>
                                <app3DWindow:DownloadWindow x:Name="DownloadWindowPart"
                                                            Width="500"
                                                            Height="300"
                                                            Background="White"
                                                            SnapsToDevicePixels="True" />
                            </Viewport2DVisual3D.Visual>
                        </Viewport2DVisual3D>
                        <!--  背面视角  -->
                        <Viewport2DVisual3D x:Name="BackViewport2DVisual3D">
                            <Viewport2DVisual3D.Transform>
                                <Transform3DGroup>
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                    <ScaleTransform3D ScaleX="1"
                                                      ScaleY="1"
                                                      ScaleZ="1" />
                                    <RotateTransform3D d:EulerAngles="0,0,0">
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D Angle="0" Axis="0,0,0" />
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                    <TranslateTransform3D OffsetX="0"
                                                          OffsetY="0"
                                                          OffsetZ="0" />
                                </Transform3DGroup>
                            </Viewport2DVisual3D.Transform>
                            <Viewport2DVisual3D.Geometry>
                                <MeshGeometry3D Positions="-250,-150,0 250,-150,0 250,150,0 -250,150,0"
                                                TextureCoordinates="1,1 0,1 0,0 1,0   "
                                                TriangleIndices="0,3,2 0,2,1" />
                            </Viewport2DVisual3D.Geometry>
                            <Viewport2DVisual3D.Material>
                                <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
                            </Viewport2DVisual3D.Material>
                            <Viewport2DVisual3D.Visual>
                                <app3DWindow:ProxyConfigView x:Name="ProxyConfigViewPart"
                                                             Width="500"
                                                             Height="300"
                                                             Background="White"
                                                             SnapsToDevicePixels="True" />
                            </Viewport2DVisual3D.Visual>
                        </Viewport2DVisual3D>
                    </ContainerUIElement3D>
     
                    <ModelVisual3D>
                        <ModelVisual3D.Content>
                            <!--  光源  -->
                            <AmbientLight x:Name="ViewLight" />
                        </ModelVisual3D.Content>
                    </ModelVisual3D>
                </Viewport3D.Children>
            </Viewport3D>
            <Grid x:Name="DisplayGrid">
                <Grid.RowDefinitions>
                    <RowDefinition Height="40" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <UserControl x:Name="DisPlayControl"
                             Grid.Row="0"
                             Grid.RowSpan="2" />
                <!--<Border x:Name="Part_Drag"
                        Grid.Row="0"
                        Background="AliceBlue"
                        PreviewMouseLeftButtonDown="DisPlayControl_OnPreviewMouseLeftButtonDown" />-->
            </Grid>
        </Grid>
    </Window>
    复制代码
    复制代码
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media.Animation;
     
    namespace App3DWindow
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
            /// <summary>
            /// 载入时进行模糊情况特殊处理
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
            {
                //return;
                SetDownloadWindowDisplayMode();
                var turn2ConfigViewStoryboard = this.TryFindResource("Turn2ConfigViewStoryboard") as Storyboard;
                if (turn2ConfigViewStoryboard != null)
                {
                    turn2ConfigViewStoryboard.Completed += (s, e1) =>
                    {//动画执行完成切换展示模式
                        SetConfigViewDisplayMode();
                        SetDownloadWindowTurningMode();
                    };
                    turn2ConfigViewStoryboard.CurrentTimeInvalidated += (s, e1) =>
                    {//动画执行时切换成翻转模式
                        SetDownloadWindowTurningMode();
                    };
                };
                var turn2DownloadViewStoryboard = this.TryFindResource("Turn2DownloadViewStoryboard") as Storyboard;
                if (turn2DownloadViewStoryboard != null)
                {
                    turn2DownloadViewStoryboard.Completed += (s, e1) =>
                    {//动画执行完成切换展示模式
                        SetDownloadWindowDisplayMode();
                        SetConfigViewTurningMode();
                    };
                    turn2DownloadViewStoryboard.CurrentTimeInvalidated += (s, e1) =>
                    {//动画执行时切换成翻转模式
                        SetConfigViewTurningMode();
                    };
                };
            }
            /// <summary>
            /// 设置下载页面进入展示模式
            /// </summary>
            private void SetDownloadWindowDisplayMode()
            {
                //var container = DownloadWindowPart.Parent as Viewport2DVisual3D;
                //if (container == null) return;
                //container.Visual = null;
                if (FrontViewport2DVisual3D.Visual==(DownloadWindowPart))
                {
                    FrontViewport2DVisual3D.Visual = null;
                }
                DisPlayControl.Content = DownloadWindowPart;
            }
            /// <summary>
            /// 设置配置页面进入展示模式
            /// </summary>
            private void SetConfigViewDisplayMode()
            {
                //var container = ProxyConfigViewPart.Parent as Viewport2DVisual3D;
                //if (container == null) return;
                //container.Visual = null;
                if (BackViewport2DVisual3D.Visual==(ProxyConfigViewPart))
                {
                    BackViewport2DVisual3D.Visual = null;
                }
                DisPlayControl.Content = ProxyConfigViewPart;
            }
            /// <summary>
            /// 设置下载页面进入翻转模式
            /// </summary>
            private void SetDownloadWindowTurningMode()
            {
                var container = DownloadWindowPart.Parent as UserControl;
                if (container == null) return;
                container.Content = null;
                FrontViewport2DVisual3D.Visual = DownloadWindowPart;
            }
            /// <summary>
            /// 设置配置页面进入翻转模式
            /// </summary>
            private void SetConfigViewTurningMode()
            {
                var container = ProxyConfigViewPart.Parent as UserControl;
                if (container == null) return;
                container.Content = null;
                BackViewport2DVisual3D.Visual = ProxyConfigViewPart;
            }
            /// <summary>
            /// 支持拖拽
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void DisPlayControl_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                this.DragMove();
            }
        }
    }
    复制代码
     呈现效果:
    效果见下图,翻转动画执行完毕后不再模糊。
     
  • 相关阅读:
    Troubleshooting ORA-01555/ORA-01628/ORA-30036 During Export and Import (Doc ID 1579437.1)
    SRDC
    Troubleshooting ORA-01555
    ORA-01555 When Max Query Length Is Less Than Undo Retention, small or 0 Seconds (Doc ID 1131474.1)
    SRDC
    故障排除指南(TSG)-ORA-01552: Cannot Use System Rollback Segment for Non-System Tablespace (Doc ID 1579215.1)
    主说明:自动Undo管理的故障排除指南(Doc ID 1579081.1)
    vue指令
    day65
    vue基础
  • 原文地址:https://www.cnblogs.com/webenh/p/16105345.html
Copyright © 2020-2023  润新知