4

我正在编写一个程序,它将沿着样条曲线绘制一个实体。我正在使用 Visual Studio 2005,并用 C++ 编写 OpenGL。我正在使用 FLTK 打开我的窗口(快速轻便的工具包)。

我目前有一个算法,将绘制一个基本三次样条,给定一组控制点,通过将点之间的间隔分解为子间隔并在这些子点之间绘制线段。子区间的数量是可变的。

画线代码效果很好,基本上工作如下:我使用样条方程沿样条曲线生成一组点并将它们存储在一个数组中(作为一个称为 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。

除非有一些问题使它在我还没有解决的正确象限中绘制出来,否则我想得到建议,看看这是否是一个好的实现,或者看看是否有人知道更好的方法。

4

3 回答 3

1

一些注意事项:
首先,这是:

for(pt = 0; pt<=numsubsegements ; ++pt) {
  glBegin(GL_LINE_STRIP);
    glVertex3fv(pt.v());
}
glEnd();

不是画任何东西的好方法。每个 glBegin() 都必须有一个 glEnd()。您可能希望将 glBegin() 退出循环。这个工作的事实是纯粹的运气。

第二件事

我目前的探索是使用“圆柱体”二次曲线沿线创建管

这不会像您期望的那样工作。“圆柱体”二次曲面有一个平顶底座和一个平底底座。即使您成功地根据样条曲线进行了正确的旋转,平顶的边缘也会从您预期的管子的体积中弹出,并且不会光滑。您可以只用一支笔和一张纸在 2D 中进行尝试。尝试仅使用带有扁平底座的较短管子绘制光滑的管子。这是不可能的。

第三,对于您的实际问题,这种旋转的权威工具是quaternions。在这个范围内解释起来有点复杂,但你可以在任何地方找到大量信息。
如果您使用 QT 而不是 FLTK,您也可以使用libQGLViewer。它有一个集成的 Quaternion 类,可以为您节省实现。如果您仍然有选择,我强烈建议您迁移到 QT。

于 2008-11-08T20:29:42.130 回答
1

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

于 2008-11-12T18:48:59.413 回答
0

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

于 2008-11-08T18:54:44.660 回答