查找 3d 点之间的旋转角度
我正在编写一个程序,它将沿着样条曲线绘制实体。 我正在使用 Visual Studio 2005,并用 C++ 编写 OpenGL。 我正在使用 FLTK 打开我的窗口(快速且轻便的工具包)。
我目前有一种算法,可以在给定一组控制点的情况下,通过将点之间的间隔分解为子间隔并在这些子点之间绘制线段来绘制基数三次样条线。 子区间的数量是可变的。
画线代码工作得非常好,基本上工作如下:我使用样条方程生成一组沿着样条曲线的点,并将它们存储在一个数组中(作为一个名为 Pnt3f 的特殊数据结构,其中坐标是 3 个浮点数,并且有一些方便的函数,例如距离、长度、点和叉积)。 然后我有一个循环,它迭代点数组并按如下方式绘制它们:
glBegin(GL_LINE_STRIP);
for(pt = 0; pt<=numsubsegements ; ++pt) {
glVertex3fv(pt.v());
}
glEnd();
如前所述,这段代码效果很好。 现在我想做的是,我不想画一条线,而是想挤出一个实体。 我目前的探索是使用“圆柱体”二次曲面沿线创建一个管子。 这有点棘手,因为我必须将 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
我的问题是获取点之间的角度。 我只需要偏航和俯仰,滚转并不重要。 我知道将两个点的点积除以两个点的大小的反余弦,将返回它们之间的角度,但这不是我可以提供给 OpenGL 进行旋转的东西。 我尝试在 2d 中执行此操作,使用 XZ 平面获得 x 旋转,并从原点创建点向量,但它不会返回正确的角度。
我目前的方法要简单得多。 对于每个旋转平面(X 和 Y),通过以下方式找到角度:
反余弦((“x”值的差异)/点之间的距离)
“x”值取决于您如何设置平面,但对于我的计算我总是使用世界x。
除非有一些问题使其绘制在我尚未解决的正确象限中,否则我想获得建议,看看这是否是一个很好的实现,或者看看是否有人知道更好的方法。
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).
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.
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:
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:
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.
My current approach is much simpler. For each plane of rotation (X and Y), find the angle by:
arc-cosine( (difference in 'x' values)/distance between the points)
the 'x' value depends on how your set your plane up, though for my calculations I always use world 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您正确地从两个相邻线段中的三个点形成两个向量,然后使用点积的反余弦来获取它们之间的角度。 要利用这个角度,您需要确定旋转所围绕的轴。 取相同两个向量的叉积即可得到该轴。 然后,您可以 构建转换矩阵 使用此轴角度或将其作为参数传递给 glRotate 。
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.
一些注意事项:
首先,这
不是绘制任何东西的好方法。 每一个 glBegin() 都必须有一个 glEnd()。 您可能希望将 glBegin() 移出循环。 事实上,这有效纯属运气。
第二件事
这不会像你期望的那样工作。“圆柱”二次曲面有一个平顶底和平底底。 即使您成功地根据样条线进行了正确的旋转,平顶的边缘也会从您想要的管子的体积中弹出,并且不会光滑。 您可以仅用笔和纸尝试 2D 形式。 尝试仅使用具有平底的较短管子来绘制光滑的管子。 这是不可能的。
第三,对于您的实际问题,此类旋转的权威工具是四元数。 在这个范围内解释起来有点复杂,但你可以在任何地方找到大量信息。
如果您使用 QT 而不是 FLTK,您也可以使用 libQGLViewer。 它有一个集成的四元数类,可以节省您的实现。 如果您还有选择,我强烈建议您转向 QT。
A few notes:
first of all, this:
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.
second thing
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.
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.
您是否考虑过
gluLookAt
? 将你的控制点作为视点,下一个点作为参考点,并使向上向量垂直于两者之间的差值。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.