package com.google.android.diskusage.opengl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.opengl.GLUtils;
import android.os.SystemClock;
import android.util.Log;
import com.google.android.diskusage.FileSystemState;
import com.google.android.diskusage.R;
import com.google.android.diskusage.entity.FileSystemEntry;
public class RenderingThread extends AbstractRenderingThread {
private Context context;
private FileSystemState eventHandler;
private static final float vertexData[][] = {
{ 0.1f, 0.2f, 0},
{ 0.9f, 0.2f, 0},
{ 0.9f, 0.9f, 0},
{ 0.1f, 0.9f, 0}
};
private final ShortBuffer indicies;
private final FloatBuffer vertexBuffer;
private final FloatBuffer texCoords;
private final FloatBuffer textTexCoords;
public Square dirSquare;
public Square fileSquare;
public Square specialSquare;
public SmallSquare smallSquare;
public CursorFrame cursorSquare;
private final static int TEXTURE_SIZE = 1 << 7;
float[] matrix = new float[16];
private static final int MAX_RECTS = 100;
private static final int MAX_INDEXES = MAX_RECTS * 6;
private static final int MAX_VERTEX = MAX_RECTS * 4;
private static final int SIZEOF_SHORT = 2;
private static final int SIZEOF_FLOAT = 4;
private static final int MAX_TEXT_DRAWS_PER_TEXTURE = 100;
private static final int MAX_TEXT_VERTEXES = MAX_TEXT_DRAWS_PER_TEXTURE * 4;
private static final int MAX_TEXT_TEXCOORDS = MAX_TEXT_VERTEXES * 2;
// private float[] dirVertexes = new float[MAX_VERTEX * 3];
//private float[] fileVertexes = new float[MAX_VERTEX * 3];
private float[] textureVertexes = new float[4 * 3];
private BitmapMap currentBitmapMap;
private Bitmap editedBitmap;
private Canvas editedCanvas;
private static final Paint textPaint = new Paint();
private int textHeight;
private float textBaseline;
private static final int padding = FileSystemEntry.padding;
ArrayList<BitmapMap> bitmaps = new ArrayList<BitmapMap>();
private static final float divTexSize = 1.f / TEXTURE_SIZE;
private float max_usage;
// private static final Paint textBgPaint = new Paint();
static {
textPaint.setColor(Color.parseColor("#FFFFFF"));
textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
textPaint.setFlags(textPaint.getFlags() | Paint.ANTI_ALIAS_FLAG);
textPaint.setShadowLayer(padding, 1, 1, Color.BLACK);
// textBgPaint.setColor(Color.parseColor("#000000"));
// textBgPaint.setStyle(Paint.Style.STROKE);
// textBgPaint.setFlags(textPaint.getFlags() | Paint.ANTI_ALIAS_FLAG);
}
public void updateFonts(Context context) {
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
float density = context.getResources().getDisplayMetrics().density;
float dpi = 160 * scaledDensity;
int width = context.getResources().getDisplayMetrics().widthPixels;
int height = context.getResources().getDisplayMetrics().heightPixels;
int min = Math.min(width, height);
float minInch = min / dpi; // my tablet: 5 inch height
// my phone: 2 inc width
Log.d("diskusage", "screen inch = " + minInch);
float defaultSize = textPaint.getTextSize();
textPaint.setTextSize(20);
// Atleast 4 times "Storage Card" should fit into the screen
float textSize = 20 * min / (textPaint.measureText("Storage card") * 4);
// 20 px font, seems confortable enough, if we end up with the font larger
// than that, we may want to fit 2x more data.
if (textSize > 20) {
textSize /= 2;
// In case we cannot fit 2x more data, we at least fit [1.0, 2.0]x more.
if (textSize < 20) {
textSize = 20;
}
}
// For low DPI devices, font size should never go below 12 px (which seems to be default value).
if (textSize < defaultSize) textSize = defaultSize;
// For very high DPI devices, we might want to check if the physical size of letters is sufficient
// Let's say, 20 px font on 300 dpi devices seems readable enough:
if (textSize / dpi < 20 / 300.f) {
textSize = 20.f / 300.f * dpi;
}
textPaint.setTextSize(textSize);
textBaseline = - textPaint.ascent() + FileSystemEntry.padding;
textHeight = (int)(textPaint.descent() - textPaint.ascent() + 1 + 2 * FileSystemEntry.padding);
max_usage = (int)((TEXTURE_SIZE - 1) / textHeight) * (TEXTURE_SIZE - 2);
FileSystemEntry.updateFonts(textSize);
}
public RenderingThread(
Context context,
FileSystemState eventHandler) {
updateFonts(context);
this.context = context;
this.eventHandler = eventHandler;
ByteBuffer pb = ByteBuffer.allocateDirect(MAX_INDEXES * SIZEOF_SHORT);
pb.order(ByteOrder.nativeOrder());
indicies = pb.asShortBuffer();
ByteBuffer tbb = ByteBuffer.allocateDirect(MAX_VERTEX * SIZEOF_FLOAT * 2);
tbb.order(ByteOrder.nativeOrder());
texCoords = tbb.asFloatBuffer();
ByteBuffer vbb = ByteBuffer.allocateDirect(MAX_VERTEX * SIZEOF_FLOAT * 3);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
ByteBuffer tbb2 = ByteBuffer.allocateDirect(MAX_TEXT_VERTEXES * SIZEOF_FLOAT * 2);
tbb2.order(ByteOrder.nativeOrder());
textTexCoords = tbb2.asFloatBuffer();
textTexCoords.position(0);
int vertex = 0;
for (int i = 0; i < MAX_RECTS; i++) {
indicies.put(new short[] {
(short)(0 + vertex), (short)(1 + vertex), (short)(2 + vertex),
(short)(0 + vertex), (short)(2 + vertex), (short)(3 + vertex)});
for (int x = 0; x < 4; x++) {
texCoords.put(vertexData[x][0]);
texCoords.put(vertexData[x][1]);
}
vertex += 4;
}
indicies.position(0);
texCoords.position(0);
}
public void drawVertexes(
float[] out, int pos, float x0, float y0, float x1, float y1) {
out[pos + 0] = x0;
out[pos + 1] = y0;
out[pos + 3] = x1;
out[pos + 4] = y0;
out[pos + 6] = x1;
out[pos + 7] = y1;
out[pos + 9] = x0;
out[pos + 10] = y1;
}
public class Square {
private int nrects = 0;
private final int texture_id;
private final float[] vertexes = new float[MAX_VERTEX * 3];
Square(int resid) {
texture_id = LoadTexture(getBitmap(resid));
}
public final void draw(float x0, float y0, float x1, float y1) {
int pos = nrects * 12;
drawVertexes(vertexes, pos, x0, y0, x1, y1);
nrects++;
if (nrects >= MAX_RECTS) {
flush();
}
}
public void flush() {
if (nrects == 0) return;
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoords);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture_id);
vertexBuffer.put(vertexes, 0, nrects * 12);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, nrects * 6,
GL10.GL_UNSIGNED_SHORT, indicies);
nrects = 0;
}
};
public class SmallSquare {
private int nrects = 0;
private final int texture_id;
private final float[] vertexes = new float[MAX_VERTEX * 3];
private final FloatBuffer texSmallCoordsBuffer;
private final float[] texSmallCoords = new float[MAX_VERTEX * 2];
SmallSquare(int resid) {
texture_id = LoadTexture(getBitmap(resid));
ByteBuffer tbb = ByteBuffer.allocateDirect(
MAX_VERTEX * SIZEOF_FLOAT * 2);
tbb.order(ByteOrder.nativeOrder());
texSmallCoordsBuffer = tbb.asFloatBuffer();
for (int i = 0; i < MAX_RECTS; i++) {
// 0 1 2 3 4 5 6 7
// 0 0, 1 0, 1 n, 0 n
texSmallCoords[i * 8 + 2] = 1;
texSmallCoords[i * 8 + 4] = 1;
}
}
public final void draw(float x0, float y0, float x1, float y1) {
int pos = nrects * 12;
drawVertexes(vertexes, pos, x0, y0, x1, y1);
texSmallCoords[nrects * 8 + 5] = (y1 - y0) / 4;
texSmallCoords[nrects * 8 + 7] = (y1 - y0) / 4;
nrects++;
if (nrects >= MAX_RECTS) {
flush();
}
}
public void flush() {
if (nrects == 0) return;
texSmallCoordsBuffer.put(texSmallCoords, 0, nrects * 8);
texSmallCoordsBuffer.position(0);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texSmallCoordsBuffer);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture_id);
vertexBuffer.put(vertexes, 0, nrects * 12);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, nrects * 6,
GL10.GL_UNSIGNED_SHORT, indicies);
nrects = 0;
}
}
public final class CursorFrame {
private final int white;
// private final int black;
private boolean dirty = false;
private final float[] vertexes = new float[4 * 4 * 3];
CursorFrame() {
white = LoadTexture(getBitmap(R.drawable.white_gradient));
// black = LoadTexture(getBitmap(R.drawable.black_gradient));
}
public final void drawVertexes(int pos, float x0, float y0,
float xoff1, float yoff1, float xoff2, float yoff2) {
vertexes[pos + 0] = x0;
vertexes[pos + 1] = y0;
vertexes[pos + 3] = x0 + xoff1;
vertexes[pos + 4] = y0 + yoff1;
vertexes[pos + 6] = x0 + xoff1 + xoff2;
vertexes[pos + 7] = y0 + yoff1 + yoff2;
vertexes[pos + 9] = x0 + xoff2;
vertexes[pos + 10] = y0 + yoff2;
}
public final void drawFrame(float x0, float y0, float x1, float y1) {
drawVertexes(0, x0, y0, x1 - x0, 0, 0, 8);
drawVertexes(12, x0, y1, 0, y0 - y1, 8, 0);
drawVertexes(24, x1, y0, 0, y1 - y0, -8, 0);
drawVertexes(36, x1, y1, x0 - x1, 0, 0, -8);
dirty = true;
}
public void flush() {
if (!dirty) return;
dirty = false;
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoords);
gl.glEnable(GL10.GL_BLEND);
// gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
// gl.glBindTexture(GL10.GL_TEXTURE_2D, black);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
gl.glBindTexture(GL10.GL_TEXTURE_2D, white);
vertexBuffer.put(vertexes, 2 * 12, 2 * 12);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, 2 * 6,
GL10.GL_UNSIGNED_SHORT, indicies);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoords);
vertexBuffer.put(vertexes, 0, 2 * 12);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, 2 * 6,
GL10.GL_UNSIGNED_SHORT, indicies);
gl.glDisable(GL10.GL_BLEND);
}
};
public int newTextureId() {
int[] ids = new int[1];
gl.glGenTextures(1, ids, 0);
return ids[0];
}
private class BitmapMap implements Comparable<BitmapMap> {
ArrayList<TextPixels> textPixelsArray = new ArrayList<TextPixels>();
int textureid;
int usage;
int last_usage;
int y;
int x;
int build_x;
int build_y;
Bitmap bitmap;
Canvas canvas;
float[] texCoords = new float[MAX_TEXT_TEXCOORDS];
float[] vertexes = new float[MAX_TEXT_VERTEXES * 3];
int nrect;
public boolean inuse;
BitmapMap() {
bitmaps.add(this);
textureid = newTextureId();
edit();
}
Paint clearPaint;
{
clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void edit() {
if (editedBitmap == null) {
editedBitmap = Bitmap.createBitmap(
TEXTURE_SIZE, TEXTURE_SIZE, Bitmap.Config.ARGB_8888);
editedCanvas = new Canvas(editedBitmap);
} else {
editedCanvas.clipRect(new Rect(0, 0, TEXTURE_SIZE, TEXTURE_SIZE));
}
editedCanvas.drawPaint(clearPaint);
bitmap = editedBitmap;
canvas = editedCanvas;
x = 1;
y = 0;
build_x = 1;
build_y = 0;
}
public void reset() {
flush();
for (TextPixels textPixels : textPixelsArray) {
textPixels.reset();
}
textPixelsArray.clear();
edit();
}
public void flushNoDeps() {
if (bitmap != null) {
buildTexture();
}
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureid);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textTexCoords);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
textTexCoords.put(texCoords, 0, nrect * 8);
vertexBuffer.put(vertexes, 0, nrect * 12);
textTexCoords.position(0);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, nrect * 6,
GL10.GL_UNSIGNED_SHORT, indicies);
nrect = 0;
gl.glDisable(GL10.GL_BLEND);
}
public void flush() {
smallSquare.flush();
dirSquare.flush();
fileSquare.flush();
specialSquare.flush();
cursorSquare.flush();
flushNoDeps();
}
public void buildTexture() {
if (build_x == x && build_y == y) return;
build_x = x;
build_y = y;
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureid);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
}
public void commit() {
buildTexture();
// bitmap.recycle();
bitmap = null;
canvas = null;
inuse = true;
}
public int score() {
if (bitmap != null) return Integer.MAX_VALUE;
return usage;
}
@Override
public int compareTo(BitmapMap another) {
int score = score();
int another_score = another.score();
if (score < another_score) return -1;
if (score > another_score) return 1;
return 0;
}
public void destroy() {
for (TextPixels textPixels : textPixelsArray) {
textPixels.reset();
}
}
}
public BitmapMap getCurrentBitmapMap() {
if (currentBitmapMap == null) {
currentBitmapMap = new BitmapMap();
}
if (currentBitmapMap == null)
throw new NullPointerException("no bitmap");
return currentBitmapMap;
}
public boolean hasReusableBitmap() {
// Avoid to hijack texture we just draw into.
// We still have references in TextPixels in current stack
// in function: TextPixels.draw()
// and it is also bad to reuse the same texture as we don't
// cache anything this way.
return !bitmaps.get(0).inuse;
}
public BitmapMap getLeastUsedBitmap() {
BitmapMap bitmapMap = bitmaps.remove(0);
bitmaps.add(bitmapMap);
bitmapMap.reset();
return bitmapMap;
}
public void nextBitmapMap() {
currentBitmapMap.commit();
if (bitmaps.size() >= 40 && hasReusableBitmap()) {
// Log.d("diskusage", "get least used bitmap, bitmaps = 5");
currentBitmapMap = getLeastUsedBitmap();
return;
}
// float bitmapUsage = bitmaps.get(0).last_usage / max_usage;
// if (bitmapUsage < 0.2 && hasReusableBitmap()) {
//// Log.d("diskusage", "get least used bitmap, usage = " + bitmapUsage);
// currentBitmapMap = getLeastUsedBitmap();
// return;
// }
// Log.d("diskusage", "new bitmap");
currentBitmapMap = new BitmapMap();
}
static class TextPixels {
private final String message;
private final int offset;
// Reminder of size after removing offset
private int size;
private BitmapMap bitmapMap;
private int mapX, mapY, mapSize;
private TextPixels nextPixels;
TextPixels(String message) {
this.message = message;
this.size = 0;
this.offset = 0;
}
public void reset() {
bitmapMap = null;
nextPixels = null;
size = 0;
}
TextPixels(String message, int size, int offset) {
this.message = message;
this.size = size;
this.offset = offset;
}
public void draw(RenderingThread rt, float x0, float y0, int elementWidth) {
int textHeight = rt.textHeight;
float textBaseline = rt.textBaseline;
if (size == 0) {
size = (int)(textPaint.measureText(message) + 1 + 2 * FileSystemEntry.padding);
}
if (bitmapMap == null) {
bitmapMap = rt.getCurrentBitmapMap();
bitmapMap.textPixelsArray.add(this);
mapX = bitmapMap.x + 1;
mapY = bitmapMap.y;
int todraw = Math.min(size, elementWidth + 20);
int sizeAvailable = (TEXTURE_SIZE - 2) - mapX;
int drawing = Math.min(sizeAvailable, todraw);
// FIXME: allow 1 additional pixel on line break
Canvas canvas = bitmapMap.canvas;
canvas.save();
canvas.clipRect(new Rect(mapX - 1, mapY,
mapX + drawing + 1, mapY + textHeight));
canvas.drawText(message, mapX - offset + padding, mapY + textBaseline, textPaint);
canvas.restore();
int newx = bitmapMap.x = mapX + drawing + 1;
if (newx > TEXTURE_SIZE - 20) {
bitmapMap.x = 1;
int newy = bitmapMap.y = mapY + textHeight;
if (newy > (TEXTURE_SIZE - 1) - textHeight) rt.nextBitmapMap();
}
mapSize = drawing;
}
int todraw = Math.min(size, elementWidth);
int drawing = Math.min(todraw, mapSize);
bitmapMap.usage += drawing;
float tex_x0 = mapX * divTexSize;
float tex_y0 = mapY * divTexSize;
float tex_x1 = (mapX + drawing) * divTexSize;
float tex_y1 = (mapY + textHeight) * divTexSize;
int nrect = bitmapMap.nrect;
int off = nrect * 8;
float[] texCoordsArray = bitmapMap.texCoords;
texCoordsArray[off + 0] = tex_x0; texCoordsArray[off + 1] = tex_y0;
texCoordsArray[off + 2] = tex_x1; texCoordsArray[off + 3] = tex_y0;
texCoordsArray[off + 4] = tex_x1; texCoordsArray[off + 5] = tex_y1;
texCoordsArray[off + 6] = tex_x0; texCoordsArray[off + 7] = tex_y1;
rt.drawVertexes(bitmapMap.vertexes, nrect * 12,
x0, y0 - textBaseline, x0 + drawing, y0 + textHeight - rt.textBaseline);
int newrect = bitmapMap.nrect = nrect + 1;
if (newrect >= MAX_TEXT_DRAWS_PER_TEXTURE) {
bitmapMap.flush();
}
if (drawing != todraw) {
if (nextPixels == null) {
nextPixels = new TextPixels(message, size - drawing, offset + drawing);
}
nextPixels.draw(rt, x0 + drawing, y0, elementWidth - drawing);
}
}
}
public void flushTexture() {
vertexBuffer.put(textureVertexes, 0, 12);
vertexBuffer.position(0);
gl.glDrawElements(GL10.GL_TRIANGLES, 6,
GL10.GL_UNSIGNED_SHORT, indicies);
}
Bitmap getBitmap(int resid) {
Drawable drawable = context.getResources().getDrawable(resid);
Bitmap bitmap = Bitmap.createBitmap(
16, 16, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.TRANSPARENT);
drawable.setBounds(0, 0, 16, 16);
drawable.draw(canvas);
return bitmap;
}
private int LoadTexture(Bitmap bitmap) {
int texture_id = newTextureId();
// Bitmap bitmap = getBitmap(resid);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture_id);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
bitmap.recycle();
gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
return texture_id;
}
private void LoadTextures(GL10 gl) {
dirSquare = new Square(R.drawable.dirbg_new);
fileSquare = new Square(R.drawable.filebg_new);
specialSquare = new Square(R.drawable.special);
smallSquare = new SmallSquare(R.drawable.small);
cursorSquare = new CursorFrame();
}
public void flush() {
smallSquare.flush();
dirSquare.flush();
fileSquare.flush();
specialSquare.flush();
cursorSquare.flush();
for (BitmapMap bitmap : bitmaps) {
bitmap.flushNoDeps();
}
}
@Override
public boolean renderFrame(GL10 gl) {
// renderFrameStart();
int color = Color.GRAY; // context.getResources().getColor(android.R.color.background_light);
float r = ((color >> 16) & 255) / 255.f;
float g = ((color >> 8) & 255) / 255.f;
float b = (color & 255) / 255.f;
gl.glClearColor(r, g, b, 1.f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glScalef(0.5f, 0.5f, 1.f);
boolean renderRequested = eventHandler.onDrawGPU(this);
flush();
// Collections.sort(bitmaps);
// for (BitmapMap bitmap : bitmaps) {
// bitmap.last_usage = bitmap.usage;
// bitmap.inuse = false;
// bitmap.usage = 0;
// }
return renderRequested;
}
@Override
public void createResources(GL10 gl) {
Log.d("diskusage", "***** surface created *****");
// Load textures
LoadTextures(gl);
}
public void releaseResources(GL10 gl) {
Log.d("diskusage", "***** surface destroyed *****");
for (BitmapMap bitmap : bitmaps) {
bitmap.destroy();
}
bitmaps.clear();
currentBitmapMap = null;
}
@Override
public void sizeChanged(GL10 gl, int width, int height) {
Log.d("diskusage", "***** surface size changed *****");
// FileSystemEntry.elementWidth = 100;// FIXME??;
// FileSystemEntry.fontSize = 20; // FIXME
eventHandler.layout(true, 0, 0, width, height, width, height);
// Init projection
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
GL10.GL_FASTEST);
gl.glViewport(0, 0, width, height);
Log.d("diskusage", "updated viewport = " + width + "x" + height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
// 0 4 8 12
// 1 5 9 13
// 2 6 10 14
// 3 7 11 15
matrix[0] = 4.f / width;
matrix[5] = -4.f / height;
matrix[10] = 1.f;
matrix[15] = 1.f;
matrix[12] = -1f;
matrix[13] = 1f;
gl.glLoadMatrixf(matrix, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glEnable(GL10.GL_DITHER);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
// gl.glEnable(GL10.GL_DEPTH_TEST);
// gl.glDepthFunc(GL10.GL_LESS);
gl.glFrontFace(GL10.GL_CW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// gl.glEnable(GL10.GL_DEPTH_TEST);
eventHandler.draw300ms();
}
}