如何旋转模型以跟随路径

Posted

技术标签:

【中文标题】如何旋转模型以跟随路径【英文标题】:How to rotate model to follow path 【发布时间】:2019-06-26 01:21:20 【问题描述】:

我有一个想要沿圆形路径移动的宇宙飞船模型。我希望船头始终指向它前进的方向。

这是我现在必须将其移动一圈的代码:

glm::mat4 m = glm::mat4(1.0f);

        //time
        long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::
                                                                                                                                          high_resolution_clock::now())
                                                                                  .time_since_epoch())
                            .count();
        //translate 
        m = glm::translate(m, translate);
        m = glm::translate(m, glm::vec3(-50, 0, -20));
        m = glm::scale(m, glm::vec3(0.025f, 0.025f, 0.025f));
        m = glm::translate(m, glm::vec3(1800, 0, 3000));

        float speed = .002;
        float x = 100 * cos(value_ms * speed); // + 1800;
        float y = 0;
        float z = 100 * sin(value_ms * speed); // + 3000;
        m = glm::translate(m, glm::vec3(x, y, z));

如何移动它以使鼻子始终指向前方?我尝试将旋转轴设置为 x 或 y 或 z 进行 glm::rotate,但我无法使其正常工作。

【问题讨论】:

提示:您的圆形路径在 x-z 平面内。 => 旋转轴应该是y(不是x or y or z)。 ;-) 并非所有转换都是可交换的。翻译是(即多个翻译的任何顺序都会导致相同的最终转换)。旋转和缩放都不是这样。 【参考方案1】:

首先看到Understanding 4x4 homogenous transform matrices,因为我正在使用那里的术语和东西......

通常将对象的变换矩阵用于导航目的,而不是相反...所以你应该有一个变换矩阵M 用于你的宇宙飞船,它在 [ 中表示它的位置和方向GCS](全球坐标系)。除此之外,有时还会乘以另一个矩阵M0,将您的太空船网格与第一个矩阵对齐(您知道有些网格不是以(0,0,0) 为中心,也不是轴对齐...)

现在,当您移动对象时,您只需在M 上进行局部变换,因此向前移动只是将M 原点位置平移多个正向轴基向量。滑动到侧面也是如此(只是使用不同的基向量),导致对象总是与它应该在的位置对齐(相对于运动)。转弯也是如此。因此,循环只是在每个时间迭代步骤(计时器)中以恒定的速度前进和转动。

您首先要向后执行此操作,然后计算位置和方向,然后尝试进行操作,从而生成可以执行相同操作的矩阵...在这种情况下,更容易构造矩阵M 而不是创建将创建它的转换...所以您需要的是:

原点位置 3 个垂直(最有可能是单位)基向量

所以原点是您的x,y,z 位置。可以从圆中获得 2 个基向量,因此向前是切线(或position-last_position),并且朝向圆心的向量 cen 用作(右或左)。第三个向量可以通过叉积得到,所以假设:

+X轴是对的 +Y 轴向上 +Z 轴向前

你得到了:

r=100.0
a=speed*t
pos = (r*cos(a),0.0,r*sin(a))
center = (0.0,0.0,0.0)

所以:

Z = (cos(a-0.5*M_PI),0.0,sin(a-0.5*M_PI))
X = (cos(a),0.0,sin(a))-ceneter
Y = cross(X,Z)
O = pos

标准化:

X /= length(X)
Y /= length(Y)
Z /= length(Z)

所以现在只需将您的 X,Y,Z,O 输入矩阵(取决于您使用的约定,例如乘法顺序、直接/逆矩阵、行优先或列优先矩阵...)

例如这样:

double M[16]=
 
 X[0],X[1],X[2],0.0,
 Y[0],Y[1],Y[2],0.0,
 Z[0],Z[1],Z[2],0.0,
 O[0],O[1],O[2],1.0,
 ;

或:

double M[16]=
 
 X[0],Y[0],Z[0],O[0],
 X[1],Y[1],Z[1],O[1],
 X[2],Y[2],Z[2],O[2],
 0.0 ,0.0 ,0.0 ,1.0,
 ;

仅此而已...矩阵可能会根据您使用的约定进行转置、倒置等。抱歉,我不使用 GLM,但语法应该非常相似......如果行或列可以通过向量加载,矩阵馈送可能会更简单......

【讨论】:

以上是关于如何旋转模型以跟随路径的主要内容,如果未能解决你的问题,请参考以下文章

虚拟仿真Unity3D中实现UI跟随3D模型旋转移动UI一直面朝屏幕

虚拟仿真Unity3D中实现UI跟随3D模型旋转移动UI一直面朝屏幕

动画文本跟随路径[关闭]

如何让我的猫头鹰旋转木马方向跟随鼠标滚轮方向

如何移动 3D 盒子以保持在旋转平面上?

如何避免旋转动画在 2π 边界处跳跃?