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" />

|
点
|
说明
|
|
A
|
视点
|
|
|
|
|
线
|
说明
|
|
BC
|
查看的目标宽度
|
|
bc
|
展示的视窗宽度
|
|
AD
|
视点到查看目标的距离
|
|
ad
|
视点到视窗的距离
|
|
|
|
|
角度
|
说明
|
|
cAb
|
视角(FieldOfView)
|
|
|
|
<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 解决透视模式时窗体模糊的更多相关文章
- 如何解决卸载McAfee时出现“处于托管模式时无法删除”问题(转)
问题现象: 这几天在为客户终端换装杀毒软件时出现这么一个问题:在控制面板的添加或删除程序里面将“McAfee VirusScan Enterprise和 McAfee AntiSpyware Ente ...
- WPF 在TextBox失去焦点时检测数据,出错重新获得焦点解决办法
WPF 在TextBox失去焦点时检测数据,出错重新获得焦点解决办法 在WPF的TextBox的LostFocus事件中直接使用Focus()方法会出现死循环的问题 正确的使用方式有2中方法: 方法一 ...
- [WPF疑难]避免窗口最大化时遮盖任务栏
原文 [WPF疑难]避免窗口最大化时遮盖任务栏 [WPF疑难]避免窗口最大化时遮盖任务栏 周银辉 WPF窗口最大化时有个很不好的现象是:如果窗口的WindowStyle被直接或间接地设置为None后( ...
- WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参
原文:WPF ContextMenu 在MVVM模式中绑定 Command及使用CommandParameter传参 ContextMenu无论定义在.cs或.xaml文件中,都不继承父级的DataC ...
- WPF中ItemsControl应用虚拟化时找到子元素的方法
原文:WPF中ItemsControl应用虚拟化时找到子元素的方法 wpf的虚拟化技术会使UI的控件只初始化看的到的子元素, 而不是所有子元素都被初始化,这样会提高UI性能. 但是我们经常会遇到一个 ...
- WPF Prism MVVM 中 弹出新窗体. 放入用户控件
原文:WPF Prism MVVM 中 弹出新窗体. 放入用户控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_37214567/artic ...
- C# WPF 一直保持多个Topmost窗体的置顶顺序
原文:C# WPF 一直保持多个Topmost窗体的置顶顺序 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37862405/article/ ...
- 解决Gradle编译时出现: 编码GBK的不可映射字符
解决Gradle编译时出现: 编码GBK的不可映射字符 在build.gradle文件中加入如下内容: [compileJava, compileTestJava]*.options*.encodin ...
- SpringMVC学习系列-后记 解决GET请求时中文乱码的问题
SpringMVC学习系列-后记 解决GET请求时中文乱码的问题 之前项目中的web.xml中的编码设置: <filter> <filter-name>CharacterEnc ...
随机推荐
- AndroidManifest.xml中声明权限——各种permission含义摘录
android.permission.EXPAND_STATUS_BAR 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序 android. ...
- MyBatis 学习记录7 一个Bug引发的思考
主题 这次学习MyBatis的主题我想记录一个使用起来可能会遇到,但是没有经验的话很不好解决的BUG,在特定情况下很容易发生. 异常 java.lang.IllegalArgumentExceptio ...
- iOS设计模式(01):观察者
iOS设计模式(01):观察者 iOS-Observer-Pattern 什么是观察者模式 什么是观察者模式?你曾经订阅过报纸吗?在订阅报纸的时候,你不用去任何地方,只需要将你的个人地址信息以及订阅信 ...
- Elasticsearch from+size 超过10000结果解决方法
方法一: 如果需要搜索分页,可以通过from size组合来进行.from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10, 如果搜索size大于10000,需要设置 ...
- 最近学习的sql查询语句连接查询,标记一下
select wordbase.name,wb.name,wordconnection.wordid,wordconnection.aid,wordbase.goodsid,goods.hscode, ...
- C#窗体中将窗体按钮与键盘关联
当击了某个按钮相当于是按了某个键盘上按键 private void btnPre_Click(object sender, EventArgs e) { this.treeView1.Focu ...
- Linux实战教学笔记48:openvpn架构实施方案(一)跨机房异地灾备
第一章VPN介绍 1.1 VPN概述 VPN(全称Virtual Private Network)虚拟专用网络,是依靠ISP和其他的NSP,在公共网络中建立专用的数据通信网络的技术,可以为企业之间或者 ...
- Linux实战教学笔记20:初级阶段结束,中级阶段起航
第二十节 第一阶段结束第二阶段起航 标签(空格分隔): Linux实战教学笔记-陈思齐 一,承上 Linux实战教学笔记的基础核心能力阶段也就是第一阶段到此也就告一段落了.如果同学们能基本全都掌握,再 ...
- 压缩包法安装mysql
之前一直安装mysql,我一直是用压缩包安装的.如果之前安装过Mysql,必须要删除注册文件,才能把Mysql彻底删除了. 先在官网下载mysql的版本.下载package版本,即.zip版本的.下载 ...
- @property 修饰符
原子性--- nonatomic 特质 在默认情况下,由编译器合成的方法会通过锁定机制确保其原子性(atomicity).如果属性具备 nonatomic 特质,则不使用同步锁.请注意,尽管没有名为“ ...