3DTools TrackballDecorator实现3D漫游

简介: 原文:3DTools TrackballDecorator实现3D漫游 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37591671/article/details/68063660 1.基本原理 WPF提供的TrackballDecorator类用来实现三维漫游功能。
原文: 3DTools TrackballDecorator实现3D漫游

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37591671/article/details/68063660

1.基本原理

WPF提供的TrackballDecorator类用来实现三维漫游功能。TrackballDecorator可以看做是在Viewport3D后面的一个虚拟球面,当鼠标点击TraclcballDecorator投影在Viewport3D的这个平面内时,可以在球面上找到与鼠标在平面上面一一对应的一个点。当鼠标运动的时候,照相机根据鼠标的运动来旋转,以此来保证鼠标在这个虚拟球面上的位置是不变的。这样就完成了把把鼠标的二维运动转换为三维运动。下面以一个立方体为模型,简单说明一下上述过程。


图1.1 Viewport3D与TtackballDecorator位置关系



图1.2 鼠标垂直拖动

图1-2表示当鼠标进行垂直移动的时候,球面绕X轴进行旋转,来保证鼠标在球面上的位置是不变的,同时球面内的模型会跟随球面运动,就能得到预期的效果。

2.实现过程

对于每次鼠标移动,都需要计算一个旋转来保证鼠标在球面上的位置是不变的。因此需要做以下两个工作:首先,确定鼠标在球面上的位置;其次,计算鼠标从一个点移动到另一个点所进行的旋转。为了找到鼠标在球体上对应的点,将UIElement坐标系中的二维点投影到的Viewport3D内部的球面上。

(1)首先如何将二维点映射到Viewport3D内部球面呢?下面显示了两个坐标系。


2.1 二维坐标系


2.2 三维坐标系

如图2-1所示,鼠标显示了其在UIElement坐标系中的位置,原点(0,0)位于坐标系的左上角。在图2-2中把鼠标映射到Viewport3D内部的球面上,鼠标的坐标也变换为了三维坐标系中的坐标。

由于最终的目的是得到相机的旋转,因此可以选择最简单的TrackballDecorator球面坐标系,因此可以假定这个球面半径为1,其圆心为坐标系的原点(0,0,0)。只需要构建一个[0,0]—[2,2]的Viewport3D,然后将原点从左上角移动至中心,这样 ViewportsD 就变成了从[-1,1]一[1,-1]。如图 2-3,图 2-4 所示。


2.3 建一个宽、高为2的Viewport3D


2.4 将原点平移至中心

假设鼠标在UIElement坐标系的坐标为(Px, Py),在TrackballDecorator坐标系中的坐标为(x,y, z)那么可得出x,y点坐标如式2-1,2-2所示。

                                                             


根据球面半径,就能得到Z坐标如式2-3所示。



获取三维坐标信息代码:

private Vector3D ProjectToTrackball(double width, double height. Point point)
{
double X = point.X / (width / 2);
double y = point. Y / (height / 2);
X = X - 1;
y = 1 - y;
double z2=l-x*x-y*y;
double z = z2 > 0 ? Math.Sqrt(z2): 0;
return new Vector3D(x, y, z);
}

这样就得到了鼠标在球面上的坐标(x,y,z)对于鼠标的每次拖动,都需要构建一个旋转,使得鼠标在球面上的位置保持不变。因此需要记录鼠标拖动之前的坐标,和鼠标拖动到当前位置的旋转。为了得到这个旋转需要计算旋转轴和旋转角度。



2.3用向量来描述鼠标的拖动

如图2.3所示向量VI和向量V2分别为原点到鼠标拖动前所在位置和拖动后所在位置的向量。可以简单计算得到旋转轴Axis和旋转角度0,如式2-4、2-5所示。


//根据右手定则,两向量叉乘,确定垂直两向量的轴,即旋转轴




Θ为球面的旋转角度,取Θ的相反数就得到了照相机的旋转角度,当有了旋转轴和旋转角度就可以控制的照相机去进行旋转。

//响应漫游

private void Track(Point currentPosition)
{
Vector3D currentPosition3D =ProjectToTrackball(
EventSource.Actual Width,EventSource.ActualHeight,
currentPosition);

Vector3D axis =Vector3D.CrossProduct(_previousPosition3D,
currentPosition3D);
double angle =Vector3D.AngleBetween(_previousPosition3D,
currentPosition3D);
Quaternion delta = new Quaternion(axis, -angle);
AxisAngleRotation3D r = _rotation;
Quaternion q = new Quatemion(_rotation.Axis, _rotation.Angle);
q*= delta;
_rotation.Axis = q.Axis;
_rotation.Angle = q.Angle;
_previousPosition3 D = currentPosition3D;
}
3.源代码

点击打开链接


目录
相关文章
|
数据采集 算法 JavaScript
彩票中奖率的真相:用 JavaScript 看透彩票背后的随机算法(上)
原本这篇文章是打算叫「假如我是彩票系统开发者」,但细想一下,如果在文章中引用太多的 JavaScript 的话,反而不是那么纯粹,毕竟也只是我的一厢情愿,彩票开发也不全如本文所讲,有所误导的话便也是得不偿失了。
|
C# C++
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
2470 0
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
|
C# Windows
【WPF】自动完成/智能提示的文本框(AutoCompleteBox)
原文:【WPF】自动完成/智能提示的文本框(AutoCompleteBox) 使用了插件WPFToolKit。(直接在Nuget中搜即可) 使用方法参考这篇文章: http://www.
2323 0
|
开发框架 缓存 前端开发
基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求
基于SqlSugar的开发框架循序渐进介绍(23)-- Winform端管理系统中平滑增加对Web API对接的需求
|
12月前
|
C#
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
|
10月前
|
API C# 开发者
基于Material Design风格开源、免费的WinForms UI控件库
基于Material Design风格开源、免费的WinForms UI控件库!
241 0
|
关系型数据库 Java MySQL
C#winform中使用SQLite数据库
C#winform中使用SQLite数据库
440 3
C#winform中使用SQLite数据库
|
开发框架 前端开发 JavaScript
基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面
基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面
|
新能源
从零开始做逆变器系列文章之逆变原理
从零开始做逆变器系列文章之逆变原理
从零开始做逆变器系列文章之逆变原理
|
Java Linux Maven
JAR文件可能已经损坏或无法正确打开
JAR文件可能已经损坏或无法正确打开
527 1