不使用 gluSphere() 在 OpenGL 中绘制球体?
有没有教程解释如何在 OpenGL 中绘制球体而无需使用 gluSphere() ?
许多 OpenGL 3D 教程都只是关于立方体。我已经搜索过,但大多数绘制球体的解决方案都是使用 gluSphere() 。还有一个网站有绘制球体的代码 这个网站,但它没有解释绘制球体背后的数学原理。我还有其他版本的如何在多边形中绘制球体而不是该链接中的四边形。但同样,我不明白如何用代码绘制球体。我希望能够可视化,以便在需要时可以修改球体。
Are there any tutorials out there that explain how I can draw a sphere in OpenGL without having to use gluSphere()
?
Many of the 3D tutorials for OpenGL are just on cubes. I have searched but most of the solutions to drawing a sphere are to use gluSphere()
. There is also a site that has the code to drawing a sphere at this site but it doesn't explain the math behind drawing the sphere. I have also other versions of how to draw the sphere in polygon instead of quads in that link. But again, I don't understand how the spheres are drawn with the code. I want to be able to visualize so that I could modify the sphere if I need to.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
一种方法是从具有三角形边的柏拉图立体开始 - 一个八面体,对于例子。然后,将每个三角形递归地分解为更小的三角形,如下所示:
一旦你有足够的数量对于点,您可以标准化它们的向量,以便它们与实体中心的距离都是恒定的。这会导致侧面凸出成类似球体的形状,随着点数的增加,平滑度也会增加。
这里的归一化意味着移动一个点,使其相对于另一个点的角度相同,但它们之间的距离不同。
这是一个二维的例子。
A 和 B 相距 6 个单位。但是假设我们想在 AB 线上找到一个距离 A 12 个单位的点。
我们可以这样说C 是 B 相对于 A 的归一化形式,距离为 12。我们可以通过如下代码获得 C:
如果我们对很多点进行归一化处理,所有点都相对于同一点 A 并且具有相同的距离R,然后是归一化点都将位于以 A 为圆心、以 R 为半径的圆弧上。
这里,黑点开始于一条线并“凸出”成弧形。
这个过程可以扩展到三个维度,在这种情况下你会得到一个球体而不是一个圆。只需将 dz 分量添加到归一化函数即可。
如果您在 Epcot,您可以看到这种技术的工作原理。它是一个十二面体,表面凸出,使其看起来更圆。
One way you can do it is to start with a platonic solid with triangular sides - an octahedron, for example. Then, take each triangle and recursively break it up into smaller triangles, like so:
Once you have a sufficient amount of points, you normalize their vectors so that they are all a constant distance from the center of the solid. This causes the sides to bulge out into a shape that resembles a sphere, with increasing smoothness as you increase the number of points.
Normalization here means moving a point so that its angle in relation to another point is the same, but the distance between them is different.
Here's a two dimensional example.
A and B are 6 units apart. But suppose we want to find a point on line AB that's 12 units away from A.
We can say that C is the normalized form of B with respect to A, with distance 12. We can obtain C with code like this:
If we do this normalization process on a lot of points, all with respect to the same point A and with the same distance R, then the normalized points will all lie on the arc of a circle with center A and radius R.
Here, the black points begin on a line and "bulge out" into an arc.
This process can be extended into three dimensions, in which case you get a sphere rather than a circle. Just add a dz component to the normalize function.
If you look at the sphere at Epcot, you can sort of see this technique at work. it's a dodecahedron with bulged-out faces to make it look rounder.
我将进一步解释使用纬度和经度生成球体的流行方法(另一种
方式,icospheres,已经在撰写本文时最流行的答案中进行了解释。)
球体可以通过以下参数方程表示:
F( u, v) = [ cos(u)*sin(v)*r, cos(v)*r, sin(u)*sin(v)*r ]
其中:
然后生成球体涉及以固定时间间隔评估参数函数。
例如,要生成 16 条经度线,沿 u 轴将有 17 条网格线,步长为
π/8 (2π/16)(第 17 行环绕)。
以下伪代码通过评估参数函数来生成三角形网格
定期(这适用于任何参数表面函数,而不仅仅是球体)。
在下面的伪代码中,UResolution是沿 U 轴的网格点数
(此处为经度线),VResolution 是沿 V 轴的网格点数
(这里是纬线)
I'll further explain a popular way of generating a sphere using latitude and longitude (another
way, icospheres, was already explained in the most popular answer at the time of this writing.)
A sphere can be expressed by the following parametric equation:
F(u, v) = [ cos(u)*sin(v)*r, cos(v)*r, sin(u)*sin(v)*r ]
Where:
Generating the sphere then involves evaluating the parametric function at fixed intervals.
For example, to generate 16 lines of longitude, there will be 17 grid lines along the u axis, with a step of
π/8 (2π/16) (the 17th line wraps around).
The following pseudocode generates a triangle mesh by evaluating a parametric function
at regular intervals (this works for any parametric surface function, not just spheres).
In the pseudocode below, UResolution is the number of grid points along the U axis
(here, lines of longitude), and VResolution is the number of grid points along the V axis
(here, lines of latitude)
示例中的代码很快得到了解释。您应该查看函数
void drawSphere(double r, int lats, int longs)
:参数
lat
定义您想要在球体中拥有多少条水平线,< code>lon 有多少条垂直线。r
是球体的半径。现在,对
lat
/lon
进行了两次迭代,并使用简单的三角函数计算顶点坐标。计算出的顶点现在使用
glVertex...()
作为GL_QUAD_STRIP
发送到您的 GPU,这意味着您发送的每两个顶点与之前的两个顶点形成一个四边形发送。现在你需要了解的是三角函数是如何工作的,但我想你可以很容易地弄清楚。
The code in the sample is quickly explained. You should look into the function
void drawSphere(double r, int lats, int longs)
:The parameters
lat
defines how many horizontal lines you want to have in your sphere andlon
how many vertical lines.r
is the radius of your sphere.Now there is a double iteration over
lat
/lon
and the vertex coordinates are calculated, using simple trigonometry.The calculated vertices are now sent to your GPU using
glVertex...()
as aGL_QUAD_STRIP
, which means you are sending each two vertices that form a quad with the previously two sent.All you have to understand now is how the trigonometry functions work, but I guess you can figure it out easily.
如果你想像狐狸一样狡猾,你可以将 GLU 的代码修改半英寸。查看 MesaGL 源代码 (http://cgit.freedesktop.org/mesa/mesa/)。
If you wanted to be sly like a fox you could half-inch the code from GLU. Check out the MesaGL source code (http://cgit.freedesktop.org/mesa/mesa/).
请参阅OpenGL红皮书: http://www.glprogramming.com/red/chapter02.html #名称8
它通过多边形细分来解决问题。
See the OpenGL red book: http://www.glprogramming.com/red/chapter02.html#name8
It solves the problem by polygon subdivision.
我的示例如何使用“三角形带”绘制“极”球体,它包括成对绘制点:
输入的第一个点(glVertex3f)如下参数方程,第二个点移动一个 alpha 角度(从下一条平行线开始)。
My example how to use 'triangle strip' to draw a "polar" sphere, it consists in drawing points in pairs:
First point entered (glVertex3f) is as follows the parametric equation and the second one is shifted by a single step of alpha angle (from next parallel).
尽管接受的答案解决了问题,但最后还是存在一些误解。 十二面体是(或可能是)正多面体,其中所有面都具有相同的面积。 Epcot 似乎就是这种情况(顺便说一下,它根本不是十二面体)。由于@Kevin 提出的解决方案没有提供此特征,我认为我可以添加一种可以提供此特征的方法。
生成 N 面多面体(其中所有顶点都位于同一个球体中且其所有面具有相似面积/表面的好方法)是从二十面体开始,并迭代细分和标准化其三角形面(如已接受的答案中所建议的)。例如,十二面体实际上是截断二十面体。
正二十面体有 20 个面(12 个顶点),可以轻松地由 3 个黄金矩形构建而成;问题只是以此为起点而不是八面体。您可以在此处找到示例。
我知道这有点偏离主题,但我相信如果有人来这里寻找这个具体案例,这可能会有所帮助。
Although the accepted answer solves the question, there's a little misconception at the end. Dodecahedrons are (or could be) regular polyhedron where all faces have the same area. That seems to be the case of the Epcot (which, by the way, is not a dodecahedron at all). Since the solution proposed by @Kevin does not provide this characteristic I thought I could add an approach that does.
A good way to generate an N-faced polyhedron where all vertices lay in the same sphere and all its faces have similar area/surface is starting with an icosahedron and the iteratively sub-dividing and normalizing its triangular faces (as suggested in the accepted answer). Dodecahedrons, for instance, are actually truncated icosahedrons.
Regular icosahedrons have 20 faces (12 vertices) and can easily be constructed from 3 golden rectangles; it's just a matter of having this as a starting point instead of an octahedron. You may find an example here.
I know this is a bit off-topic but I believe it may help if someone gets here looking for this specific case.
@Constantinius 答案的 Python 改编:
Python adaptation of @Constantinius answer:
一种方法是制作一个面向相机的四边形,并编写一个顶点和片段着色器来渲染看起来像球体的东西。您可以使用在互联网上找到的圆/球体方程。
一件好事是球体的轮廓从任何角度看起来都是一样的。然而,如果球体不在透视图的中心,那么它看起来可能更像一个椭圆形。您可以计算出这个方程并将它们放入片段阴影中。如果您确实有一个玩家在球体周围的 3D 空间中移动,那么光线着色需要随着玩家的移动而改变。
任何人都可以评论一下他们是否尝试过这个或者它是否太昂贵而不实用?
One way is to make a quad that faces the camera and write a vertex and fragment shader that renders something that looks like a sphere. You could use equations for a circle/sphere that you can find on the internet.
One nice thing is that the silhouette of a sphere looks the same from any angle. However, if the sphere is not in the center of a perspective view, then it would appear perhaps more like an ellipse. You could work out the equations for this and put them in the fragment shading. Then the light shading needs to changed as the player moves, if you do indeed have a player moving in 3D space around the sphere.
Can anyone comment on if they have tried this or if it would be too expensive to be practical?