Класс кнопки в Android OpenGL с указателем TextureBuffer

Я создаю класс кнопок, который будет отображать синий кружок, если он не нажимается, и красный кружок, если он нажимается. Я начинаю с построения четырехвершинного четырехугольника, состоящего из двух треугольников. Я создаю собственное растровое изображение и рисую на нем два круга рядом друг с другом, слева направо. Затем я создаю буфер текстуры с 4 точками УФ, я создаю его с 8, одна, которая отображает синий круг, другая, которая отображает красный круг. Затем я хотел бы отобразить красный кружок при нажатии кнопки. В идеале я бы назвал

gl.glTexCoordPointer

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

public void InitializeButton(GL10 gl, int upcolor, int downcolor, String symbol)
    {
        //Our variables for creating a bitmap and texture
        Canvas canvas   = null; 
        Bitmap bitmap   = null;
        Paint  paint    = null;

    //Set up the bitmap type
    Bitmap.Config conf = Bitmap.Config.ARGB_8888;


    /*
     * We now want to calculate the size of the texture. Remember it is best to be a square
     * texture or at least a power of 2. The below equation below will do this. For example
     * if the width of the button was say 20, we need to find the smallest power of 2 that is
     * greater than 20. In this case we know it is 32. But how do we calculate that? First we
     * have to find out the exponent of what 2^x = 20. Then we find the ceiling of tha number.
     * In order to make that calculation we have to take the log of that, but in order to use
     * the log function which is base 10, we have to switch to base 2 so that means 
     * we have to take the log(width)/log(2) to switch to base 2, then get the ceiling of that
     * number because it would be between 4 and 5 in this case. When we take the ceiling we get
     * 5 and 2^5 is 32.
     * 
     * Side note, we want to double the size to make sure there is room for the up and the down
     * actions.
     */
    widthTexture = (int) Math.pow(2,Math.ceil((Math.log(this.width*2)/Math.log(2))));
    heightTexture = (int) Math.pow(2,Math.ceil((Math.log(this.height*2)/Math.log(2))));

    /*
     * Now we will create the bitmap for the creation of the button
     */
    bitmap = Bitmap.createBitmap(widthTexture,heightTexture,conf);

    //Now create a new canvas from that bitmap
    canvas = new Canvas(bitmap);

    //Create a new Paint
    paint = new Paint();

    /*
     * Now we want to render the draw the up and down button on the texture. We are just going
     * to use two different colors to represent up and down. So we will draw the up circle button
     * starting at 0 0 and the down button off to the right.
     */
    paint.setColor(upcolor);
    paint.setAlpha(120);
    canvas.drawOval(new RectF(0,0,width,height), paint);
    paint.setColor(Color.BLACK);
    canvas.drawText(symbol, width/2, height/2, paint);
    paint.setColor(Color.WHITE);
    canvas.drawText(symbol, width/2+3, height/2+3, paint);

    //Draw the down color button
    paint.setColor(downcolor);
    paint.setAlpha(120);
    canvas.drawOval(new RectF(width,0,width*2,height), paint);
    paint.setColor(Color.WHITE);
    canvas.drawText(symbol, width+(width/2), height/2, paint);
    paint.setColor(Color.BLACK);
    canvas.drawText(symbol, width+(width/2)+3, height/2+3, paint);

    float widthpercent  =  ((float)width/(float)widthTexture);
    float heightpercent =  ((float)height/(float)heightTexture);

    /*
     * Now create two texture maps. One for the up button and one for the down button
     * You can change the offset of the draw texture thing to change the animations now
     */
    float uvTextures[] = {0f,                   heightpercent,
                          widthpercent,         heightpercent,
                          widthpercent,         0f,
                          0f,                   0f,
                          widthpercent,         heightpercent,
                          widthpercent*2,       heightpercent,
                          widthpercent*2,       0f,
                          widthpercent,         0f,
                          };

    /*
     * Allocate the byte buffer so it is a normal array of floats and not a java array.
     * load the uvTexture values inside.
     */
    ByteBuffer tbb = ByteBuffer.allocateDirect(uvTextures.length*4);
    tbb.order(ByteOrder.nativeOrder());
    textureBuffer = tbb.asFloatBuffer();
    textureBuffer.put(uvTextures);
    textureBuffer.position(0);  

    int [] textures = new int[1];

    gl.glGenTextures(1, textures,0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D,  textures[0]);
    textureID = textures[0];
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,bitmap,0);


    //Don't forget to deallocate the bitmap
    bitmap.recycle();
}

Итак, в конечном итоге в методе рендеринга я хочу иметь возможность отображать разные координаты на карте текстуры для одних и тех же вершин. Поэтому я вызываю glTexCoordPointer и меняю смещение на «counter», где счетчик должен быть 6 * 4 (6 вершин умножить на 4 байта на число с плавающей запятой), но это не работает, поэтому я попробовал счетчик на 0 и увеличил его, но так и не нашел волшебного номер, который будет отображать красную кнопку. Кстати, когда я пробовал это, я получал очень странные узоры, иногда показывающие от 10 до 15 мини-синих и красных кругов.

    if(isdown)
        gl.glTexCoordPointer(2,GL10.GL_FLOAT,counter,textureBuffer);
    else
        gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,textureBuffer);

person Matthew    schedule 09.12.2012    source источник
comment
gl.glTexCoordPointer(..) третий параметр - это шаг между элементами, а не точное смещение. Если вы хотите иметь смещение, вы можете вызвать textureBuffer.position(startPosition) перед вызовом glTexCoordPointer.   -  person harism    schedule 09.12.2012
comment
Мистер @harism Genius! Это работает! Я изменил позицию на 8, когда кнопка нажата и все работает отлично! Могу ли я снизить производительность, изменив положение буфера? (не O (n) копирование или что-то в этом роде?) Кроме того, если вы не против ответить на вопрос, я голосую и принимаю его!   -  person Matthew    schedule 09.12.2012


Ответы (1)


@Harism был правильным для моей ситуации. Надеюсь, я все еще использую это правильно. Я думал, что переменную шага можно изменить, но мне пришлось изменить положение буфера. Это работало для анимации текстур на 3D-поверхностях. Я не знаю, является ли это «лучшим» способом сделать это, но до тех пор я буду использовать его.

person Matthew    schedule 10.12.2012