【问题标题】:calculating a sphere in opengl在opengl中计算球体
【发布时间】:2011-10-30 18:11:01
【问题描述】:

我想计算所有需要的顶点并将它们用线连接起来,所以我最终想出了一个球体。有多少种方法可以做到?顶点之间的线也是笔直的;我怎样才能让它们“弯曲”我知道我可以使用 glutWireSphere(),但我对实际计算顶点感兴趣。我想到的一种方法是将所有顶点手动放入一个数组中,但我想这不是它的完成方式。

【问题讨论】:

标签: opengl geometry


【解决方案1】:

复制并粘贴我最初在Creating a 3D sphere in Opengl using Visual C++ 中编写的一些代码

class SolidSphere
{
protected
    std::vector<GLfloat> vertices;
    std::vector<GLfloat> normals;
    std::vector<GLfloat> texcoords;
    std::vector<GLushort> indices;

public:
    void SolidSphere(float radius, unsigned int rings, unsigned int sectors)
    {
        float const R = 1./(float)(rings-1);
        float const S = 1./(float)(sectors-1);
        int r, s;

        sphere_vertices.resize(rings * sectors * 3);
        sphere_normals.resize(rings * sectors * 3);
        sphere_texcoords.resize(rings * sectors * 2);
        std::vector<GLfloat>::iterator v = sphere_vertices.begin();
        std::vector<GLfloat>::iterator n = sphere_normals.begin();
        std::vector<GLfloat>::iterator t = sphere_texcoords.begin();
        for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) {
                float const y = sin( -M_PI_2 + M_PI * r * R );
                float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
                float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );

                *t++ = s*S;
                *t++ = r*R;

                *v++ = x * radius;
                *v++ = y * radius;
                *v++ = z * radius;

                *n++ = x;
                *n++ = y;
                *n++ = z;
        }

        sphere_indices.resize(rings * sectors * 4);
        std:vector<GLushort>::iterator i = sphere_indices.begin();
        for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) {
                *i++ = r * sectors + s;
                *i++ = r * sectors + (s+1);
                *i++ = (r+1) * sectors + (s+1);
                *i++ = (r+1) * sectors + s;
        }
    }

    void draw(GLfloat x, GLfloat y, GLfloat z)
    {
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(x,y,z);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glVertexPointer(3, GL_FLOAT, 0, &sphere_vertices[0]);
        glNormalPointer(GL_FLOAT, 0, &sphere_normals[0]);
        glTexCoordPointer(2, GL_FLOAT, 0, &sphere_texcoords[0]);
        glDrawElements(GL_QUADS, sphere_indices.size()/4, GL_UNSIGNED_SHORT, sphere_indices);
        glPopMatrix();
    }
}

我怎样才能让它们“弯曲”

你不能。所有 OpenGL 基元都是“仿射的”,即平面或直线。通过绘制具有足够分辨率的短而直的部分来模拟曲率。

【讨论】:

  • 你的代码生成的球体搞砸了:UV错了,有些顶点也错了。用三角带试了一下。
  • @MichaelIV: 球体不适用于三角带。
  • 您没有正确粘贴它:索引部分应该在扇区 1 和环 1 处停止。不过,您的另一篇文章是正确的。其实复制粘贴会更安全!
【解决方案2】:

有不止一种方法可以做到这一点:a) icosphere 生成和 b)UV 球生成。可能有更多方法可以做到这一点。一些谷歌搜索让我this excellent post on icosphere generation。但是我找不到 UV 球体生成方法。

【讨论】:

【解决方案3】:

Paul Bourke 实际上对sphere generation 有一个很好的介绍。而对于曲线,OpenGL中没有这样的东西。您只能通过添加更多中间连接点使它们看起来弯曲。

【讨论】:

    【解决方案4】:

    datenwolf 的回答很棒,但包含一些错误。 使用 vbo 时,启用后必须禁用客户端状态。

    添加三行绘制代码

    void draw(GLfloat x, GLfloat y, GLfloat z)
    {
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glTranslatef(x,y,z);
    
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
        glVertexPointer(3, GL_FLOAT, 0, &sphere_vertices[0]);
        glNormalPointer(GL_FLOAT, 0, &sphere_normals[0]);
        glTexCoordPointer(2, GL_FLOAT, 0, &sphere_texcoords[0]);
        glDrawElements(GL_QUADS, sphere_indices.size()/4, GL_UNSIGNED_SHORT, sphere_indices);
    
        **glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);**
    
        glPopMatrix();
    }
    

    【讨论】:

      【解决方案5】:

      图标圈可以解决问题。 不过,要用它制作一个球体,您必须细分它的三角形。

      【讨论】:

        【解决方案6】:

        在我看来,关于如何制作 icospheres 的教程非常丰富,但关于使用极坐标近似刻面的方法的教程却不多。

        这里有一个来自 Richard S. Wright Jr. 的 OpenGL Superbible 4th Edition 书中经过轻微编辑的代码示例。

        由于它是固定功能管道的非常简单的用法(没有 glDrawElements 等),我发现它对教育目的很有用。

        堆栈被绘制为一系列三角形条带。显然不是最佳性能,但它确实有效!

        // For best results, put this in a display list
        // Draw a sphere at the origin
        void RenderSphere(const float fRadius, const int iStacks, const int iSlices)
            {
                const auto PI = (float)M_PI;
                const auto PIx2 = (float)(M_PI * 2.0);
            
                GLfloat drho = PI / (GLfloat)iStacks;
                GLfloat dtheta = PIx2 / (GLfloat)iSlices;
                GLfloat ds = 1.0f / (GLfloat)iSlices;
                GLfloat dt = 1.0f / (GLfloat)iStacks;
                GLfloat t = 1.0f;
                GLfloat s = 0.0f;
            
                for (int i = 0; i < iStacks; i++)
                {
                    const GLfloat rho = (GLfloat)i * drho;
                    const GLfloat srho = (GLfloat)(std::sinf(rho));
                    const GLfloat crho = (GLfloat)(std::cosf(rho));
                    const GLfloat srhodrho = (GLfloat)(std::sinf(rho + drho));
                    const GLfloat crhodrho = (GLfloat)(std::cosf(rho + drho));
            
                    // Many sources of OpenGL sphere drawing code uses a triangle fan
                    // for the caps of the sphere. This however introduces texturing
                    // artifacts at the poles on some OpenGL implementations
                    glBegin(GL_TRIANGLE_STRIP);
                    s = 0.0f;
                    for (int j = 0; j <= iSlices; j++)
                    {
                        const GLfloat theta = (j == iSlices) ? 0.0f : j * dtheta;
                        const GLfloat stheta = (GLfloat)(-std::sinf(theta));
                        const GLfloat ctheta = (GLfloat)(std::cosf(theta));
            
                        GLfloat x = stheta * srho;
                        GLfloat y = ctheta * srho;
                        GLfloat z = crho;
            
                        glTexCoord2f(s, t);
                        glNormal3f(x, y, z);
                        glVertex3f(x * fRadius, y * fRadius, z * fRadius);
            
                        x = stheta * srhodrho;
                        y = ctheta * srhodrho;
                        z = crhodrho;
                        glTexCoord2f(s, t - dt);
                        s += ds;
                        glNormal3f(x, y, z);
                        glVertex3f(x * fRadius, y * fRadius, z * fRadius);
                    }
                    glEnd();
            
                    t -= dt;
                }
            }
        

        不幸的是,我找不到该源代码的原始在线存储库的链接,它非常古老。如果您知道在哪里可以找到它,请随时发布!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-03
          • 2012-09-28
          • 1970-01-01
          相关资源
          最近更新 更多