为了生成曲线,函数需要通过4个在沿着重量值在0和1之间的路径上连贯的位置。由于重量在这些2个值之间增加,曲线返回在更远的路径上的坐标。

当所提供的重量值为0,曲线将返回正确的坐标在第二个输入坐标。当所提供的重量值为1,曲线将返回一个准确的坐标在第三个输入位置。然而,所有4个值在这些计算中来使用, 来确保在第二个和第三个位置之间的平滑路径,并同样向前进到下一组运行点。

这个可以使用图表来举例说明,在图所示。如果使用点0,1,2和3来计算曲线,重量在0.0,由此产生的位置会是1。如果重量增加到1.0,曲线坐标轨迹将沿着在点1和点2之间的线,当重量到达1.0,将到达点2。注意,从这个点的,曲线坐标没有返回值在线上,朝点0或点3,即使它们将通过曲线函数:这些外部点仅使用来计算在中心的2个点之间的曲线角度。

一旦重量到达1.0,曲线可以移动到下一组点,进入点1,2,3和4。然后重量再次从0.0增加到1.0后,导致计算的坐标,沿着点2和点3之间的线。

从这组点,它不可能返回在点0和1之间的曲线坐标,或者在点4和5之间(图表中显示灰色),有要处理的路径这些部分的不足外部点。

通过在点到点之间的移动路径,一个平滑曲线可以减少,穿过所有定义的位置。这一切在三维空间也能做的很好。

提示:当定义一个路径,别忘记它将采取完全相同的大量时间在每一个连贯的路径点之间移动。因此,你应该尝试去确保点近似等距。点有不同于其它的大的差距将导致更快的移动,在固定时间间隔内穿过增加的距离,点更接近在一起将导致移动缓慢,因为少距离必须要去移动。

为了创建一个封闭的路径,允许飞机去循环,无缝的回到它最初的点再重新开始,我们必须确保最终的曲线的三个点与三个点的第一个相同。当三个点的重量到达1.0时,曲线坐标将终于到达回正确的在移动路径上的点1的位置,允许整个路径从再次从最开始就可以被跟踪。

我们在PaperPlaneObject代码中实现它,通过存储2个类级变量,一个int值称为_splineIndex,它定义4个点的第一个索引来使用曲线计算;一个浮点值称为_splineWeight,它允许我们来沿着曲线在定义点之间穿过路径。

在Update函数中,我们添加一个小的总额到_splineWeight变量中。如果它到达或超过1.0,我们要将它减1.0,并增加_splineIndex。如果_splineIndex通过移动路径的最后的数组点,它重新设置回开始。这些更新沿着曲线移动飞机,并当它到达它的移动路径的重点后,重新设置回起点。

在这些更新模式下,我们调用GetPlanePosition函数来执行曲线计算,并返回最终飞行坐标。这个函数,期望曲线索引和曲线重量值来作为参数来传递,下面代码将描述。

private Vector3 GetPlanePosition(int splineIndex, float  splineWeight)
{Vector3 ret;// If the  weight  exceeds 1,  reduce by 1 and move  to  the  next  index if (splineWeight > 1){splineWeight  -=  1;splineIndex += 1;}// Keep  the  spline index  within the  array  boundssplineIndex = splineIndex %   _movementPath.Length;// Calculate  the  spline positionret = Vector3.CatmullRom(_movementPath[splineIndex],_movementPath[(splineIndex + 1)  %   _movementPathLength],_movementPath[(splineIndex + 2)  %   _movementPathLength],_movementPath[(splineIndex + 3)  %   _movementPathLength], splineWeight);return ret;
}

这代码首先检查曲线重量是否大于1。如果是,它就减去1并且切换到下一个曲线索引(我们将一会儿看到这个原因)。其次是检查循环曲线索引,是否它超过_movementPath数组项目的界限。

曲线坐标然后会简单的计算,通过传递4个矢量坐标和曲线重量到Vector3.CatmullRom函数。注意,然而,因为我们在曲线索引指上使用指数运算符,如果它们超过数组长度,它们会循环回到最初的开始。这个运算允许我们去实现我们的闭合环路(要求重复前3个点),而不必实际在数组中重复它们:它们只是一开始就重复使用,当到达数组末尾时。

随着有能力手动去计算飞行坐标,我们现在可以设置飞行的坐标和沿着轨迹去平滑移动。这是好的开始,但这是非常明显的可视化问题,当它在运动时:飞行总是对着同一个方向。当然,总是朝着移动的方向(纸飞机通常来说不会侧面飞行的很好)。

幸运的是,这是非常容易让飞行看上去它是正在飞行的。我们需要做的第一件事是计算另一个飞行坐标,仅远一点沿着轨迹。我们通过调用GetPlanePosition函数,在1秒钟内来完成它,这个时候添加0.1到曲线重量中。此外的原因是GetPlanePosition函数检查是否重量超过1.0,因为这一秒可以引起溢出的发生。

第二个调用允许我们看到现在在哪里飞行,下一秒后将会在哪里。飞行的方向必须从这些点到下一秒所在的点,因为它的轨迹是移动的。因此我们需要一个旋转飞机的方法以便它面朝从第一个位置到下一个秒所要到的位置。

这个旋转可以使用另一个便利的静态的矩阵函数来完成:CreateWorld。CreateWorld函数创建一个世界矩阵(它是最后我们要在每一个对象的Update方法中尝试去做的)以便它放置在特别的位置上,面对特别的方向。这就是我们所需要的:位置是我们已计算出来的第一条曲线,方向从这到下一条曲线点。

通过从下一个位置减去当前位置来简单计算方向。由此产生的矢量准备作为参数传递给CreateWorld。

有一个小问题任然存在:飞机是持续向一侧飞行的,因为它的一侧已经在SketchUp模式下定义了。要修正这个问题,矩阵计算后,我们简单旋转90度角来旋转它。

计算位置和飞行方向的完整代码如下代码所示。

// Calculate  the  current position and store  in the  Position property
Vector3 Position = GetPlanePosition(_splineIndex, _splineWeight);// Calculate  the  next  position too  so we  know  which way we  are moving
Vector3 nextPosition = GetPlanePosition(_splineIndex, _splineWeight  + 0.1f);// Find the  movement  direction
Vector3 delta  = nextPosition - Position;// Create the  world  matrix  for the  plane
Transformation  = Matrix.CreateWorld(Position, delta,  Vector3.Up);
// The plane needs to  be rotated 90 degrees   so that  it points
// forward, so apply  a rotation
ApplyTransformation(Matrix.CreateRotationY(MathHelper.ToRadians(-90)));

最终结果是我们有一个平滑的逼真的在房屋间围绕场景飞行。你可以通过运行ChaseCam工程看到实际效果—最初的视图使用一个不会追逐飞行轨迹的相机,而是慢慢的环绕这个场景,允许简单的看到飞行轨迹。

转载于:https://www.cnblogs.com/appleseeker/archive/2012/05/24/e5889be5bbbae4b880e4b8aae8bfbde8b8aae69184e5838fe69cba2.html

创建一个追踪摄像机(2)相关推荐

  1. 【Unity】创建一个自己的AR安卓程序

    目录 1 环境配置 2 下载官方提供的AR Starter工程 3 AR Starter工程中的包以及打包设置 3.1 Package Manager 3.2 Player Settings 4 创建 ...

  2. 【Unity】创建一个自己的可交互AR安卓程序

    目录 1 创建一个AR场景 2 配置AR Camera为前置摄像头 3 配置打包场景 4 下载官方提供的InteractiveFaceFilterAssets资源 5 配置AR Face Manage ...

  3. 【Unity】创建一个自己的AR脸部特效安卓程序

    目录 1 创建一个换脸AR场景 2 下载官方提供的BasicFaceFilterAssets资源 3 设置AR面部追踪 4 配置AR Face Manager 5 配置AR Camera为前置摄像头 ...

  4. 学习用C#在Unity中创建一个2D Metroidvania游戏

    学习用C#在Unity中创建一个2D Metroidvania游戏 你会学到: 构建2D Unity游戏 用C#编程 玩家统计,水平提升,米尔和远程攻击 敌方人工智能系统 制定级别和级别选择 Lear ...

  5. 如何创建一个最小的区块链

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 这是我在一个外文网站上看到的一篇博文,作者通过50行代码写出了区块链的简化版本.麻雀虽小,但是五脏俱全.我觉得通过实践, ...

  6. unity双击打不开脚本_游戏对象和脚本 (创建一个时钟)

    该文章是一篇译文,附上原文链接 Game Objects and Scripts​catlikecoding.com 使用简单对象构建一个时钟 编写一个C#脚本 转动时钟的指针来显示时间 创建指针动画 ...

  7. 用python画篮球场_如何使用 Python 创建一个 NBA 得分图?

    本文意在创建一个得分图,该图同时描绘了从场上不同位置投篮得分的百分比和投篮次数,这和 Austin Clemen 个人网站上的帖子 http://www.austinclemens.com/shotc ...

  8. Vue中用Three.js创建一个3D会议室(三)拖动与旋转

    第三章 文章目录 拖动 DragControls 旋转 获取鼠标选中的3D模型 添加旋转按钮以及旋转方法 小贴士 虽然现在基本的模型都创建出来了,但是我们3D会议室的主要目的是可以自己摆放会议室中的物 ...

  9. 手把手带你 Unity 入门之从零创建一个时钟(GameObjects 与 Scripts)

    目录 写作背景 要点提要 1.创建一个时钟 1.1 创建一个 Game Object 1.2 创建钟盘 1.3 创建时钟的其他部分 1.4 创建指针 2.让时钟动起来 2.1 定义组件类型 2.2 拿 ...

最新文章

  1. BCH虫洞项目有多安全以及WHC究竟能干什么?
  2. 台湾大学林轩田机器学习基石课程学习笔记3 -- Types of Learning
  3. Text determination debug
  4. php mail函数_php 发送邮件函数
  5. linux安装nfs服务器
  6. 华为OJ之奥运会金牌排名显示国家名称
  7. Ubuntu20.04 安装wine QQ
  8. 快速截图工具——百度输入法的扩展功能
  9. 2007 word打开无响应
  10. 新唐 Nuvoton ML51PC 入门 点亮板载LED
  11. #后疫情时代的新思考#AI助力,“无接触”服务加速金融数字化转型丨数据猿公益策划...
  12. APP开发商城时,常说三级分销,你知道什么是分销机制吗?
  13. 1g等于多少mb计算机网络,1g能存多少首歌曲,1GB等于多少MB
  14. Navicat还原nb3备份文件步骤
  15. 异常(The host [tomcat_server] is not valid)(Nginx配置异常)
  16. 数字图像处理第二章----数字图像基础
  17. raise ContentTooShortError(urllib.error.ContentTooShortError: <urlopen error retrieval incomplete:
  18. iMeta期刊26位编委入选2022年全球高被引学者
  19. 线程的几种状态(详细)
  20. 国产自编程语言Maggot++发布测试版!

热门文章

  1. 【sklearrn学习】朴素贝叶斯
  2. 『Python』python 弹窗、提示和警告框MessageBox部件
  3. Windows 10配置VS Code C++环境(超详细,面向小白以及大佬们)
  4. maven eclipse 配置
  5. 如何使用makefile编译不同平台的目标文件(makefile的参数传递)
  6. 【Ubuntu-Opencv】Ubuntu14.04 Opencv3.3.0 完整卸载方案
  7. PCB的阻抗控制与前端仿真(SI9000的应用)(Z)
  8. 11 个重要的数据库设计规则
  9. 【python 10】python 魔术方法
  10. 变压器耦合和电容耦合_超越变压器和抱抱面的分类