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;
}
}

  接下来我们就来看一下这两个变换方法的具体实现:

垂直变换:

 
private void VerticalTransform(bool upDown, double angleDeltaFactor)
{
    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);
}
 

最后还有一个鼠标滚轮调节视距的变换,如下:

 
private void Viewport3D_MouseWheel(object sender, MouseWheelEventArgs e)
{
    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;
        }
    }

    if (e.Delta == -120)//getting far
    {
        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变换应用的更多相关文章

  1. WPF 3D 小小小小引擎 - ·WPF 3D变换应用

    原文:WPF 3D 小小小小引擎 - ·WPF 3D变换应用 WPF可以提供的3D模型使我们可以轻松地创建3D实体,虽然目前来看还很有一些性能上的问题,不过对于一些简单的3D应用应该是可取的,毕竟其开 ...

  2. WPF 3D:使用变换中的TranslateTransform3D

    原文:WPF 3D:使用变换中的TranslateTransform3D 程序效果: WPF 3D中的TranslateTransform3D应该是所有3D变换中最简单的变换,使用起来非常简单,先定义 ...

  3. WPF中的3D变换PlaneProjection

    在UWP中有一个比较好用的伪3D变换PlaneProjection,可以以一种轻量级和非常简单的方式实现3D的效果.这种效果在Silverlight中也有这种变换,但在WPF中确一直没有提供. 虽然W ...

  4. WPF 3D 知识点大全以及实例

    引言 现在物联网概念这么火,如果监控的信息能够实时在手机的客服端中以3D形式展示给我们,那种体验大家可以发挥自己的想象. 那生活中我们还有很多地方用到这些,如上图所示的Kinect 在医疗上的应用,当 ...

  5. 最优化WPF 3D性能(基于“Tier-2”硬件)

    原文:最优化WPF 3D性能(基于"Tier-2"硬件) 原文地址:Maximizing WPF 3D Performance on Tier-2 Hardware 开发人员在应用 ...

  6. CSS3之3d变换与关键帧

    3d变换是在transform基础上实现的 transform-style:preserve-3d; 建立3d空间 perspective:; 景深(设置用户看的距离) perspective-ori ...

  7. 关于ios 3D变换 CGAffineTransformIdentity

    每次做完3D变换以后,重新设置view的frame时,记得用CGAffineTransformIdentity 对3D变换进行还原,否则将会影响frame.当你对view进行3D变换后,重新设置vie ...

  8. CSS3之3D变换实例详解

    CSS3的3D效果很赞,本文实现简单的两种3D翻转效果.首先看效果和源代码,文末是文绉绉的总结部分^_^ 以下CSS代码为了简洁没有添加前缀,请视情况自行添加(自动化时代推荐使用其他的一些方法,如gu ...

  9. 优化WPF 3D性能

    Maximize WPF 3D Performance .NET Framework 4.5   As you use the Windows Presentation Foundation (WPF ...

随机推荐

  1. [Angular] FadeIn and FadeOut animation in Angular

    To define an Angular Animation, we using DSL type of language. Means we are going to define few anim ...

  2. 全面解析Activity的生命周期

    欢迎Follow我的GitHub, 关注我的CSDN. 在Android应用中, Activity是最重要的组件, 其生命周期(Lifecycle)被大家所熟知. 可是, 大家须要注意一些细节, 才干 ...

  3. ajax日期參数格式问题

    今天遇到ajax传输日期參数后台无法识别的问题,错误异常例如以下. 从异常中能够看出传输到后台的日期数据格式为Thu Aug 13 2015 19:45:20 GMT+0800 (中国标准时间),这样 ...

  4. C#调用oracle存储过程自定义表类型

    http://blog.csdn.net/studyzy/article/details/11524527

  5. bow lsa plsa

    Bag-of-Words (BoW) 模型是NLP和IR领域中的一个基本假设.在这个模型中,一个文档(document)被表示为一组单词(word/term)的无序组合,而忽略了语法或者词序的部分.B ...

  6. ZOJ 1108 FatMouse's Speed (HDU 1160) DP

    传送门: ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=108 HDU :http://acm.hdu.edu.cn/s ...

  7. 35、在JZ2440上使用3G上网卡

    1. 简单使用:1.1 选型:中国联通:E网时空 EW65 (64元), ZTE中兴 MF637U (160多)中国电信:Benton/本腾 EQ10B (35元)中国移动:华为 ET128 (99元 ...

  8. Linux 系统 杀Oracle 进程

    Linux 系统 杀Oracle 进程 杀掉进程用此方法比较好,能保证杀得干净,而不是用SQL  alter system kill kill -9 `ps -ef|grep "oracle ...

  9. term- xshell VS securecrt

    Xshell使用技巧总结 https://www.cnblogs.com/zhangwuji/p/7155575.html SecureCRT与Xshell简单对比 http://ju.outofme ...

  10. com.octo.captcha.service.CaptchaServiceException: Invalid ID, could not validate unexisting o

    <p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"& ...