在3d点之间查找旋转角度

时间:2022-09-10 18:54:02

I am writing a program that will draw a solid along the curve of a spline. I am using visual studio 2005, and writing in C++ for OpenGL. I'm using FLTK to open my windows (fast and light toolkit).

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

I currently have an algorithm that will draw a Cardinal Cubic Spline, given a set of control points, by breaking the intervals between the points up into subintervals and drawing linesegments between these sub points. The number of subintervals is variable.

我现在有一个算法,通过将点之间的间隔分解为子区间并在这些子点之间绘制linesegments,在给定一组控制点的情况下绘制Cardinal Cubic Spline。子间隔的数量是可变的。

The line drawing code works wonderfully, and basically works as follows: I generate a set of points along the spline curve using the spline equation and store them in an array (as a special datastructure called Pnt3f, where the coordinates are 3 floats and there are some handy functions such as distance, length, dot and crossproduct). Then i have a single loop that iterates through the array of points and draws them as so:

线条图代码运行得非常好,基本上如下工作:我使用样条曲线方程沿样条曲线生成一组点并将它们存储在一个数组中(作为一个特殊的数据结构,称为Pnt3f,其中坐标是3个浮点数,有一些方便的功能,如距离,长度,点和交叉产品)。然后我有一个循环遍历点数组并按如下方式绘制它们:

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

As stated, this code works great. Now what i want to do is, instead of drawing a line, I want to extrude a solid. My current exploration is using a 'cylinder' quadric to create a tube along the line. This is a bit trickier, as I have to orient openGL in the direction i want to draw the cylinder. My idea is to do this:

如上所述,此代码非常有用。现在我想要做的是,而不是画一条线,我想挤出一个实体。我目前的探索是使用“圆柱”二次曲线在线上创建一个管子。这有点棘手,因为我必须在我想要绘制圆柱体的方向上定向openGL。我的想法是这样做:

Psuedocode:

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

My problem is getting the angles between the points. I only need yaw and pitch, roll isnt important. I know take the arc-cosine of the dot product of the two points divided by the magnitude of both points, will return the angle between them, but this is not something i can feed to OpenGL to rotate with. I've tried doing this in 2d, using the XZ plane to get x rotation, and making the points vectors from the origin, but it does not return the correct angle.

我的问题是获得点之间的角度。我只需要偏航和俯仰,滚动并不重要。我知道将两点的点积的弧余弦除以两点的大小,将返回它们之间的角度,但这不是我可以提供给OpenGL旋转的东西。我已经尝试在2d做这个,使用XZ平面获得x旋转,并从原点制作点矢量,但它不会返回正确的角度。

My current approach is much simpler. For each plane of rotation (X and Y), find the angle by:

我目前的方法更简单。对于每个旋转平面(X和Y),通过以下方式找到角度:

arc-cosine( (difference in 'x' values)/distance between the points)

arc-cosine(('x'值的差异)/点之间的距离)

the 'x' value depends on how your set your plane up, though for my calculations I always use world x.

'x'值取决于你如何设置你的飞机,但是对于我的计算,我总是使用世界x。

Barring a few issues of it making it draw in the correct quadrant that I havent worked out yet, I want to get advice to see if this was a good implementation, or to see if someone knew a better way.

除了它的一些问题使它在我尚未制定的正确象限中绘制,我想得到建议,看看这是一个好的实现,还是看看有人知道更好的方法。

3 个解决方案

#1


1  

You are correct in forming two vectors from the three points in two adjacent line segments and then using the arccosine of the dot product to get the angle between them. To make use of this angle you need to determine the axis around which the rotation should occur. Take the cross product of the same two vectors to get this axis. You can then build a transformation matrix using this axis-angle or pass it as parameters to glRotate.

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

#2


1  

A few notes:
first of all, this:

几点说明:首先,这个:

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

is not a good way to draw anything. You MUST have one glEnd() for every single glBegin(). you probably want to get the glBegin() out of the loop. the fact that this works is pure luck.

绘制任何东西都不是一个好方法。每个glBegin()必须有一个glEnd()。你可能想让glBegin()退出循环。事实上,这是真正的运气。

second thing

My current exploration is using a 'cylinder' quadric to create a tube along the line

我目前的探索是使用“圆柱”二次曲线在线上创建一个管子

This will not work as you expect. the 'cylinder' quadric has a flat top base and a flat bottom base. Even if you success in making the correct rotations according to the spline the edges of the flat tops are going to pop out of the volume of your intended tube and it will not be smooth. You can try it in 2D with just a pen and a paper. Try to draw a smooth tube using only shorter tubes with a flat bases. This is impossible.

这不会像你期望的那样工作。 '圆柱'二次曲面有一个平底座和一个平底座。即使你成功地根据花键进行正确的旋转,平顶的边缘也会从你想要的管子的体积中弹出,而且不会很光滑。您可以使用笔和纸在2D中进行尝试。尝试使用较短的扁平底座管来绘制光滑的管子。这是不可能的。

Third, to your actual question, The definitive tool for such rotations are quaternions. Its a bit complex to explain in this scope but you can find plentyful information anywhere you look.
If you'd have used QT instead of FLTK you could have also used libQGLViewer. It has an integrated Quaternion class which would save you the implementation. If you still have a choice I strongly recommend moving to QT.

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

#3


0  

Have you considered gluLookAt? Put your control point as the eye point, the next point as the reference point, and make the up vector perpendicular to the difference between the two.

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

#1


1  

You are correct in forming two vectors from the three points in two adjacent line segments and then using the arccosine of the dot product to get the angle between them. To make use of this angle you need to determine the axis around which the rotation should occur. Take the cross product of the same two vectors to get this axis. You can then build a transformation matrix using this axis-angle or pass it as parameters to glRotate.

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

#2


1  

A few notes:
first of all, this:

几点说明:首先,这个:

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

is not a good way to draw anything. You MUST have one glEnd() for every single glBegin(). you probably want to get the glBegin() out of the loop. the fact that this works is pure luck.

绘制任何东西都不是一个好方法。每个glBegin()必须有一个glEnd()。你可能想让glBegin()退出循环。事实上,这是真正的运气。

second thing

My current exploration is using a 'cylinder' quadric to create a tube along the line

我目前的探索是使用“圆柱”二次曲线在线上创建一个管子

This will not work as you expect. the 'cylinder' quadric has a flat top base and a flat bottom base. Even if you success in making the correct rotations according to the spline the edges of the flat tops are going to pop out of the volume of your intended tube and it will not be smooth. You can try it in 2D with just a pen and a paper. Try to draw a smooth tube using only shorter tubes with a flat bases. This is impossible.

这不会像你期望的那样工作。 '圆柱'二次曲面有一个平底座和一个平底座。即使你成功地根据花键进行正确的旋转,平顶的边缘也会从你想要的管子的体积中弹出,而且不会很光滑。您可以使用笔和纸在2D中进行尝试。尝试使用较短的扁平底座管来绘制光滑的管子。这是不可能的。

Third, to your actual question, The definitive tool for such rotations are quaternions. Its a bit complex to explain in this scope but you can find plentyful information anywhere you look.
If you'd have used QT instead of FLTK you could have also used libQGLViewer. It has an integrated Quaternion class which would save you the implementation. If you still have a choice I strongly recommend moving to QT.

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

#3


0  

Have you considered gluLookAt? Put your control point as the eye point, the next point as the reference point, and make the up vector perpendicular to the difference between the two.

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