原文:WPF Viewport3D 解决透视模式时窗体模糊

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

三维图形概述:

https://msdn.microsoft.com/zh-cn/library/ms747437.aspx

概要

三维坐标系


       二维图形的 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();}}
}

呈现效果:
效果见下图,翻转动画执行完毕后不再模糊。

WPF Viewport3D 解决透视模式时窗体模糊相关推荐

  1. Visio生成高清PDF的方法:解决生成PDF时图片模糊、文字变形等问题

    选择打印生成PDF,而不是直接另存为PDF 尽量选择大的纸张打印成PDF,之后再进行裁剪: 在上图中的"页面设置"里把打印缩放比调高: 打印生成PDF,并利用Adobe Acrob ...

  2. 如何解决卸载McAfee时出现“处于托管模式时无法删除”问题

     如何解决卸载McAfee时出现"处于托管模式时无法删除"问题 问题现象: 这几天在为客户终端换装杀毒软件时出现这么一个问题:在控制面板的添加或删除程序里面将"McA ...

  3. 【已解决】leaflet-geoman启用编辑模式时,map上所有(marker、polyline、Polygon等)元素处于编辑状态

    文章目录 leaflet-geoman启用编辑模式时,map上所有(marker.polyline.Polygon等)元素处于编辑状态特别影响体验,尤其是使用了L.motion后,由于切割较碎导致数据 ...

  4. WPF中的MVVM模式

    WPF中的MVVM模式 WPF中的MVVM模式                                               周银辉 "设计模式"这样的话题似乎快被园 ...

  5. [WPF疑难]避免窗口最大化时遮盖任务栏

    [WPF疑难]避免窗口最大化时遮盖任务栏 周银辉 WPF窗口最大化时有个很不好的现象是:如果窗口的WindowStyle被直接或间接地设置为None后(比如很多情况下你会覆盖默认的窗体样式,即不采用W ...

  6. mysql %和正则_mysql 正则模式和like模糊查询

    MySql like模糊查询使用详解 一.SQL的模式匹配允许你使用"_"匹配任何单个字符,而"%"匹配任意数目字符(包括零个字符).在 MySQL中,SQL的 ...

  7. 解决多进程模式下引起的“惊群”效应

    导语: 对不起,我是标题党,本文解决的不是我们理解的"惊群"效应,先为我们操作系统组的正下名,因为腾讯服务器的内核版本,已经解决epoll模式下的惊群现象(本文描述的现象跟惊群其实 ...

  8. 打开模式时防止BODY滚动

    本文翻译自:Prevent BODY from scrolling when a modal is opened I want my body to stop scrolling when using ...

  9. sublime 下 解决Vintage模式下,normal 模式下中文输入的问题。

    * sublime 下 解决Vintage模式下,normal 模式下中文输入的问题.* 大家好,相信有不少sublime 铁粉在vintage 模式下,使用vim 快捷键时,在转换normal 与 ...

最新文章

  1. Python:列表前加*的作用
  2. 汇编 加法减法指令 inc dec add sub neg 标志寄存器测试
  3. Oracle查询表结构的一些相关语句
  4. en45545防火标准_揭秘:600岁故宫如何防火?
  5. android各种color值
  6. java char 空_2020重新出发,JAVA入门,数据类型
  7. php 修改文件访问时间,PHP中获取文件创建日期、修改日期、访问时间的方法
  8. 政府门户应该怎样建设?——解读中国政府网站绩效评估标准
  9. C++ 构造函数 与 析构函数
  10. Allegro16.6导出位号图
  11. 吴恩达机器学习编程作业
  12. jmeter性能测试2-模拟多用户登录
  13. 设计模式:设计模式经典总结
  14. 【Linux云计算架构:第三阶段-Linux高级运维架构】第26章——tcp三次握手四次挥手及在局域网中使用 awl伪装MAC地址进行多线程SYN攻击
  15. 不礼让行人怎么抓拍的_斑马线前不礼让行人抓拍处罚,到底怎么才算
  16. 短视频的特点和分类——今抖云创
  17. Visual Stdio C++ 编译器 编译 (GSL) GNU Scientific Library 的方法介绍(5)
  18. word内多级列表标题变成黑块解决办法
  19. 软件工程知识-软件测试
  20. 如何开始人工智能之旅: 技术路径不只一条,您的选择也不只一个

热门文章

  1. oauth2 增加token 返回参数_RingCentral Tech | OAuth2.0面面观
  2. Hive Serde、Beeline、JDBC
  3. Java深拷贝与浅拷贝
  4. 【Android View绘制体系】requestLayout
  5. 字符串大小写转换通用函数
  6. Flutter中通过循环渲染组件
  7. Django生命周期
  8. 约会安排 (区间合并)毒瘤题
  9. 第一个hibernate程序HelloWorldHibernate
  10. OpenGL入门学习(十二) 【转】