WPF 3D变换应用
WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开发效率高,而且也容易上手。
下面给大家演示的是使用在WPF 3D上实现视角变换,通过鼠标拖动来变换观察视角,通过滚轮来放缩视距。
首先创建一个3D立方体,立方体是由六个面构成(F1, F2 ....F6)其XAML代码如下:
<Viewport3D>
<Viewport3D.Camera>
<!--<camera Position="15,15,15" LookDirection="-1,-1,-1" Width="15"></camera>-->
<!--<camera Position="-5,-5,-5" LookDirection="1,1,1" Width="10" x:Name="camera"></camera>-->
<!--<PerspectiveCamera Position="-5,-5,-5" LookDirection="1 1 1" FieldOfView="90"></PerspectiveCamera>-->
<!--<PerspectiveCamera Position="-4,-4,-4" LookDirection="1 1 1" FieldOfView="75" x:Name="camera"></PerspectiveCamera>-->
<PerspectiveCamera Position="8,8,8" LookDirection="-1 -1 -1" FieldOfView="75" UpDirection="-1 1 -1" x:Name="camera"></PerspectiveCamera>
</Viewport3D.Camera>
<Viewport3D.Children>
<ModelVisual3D x:Name="light">
<ModelVisual3D.Content>
<AmbientLight />
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D x:Name="magicCube">
<ModelVisual3D.Content>
<!-- 0: 0,0,0 1: 0,0,2 2: 2,0,2 3: 2,0,0 4: 2,2,0 5: 0,2,0 6: 0,2,2 7: 2,2,2 -->
<Model3DGroup x:Name="cube">
<Model3DGroup.Transform>
<TranslateTransform3D OffsetX="-1" OffsetY="-1" OffsetZ="-1" />
</Model3DGroup.Transform>
<!--F1: 0,3,2,1-->
<GeometryModel3D x:Name="F1">
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Blue"/>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,0,0 2,0,0 2,0,2 0,0,2" TriangleIndices="0,1,2 0,2,3"></MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!--F2: 0,1,6,5-->
<GeometryModel3D x:Name="F2">
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Green"/>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="0,0,0 0,0,2 0,2,2 0,2,0" TriangleIndices="0 1 2 0 2 3"></MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!--F3: 4,5,6,7-->
<GeometryModel3D x:Name="F3">
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions="2,2,0 0,2,0 0,2,2 2,2,2" TriangleIndices="0 1 2 0 2 3"></MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!--F4: 2,3,4,7-->
<GeometryModel3D x:Name="F4">
<GeometryModel3D.Material>
<!--<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush>
<VisualBrush.Visual>
<Image Source="cubesurface.jpg">
<Image.Style>
<Style>
<Setter Property="Image.Opacity" Value="0.6"></Setter>
</Style>
</Image.Style>
</Image>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>-->
<DiffuseMaterial Brush="Yellow"/>
</GeometryModel3D.Material> <GeometryModel3D.Geometry>
<MeshGeometry3D Positions="2,0,2 2,0,0 2,2,0 2,2,2" TriangleIndices="0 1 2 0 2 3" TextureCoordinates="0,0 0,1 1,1 1,0">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!--F5: 1,2,7,6-->
<GeometryModel3D x:Name="F5">
<GeometryModel3D.Material>
<DiffuseMaterial Brush="White"/>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions=" 0,0,2 2,0,2 2,2,2 0,2,2" TriangleIndices="0 1 2 0 2 3"></MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
<!--F6: 0,5,4,3-->
<GeometryModel3D x:Name="F6">
<GeometryModel3D.Material>
<DiffuseMaterial Brush="Orange"/>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions=" 0,0,0 0,2,0 2,2,0 2,0,0" TriangleIndices="0 1 2 0 2 3"></MeshGeometry3D>
</GeometryModel3D.Geometry>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
在Viewport中用六个面构成一个立方体, 每一个面都是一个GeometryModel3D。
下面就是如何来实现通过鼠标拖动来变换视角的功能。首先给Window对象添加几个有关的鼠标的事件:MouseMove、MouseLeftButtonDown和MouseWheel。
<Window x:Class="MagicCube.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="295" Width="525" Background="Black"
MouseMove="Viewport3D_MouseMove"
MouseLeftButtonDown="Viewport3D_MouseLeftButtonDown"
MouseWheel="Viewport3D_MouseWheel"
KeyDown="Window_KeyDown">
<Viewport3D …>
</Window>
说明一下使用到的几个变量:
其中MouseLeftButtonDown是用来获取鼠标在进入拖动状态之前的位置,这样我们就可以根据鼠标位置的改变类变换视角。
Point mouseLastPosition;
private void Viewport3D_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
mouseLastPosition = e.GetPosition(this);
}
下面是MouseMove事件,实现视角的变换。首先鼠标在拖动的过程中,可能发生水平方向上的变化和垂直方向上的变化,所以,我们将对不同的变化方向进行不同的变换。这里我将水平变换和垂直变换已经分别封装至两个方法中:HorizontalTransform(水平变换)和VerticalTransform(垂直变换)
private void Viewport3D_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
Point newMousePosition = e.GetPosition(this);
if (mouseLastPosition.X != newMousePosition.X)
{
HorizontalTransform(mouseLastPosition.X < newMousePosition.X, mouseDeltaFactor);//水平变换
} if (mouseLastPosition.Y != newMousePosition.Y)// change position in the horizontal direction
{
VerticalTransform(mouseLastPosition.Y > newMousePosition.Y, mouseDeltaFactor);//垂直变换
} mouseLastPosition = newMousePosition;
}
}
接下来我们就来看一下这两个变换方法的具体实现:
垂直变换:
{
Vector3D postion = new Vector3D(camera.Position.X, camera.Position.Y, camera.Position.Z);
Vector3D rotateAxis = Vector3D.CrossProduct(postion, camera.UpDirection);
RotateTransform3D rt3d = new RotateTransform3D();
AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, angleDeltaFactor * (upDown ? -1 : 1));
rt3d.Rotation = rotate;
Matrix3D matrix = rt3d.Value;
Point3D newPostition = matrix.Transform(camera.Position);
camera.Position = newPostition;
camera.LookDirection = new Vector3D(-newPostition.X, -newPostition.Y, -newPostition.Z);
//update the up direction
Vector3D newUpDirection = Vector3D.CrossProduct(camera.LookDirection, rotateAxis);
newUpDirection.Normalize();
camera.UpDirection = newUpDirection;
}
private void HorizontalTransform(bool leftRight, double angleDeltaFactor)
{
Vector3D postion = new Vector3D(camera.Position.X, camera.Position.Y, camera.Position.Z);
Vector3D rotateAxis = camera.UpDirection;
RotateTransform3D rt3d = new RotateTransform3D();
AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, angleDeltaFactor * (leftRight ? -1 : 1));
rt3d.Rotation = rotate;
Matrix3D matrix = rt3d.Value;
Point3D newPostition = matrix.Transform(camera.Position);
camera.Position = newPostition;
camera.LookDirection = new Vector3D(-newPostition.X, -newPostition.Y, -newPostition.Z);
}
最后还有一个鼠标滚轮调节视距的变换,如下:
{
double scaleFactor = 3;
//120 near , -120 far
System.Diagnostics.Debug.WriteLine(e.Delta.ToString());
Point3D currentPosition = camera.Position;
Vector3D lookDirection = camera.LookDirection;//new Vector3D(camera.LookDirection.X, camera.LookDirection.Y, camera.LookDirection.Z);
lookDirection.Normalize();
lookDirection *= scaleFactor;
if (e.Delta == 120)//getting near
{
if ((currentPosition.X + lookDirection.X) * currentPosition.X > 0)
{
currentPosition += lookDirection;
}
}
{
currentPosition -= lookDirection;
}
Point3DAnimation positionAnimation = new Point3DAnimation();
positionAnimation.BeginTime = new TimeSpan(0, 0, 0);
positionAnimation.Duration = TimeSpan.FromMilliseconds(100);
positionAnimation.To = currentPosition;
positionAnimation.From = camera.Position;
positionAnimation.Completed += new EventHandler(positionAnimation_Completed);
camera.BeginAnimation(PerspectiveCamera.PositionProperty, positionAnimation, HandoffBehavior.Compose);
}
有了这个小程序之后,我们以后如果需要制作WPF 3D实体,也可以通过它来360度全方位地观测构建的3D实体。
WPF 3D变换应用的更多相关文章
- WPF 3D 小小小小引擎 - ·WPF 3D变换应用
原文:WPF 3D 小小小小引擎 - ·WPF 3D变换应用 WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开 ...
- WPF 3D:使用变换中的TranslateTransform3D
原文:WPF 3D:使用变换中的TranslateTransform3D 程序效果: WPF 3D中的TranslateTransform3D应该是所有3D变换中最简单的变换,使用起来非常简单,先定义 ...
- WPF中的3D变换PlaneProjection
在UWP中有一个比较好用的伪3D变换PlaneProjection,可以以一种轻量级和非常简单的方式实现3D的效果.这种效果在Silverlight中也有这种变换,但在WPF中确一直没有提供. 虽然W ...
- WPF 3D 知识点大全以及实例
引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...
- 最优化WPF 3D性能(基于“Tier-2”硬件)
原文:最优化WPF 3D性能(基于"Tier-2"硬件) 原文地址:Maximizing WPF 3D Performance on Tier-2 Hardware 开发人员在应用 ...
- CSS3之3d变换与关键帧
3d变换是在transform基础上实现的 transform-style:preserve-3d; 建立3d空间 perspective:; 景深(设置用户看的距离) perspective-ori ...
- 关于ios 3D变换 CGAffineTransformIdentity
每次做完3D变换以后,重新设置view的frame时,记得用CGAffineTransformIdentity 对3D变换进行还原,否则将会影响frame.当你对view进行3D变换后,重新设置vie ...
- CSS3之3D变换实例详解
CSS3的3D效果很赞,本文实现简单的两种3D翻转效果.首先看效果和源代码,文末是文绉绉的总结部分^_^ 以下CSS代码为了简洁没有添加前缀,请视情况自行添加(自动化时代推荐使用其他的一些方法,如gu ...
- 优化WPF 3D性能
Maximize WPF 3D Performance .NET Framework 4.5 As you use the Windows Presentation Foundation (WPF ...
随机推荐
- 短网址ShortUrl的算法
场景: 我们在新浪微博上公布网址的时候.微博会自己主动判别网址.并将其转换.比如:http://t.cn/hrYnr0. 为什么要这样做的,原因我想有这样几点: 1.微博限制字数为140字一条,那么假 ...
- Altium Designer设置走线间距
- 【Codeforces Round #440 (Div. 2) C】 Maximum splitting
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 肯定用尽量多的4最好. 然后对4取模的结果 为0,1,2,3分类讨论即可 [代码] #include <bits/stdc++ ...
- RISC-V工具链环境(基于Debian/Linux操作系统)
RISC-V工具链环境(基于Debian/Linux操作系统) 提要 Debian/Linux虚拟机导入 启动虚拟机 SiFive/Nuclei SDK运行指南 Debian/Linux虚拟机存储位置 ...
- 切换根控制器UIApplication 主屏幕UIScreen 读取文件资源NSBundle
//主屏幕设为webView CGRect frame = [UIScreen mainScreen].applicationFrame; UIWebView *webView = [[[UIWebV ...
- BZOJ 2245 SDOI 2011 工作安排 费用流
题目大意:有一些商品须要被制造.有一些员工.每个员工会做一些物品,然而这些员工做物品越多,他们的愤慨值越大,这满足一个分段函数.给出哪些员工能够做哪些东西,给出这些分段函数,求最小的愤慨值以满足须要被 ...
- leetcode-combination sum and combination sum II
Combination sum: Given a set of candidate numbers (C) and a target number (T), find all unique combi ...
- tomcat总体架构
Tomcat 总体结构图 从上图中可以看出Tomcat的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍.Connector 组件是可以被替换,这样可以提供给 ...
- crontab经验 分类: B3_LINUX 2015-03-06 11:17 282人阅读 评论(0) 收藏
1.基本格式 第1列分钟1-59 第2列小时1-23(0表示子夜) 第3列日1-31 第4列月1-12 第5列星期0-6(0表示星期天) 第6列要运行的命令 2.关于日志 (1)基本日志位 ...
- 【27.85%】【codeforces 743D】Chloe and pleasant prizes
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...