如何使用OpenGLES绘制圆柱体?

3
如何使用OpenGLES绘制圆柱体?
5个回答

3

第一步是编写一个绘制三角形的子程序。我会把这个任务留给你。然后,只需绘制一系列三角形来组成圆柱的形状。诀窍是用像64这样的大量边数的多边形来近似表示圆形。以下是我脑海中的一些伪代码。

for (i = 0; i < 64; i++)
{
    angle = 360 * i / 63;  // Or perhaps 2 * PI * i / 63
    cx[i] = sin(angle);
    cy[i] = cos(angle);
}

for (i = 0; i < 63; i++)
{
    v0 = Vertex(cx[i], cy[i], 0);
    v1 = Vertex(cx[i + 1], cy[i + 1], 0);
    v2 = Vertex(cx[i], cy[i], 1);
    v3 = Vertex(cx[i + 1], cy[i + 1], 1);

    DrawTriangle(v0, v1, v2);
    DrawTriangle(v1, v3, v2);
    // If you have it:  DrawQuad(v0, v1, v3, v2);
}

代码中几乎肯定有错误。最可能的情况是我在三角形绘制中搞错了卷绕顺序,导致你可能只能看到一半的三角形或者一个非常奇怪的情况,只能看到背面。

为了提高效率,很快就需要使用三角形条带和扇形进行绘制,但这应该可以让你开始。


1

我希望这可以帮助你,这是我在Android上使用OpenGLES 2.0实现的圆柱体。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Cylinder {

    public Cylinder(int n) {

        this.numOfVertex = n;

        float[] vertex = new float[3 * (n + 1) * 2];
        byte[] baseIndex = new byte[n];
        byte[] topIndex = new byte[n];
        byte[] edgeIndex = new byte[n*2 + 2];

        double perAngle = 2 * Math.PI / n;

        for (int i = 0; i < n; i++) {
            double angle = i * perAngle;
            int offset = 6 * i;

            vertex[offset + 0] = (float)(Math.cos(angle) * radious) + cx;
            vertex[offset + 1] = -height;
            vertex[offset + 2] = (float)(Math.sin(angle) * radious) + cy;

            vertex[offset + 3] = (float)(Math.cos(angle) * radious) + cx;
            vertex[offset + 4] = height;
            vertex[offset + 5] = (float)(Math.sin(angle) * radious) + cy;

            topIndex[i] = (byte)(2*i);

            baseIndex[i] = (byte)(2*i +1);

            edgeIndex[2*i + 1] = baseIndex[i];
            edgeIndex[2*i] = topIndex[i];

        }


        edgeIndex[2*n] = topIndex[0];
        edgeIndex[2*n+1] = baseIndex[0];

        ByteBuffer vbb = ByteBuffer
                .allocateDirect(vertex.length * 4)
                .order(ByteOrder.nativeOrder());

        mFVertexBuffer = vbb.asFloatBuffer();
        mFVertexBuffer.put(vertex);
        mFVertexBuffer.position(0);

        normalBuffer = mFVertexBuffer;

        mCircleBottom = ByteBuffer.allocateDirect(baseIndex.length);
        mCircleBottom.put(baseIndex);
        mCircleBottom.position(0);

        mCircleTop = ByteBuffer.allocateDirect(topIndex.length);
        mCircleTop.put(topIndex);
        mCircleTop.position(0);

        mEdge = ByteBuffer.allocateDirect(edgeIndex.length);
        mEdge.put(edgeIndex);
        mEdge.position(0);
    }

    public void draw(GL10 gl)
    {
        gl.glCullFace(GL10.GL_BACK);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
        gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        gl.glPushMatrix();

        gl.glColor4f(1f, 0, 0, 0);
        gl.glDrawElements( GL10.GL_TRIANGLE_STRIP, numOfVertex * 2 + 2, GL10.GL_UNSIGNED_BYTE, mEdge);
        gl.glPopMatrix();
        gl.glPushMatrix();

        gl.glColor4f(0.9f, 0, 0, 0);
        gl.glDrawElements( GL10.GL_TRIANGLE_FAN, numOfVertex, GL10.GL_UNSIGNED_BYTE, mCircleTop);
        gl.glPopMatrix();

        gl.glPushMatrix();

        gl.glTranslatef(0, 2*height, 0);
        gl.glRotatef(-180, 1, 0, 0); 

        gl.glColor4f(0.9f,0, 0, 0);
        gl.glDrawElements( GL10.GL_TRIANGLE_FAN, numOfVertex , GL10.GL_UNSIGNED_BYTE, mCircleBottom);
        gl.glPopMatrix();

    }

    private FloatBuffer mFVertexBuffer;
    private FloatBuffer normalBuffer;
    private ByteBuffer mCircleBottom;
    private ByteBuffer mCircleTop;
    private ByteBuffer mEdge;
    private int numOfVertex;
    private int cx = 0;
    private int cy = 0;
    private int height = 1;
    private float radious = 1;
}

1

你需要通过对象加载来完成。使用Open GL ES无法调用3D形状基元。

浏览Jeff Lamarche的博客,那里有很多关于如何进行对象加载的非常好的资源。链接文本


谢谢回复。然而,我被告知在OpenGLES中可以通过仅使用“四边形”来绘制圆柱体。而且我想在这个阶段避免使用3D建模软件。有人能给出更具体的答案吗? - RexOnRoids
四边形在OpenGL ES中不可用,因为它们被移除以减小包的大小。绘制圆柱体的最简单编程方式是使用GLUT,但这在OpenGL ES中不可用。 - David Wong
最终我下载了Blender并安装了别人的Objective-C导出脚本,将3D模型创建/导出到iPhone SDK OpenGL项目中。这花了一点时间,但一旦所有东西都准备就绪,就运行良好。我很高兴没有尝试在Xcode中手动编写处理3D模型圆柱体的程序,因为最终的3D模型有大约500个顶点和约700个面孔 LOL。谢谢。 - RexOnRoids

1

通过计算物体的几何形状,您确实可以在OpenGL ES中绘制圆柱体。开源GLUT|ES项目在其glutes_geometry.c源文件中具有用于固体(圆柱体、球体等)的几何绘制例程。不幸的是,这些函数使用了glBegin()和glEnd()调用,在OpenGL ES中不存在。

部分工作的圆柱体实现代码可以在论坛帖子这里中找到。


0

你可以通过计算几何来程序性地绘制圆柱体。除此之外,你还需要让它支持三角形剥离,并且可能还需要计算映射坐标和法向量。因此,从头开始这样做需要一些思考。

我已经在C#中为Unity3D创建了一个模块,可以完全实现这一点,并允许你调整参数。由于无论在哪里,几何计算都是相同的,所以你应该能够轻松转换为C或C++。观看视频,了解其内容,并从GitHub下载代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接