GLSurfaceView меняет отображаемые 2D растровые изображения - PullRequest
0 голосов
/ 09 сентября 2010

У меня есть приложение, которое получает информацию из базы данных и используется для визуализации двумерных растровых изображений в GLSurfaceView.Полученная информация будет определять x-положение растрового изображения и то, какое растровое изображение использовать (в моей папке res есть 4 разных растровых изображения на выбор).

Ниже приведены три класса, которые используются.Activity устанавливает объекты Shapes, которые должны быть нарисованы, передавая ArrayList классу GLLayer.Этот ArrayList передается экземпляру класса ShapeStorage с помощью другого метода setList.Этот класс отвечает за рисование при получении.

Проблема, с которой я столкнулся, заключается в следующем.Предположим, я получил один объект (скажем, это квадрат в точке с х = 1).Проходит некоторое время, и я получаю другую фигуру (на этот раз это треугольник, и он расположен в точке х = -1).Однако, когда эта новая форма появляется на экране, внешний вид старого растрового изображения изменяется на треугольник, а новый становится квадратом.Другими словами, сами объекты находятся в правильном положении, в котором они должны быть, но растровое изображение, связанное с ними, изменилось.Кто-нибудь знает, что может быть причиной этого?Я все еще новичок в OpenGL-ES, и хотя этот код выглядит очень замысловатым, он просто устанавливает множество различных свойств для View.Пожалуйста, помогите мне, StackOverflow!Ты моя единственная надежда.

public class GLLayer extends GLSurfaceView implements Renderer {
    int onDrawFrameCounter=1;
    int[] cameraTexture;
    byte[] glCameraFrame=new byte[256*256]; //size of a texture must be a power of 2
    private Context context;
    FloatBuffer cubeBuff;
    FloatBuffer texBuff;
    ShapeStorage shapes;
    ArrayList<Shapes> shapereceptionbuffer;

    public GLLayer(Context c) {
        super(c);
        this.context=c;
        //Initiate our stars class with the number of stars
        shapes = new ShapeStorage();
        shapereceptionbuffer=new ArrayList<Shapes>();

        this.setEGLConfigChooser(5, 6, 5, 8, 16, 0);
        this.setRenderer(this); //set the following class as a GLSurfaceView renderer
        this.getHolder().setFormat(PixelFormat.TRANSPARENT); //makes the GLSurfaceView translucent

    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        try {       
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
            gl.glShadeModel(GL10.GL_SMOOTH);                    //Enable Smooth Shading
            gl.glEnable(GL10.GL_TEXTURE_2D);                    //Enable Texture Mapping
            gl.glEnable(GL10.GL_BLEND);                         //Enable blending
            gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);            //Black Background
            gl.glClearDepthf(1.0f);                             //Depth Buffer Setup
            gl.glDisable(GL10.GL_DEPTH_TEST);                   //Disable depth test
            gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);     //Set The Blending Function For Translucency
            shapes.setTextures(gl,context);



        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d("Created",e.getMessage());
        }
    }//end of surfacecreated    

    public void setList(ArrayList<Shapes> receivedList){
        synchronized(this.shapereceptionbuffer){
            shapereceptionbuffer=receivedList;

        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {  
        try {

            if(height == 0) {                       //Prevent A Divide By Zero By
                height = 1;                         //Making Height Equal One
            }

            gl.glViewport(0, 0, width, height);//specifies transformation from normalized device coordinates to window coordinates
            float ratio = (float) width / height;
            gl.glMatrixMode(GL11.GL_PROJECTION); //Select The Projection Matrix
            gl.glLoadIdentity();//Reset The Projection Matrix
            GLU.gluPerspective(gl, 45.0f, ratio, 0.1f, 100.0f);
            gl.glMatrixMode(GL11.GL_MODELVIEW);//Select The Modelview Matrix
            gl.glLoadIdentity();//Reset The Modelview Matrix
        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d("Changed",e.getMessage());
        }
        //GLU.gluLookAt(gl, 0, 0, 4.2f, 0, 0, 0, 0, 1, 0);//eye-point location, center of the scene and an UP vector        
    }//end of surfacechanged

    public void onDrawFrame(GL10 gl) {
        try {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //Clear Screen And Depth Buffer
            Log.d("Buffer Size", String.valueOf(shapereceptionbuffer.size()));
            synchronized(this.shapereceptionbuffer){

                shapes.setShapes(shapereceptionbuffer);
                shapes.draw(gl, this.context);
            }

        } catch (Exception e) {
            Log.d("Draw",e.getMessage());
        }   
    }//end of ondrawframe
}

Этот класс отвечает за рисование каждой из фигур, полученных из внешней базы данных.

/**
 * This class contains, loads, initiates textures and draws our Shapes
 */
public class ShapeStorage {
    private ArrayList<Shapes> shapestoragebuffer;
    private Random rand = new Random(); // Initiate Random for random values of
                                        // stars

    /** Our texture pointer */
    private int[] textures = new int[4];

    /**
     * Constructor for our holder
     */
    public ShapeStorage() {
        shapestoragebuffer = new ArrayList<Shapes>();
    }

    public void setShapes(ArrayList<Shapes> receivedlist) {
        shapestoragebuffer = receivedList;
    }

    public void setupTextures(GL10 gl, Context context) {
        // Get the texture from the Android resource directory
        InputStream is = null;
        gl.glGenTextures(4, textures, 0);
        for (int i = 2; i < 6; i++) {
            switch (i) {
            case 2:
                is = context.getResources().openRawResource(R.drawable.square);
                break;
            case 3:
                is = context.getResources().openRawResource(R.drawable.circle);
                break;

            case 4:
                is = context.getResources().openRawResource(R.drawable.hexagon);
                break;

            case 5:
                is = context.getResources()
                        .openRawResource(R.drawable.triangle);
                break;
            }

            Bitmap bitmap = null;
            try {
                // BitmapFactory is an Android graphics utility for images
                bitmap = BitmapFactory.decodeStream(is);

            } finally {
                // Always clear and close
                try {
                    is.close();
                    is = null;
                } catch (IOException e) {
                }
            }

            // Generate the texture pointer

            // Create Linear Filtered Texture and bind it to texture
            GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
            gl.glBindTexture(GL11.GL_TEXTURE_2D, textures[i - 2]);
            gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
                    GL11.GL_LINEAR);
            gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
                    GL11.GL_LINEAR);

            // Clean up
            bitmap.recycle();
        }
    }

    /**
     * The drawing function.
     * 
     * @param gl
     *            - The GL Context
     * @param twinkle
     *            - Twinkle on or off
     */
    public void draw(GL10 gl, Context context) {
        // Bind the icon texture for all Shapes



        for (int loop = 0; loop < shapestoragebuffer.size(); loop++) {
            // Recover the current star into an object
            Shapes shape = shapestoragebuffer.get(loop);

            gl.glLoadIdentity(); // Reset The Current Modelview Matrix
            // gl.glRotatef(180.0f, -1.0f, 0.0f, 0.0f);
            float x = shape.get_Offset_from_center();
            gl.glTranslatef(x, 0.0f, -40.0f);

            // Draw
            switch (victim.getType()) {
            // green
            case 2:
                shape.draw(gl, textures[0]);
                break;
            // red
            case 3:
                shape.draw(gl, textures[1]);
                break;
            // yellow
            case 4:
                shape.draw(gl, textures[2]);
                break;

            case 5:
                shape.draw(gl, textures[3]);
                break;
            }

        }
    }
}

Вот класс, который определяет каждый из объектов, которые рисуются в GLSurfaceView;каждая из фигур, которые рисуются.

public class Shapes {


    private int _Offset_from_center;
    private int type;

    Context c;
    /** The buffer holding the vertices */
    private FloatBuffer vertexBuffer;
    /** The buffer holding the texture coordinates */
    private FloatBuffer textureBuffer;

    /** The initial vertex definition */
    private float vertices[] = {
                                -1.0f, -1.0f, 0.0f,     //Bottom Left
                                1.0f, -1.0f, 0.0f,      //Bottom Right
                                -1.0f, 1.0f, 0.0f,      //Top Left
                                1.0f, 1.0f, 0.0f        //Top Right
                                                    };

    /** The initial texture coordinates (u, v) */   
    private float texture[] = {
                                0.0f, 0.0f, 
                                1.0f, 0.0f, 
                                0.0f, 1.0f, 
                                1.0f, 1.0f,
                                            };
    public Shapes() {
        //
        ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuf.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        //
        byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuf.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);
    }


    public int get_Offset_from_center() {
        return _Offset_from_center;
    }

    public void set_Offset_from_center(int _Offset_from_center) {
        this._Offset_from_center = _Offset_from_center;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    /**
     * The object own drawing function.
     * Called from the renderer to redraw this instance
     * with possible changes in values.
     * 
     * @param gl - The GL Context
     */
    public void draw(GL10 gl,int texture) {
        gl.glBindTexture(GL11.GL_TEXTURE_2D, texture);
        //Enable the vertex, texture and normal state
        gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        //Point to our buffers
        gl.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, textureBuffer);

        //Draw the vertices as triangle strip
        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        //Disable the client state before leaving
        gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);


    }


} 

1 Ответ

4 голосов
/ 09 сентября 2010

Вы делаете что-то очень странное с текстурами.Почему вы загружаете данные изображения текстуры для каждой фигуры в каждом кадре, и почему вы делаете это после рендеринга фигуры?

Вот как используется обычный поток текстурыв OpenGL работает:

Во время инициализации приложения:

  1. Создание идентификатора текстуры с использованием glGenTextures.
  2. Использование glBindTexture для создания этого идентификаторатекущая текстура.
  3. Установка параметров текстуры.
  4. Загрузка данных изображения с texImage2D или подобным.

Затем каждый раз, когда вам нужно визуализировать материал с помощьютекстура:

  1. Свяжите текстуру с glBindTexture с тем же идентификатором, который вы использовали выше.
  2. Визуализируйте вещи, которые будут использовать текстуру.

Я бы порекомендовал вот что:

Когда ваша деятельность запускается (вызывается косвенно с onCreate или, возможно, onResume в зависимости от того, как работает Android OpenGL):

  1. Сделайте textures массив из 5 элементов и передайте 5 в glGenTextures
  2. Цикл, и для каждого из ваших пяти ресурсовes, свяжите одно из четырех выше и загрузите ваше изображение с texImage2D точно так же, как вы.

Затем, когда вам действительно нужно нарисовать фигуру:

  1. Передайте int для текстуры, а не int [];выберите правильный, основываясь на нужной фигуре.
  2. Вызовите glBindTexture в вашей функции рисования, сначала с этим значением.
  3. Делайте не звонитеtexImage2D в вашем проходе рендеринга.
  4. Позвоните glDrawArrays, чтобы нарисовать фигуру, которую вы выбрали с помощью glBindTexture.

Обратите внимание, что все ваши фигуры могут иметь одну и ту же вершину итекстурные буферы, так как их содержимое одинаково;это просто вещь эффективности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...