Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在OpenGL ES 2.0中绘制球体_Java_Android_Opengl Es_Glsl_Opengl Es 2.0 - Fatal编程技术网

Java 在OpenGL ES 2.0中绘制球体

Java 在OpenGL ES 2.0中绘制球体,java,android,opengl-es,glsl,opengl-es-2.0,Java,Android,Opengl Es,Glsl,Opengl Es 2.0,我试图在Android上用openGL ES 2.0绘制一个球体。我已经看了相关的问题,并尝试了他们的一些代码,但我仍然无法让它工作 基于这一点,我想出了下面的代码。但是它没有正确绘制;当使用glDrawArrays渲染工作但结果不正确时,当使用glDrawElements时,我得到一个GLU INVALID_操作错误。我在下面列出了缓冲区的内容 java public class Sphere { private int stacks; private int slices;

我试图在Android上用openGL ES 2.0绘制一个球体。我已经看了相关的问题,并尝试了他们的一些代码,但我仍然无法让它工作

基于这一点,我想出了下面的代码。但是它没有正确绘制;当使用glDrawArrays渲染工作但结果不正确时,当使用glDrawElements时,我得到一个GLU INVALID_操作错误。我在下面列出了缓冲区的内容

java

public class Sphere
{
    private int stacks;
    private int slices;
    private float radius;

    //Buffers
    private FloatBuffer vertexBuffer;
    private FloatBuffer colorBuffer;
    private ShortBuffer indexBuffer;

    //Buffer sizes in aantal bytes
    private int vertexBufferSize;
    private int colorBufferSize;
    private int indexBufferSize;

    private int vertexCount;

    private int program;

    static final int FLOATS_PER_VERTEX = 3; // Het aantal floats in een vertex (x, y, z)
    static final int FLOATS_PER_COLOR = 4;  // Het aantal floats in een kleur (r, g, b, a)
    static final int SHORTS_PER_INDEX = 2;  
    static final int BYTES_PER_FLOAT = 4;   
    static final int BYTES_PER_SHORT = 2;   

    static final int BYTES_PER_VERTEX = FLOATS_PER_VERTEX * BYTES_PER_FLOAT;
    static final int BYTES_PER_COLOR = FLOATS_PER_COLOR * BYTES_PER_FLOAT;
    static final int BYTES_PER_INDEX_ENTRY = SHORTS_PER_INDEX * BYTES_PER_SHORT;

    // Set color with red, green, blue and alpha (opacity) values
    private float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Sphere(float radius, int stacks, int slices)
    {
        this.stacks = stacks;
        this.slices = slices;
        this.radius = radius;

        vertexCount         = (stacks+1) * (slices+1);
        vertexBufferSize    = vertexCount * BYTES_PER_VERTEX;
        colorBufferSize     = vertexCount * BYTES_PER_COLOR;
        indexBufferSize     = vertexCount * BYTES_PER_INDEX_ENTRY;

        program = GLHelpers.createProgram();
        if (program == 0) {
            return;
        }
        GLHelpers.checkGlError("program");

        // Setup vertex-array buffer. Vertices in float. A float has 4 bytes.
        vertexBuffer = ByteBuffer.allocateDirect(vertexBufferSize).order(ByteOrder.nativeOrder()).asFloatBuffer();
        colorBuffer = ByteBuffer.allocateDirect(colorBufferSize).order(ByteOrder.nativeOrder()).asFloatBuffer();
        indexBuffer = ByteBuffer.allocateDirect(indexBufferSize).order(ByteOrder.nativeOrder()).asShortBuffer();    

        generateSphereCoords(radius, stacks, slices);

        vertexBuffer.position(0);
        colorBuffer.position(0);
        indexBuffer.position(0);
    }


    public void draw(float[] modelViewProjectionMatrix)
    {
        GLES20.glUseProgram(program);

        GLHelpers.checkGlError("useprogram");

        int positionHandle = GLES20.glGetAttribLocation(program, "a_Position");
        GLES20.glEnableVertexAttribArray(positionHandle);
        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, BYTES_PER_VERTEX, vertexBuffer);
        GLHelpers.checkGlError("pos");

        //int colorHandle = GLES20.glGetAttribLocation(program, "a_Color");
        //GLES20.glEnableVertexAttribArray(colorHandle);
        //GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, BYTES_PER_COLOR, colorBuffer);
        //GLHelpers.checkGlError("color");

        int matrixHandle = GLES20.glGetUniformLocation(program, "u_Matrix");
        GLES20.glUniformMatrix4fv(matrixHandle, 1, false, modelViewProjectionMatrix, 0);

        /*
         * When using glDrawArrays rendering works but the results are not correct, when using glDrawElements I get an GL_INVALID_OPERATION error.
         */
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexBuffer.capacity(), GLES20.GL_SHORT, indexBuffer);
        //GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount);

        GLHelpers.checkGlError("draw");

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(positionHandle);
        //GLES20.glDisableVertexAttribArray(colorHandle);
    }

    private void generateSphereCoords(float radius, int stacks, int slices)
    {
        for (int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
            {
                float theta = (float) (stackNumber * Math.PI / stacks);
                float phi = (float) (sliceNumber * 2 * Math.PI / slices);
                float sinTheta = FloatMath.sin(theta);
                float sinPhi = FloatMath.sin(phi);
                float cosTheta = FloatMath.cos(theta);
                float cosPhi = FloatMath.cos(phi);
                vertexBuffer.put(new float[]{radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta});
            }
        }

        for (int stackNumber = 0; stackNumber < stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
            {
                indexBuffer.put((short) ((stackNumber * slices) + (sliceNumber % slices)));
                indexBuffer.put((short) (((stackNumber + 1) * slices) + (sliceNumber % slices)));
            }
        }
    }
}
vertexBuffer的内容

indexBuffer的内容

使用GLDrawArray时的结果:

您将vertexCount设置为每个浮点的lat*lon*bytes,这在我看来非常奇怪

我认为您将这个变量命名错误,因为顶点的数量与每个浮点的字节数无关

在glDrawArrays中使用相同的变量,在我看来,该变量没有精确的顶点数

您将vertexCount设置为每个浮点的lat*lon*bytes,这在我看来非常奇怪

我认为您将这个变量命名错误,因为顶点的数量与每个浮点的字节数无关


在glDrawArrays中使用相同的变量,在我看来,该变量没有精确的顶点数

正如创建球体的工作代码所承诺的:

    public static Model3D createSphere(float radius, int stacks, int slices)
    {
        int vertexCount = (stacks + 1) * (slices + 1);
        FloatBuffer vertexBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_VERTEX).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer normalBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_NORMAL).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer textureCoordBuffer  = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TEXTURE_COORD).order(ByteOrder.nativeOrder()).asFloatBuffer();
        ShortBuffer indexBuffer         = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TRIANGLE_INDEX).order(ByteOrder.nativeOrder()).asShortBuffer();

        for (int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
            {
                float theta = (float) (stackNumber * Math.PI / stacks);
                float phi = (float) (sliceNumber * 2 * Math.PI / slices);
                float sinTheta = FloatMath.sin(theta);
                float sinPhi = FloatMath.sin(phi);
                float cosTheta = FloatMath.cos(theta);
                float cosPhi = FloatMath.cos(phi);

                float nx = cosPhi * sinTheta;
                float ny = cosTheta;
                float nz = sinPhi * sinTheta;


                float x = radius * nx;
                float y = radius * ny;
                float z = radius * nz;

                float u = 1.f - ((float)sliceNumber / (float)slices);
                float v = (float)stackNumber / (float)stacks;



                normalBuffer.put(nx);
                normalBuffer.put(ny);
                normalBuffer.put(nz);

                vertexBuffer.put(x);
                vertexBuffer.put(y);
                vertexBuffer.put(z);

                textureCoordBuffer.put(u);
                textureCoordBuffer.put(v);
            }
        }

        for (int stackNumber = 0; stackNumber < stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
            {
                int second = (sliceNumber * (stacks + 1)) + stackNumber;
                int first = second + stacks + 1;

                //int first = (stackNumber * slices) + (sliceNumber % slices);
                //int second = ((stackNumber + 1) * slices) + (sliceNumber % slices);

                indexBuffer.put((short) first);
                indexBuffer.put((short) second);
                indexBuffer.put((short) (first + 1));

                indexBuffer.put((short) second);
                indexBuffer.put((short) (second + 1));
                indexBuffer.put((short) (first + 1));
            }
        }

        vertexBuffer.rewind();
        normalBuffer.rewind();
        indexBuffer.rewind();
        textureCoordBuffer.rewind();

        Model3D sphere = new Model3D().setVertexBuffer(vertexBuffer)
                                      .setNormalBuffer(normalBuffer)
                                      .setIndexBuffer(indexBuffer)
                                      .setTexture(R.drawable.earth)
                                      .setTextureCoordBuffer(textureCoordBuffer)
                                      .setDiffuseLighting(-3f, 2.3f, 2f);
        return sphere;

    }

正如创建球体的工作代码所承诺的:

    public static Model3D createSphere(float radius, int stacks, int slices)
    {
        int vertexCount = (stacks + 1) * (slices + 1);
        FloatBuffer vertexBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_VERTEX).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer normalBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_NORMAL).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer textureCoordBuffer  = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TEXTURE_COORD).order(ByteOrder.nativeOrder()).asFloatBuffer();
        ShortBuffer indexBuffer         = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TRIANGLE_INDEX).order(ByteOrder.nativeOrder()).asShortBuffer();

        for (int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
            {
                float theta = (float) (stackNumber * Math.PI / stacks);
                float phi = (float) (sliceNumber * 2 * Math.PI / slices);
                float sinTheta = FloatMath.sin(theta);
                float sinPhi = FloatMath.sin(phi);
                float cosTheta = FloatMath.cos(theta);
                float cosPhi = FloatMath.cos(phi);

                float nx = cosPhi * sinTheta;
                float ny = cosTheta;
                float nz = sinPhi * sinTheta;


                float x = radius * nx;
                float y = radius * ny;
                float z = radius * nz;

                float u = 1.f - ((float)sliceNumber / (float)slices);
                float v = (float)stackNumber / (float)stacks;



                normalBuffer.put(nx);
                normalBuffer.put(ny);
                normalBuffer.put(nz);

                vertexBuffer.put(x);
                vertexBuffer.put(y);
                vertexBuffer.put(z);

                textureCoordBuffer.put(u);
                textureCoordBuffer.put(v);
            }
        }

        for (int stackNumber = 0; stackNumber < stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
            {
                int second = (sliceNumber * (stacks + 1)) + stackNumber;
                int first = second + stacks + 1;

                //int first = (stackNumber * slices) + (sliceNumber % slices);
                //int second = ((stackNumber + 1) * slices) + (sliceNumber % slices);

                indexBuffer.put((short) first);
                indexBuffer.put((short) second);
                indexBuffer.put((short) (first + 1));

                indexBuffer.put((short) second);
                indexBuffer.put((short) (second + 1));
                indexBuffer.put((short) (first + 1));
            }
        }

        vertexBuffer.rewind();
        normalBuffer.rewind();
        indexBuffer.rewind();
        textureCoordBuffer.rewind();

        Model3D sphere = new Model3D().setVertexBuffer(vertexBuffer)
                                      .setNormalBuffer(normalBuffer)
                                      .setIndexBuffer(indexBuffer)
                                      .setTexture(R.drawable.earth)
                                      .setTextureCoordBuffer(textureCoordBuffer)
                                      .setDiffuseLighting(-3f, 2.3f, 2f);
        return sphere;

    }

另外,整个球体是用一个三角形扇子画的?我希望电杆有两个,然后是一些条纹。谢谢你的回答,代码很混乱,问题可能会更好。我用更好的代码和更多的细节更新了我的问题。另外,整个球体是用一个三角形扇子画的?我希望电杆有两个,然后是一些条纹。谢谢你的回答,代码很混乱,问题可能会更好。我用更好的代码和更多的细节更新了我的问题。如果你只想要一个平滑的球体,你可以用两个三角形作为冒名顶替者,就像我在中描述的那样。如果你只想要一个平滑的球体,你可以用我在中描述的两个三角形作为冒名顶替者来做。什么是Model3D?什么是Model3D?
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    public static Model3D createSphere(float radius, int stacks, int slices)
    {
        int vertexCount = (stacks + 1) * (slices + 1);
        FloatBuffer vertexBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_VERTEX).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer normalBuffer        = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_NORMAL).order(ByteOrder.nativeOrder()).asFloatBuffer();
        FloatBuffer textureCoordBuffer  = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TEXTURE_COORD).order(ByteOrder.nativeOrder()).asFloatBuffer();
        ShortBuffer indexBuffer         = ByteBuffer.allocateDirect(vertexCount * GLHelpers.BYTES_PER_TRIANGLE_INDEX).order(ByteOrder.nativeOrder()).asShortBuffer();

        for (int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
            {
                float theta = (float) (stackNumber * Math.PI / stacks);
                float phi = (float) (sliceNumber * 2 * Math.PI / slices);
                float sinTheta = FloatMath.sin(theta);
                float sinPhi = FloatMath.sin(phi);
                float cosTheta = FloatMath.cos(theta);
                float cosPhi = FloatMath.cos(phi);

                float nx = cosPhi * sinTheta;
                float ny = cosTheta;
                float nz = sinPhi * sinTheta;


                float x = radius * nx;
                float y = radius * ny;
                float z = radius * nz;

                float u = 1.f - ((float)sliceNumber / (float)slices);
                float v = (float)stackNumber / (float)stacks;



                normalBuffer.put(nx);
                normalBuffer.put(ny);
                normalBuffer.put(nz);

                vertexBuffer.put(x);
                vertexBuffer.put(y);
                vertexBuffer.put(z);

                textureCoordBuffer.put(u);
                textureCoordBuffer.put(v);
            }
        }

        for (int stackNumber = 0; stackNumber < stacks; ++stackNumber)
        {
            for (int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
            {
                int second = (sliceNumber * (stacks + 1)) + stackNumber;
                int first = second + stacks + 1;

                //int first = (stackNumber * slices) + (sliceNumber % slices);
                //int second = ((stackNumber + 1) * slices) + (sliceNumber % slices);

                indexBuffer.put((short) first);
                indexBuffer.put((short) second);
                indexBuffer.put((short) (first + 1));

                indexBuffer.put((short) second);
                indexBuffer.put((short) (second + 1));
                indexBuffer.put((short) (first + 1));
            }
        }

        vertexBuffer.rewind();
        normalBuffer.rewind();
        indexBuffer.rewind();
        textureCoordBuffer.rewind();

        Model3D sphere = new Model3D().setVertexBuffer(vertexBuffer)
                                      .setNormalBuffer(normalBuffer)
                                      .setIndexBuffer(indexBuffer)
                                      .setTexture(R.drawable.earth)
                                      .setTextureCoordBuffer(textureCoordBuffer)
                                      .setDiffuseLighting(-3f, 2.3f, 2f);
        return sphere;

    }