在3D点之间寻找旋转角度

4
我正在编写一个程序,可以沿着样条曲线绘制实体。我使用的是Visual Studio 2005,在C++中为OpenGL编写代码。我使用FLTK打开窗口(快速且轻量级的工具包)。
目前,我有一个算法,可以通过将控制点之间的区间分成子区间,并在这些子点之间绘制线段,来绘制Cardinal Cubic Spline。子区间的数量是可变的。
绘制线段的代码非常出色,基本上是这样的:我使用样条方程生成一组沿着样条曲线的点,并将它们存储在一个数组中(作为名为Pnt3f的特殊数据结构,其中坐标是3个浮点数,并且有一些方便的函数,如距离、长度、点积和叉积)。然后,我有一个循环遍历点数组,并按如下方式绘制它们:
glBegin(GL_LINE_STRIP);
for(pt = 0; pt<=numsubsegements ; ++pt) {
    glVertex3fv(pt.v());
}
glEnd();

如上所述,这段代码运行得很好。现在我想做的是,不再画一条线,而是挤出一个实体。我的当前尝试是使用“圆柱”四面体创建沿着线的管道。这有点棘手,因为我必须将openGL定向到我想要绘制圆柱体的方向。我的想法是这样做:

伪代码:

Push the current matrix,
translate to the first control point
rotate to face the next point
draw a cylinder (length = distance between the points)
Pop the matrix
repeat

我的问题是如何获得点之间的角度。我只需要偏航角和俯仰角,滚转角并不重要。我知道,将两个点的点积除以两个点的大小所得到的反余弦值将返回它们之间的角度,但这不是我可以输入OpenGL进行旋转的内容。我尝试在2D中执行此操作,使用XZ平面获取x旋转,并使点向量从原点开始,但它没有返回正确的角度。
我的当前方法要简单得多。对于每个旋转平面(X和Y),通过以下方式找到角度:
反余弦值(“x”值的差异/点之间的距离)
“x”值取决于您如何设置平面,但对于我的计算,我总是使用世界x。
除了一些绘制在我还没有解决的正确象限的问题之外,我想寻求建议,看看这是否是一个好的实现,或者是否有更好的方法。
3个回答

1

你的做法是正确的,可以从相邻两条线段中的三个点形成两个向量,然后使用点积的反余弦函数来获取它们之间的夹角。为了利用这个角度,你需要确定旋转应该发生的轴。取这两个向量的叉积即可得到此轴。然后,你可以使用这个轴角或将其作为参数传递给glRotate,以构建一个变换矩阵


1
一些注释:
首先,这个:
for(pt = 0; pt<=numsubsegements ; ++pt) {
  glBegin(GL_LINE_STRIP);
    glVertex3fv(pt.v());
}
glEnd();

不是一个好的绘图方式。你必须为每个glBegin()有一个glEnd()。你可能想把glBegin()放在循环外面。这个能工作纯属巧合。

第二件事

我的当前探索是使用 'cylinder' 二次曲面来创建沿着线的管道

这不会按照你的期望工作。'cylinder' 二次曲面有一个平顶底和一个平底底。即使你成功地根据样条线进行正确旋转,平顶部分的边缘也会突出管道体积之外,它不会是光滑的。你可以用笔和纸在2D上尝试一下。只使用带有平底的短管道来画一个光滑的管道是不可能的。

第三,回答你的实际问题,这种旋转的明确工具是四元数。在这个范围内解释有点复杂,但你可以在任何地方找到丰富的信息。
如果你使用的是QT而不是FLTK,你也可以使用libQGLViewer。它有一个集成的四元数类,可以节省你的实现时间。如果你还有选择的余地,我强烈建议转向QT。


glBegin 是一个打字错误。感谢你发现了这个问题。我已经进行了更正。 - Avatar_Squadron
不幸的是,这是一个需要FLTK的课程。你知道如何绘制管道吗?我猜我得将四面体自身编码为一种类似于长方体的形状? - Avatar_Squadron

0
你考虑过 gluLookAt 吗? 将你的控制点作为眼睛坐标,下一个点作为参考点,并使上向量垂直于两者之间的差。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接