Android OpenGL круг (сфера) выглядит как эллипс.. нет проекции / камеры

введите описание изображения здесь

также приложил снимок экрана с устройства, можете ли вы помочь мне решить проблему... его версия Android KitKat

public class Balloon
{
    private final String vertexShaderCode =
            // This matrix member variable provides a hook to manipulate
            // the coordinates of the objects that use this vertex shader
                    "attribute vec4 vPosition;" +
                    "void main() {" +
                    "gl_PointSize = 5.0;                  "+
                    "  gl_Position =  vPosition;" +
                    "}";

    private final String fragmentShaderCode =
            "precision mediump float;" +
                    "uniform vec4 vColor;" +
                    "void main() {" +
                    "  gl_FragColor = vColor;" +
                    "}";

    private FloatBuffer vertexBuffer;
    private final int mProgram;
    private int mPositionHandle;
    private int mColorHandle;
    private int mMVPMatrixHandle;

    private float[] data = new float[126];

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;

    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };

    /**
     * Sets up the drawing object data for use in an OpenGL ES context.
     */
    public Balloon() {

        // prepare shaders and OpenGL program
        int vertexShader = MyGLRenderer.loadShader(
                GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(
                GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

        mProgram = GLES20.glCreateProgram();             
        // create empty OpenGL Program
        GLES20.glAttachShader(mProgram, vertexShader);   
        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, fragmentShader); 
        // add the fragment shader to program
        GLES20.glLinkProgram(mProgram);                  
       // create OpenGL program executables

    }

    private void FillBalloon(float x1,float y1,float r1)
    {
        int i=0,j=0;
        float angle = 0;

        float twicePI = (float)2.0 * (float)3.1415926;


        float angle_stepsize = 0.1f;

        // go through all angles from 0 to 2 * PI radians
        for(;angle < twicePI;angle = (angle + angle_stepsize))
        {
            // calculate x, y from a vector with known length and angle
            data[j++] = x1 + r1 * (float)Math.cos(angle);
            data[j++] = y1 + r1 * (float)Math.sin(angle);

        }

        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                j * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        vertexBuffer.put(data);
        // set the buffer to read the first coordinate
        vertexBuffer.position(0);

    }


    /**
     * Encapsulates the OpenGL ES instructions for drawing this shape.
     *
     */
    public void draw() {
        // Add program to OpenGL environment
        GLES20.glUseProgram(mProgram);

        float posX = 0.0f,posY = 0.0f,radius =0.2f;

        FillBalloon(posX, posY, radius);

        // get handle to vertex shader's vPosition member
        mPositionHandle = 
                GLES20.glGetAttribLocation(mProgram,"vPosition");

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(mPositionHandle);

        // Prepare the balloon coordinate data

        GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);

        // get handle to fragment shader's vColor member
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

        // Set color for drawing the triangle
        GLES20.glUniform4fv(mColorHandle, 1, color, 0);
        MyGLRenderer.checkGlError("mColorHandle");


        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 63);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }
}

также приложил снимок экрана с устройства, можете ли вы помочь мне решить проблему... его версия Android KitKat

2 ответа

Чтобы воздушные шары выглядели как круги, добавьте float (назовем его X_SCALE) в качестве параметра для рисования:

public void draw(float X_SCALE) {
   ...
   FillBaloon(posX, posY, radius, X_SCALE);
   ...
}

Затем умножьте координату времени рисования на этот масштабный коэффициент в FillBaloon(...):

data[j++] = x1 + X_SCALE * r1 * (float)Math.cos(angle);

И установите масштабный коэффициент в вашем вызове отрисовки ( X_SCALE):

X_SCALE = (float)MyGLSurfaceView.getHeight()/(float)MyGLSurfaceView.getWidth();
myBaloon.draw(X_SCALE);

Еще лучше было бы установить X_SCALE один раз в onSurfaceCreated ( ...) и каждый раз, когда поверхность изменяется в onSurfaceChanged ( ...) .

И последнее: вы можете избежать приведения двойников к числу с плавающей точкой, используя суффикс "f" при явной инициализации:

float twicePI = 6.28318530717959f;

Это ожидаемое поведение. Система координат по умолчанию для openGL - [-1, 1] по каждой оси. Это означает, что самая левая точка будет иметь x=-1крайний справа x=1самый верхний y=1 и самый нижний y=-1, Теперь в зависимости от соотношения сторон экрана результат будет иметь одинаковое соотношение растяжений.

Вы сами управляете сценой, чтобы нарисовать форму, как вам угодно. Одним из способов является масштабирование данных вершин при их генерации, но я настоятельно не рекомендую вам делать это, так как данные вершин модели должны быть такими, какими они должны быть. Другой способ - просто создать квадратный вид поверхности, который затем ограничивает поверхность для рисования, так что это снова не лучший подход. Еще один способ - использовать видовой экран и установить прямоугольник, внутри которого вы хотите нарисовать свою фигуру, что может быть в порядке, но вы должны помнить, чтобы вернуть его на полную ширину и высоту. И тогда есть матрицы...

Используйте матрицу для определения вашей системы координат. Для 2D лучше всего использовать метод Ortho который использует параметры границы (слева, сверху, снизу, справа), которые затем могут быть установлены на то, что вы хотите. Например, вы можете использовать координаты вида (left = 0, right = viewWidth, top = 0, bottom = viewHeight) или вы можете нормализовать систему около нуля и выбрать, какая граница должна иметь значение 1.0: Для горизонтальной нормализации у вас будет (left = -1, right = 1, top = viewHeight/viewWidth, bottom = -viewHeight/viewWidth) и для вертикальной (left = -viewWidth/viewHeight, right = viewWidth/viewHeight, top = 1.0, bottom = -1.0).

Другие вопросы по тегам