OpenGL Sprite Text Activity
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.graphics.spritetext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10Ext;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
/**
* An OpenGL text label maker.
*
*
* OpenGL labels are implemented by creating a Bitmap, drawing all the labels
* into the Bitmap, converting the Bitmap into an Alpha texture, and drawing
* portions of the texture using glDrawTexiOES.
*
* The benefits of this approach are that the labels are drawn using the high
* quality anti-aliased font rasterizer, full character set support, and all the
* text labels are stored on a single texture, which makes it faster to use.
*
* The drawbacks are that you can only have as many labels as will fit onto one
* texture, and you have to recreate the whole texture if any label text
* changes.
*
*/
class LabelMaker {
/**
* Create a label maker or maximum compatibility with various OpenGL ES
* implementations, the strike width and height must be powers of two, We
* want the strike width to be at least as wide as the widest window.
*
* @param fullColor
* true if we want a full color backing store (4444), otherwise
* we generate a grey L8 backing store.
* @param strikeWidth
* width of strike
* @param strikeHeight
* height of strike
*/
public LabelMaker(boolean fullColor, int strikeWidth, int strikeHeight) {
mFullColor = fullColor;
mStrikeWidth = strikeWidth;
mStrikeHeight = strikeHeight;
mTexelWidth = (float) (1.0 / mStrikeWidth);
mTexelHeight = (float) (1.0 / mStrikeHeight);
mClearPaint = new Paint();
mClearPaint.setARGB(0, 0, 0, 0);
mClearPaint.setStyle(Style.FILL);
mState = STATE_NEW;
}
/**
* Call to initialize the class. Call whenever the surface has been created.
*
* @param gl
*/
public void initialize(GL10 gl) {
mState = STATE_INITIALIZED;
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
// Use Nearest for performance.
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
}
/**
* Call when the surface has been destroyed
*/
public void shutdown(GL10 gl) {
if (gl != null) {
if (mState > STATE_NEW) {
int[] textures = new int[1];
textures[0] = mTextureID;
gl.glDeleteTextures(1, textures, 0);
mState = STATE_NEW;
}
}
}
/**
* Call before adding labels. Clears out any existing labels.
*
* @param gl
*/
public void beginAdding(GL10 gl) {
checkState(STATE_INITIALIZED, STATE_ADDING);
mLabels.clear();
mU = 0;
mV = 0;
mLineHeight = 0;
Bitmap.Config config = mFullColor ? Bitmap.Config.ARGB_4444
: Bitmap.Config.ALPHA_8;
mBitmap = Bitmap.createBitmap(mStrikeWidth, mStrikeHeight, config);
mCanvas = new Canvas(mBitmap);
mBitmap.eraseColor(0);
}
/**
* Call to add a label
*
* @param gl
* @param text
* the text of the label
* @param textPaint
* the paint of the label
* @return the id of the label, used to measure and draw the label
*/
public int add(GL10 gl, String text, Paint textPaint) {
return add(gl, null, text, textPaint);
}
/**
* Call to add a label
*
* @param gl
* @param text
* the text of the label
* @param textPaint
* the paint of the label
* @return the id of the label, used to measure and draw the label
*/
public int add(GL10 gl, Drawable background, String text, Paint textPaint) {
return add(gl, background, text, textPaint, 0, 0);
}
/**
* Call to add a label
*
* @return the id of the label, used to measure and draw the label
*/
public int add(GL10 gl, Drawable drawable, int minWidth, int minHeight) {
return add(gl, drawable, null, null, minWidth, minHeight);
}
/**
* Call to add a label
*
* @param gl
* @param text
* the text of the label
* @param textPaint
* the paint of the label
* @return the id of the label, used to measure and draw the label
*/
public int add(GL10 gl, Drawable background, String text, Paint textPaint,
int minWidth, int minHeight) {
checkState(STATE_ADDING, STATE_ADDING);
boolean drawBackground = background != null;
boolean drawText = (text != null) && (textPaint != null);
Rect padding = new Rect();
if (drawBackground) {
background.getPadding(padding);
minWidth = Math.max(minWidth, background.getMinimumWidth());
minHeight = Math.max(minHeight, background.getMinimumHeight());
}
int ascent = 0;
int descent = 0;
int measuredTextWidth = 0;
if (drawText) {
// Paint.ascent is negative, so negate it.
ascent = (int) Math.ceil(-textPaint.ascent());
descent = (int) Math.ceil(textPaint.descent());
measuredTextWidth = (int) Math.ceil(textPaint.measureText(text));
}
int textHeight = ascent + descent;
int textWidth = Math.min(mStrikeWidth, measuredTextWidth);
int padHeight = padding.top + padding.bottom;
int padWidth = padding.left + padding.right;
int height = Math.max(minHeight, textHeight + padHeight);
int width = Math.max(minWidth, textWidth + padWidth);
int effectiveTextHeight = height - padHeight;
int effectiveTextWidth = width - padWidth;
int centerOffsetHeight = (effectiveTextHeight - textHeight) / 2;
int centerOffsetWidth = (effectiveTextWidth - textWidth) / 2;
// Make changes to the local variables, only commit them
// to the member variables after we've decided not to throw
// any exceptions.
int u = mU;
int v = mV;
int lineHeight = mLineHeight;
if (width > mStrikeWidth) {
width = mStrikeWidth;
}
// Is there room for this string on the current line?
if (u + width > mStrikeWidth) {
// No room, go to the next line:
u = 0;
v += lineHeight;
lineHeight = 0;
}
lineHeight = Math.max(lineHeight, height);
if (v + lineHeight > mStrikeHeight) {
throw new IllegalArgumentException("Out of texture space.");
}
int u2 = u + width;
int vBase = v + ascent;
int v2 = v + height;
if (drawBackground) {
background.setBounds(u, v, u + width, v + height);
background.draw(mCanvas);
}
if (drawText) {
mCanvas.drawText(text, u + padding.left + centerOffsetWidth, vBase
+ padding.top + centerOffsetHeight, textPaint);
}
// We know there's enough space, so update the member variables
mU = u + width;
mV = v;
mLineHeight = lineHeight;
mLabels.add(new Label(width, height, ascent, u, v + height, width,
-height));
return mLabels.size() - 1;
}
/**
* Call to end adding labels. Must be called before drawing starts.
*
* @param gl
*/
public void endAdding(GL10 gl) {
checkState(STATE_ADDING, STATE_INITIALIZED);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);
// Reclaim storage used by bitmap and canvas.
mBitmap.recycle();
mBitmap = null;
mCanvas = null;
}
/**
* Get the width in pixels of a given label.
*
* @param labelID
* @return the width in pixels
*/
public float getWidth(int labelID) {
return mLabels.get(labelID).width;
}
/**
* Get the height in pixels of a given label.
*
* @param labelID
* @return the height in pixels
*/
public float getHeight(int labelID) {
return mLabels.get(labelID).height;
}
/**
* Get the baseline of a given label. That's how many pixels from the top of
* the label to the text baseline. (This is equivalent to the negative of
* the label's paint's ascent.)
*
* @param labelID
* @return the baseline in pixels.
*/
public float getBaseline(int labelID) {
return mLabels.get(labelID).baseline;
}
/**
* Begin drawing labels. Sets the OpenGL state for rapid drawing.
*
* @param gl
* @param viewWidth
* @param viewHeight
*/
public void beginDrawing(GL10 gl, float viewWidth, float viewHeight) {
checkState(STATE_INITIALIZED, STATE_DRAWING);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glShadeModel(GL10.GL_FLAT);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrthof(0.0f, viewWidth, 0.0f, viewHeight, 0.0f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
// Magic offsets to promote consistent rasterization.
gl.glTranslatef(0.375f, 0.375f, 0.0f);
}
/**
* Draw a given label at a given x,y position, expressed in pixels, with the
* lower-left-hand-corner of the view being (0,0).
*
* @param gl
* @param x
* @param y
* @param labelID
*/
public void draw(GL10 gl, float x, float y, int labelID) {
checkState(STATE_DRAWING, STATE_DRAWING);
Label label = mLabels.get(labelID);
gl.glEnable(GL10.GL_TEXTURE_2D);
((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
GL11Ext.GL_TEXTURE_CROP_RECT_OES, label.mCrop, 0);
((GL11Ext) gl).glDrawTexiOES((int) x, (int) y, 0, (int) label.width,
(int) label.height);
}
/**
* Ends the drawing and restores the OpenGL state.
*
* @param gl
*/
public void endDrawing(GL10 gl) {
checkState(STATE_DRAWING, STATE_INITIALIZED);
gl.glDisable(GL10.GL_BLEND);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPopMatrix();
}
private void checkState(int oldState, int newState) {
if (mState != oldState) {
throw new IllegalArgumentException("Can't call this method now.");
}
mState = newState;
}
private static class Label {
public Label(float width, float height, float baseLine, int cropU,
int cropV, int cropW, int cropH) {
this.width = width;
this.height = height;
this.baseline = baseLine;
int[] crop = new int[4];
crop[0] = cropU;
crop[1] = cropV;
crop[2] = cropW;
crop[3] = cropH;
mCrop = crop;
}
public float width;
public float height;
public float baseline;
public int[] mCrop;
}
private int mStrikeWidth;
private int mStrikeHeight;
private boolean mFullColor;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mClearPaint;
private int mTextureID;
private float mTexelWidth; // Convert texel to U
private float mTexelHeight; // Convert texel to V
private int mU;
private int mV;
private int mLineHeight;
private ArrayList<Label> mLabels = new ArrayList<Label>();
private static final int STATE_NEW = 0;
private static final int STATE_INITIALIZED = 1;
private static final int STATE_ADDING = 2;
private static final int STATE_DRAWING = 3;
private int mState;
}
class SpriteTextRenderer implements GLSurfaceView.Renderer {
public SpriteTextRenderer(Context context) {
mContext = context;
mTriangle = new Triangle();
mProjector = new Projector();
mLabelPaint = new Paint();
mLabelPaint.setTextSize(32);
mLabelPaint.setAntiAlias(true);
mLabelPaint.setARGB(0xff, 0x00, 0x00, 0x00);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
/*
* By default, OpenGL enables features that improve quality but reduce
* performance. One might want to tweak that especially on software
* renderer.
*/
gl.glDisable(GL10.GL_DITHER);
/*
* Some one-time OpenGL initialization can be made here probably based
* on features of this particular context
*/
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(.5f, .5f, .5f, 1);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
/*
* Create our texture. This has to be done each time the surface is
* created.
*/
int[] textures = new int[1];
gl.glGenTextures(1, textures, 0);
mTextureID = textures[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
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_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
InputStream is = mContext.getResources().openRawResource(R.raw.robot);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
// Ignore.
}
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
if (mLabels != null) {
mLabels.shutdown(gl);
} else {
mLabels = new LabelMaker(true, 256, 64);
}
mLabels.initialize(gl);
mLabels.beginAdding(gl);
mLabelA = mLabels.add(gl, "A", mLabelPaint);
mLabelB = mLabels.add(gl, "B", mLabelPaint);
mLabelC = mLabels.add(gl, "C", mLabelPaint);
mLabelMsPF = mLabels.add(gl, "ms/f", mLabelPaint);
mLabels.endAdding(gl);
if (mNumericSprite != null) {
mNumericSprite.shutdown(gl);
} else {
mNumericSprite = new NumericSprite();
}
mNumericSprite.initialize(gl, mLabelPaint);
}
public void onDrawFrame(GL10 gl) {
/*
* By default, OpenGL enables features that improve quality but reduce
* performance. One might want to tweak that especially on software
* renderer.
*/
gl.glDisable(GL10.GL_DITHER);
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_MODULATE);
/*
* Usually, the first thing one might want to do is to clear the screen.
* The most efficient way of doing this is to use glClear().
*/
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
/*
* Now we're ready to draw some 3D objects
*/
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0.0f, 0.0f, -2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
if (false) {
long time = SystemClock.uptimeMillis();
if (mLastTime != 0) {
long delta = time - mLastTime;
Log.w("time", Long.toString(delta));
}
mLastTime = time;
}
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
gl.glRotatef(angle, 0, 0, 1.0f);
gl.glScalef(2.0f, 2.0f, 2.0f);
mTriangle.draw(gl);
mProjector.getCurrentModelView(gl);
mLabels.beginDrawing(gl, mWidth, mHeight);
drawLabel(gl, 0, mLabelA);
drawLabel(gl, 1, mLabelB);
drawLabel(gl, 2, mLabelC);
float msPFX = mWidth - mLabels.getWidth(mLabelMsPF) - 1;
mLabels.draw(gl, msPFX, 0, mLabelMsPF);
mLabels.endDrawing(gl);
drawMsPF(gl, msPFX);
}
private void drawMsPF(GL10 gl, float rightMargin) {
long time = SystemClock.uptimeMillis();
if (mStartTime == 0) {
mStartTime = time;
}
if (mFrames++ == SAMPLE_PERIOD_FRAMES) {
mFrames = 0;
long delta = time - mStartTime;
mStartTime = time;
mMsPerFrame = (int) (delta * SAMPLE_FACTOR);
}
if (mMsPerFrame > 0) {
mNumericSprite.setValue(mMsPerFrame);
float numWidth = mNumericSprite.width();
float x = rightMargin - numWidth;
mNumericSprite.draw(gl, x, 0, mWidth, mHeight);
}
}
private void drawLabel(GL10 gl, int triangleVertex, int labelId) {
float x = mTriangle.getX(triangleVertex);
float y = mTriangle.getY(triangleVertex);
mScratch[0] = x;
mScratch[1] = y;
mScratch[2] = 0.0f;
mScratch[3] = 1.0f;
mProjector.project(mScratch, 0, mScratch, 4);
float sx = mScratch[4];
float sy = mScratch[5];
float height = mLabels.getHeight(labelId);
float width = mLabels.getWidth(labelId);
float tx = sx - width * 0.5f;
float ty = sy - height * 0.5f;
mLabels.draw(gl, tx, ty, labelId);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
mWidth = w;
mHeight = h;
gl.glViewport(0, 0, w, h);
mProjector.setCurrentView(0, 0, w, h);
/*
* Set our projection matrix. This doesn't have to be done each time we
* draw, but usually a new projection needs to be set when the viewport
* is resized.
*/
float ratio = (float) w / h;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
mProjector.getCurrentProjection(gl);
}
private int mWidth;
private int mHeight;
private Context mContext;
private Triangle mTriangle;
private int mTextureID;
private int mFrames;
private int mMsPerFrame;
private final static int SAMPLE_PERIOD_FRAMES = 12;
private final static float SAMPLE_FACTOR = 1.0f / SAMPLE_PERIOD_FRAMES;
private long mStartTime;
private LabelMaker mLabels;
private Paint mLabelPaint;
private int mLabelA;
private int mLabelB;
private int mLabelC;
private int mLabelMsPF;
private Projector mProjector;
private NumericSprite mNumericSprite;
private float[] mScratch = new float[8];
private long mLastTime;
}
class Triangle {
public Triangle() {
// Buffers to be passed to gl*Pointer() functions
// must be direct, i.e., they must be placed on the
// native heap where the garbage collector cannot
// move them.
//
// Buffers with multi-byte datatypes (e.g., short, int, float)
// must have their byte order set to native order
ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
tbb.order(ByteOrder.nativeOrder());
mTexBuffer = tbb.asFloatBuffer();
ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
ibb.order(ByteOrder.nativeOrder());
mIndexBuffer = ibb.asShortBuffer();
for (int i = 0; i < VERTS; i++) {
for (int j = 0; j < 3; j++) {
mFVertexBuffer.put(sCoords[i * 3 + j]);
}
}
for (int i = 0; i < VERTS; i++) {
for (int j = 0; j < 2; j++) {
mTexBuffer.put(sCoords[i * 3 + j] * 2.0f + 0.5f);
}
}
for (int i = 0; i < VERTS; i++) {
mIndexBuffer.put((short) i);
}
mFVertexBuffer.position(0);
mTexBuffer.position(0);
mIndexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
}
public float getX(int vertex) {
return sCoords[3 * vertex];
}
public float getY(int vertex) {
return sCoords[3 * vertex + 1];
}
private final static int VERTS = 3;
private FloatBuffer mFVertexBuffer;
private FloatBuffer mTexBuffer;
private ShortBuffer mIndexBuffer;
// A unit-sided equalateral triangle centered on the origin.
private final static float[] sCoords = {
// X, Y, Z
-0.5f, -0.25f, 0, 0.5f, -0.25f, 0, 0.0f, 0.559016994f, 0 };
}
/**
* A utility that projects
*
*/
class Projector {
public Projector() {
mMVP = new float[16];
mV = new float[4];
mGrabber = new MatrixGrabber();
}
public void setCurrentView(int x, int y, int width, int height) {
mX = x;
mY = y;
mViewWidth = width;
mViewHeight = height;
}
public void project(float[] obj, int objOffset, float[] win, int winOffset) {
if (!mMVPComputed) {
Matrix.multiplyMM(mMVP, 0, mGrabber.mProjection, 0,
mGrabber.mModelView, 0);
mMVPComputed = true;
}
Matrix.multiplyMV(mV, 0, mMVP, 0, obj, objOffset);
float rw = 1.0f / mV[3];
win[winOffset] = mX + mViewWidth * (mV[0] * rw + 1.0f) * 0.5f;
win[winOffset + 1] = mY + mViewHeight * (mV[1] * rw + 1.0f) * 0.5f;
win[winOffset + 2] = (mV[2] * rw + 1.0f) * 0.5f;
}
/**
* Get the current projection matrix. Has the side-effect of setting current
* matrix mode to GL_PROJECTION
*
* @param gl
*/
public void getCurrentProjection(GL10 gl) {
mGrabber.getCurrentProjection(gl);
mMVPComputed = false;
}
/**
* Get the current model view matrix. Has the side-effect of setting current
* matrix mode to GL_MODELVIEW
*
* @param gl
*/
public void getCurrentModelView(GL10 gl) {
mGrabber.getCurrentModelView(gl);
mMVPComputed = false;
}
private MatrixGrabber mGrabber;
private boolean mMVPComputed;
private float[] mMVP;
private float[] mV;
private int mX;
private int mY;
private int mViewWidth;
private int mViewHeight;
}
/**
* Allows retrieving the current matrix even if the current OpenGL ES driver
* does not support retrieving the current matrix.
*
* Note: the actual matrix may differ from the retrieved matrix, due to
* differences in the way the math is implemented by GLMatrixWrapper as compared
* to the way the math is implemented by the OpenGL ES driver.
*/
class MatrixTrackingGL implements GL, GL10, GL10Ext, GL11, GL11Ext {
private GL10 mgl;
private GL10Ext mgl10Ext;
private GL11 mgl11;
private GL11Ext mgl11Ext;
private int mMatrixMode;
private MatrixStack mCurrent;
private MatrixStack mModelView;
private MatrixStack mTexture;
private MatrixStack mProjection;
private final static boolean _check = false;
ByteBuffer mByteBuffer;
FloatBuffer mFloatBuffer;
float[] mCheckA;
float[] mCheckB;
public MatrixTrackingGL(GL gl) {
mgl = (GL10) gl;
if (gl instanceof GL10Ext) {
mgl10Ext = (GL10Ext) gl;
}
if (gl instanceof GL11) {
mgl11 = (GL11) gl;
}
if (gl instanceof GL11Ext) {
mgl11Ext = (GL11Ext) gl;
}
mModelView = new MatrixStack();
mProjection = new MatrixStack();
mTexture = new MatrixStack();
mCurrent = mModelView;
mMatrixMode = GL10.GL_MODELVIEW;
}
// ---------------------------------------------------------------------
// GL10 methods:
public void glActiveTexture(int texture) {
mgl.glActiveTexture(texture);
}
public void glAlphaFunc(int func, float ref) {
mgl.glAlphaFunc(func, ref);
}
public void glAlphaFuncx(int func, int ref) {
mgl.glAlphaFuncx(func, ref);
}
public void glBindTexture(int target, int texture) {
mgl.glBindTexture(target, texture);
}
public void glBlendFunc(int sfactor, int dfactor) {
mgl.glBlendFunc(sfactor, dfactor);
}
public void glClear(int mask) {
mgl.glClear(mask);
}
public void glClearColor(float red, float green, float blue, float alpha) {
mgl.glClearColor(red, green, blue, alpha);
}
public void glClearColorx(int red, int green, int blue, int alpha) {
mgl.glClearColorx(red, green, blue, alpha);
}
public void glClearDepthf(float depth) {
mgl.glClearDepthf(depth);
}
public void glClearDepthx(int depth) {
mgl.glClearDepthx(depth);
}
public void glClearStencil(int s) {
mgl.glClearStencil(s);
}
public void glClientActiveTexture(int texture) {
mgl.glClientActiveTexture(texture);
}
public void glColor4f(float red, float green, float blue, float alpha) {
mgl.glColor4f(red, green, blue, alpha);
}
public void glColor4x(int red, int green, int blue, int alpha) {
mgl.glColor4x(red, green, blue, alpha);
}
public void glColorMask(boolean red, boolean green, boolean blue,
boolean alpha) {
mgl.glColorMask(red, green, blue, alpha);
}
public void glColorPointer(int size, int type, int stride, Buffer pointer) {
mgl.glColorPointer(size, type, stride, pointer);
}
public void glCompressedTexImage2D(int target, int level,
int internalformat, int width, int height, int border,
int imageSize, Buffer data) {
mgl.glCompressedTexImage2D(target, level, internalformat, width,
height, border, imageSize, data);
}
public void glCompressedTexSubImage2D(int target, int level, int xoffset,
int yoffset, int width, int height, int format, int imageSize,
Buffer data) {
mgl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width,
height, format, imageSize, data);
}
public void glCopyTexImage2D(int target, int level, int internalformat,
int x, int y, int width, int height, int border) {
mgl.glCopyTexImage2D(target, level, internalformat, x, y, width,
height, border);
}
public void glCopyTexSubImage2D(int target, int level, int xoffset,
int yoffset, int x, int y, int width, int height) {
mgl.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
height);
}
public void glCullFace(int mode) {
mgl.glCullFace(mode);
}
public void glDeleteTextures(int n, int[] textures, int offset) {
mgl.glDeleteTextures(n, textures, offset);
}
public void glDeleteTextures(int n, IntBuffer textures) {
mgl.glDeleteTextures(n, textures);
}
public void glDepthFunc(int func) {
mgl.glDepthFunc(func);
}
public void glDepthMask(boolean flag) {
mgl.glDepthMask(flag);
}
public void glDepthRangef(float near, float far) {
mgl.glDepthRangef(near, far);
}
public void glDepthRangex(int near, int far) {
mgl.glDepthRangex(near, far);
}
public void glDisable(int cap) {
mgl.glDisable(cap);
}
public void glDisableClientState(int array) {
mgl.glDisableClientState(array);
}
public void glDrawArrays(int mode, int first, int count) {
mgl.glDrawArrays(mode, first, count);
}
public void glDrawElements(int mode, int count, int type, Buffer indices) {
mgl.glDrawElements(mode, count, type, indices);
}
public void glEnable(int cap) {
mgl.glEnable(cap);
}
public void glEnableClientState(int array) {
mgl.glEnableClientState(array);
}
public void glFinish() {
mgl.glFinish();
}
public void glFlush() {
mgl.glFlush();
}
public void glFogf(int pname, float param) {
mgl.glFogf(pname, param);
}
public void glFogfv(int pname, float[] params, int offset) {
mgl.glFogfv(pname, params, offset);
}
public void glFogfv(int pname, FloatBuffer params) {
mgl.glFogfv(pname, params);
}
public void glFogx(int pname, int param) {
mgl.glFogx(pname, param);
}
public void glFogxv(int pname, int[] params, int offset) {
mgl.glFogxv(pname, params, offset);
}
public void glFogxv(int pname, IntBuffer params) {
mgl.glFogxv(pname, params);
}
public void glFrontFace(int mode) {
mgl.glFrontFace(mode);
}
public void glFrustumf(float left, float right, float bottom, float top,
float near, float far) {
mCurrent.glFrustumf(left, right, bottom, top, near, far);
mgl.glFrustumf(left, right, bottom, top, near, far);
if (_check)
check();
}
public void glFrustumx(int left, int right, int bottom, int top, int near,
int far) {
mCurrent.glFrustumx(left, right, bottom, top, near, far);
mgl.glFrustumx(left, right, bottom, top, near, far);
if (_check)
check();
}
public void glGenTextures(int n, int[] textures, int offset) {
mgl.glGenTextures(n, textures, offset);
}
public void glGenTextures(int n, IntBuffer textures) {
mgl.glGenTextures(n, textures);
}
public int glGetError() {
int result = mgl.glGetError();
return result;
}
public void glGetIntegerv(int pname, int[] params, int offset) {
mgl.glGetIntegerv(pname, params, offset);
}
public void glGetIntegerv(int pname, IntBuffer params) {
mgl.glGetIntegerv(pname, params);
}
public String glGetString(int name) {
String result = mgl.glGetString(name);
return result;
}
public void glHint(int target, int mode) {
mgl.glHint(target, mode);
}
public void glLightModelf(int pname, float param) {
mgl.glLightModelf(pname, param);
}
public void glLightModelfv(int pname, float[] params, int offset) {
mgl.glLightModelfv(pname, params, offset);
}
public void glLightModelfv(int pname, FloatBuffer params) {
mgl.glLightModelfv(pname, params);
}
public void glLightModelx(int pname, int param) {
mgl.glLightModelx(pname, param);
}
public void glLightModelxv(int pname, int[] params, int offset) {
mgl.glLightModelxv(pname, params, offset);
}
public void glLightModelxv(int pname, IntBuffer params) {
mgl.glLightModelxv(pname, params);
}
public void glLightf(int light, int pname, float param) {
mgl.glLightf(light, pname, param);
}
public void glLightfv(int light, int pname, float[] params, int offset) {
mgl.glLightfv(light, pname, params, offset);
}
public void glLightfv(int light, int pname, FloatBuffer params) {
mgl.glLightfv(light, pname, params);
}
public void glLightx(int light, int pname, int param) {
mgl.glLightx(light, pname, param);
}
public void glLightxv(int light, int pname, int[] params, int offset) {
mgl.glLightxv(light, pname, params, offset);
}
public void glLightxv(int light, int pname, IntBuffer params) {
mgl.glLightxv(light, pname, params);
}
public void glLineWidth(float width) {
mgl.glLineWidth(width);
}
public void glLineWidthx(int width) {
mgl.glLineWidthx(width);
}
public void glLoadIdentity() {
mCurrent.glLoadIdentity();
mgl.glLoadIdentity();
if (_check)
check();
}
public void glLoadMatrixf(float[] m, int offset) {
mCurrent.glLoadMatrixf(m, offset);
mgl.glLoadMatrixf(m, offset);
if (_check)
check();
}
public void glLoadMatrixf(FloatBuffer m) {
int position = m.position();
mCurrent.glLoadMatrixf(m);
m.position(position);
mgl.glLoadMatrixf(m);
if (_check)
check();
}
public void glLoadMatrixx(int[] m, int offset) {
mCurrent.glLoadMatrixx(m, offset);
mgl.glLoadMatrixx(m, offset);
if (_check)
check();
}
public void glLoadMatrixx(IntBuffer m) {
int position = m.position();
mCurrent.glLoadMatrixx(m);
m.position(position);
mgl.glLoadMatrixx(m);
if (_check)
check();
}
public void glLogicOp(int opcode) {
mgl.glLogicOp(opcode);
}
public void glMaterialf(int face, int pname, float param) {
mgl.glMaterialf(face, pname, param);
}
public void glMaterialfv(int face, int pname, float[] params, int offset) {
mgl.glMaterialfv(face, pname, params, offset);
}
public void glMaterialfv(int face, int pname, FloatBuffer params) {
mgl.glMaterialfv(face, pname, params);
}
public void glMaterialx(int face, int pname, int param) {
mgl.glMaterialx(face, pname, param);
}
public void glMaterialxv(int face, int pname, int[] params, int offset) {
mgl.glMaterialxv(face, pname, params, offset);
}
public void glMaterialxv(int face, int pname, IntBuffer params) {
mgl.glMaterialxv(face, pname, params);
}
public void glMatrixMode(int mode) {
switch (mode) {
case GL10.GL_MODELVIEW:
mCurrent = mModelView;
break;
case GL10.GL_TEXTURE:
mCurrent = mTexture;
break;
case GL10.GL_PROJECTION:
mCurrent = mProjection;
break;
default:
throw new IllegalArgumentException("Unknown matrix mode: " + mode);
}
mgl.glMatrixMode(mode);
mMatrixMode = mode;
if (_check)
check();
}
public void glMultMatrixf(float[] m, int offset) {
mCurrent.glMultMatrixf(m, offset);
mgl.glMultMatrixf(m, offset);
if (_check)
check();
}
public void glMultMatrixf(FloatBuffer m) {
int position = m.position();
mCurrent.glMultMatrixf(m);
m.position(position);
mgl.glMultMatrixf(m);
if (_check)
check();
}
public void glMultMatrixx(int[] m, int offset) {
mCurrent.glMultMatrixx(m, offset);
mgl.glMultMatrixx(m, offset);
if (_check)
check();
}
public void glMultMatrixx(IntBuffer m) {
int position = m.position();
mCurrent.glMultMatrixx(m);
m.position(position);
mgl.glMultMatrixx(m);
if (_check)
check();
}
public void glMultiTexCoord4f(int target, float s, float t, float r, float q) {
mgl.glMultiTexCoord4f(target, s, t, r, q);
}
public void glMultiTexCoord4x(int target, int s, int t, int r, int q) {
mgl.glMultiTexCoord4x(target, s, t, r, q);
}
public void glNormal3f(float nx, float ny, float nz) {
mgl.glNormal3f(nx, ny, nz);
}
public void glNormal3x(int nx, int ny, int nz) {
mgl.glNormal3x(nx, ny, nz);
}
public void glNormalPointer(int type, int stride, Buffer pointer) {
mgl.glNormalPointer(type, stride, pointer);
}
public void glOrthof(float left, float right, float bottom, float top,
float near, float far) {
mCurrent.glOrthof(left, right, bottom, top, near, far);
mgl.glOrthof(left, right, bottom, top, near, far);
if (_check)
check();
}
public void glOrthox(int left, int right, int bottom, int top, int near,
int far) {
mCurrent.glOrthox(left, right, bottom, top, near, far);
mgl.glOrthox(left, right, bottom, top, near, far);
if (_check)
check();
}
public void glPixelStorei(int pname, int param) {
mgl.glPixelStorei(pname, param);
}
public void glPointSize(float size) {
mgl.glPointSize(size);
}
public void glPointSizex(int size) {
mgl.glPointSizex(size);
}
public void glPolygonOffset(float factor, float units) {
mgl.glPolygonOffset(factor, units);
}
public void glPolygonOffsetx(int factor, int units) {
mgl.glPolygonOffsetx(factor, units);
}
public void glPopMatrix() {
mCurrent.glPopMatrix();
mgl.glPopMatrix();
if (_check)
check();
}
public void glPushMatrix() {
mCurrent.glPushMatrix();
mgl.glPushMatrix();
if (_check)
check();
}
public void glReadPixels(int x, int y, int width, int height, int format,
int type, Buffer pixels) {
mgl.glReadPixels(x, y, width, height, format, type, pixels);
}
public void glRotatef(float angle, float x, float y, float z) {
mCurrent.glRotatef(angle, x, y, z);
mgl.glRotatef(angle, x, y, z);
if (_check)
check();
}
public void glRotatex(int angle, int x, int y, int z) {
mCurrent.glRotatex(angle, x, y, z);
mgl.glRotatex(angle, x, y, z);
if (_check)
check();
}
public void glSampleCoverage(float value, boolean invert) {
mgl.glSampleCoverage(value, invert);
}
public void glSampleCoveragex(int value, boolean invert) {
mgl.glSampleCoveragex(value, invert);
}
public void glScalef(float x, float y, float z) {
mCurrent.glScalef(x, y, z);
mgl.glScalef(x, y, z);
if (_check)
check();
}
public void glScalex(int x, int y, int z) {
mCurrent.glScalex(x, y, z);
mgl.glScalex(x, y, z);
if (_check)
check();
}
public void glScissor(int x, int y, int width, int height) {
mgl.glScissor(x, y, width, height);
}
public void glShadeModel(int mode) {
mgl.glShadeModel(mode);
}
public void glStencilFunc(int func, int ref, int mask) {
mgl.glStencilFunc(func, ref, mask);
}
public void glStencilMask(int mask) {
mgl.glStencilMask(mask);
}
public void glStencilOp(int fail, int zfail, int zpass) {
mgl.glStencilOp(fail, zfail, zpass);
}
public void glTexCoordPointer(int size, int type, int stride, Buffer pointer) {
mgl.glTexCoordPointer(size, type, stride, pointer);
}
public void glTexEnvf(int target, int pname, float param) {
mgl.glTexEnvf(target, pname, param);
}
public void glTexEnvfv(int target, int pname, float[] params, int offset) {
mgl.glTexEnvfv(target, pname, params, offset);
}
public void glTexEnvfv(int target, int pname, FloatBuffer params) {
mgl.glTexEnvfv(target, pname, params);
}
public void glTexEnvx(int target, int pname, int param) {
mgl.glTexEnvx(target, pname, param);
}
public void glTexEnvxv(int target, int pname, int[] params, int offset) {
mgl.glTexEnvxv(target, pname, params, offset);
}
public void glTexEnvxv(int target, int pname, IntBuffer params) {
mgl.glTexEnvxv(target, pname, params);
}
public void glTexImage2D(int target, int level, int internalformat,
int width, int height, int border, int format, int type,
Buffer pixels) {
mgl.glTexImage2D(target, level, internalformat, width, height, border,
format, type, pixels);
}
public void glTexParameterf(int target, int pname, float param) {
mgl.glTexParameterf(target, pname, param);
}
public void glTexParameterx(int target, int pname, int param) {
mgl.glTexParameterx(target, pname, param);
}
public void glTexParameteriv(int target, int pname, int[] params, int offset) {
mgl11.glTexParameteriv(target, pname, params, offset);
}
public void glTexParameteriv(int target, int pname, IntBuffer params) {
mgl11.glTexParameteriv(target, pname, params);
}
public void glTexSubImage2D(int target, int level, int xoffset,
int yoffset, int width, int height, int format, int type,
Buffer pixels) {
mgl.glTexSubImage2D(target, level, xoffset, yoffset, width, height,
format, type, pixels);
}
public void glTranslatef(float x, float y, float z) {
mCurrent.glTranslatef(x, y, z);
mgl.glTranslatef(x, y, z);
if (_check)
check();
}
public void glTranslatex(int x, int y, int z) {
mCurrent.glTranslatex(x, y, z);
mgl.glTranslatex(x, y, z);
if (_check)
check();
}
public void glVertexPointer(int size, int type, int stride, Buffer pointer) {
mgl.glVertexPointer(size, type, stride, pointer);
}
public void glViewport(int x, int y, int width, int height) {
mgl.glViewport(x, y, width, height);
}
public void glClipPlanef(int plane, float[] equation, int offset) {
mgl11.glClipPlanef(plane, equation, offset);
}
public void glClipPlanef(int plane, FloatBuffer equation) {
mgl11.glClipPlanef(plane, equation);
}
public void glClipPlanex(int plane, int[] equation, int offset) {
mgl11.glClipPlanex(plane, equation, offset);
}
public void glClipPlanex(int plane, IntBuffer equation) {
mgl11.glClipPlanex(plane, equation);
}
// Draw Texture Extension
public void glDrawTexfOES(float x, float y, float z, float width,
float height) {
mgl11Ext.glDrawTexfOES(x, y, z, width, height);
}
public void glDrawTexfvOES(float[] coords, int offset) {
mgl11Ext.glDrawTexfvOES(coords, offset);
}
public void glDrawTexfvOES(FloatBuffer coords) {
mgl11Ext.glDrawTexfvOES(coords);
}
public void glDrawTexiOES(int x, int y, int z, int width, int height) {
mgl11Ext.glDrawTexiOES(x, y, z, width, height);
}
public void glDrawTexivOES(int[] coords, int offset) {
mgl11Ext.glDrawTexivOES(coords, offset);
}
public void glDrawTexivOES(IntBuffer coords) {
mgl11Ext.glDrawTexivOES(coords);
}
public void glDrawTexsOES(short x, short y, short z, short width,
short height) {
mgl11Ext.glDrawTexsOES(x, y, z, width, height);
}
public void glDrawTexsvOES(short[] coords, int offset) {
mgl11Ext.glDrawTexsvOES(coords, offset);
}
public void glDrawTexsvOES(ShortBuffer coords) {
mgl11Ext.glDrawTexsvOES(coords);
}
public void glDrawTexxOES(int x, int y, int z, int width, int height) {
mgl11Ext.glDrawTexxOES(x, y, z, width, height);
}
public void glDrawTexxvOES(int[] coords, int offset) {
mgl11Ext.glDrawTexxvOES(coords, offset);
}
public void glDrawTexxvOES(IntBuffer coords) {
mgl11Ext.glDrawTexxvOES(coords);
}
public int glQueryMatrixxOES(int[] mantissa, int mantissaOffset,
int[] exponent, int exponentOffset) {
return mgl10Ext.glQueryMatrixxOES(mantissa, mantissaOffset, exponent,
exponentOffset);
}
public int glQueryMatrixxOES(IntBuffer mantissa, IntBuffer exponent) {
return mgl10Ext.glQueryMatrixxOES(mantissa, exponent);
}
// Unsupported GL11 methods
public void glBindBuffer(int target, int buffer) {
throw new UnsupportedOperationException();
}
public void glBufferData(int target, int size, Buffer data, int usage) {
throw new UnsupportedOperationException();
}
public void glBufferSubData(int target, int offset, int size, Buffer data) {
throw new UnsupportedOperationException();
}
public void glColor4ub(byte red, byte green, byte blue, byte alpha) {
throw new UnsupportedOperationException();
}
public void glDeleteBuffers(int n, int[] buffers, int offset) {
throw new UnsupportedOperationException();
}
public void glDeleteBuffers(int n, IntBuffer buffers) {
throw new UnsupportedOperationException();
}
public void glGenBuffers(int n, int[] buffers, int offset) {
throw new UnsupportedOperationException();
}
public void glGenBuffers(int n, IntBuffer buffers) {
throw new UnsupportedOperationException();
}
public void glGetBooleanv(int pname, boolean[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetBooleanv(int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetBufferParameteriv(int target, int pname, int[] params,
int offset) {
throw new UnsupportedOperationException();
}
public void glGetBufferParameteriv(int target, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetClipPlanef(int pname, float[] eqn, int offset) {
throw new UnsupportedOperationException();
}
public void glGetClipPlanef(int pname, FloatBuffer eqn) {
throw new UnsupportedOperationException();
}
public void glGetClipPlanex(int pname, int[] eqn, int offset) {
throw new UnsupportedOperationException();
}
public void glGetClipPlanex(int pname, IntBuffer eqn) {
throw new UnsupportedOperationException();
}
public void glGetFixedv(int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetFixedv(int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetFloatv(int pname, float[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetFloatv(int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetLightfv(int light, int pname, float[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetLightfv(int light, int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetLightxv(int light, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetLightxv(int light, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetMaterialfv(int face, int pname, float[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetMaterialfv(int face, int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetMaterialxv(int face, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetMaterialxv(int face, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetTexEnviv(int env, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetTexEnviv(int env, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetTexEnvxv(int env, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glGetTexEnvxv(int env, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetTexParameterfv(int target, int pname, float[] params,
int offset) {
throw new UnsupportedOperationException();
}
public void glGetTexParameterfv(int target, int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetTexParameteriv(int target, int pname, int[] params,
int offset) {
throw new UnsupportedOperationException();
}
public void glGetTexParameteriv(int target, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glGetTexParameterxv(int target, int pname, int[] params,
int offset) {
throw new UnsupportedOperationException();
}
public void glGetTexParameterxv(int target, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public boolean glIsBuffer(int buffer) {
throw new UnsupportedOperationException();
}
public boolean glIsEnabled(int cap) {
throw new UnsupportedOperationException();
}
public boolean glIsTexture(int texture) {
throw new UnsupportedOperationException();
}
public void glPointParameterf(int pname, float param) {
throw new UnsupportedOperationException();
}
public void glPointParameterfv(int pname, float[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glPointParameterfv(int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glPointParameterx(int pname, int param) {
throw new UnsupportedOperationException();
}
public void glPointParameterxv(int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glPointParameterxv(int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glPointSizePointerOES(int type, int stride, Buffer pointer) {
throw new UnsupportedOperationException();
}
public void glTexEnvi(int target, int pname, int param) {
throw new UnsupportedOperationException();
}
public void glTexEnviv(int target, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glTexEnviv(int target, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glTexParameterfv(int target, int pname, float[] params,
int offset) {
throw new UnsupportedOperationException();
}
public void glTexParameterfv(int target, int pname, FloatBuffer params) {
throw new UnsupportedOperationException();
}
public void glTexParameteri(int target, int pname, int param) {
throw new UnsupportedOperationException();
}
public void glTexParameterxv(int target, int pname, int[] params, int offset) {
throw new UnsupportedOperationException();
}
public void glTexParameterxv(int target, int pname, IntBuffer params) {
throw new UnsupportedOperationException();
}
public void glColorPointer(int size, int type, int stride, int offset) {
throw new UnsupportedOperationException();
}
public void glDrawElements(int mode, int count, int type, int offset) {
throw new UnsupportedOperationException();
}
public void glGetPointerv(int pname, Buffer[] params) {
throw new UnsupportedOperationException();
}
public void glNormalPointer(int type, int stride, int offset) {
throw new UnsupportedOperationException();
}
public void glTexCoordPointer(int size, int type, int stride, int offset) {
throw new UnsupportedOperationException();
}
public void glVertexPointer(int size, int type, int stride, int offset) {
throw new UnsupportedOperationException();
}
public void glCurrentPaletteMatrixOES(int matrixpaletteindex) {
throw new UnsupportedOperationException();
}
public void glLoadPaletteFromModelViewMatrixOES() {
throw new UnsupportedOperationException();
}
public void glMatrixIndexPointerOES(int size, int type, int stride,
Buffer pointer) {
throw new UnsupportedOperationException();
}
public void glMatrixIndexPointerOES(int size, int type, int stride,
int offset) {
throw new UnsupportedOperationException();
}
public void glWeightPointerOES(int size, int type, int stride,
Buffer pointer) {
throw new UnsupportedOperationException();
}
public void glWeightPointerOES(int size, int type, int stride, int offset) {
throw new UnsupportedOperationException();
}
/**
* Get the current matrix
*/
public void getMatrix(float[] m, int offset) {
mCurrent.getMatrix(m, offset);
}
/**
* Get the current matrix mode
*/
public int getMatrixMode() {
return mMatrixMode;
}
private void check() {
int oesMode;
switch (mMatrixMode) {
case GL_MODELVIEW:
oesMode = GL11.GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES;
break;
case GL_PROJECTION:
oesMode = GL11.GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES;
break;
case GL_TEXTURE:
oesMode = GL11.GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES;
break;
default:
throw new IllegalArgumentException("Unknown matrix mode");
}
if (mByteBuffer == null) {
mCheckA = new float[16];
mCheckB = new float[16];
mByteBuffer = ByteBuffer.allocateDirect(64);
mByteBuffer.order(ByteOrder.nativeOrder());
mFloatBuffer = mByteBuffer.asFloatBuffer();
}
mgl.glGetIntegerv(oesMode, mByteBuffer.asIntBuffer());
for (int i = 0; i < 16; i++) {
mCheckB[i] = mFloatBuffer.get(i);
}
mCurrent.getMatrix(mCheckA, 0);
boolean fail = false;
for (int i = 0; i < 16; i++) {
if (mCheckA[i] != mCheckB[i]) {
Log.d("GLMatWrap", "i:" + i + " a:" + mCheckA[i] + " a:"
+ mCheckB[i]);
fail = true;
}
}
if (fail) {
throw new IllegalArgumentException("Matrix math difference.");
}
}
}
/**
* A 2D rectangular mesh. Can be drawn textured or untextured.
*
*/
class Grid {
public Grid(int w, int h) {
if (w < 0 || w >= 65536) {
throw new IllegalArgumentException("w");
}
if (h < 0 || h >= 65536) {
throw new IllegalArgumentException("h");
}
if (w * h >= 65536) {
throw new IllegalArgumentException("w * h >= 65536");
}
mW = w;
mH = h;
int size = w * h;
final int FLOAT_SIZE = 4;
final int CHAR_SIZE = 2;
mVertexBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 3)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
int quadW = mW - 1;
int quadH = mH - 1;
int quadCount = quadW * quadH;
int indexCount = quadCount * 6;
mIndexCount = indexCount;
mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount)
.order(ByteOrder.nativeOrder()).asCharBuffer();
/*
* Initialize triangle list mesh.
*
* [0]-----[ 1] ... | / | | / | | / | [w]-----[w+1] ... | |
*/
{
int i = 0;
for (int y = 0; y < quadH; y++) {
for (int x = 0; x < quadW; x++) {
char a = (char) (y * mW + x);
char b = (char) (y * mW + x + 1);
char c = (char) ((y + 1) * mW + x);
char d = (char) ((y + 1) * mW + x + 1);
mIndexBuffer.put(i++, a);
mIndexBuffer.put(i++, b);
mIndexBuffer.put(i++, c);
mIndexBuffer.put(i++, b);
mIndexBuffer.put(i++, c);
mIndexBuffer.put(i++, d);
}
}
}
}
void set(int i, int j, float x, float y, float z, float u, float v) {
if (i < 0 || i >= mW) {
throw new IllegalArgumentException("i");
}
if (j < 0 || j >= mH) {
throw new IllegalArgumentException("j");
}
int index = mW * j + i;
int posIndex = index * 3;
mVertexBuffer.put(posIndex, x);
mVertexBuffer.put(posIndex + 1, y);
mVertexBuffer.put(posIndex + 2, z);
int texIndex = index * 2;
mTexCoordBuffer.put(texIndex, u);
mTexCoordBuffer.put(texIndex + 1, v);
}
public void draw(GL10 gl, boolean useTexture) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
if (useTexture) {
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexCoordBuffer);
gl.glEnable(GL10.GL_TEXTURE_2D);
} else {
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D);
}
gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount,
GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
private FloatBuffer mVertexBuffer;
private FloatBuffer mTexCoordBuffer;
private CharBuffer mIndexBuffer;
private int mW;
private int mH;
private int mIndexCount;
}
class MatrixGrabber {
public MatrixGrabber() {
mModelView = new float[16];
mProjection = new float[16];
}
/**
* Record the current modelView and projection matrix state. Has the side
* effect of setting the current matrix state to GL_MODELVIEW
*
* @param gl
*/
public void getCurrentState(GL10 gl) {
getCurrentProjection(gl);
getCurrentModelView(gl);
}
/**
* Record the current modelView matrix state. Has the side effect of setting
* the current matrix state to GL_MODELVIEW
*
* @param gl
*/
public void getCurrentModelView(GL10 gl) {
getMatrix(gl, GL10.GL_MODELVIEW, mModelView);
}
/**
* Record the current projection matrix state. Has the side effect of
* setting the current matrix state to GL_PROJECTION
*
* @param gl
*/
public void getCurrentProjection(GL10 gl) {
getMatrix(gl, GL10.GL_PROJECTION, mProjection);
}
private void getMatrix(GL10 gl, int mode, float[] mat) {
MatrixTrackingGL gl2 = (MatrixTrackingGL) gl;
gl2.glMatrixMode(mode);
gl2.getMatrix(mat, 0);
}
public float[] mModelView;
public float[] mProjection;
}
/**
* A matrix stack, similar to OpenGL ES's internal matrix stack.
*/
class MatrixStack {
public MatrixStack() {
commonInit(DEFAULT_MAX_DEPTH);
}
public MatrixStack(int maxDepth) {
commonInit(maxDepth);
}
private void commonInit(int maxDepth) {
mMatrix = new float[maxDepth * MATRIX_SIZE];
mTemp = new float[MATRIX_SIZE * 2];
glLoadIdentity();
}
public void glFrustumf(float left, float right, float bottom, float top,
float near, float far) {
Matrix.frustumM(mMatrix, mTop, left, right, bottom, top, near, far);
}
public void glFrustumx(int left, int right, int bottom, int top, int near,
int far) {
glFrustumf(fixedToFloat(left), fixedToFloat(right),
fixedToFloat(bottom), fixedToFloat(top), fixedToFloat(near),
fixedToFloat(far));
}
public void glLoadIdentity() {
Matrix.setIdentityM(mMatrix, mTop);
}
public void glLoadMatrixf(float[] m, int offset) {
System.arraycopy(m, offset, mMatrix, mTop, MATRIX_SIZE);
}
public void glLoadMatrixf(FloatBuffer m) {
m.get(mMatrix, mTop, MATRIX_SIZE);
}
public void glLoadMatrixx(int[] m, int offset) {
for (int i = 0; i < MATRIX_SIZE; i++) {
mMatrix[mTop + i] = fixedToFloat(m[offset + i]);
}
}
public void glLoadMatrixx(IntBuffer m) {
for (int i = 0; i < MATRIX_SIZE; i++) {
mMatrix[mTop + i] = fixedToFloat(m.get());
}
}
public void glMultMatrixf(float[] m, int offset) {
System.arraycopy(mMatrix, mTop, mTemp, 0, MATRIX_SIZE);
Matrix.multiplyMM(mMatrix, mTop, mTemp, 0, m, offset);
}
public void glMultMatrixf(FloatBuffer m) {
m.get(mTemp, MATRIX_SIZE, MATRIX_SIZE);
glMultMatrixf(mTemp, MATRIX_SIZE);
}
public void glMultMatrixx(int[] m, int offset) {
for (int i = 0; i < MATRIX_SIZE; i++) {
mTemp[MATRIX_SIZE + i] = fixedToFloat(m[offset + i]);
}
glMultMatrixf(mTemp, MATRIX_SIZE);
}
public void glMultMatrixx(IntBuffer m) {
for (int i = 0; i < MATRIX_SIZE; i++) {
mTemp[MATRIX_SIZE + i] = fixedToFloat(m.get());
}
glMultMatrixf(mTemp, MATRIX_SIZE);
}
public void glOrthof(float left, float right, float bottom, float top,
float near, float far) {
Matrix.orthoM(mMatrix, mTop, left, right, bottom, top, near, far);
}
public void glOrthox(int left, int right, int bottom, int top, int near,
int far) {
glOrthof(fixedToFloat(left), fixedToFloat(right), fixedToFloat(bottom),
fixedToFloat(top), fixedToFloat(near), fixedToFloat(far));
}
public void glPopMatrix() {
preflight_adjust(-1);
adjust(-1);
}
public void glPushMatrix() {
preflight_adjust(1);
System.arraycopy(mMatrix, mTop, mMatrix, mTop + MATRIX_SIZE,
MATRIX_SIZE);
adjust(1);
}
public void glRotatef(float angle, float x, float y, float z) {
Matrix.setRotateM(mTemp, 0, angle, x, y, z);
System.arraycopy(mMatrix, mTop, mTemp, MATRIX_SIZE, MATRIX_SIZE);
Matrix.multiplyMM(mMatrix, mTop, mTemp, MATRIX_SIZE, mTemp, 0);
}
public void glRotatex(int angle, int x, int y, int z) {
glRotatef(angle, fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
}
public void glScalef(float x, float y, float z) {
Matrix.scaleM(mMatrix, mTop, x, y, z);
}
public void glScalex(int x, int y, int z) {
glScalef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
}
public void glTranslatef(float x, float y, float z) {
Matrix.translateM(mMatrix, mTop, x, y, z);
}
public void glTranslatex(int x, int y, int z) {
glTranslatef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
}
public void getMatrix(float[] dest, int offset) {
System.arraycopy(mMatrix, mTop, dest, offset, MATRIX_SIZE);
}
private float fixedToFloat(int x) {
return x * (1.0f / 65536.0f);
}
private void preflight_adjust(int dir) {
int newTop = mTop + dir * MATRIX_SIZE;
if (newTop < 0) {
throw new IllegalArgumentException("stack underflow");
}
if (newTop + MATRIX_SIZE > mMatrix.length) {
throw new IllegalArgumentException("stack overflow");
}
}
private void adjust(int dir) {
mTop += dir * MATRIX_SIZE;
}
private final static int DEFAULT_MAX_DEPTH = 32;
private final static int MATRIX_SIZE = 16;
private float[] mMatrix;
private int mTop;
private float[] mTemp;
}
class NumericSprite {
public NumericSprite() {
mText = "";
mLabelMaker = null;
}
public void initialize(GL10 gl, Paint paint) {
int height = roundUpPower2((int) paint.getFontSpacing());
final float interDigitGaps = 9 * 1.0f;
int width = roundUpPower2((int) (interDigitGaps + paint
.measureText(sStrike)));
mLabelMaker = new LabelMaker(true, width, height);
mLabelMaker.initialize(gl);
mLabelMaker.beginAdding(gl);
for (int i = 0; i < 10; i++) {
String digit = sStrike.substring(i, i + 1);
mLabelId[i] = mLabelMaker.add(gl, digit, paint);
mWidth[i] = (int) Math.ceil(mLabelMaker.getWidth(i));
}
mLabelMaker.endAdding(gl);
}
public void shutdown(GL10 gl) {
mLabelMaker.shutdown(gl);
mLabelMaker = null;
}
/**
* Find the smallest power of two >= the input value. (Doesn't work for
* negative numbers.)
*/
private int roundUpPower2(int x) {
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
public void setValue(int value) {
mText = format(value);
}
public void draw(GL10 gl, float x, float y, float viewWidth,
float viewHeight) {
int length = mText.length();
mLabelMaker.beginDrawing(gl, viewWidth, viewHeight);
for (int i = 0; i < length; i++) {
char c = mText.charAt(i);
int digit = c - '0';
mLabelMaker.draw(gl, x, y, mLabelId[digit]);
x += mWidth[digit];
}
mLabelMaker.endDrawing(gl);
}
public float width() {
float width = 0.0f;
int length = mText.length();
for (int i = 0; i < length; i++) {
char c = mText.charAt(i);
width += mWidth[c - '0'];
}
return width;
}
private String format(int value) {
return Integer.toString(value);
}
private LabelMaker mLabelMaker;
private String mText;
private int[] mWidth = new int[10];
private int[] mLabelId = new int[10];
private final static String sStrike = "0123456789";
}
public class SpriteTextActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLSurfaceView = new GLSurfaceView(this);
mGLSurfaceView.setGLWrapper(new GLSurfaceView.GLWrapper() {
public GL wrap(GL gl) {
return new MatrixTrackingGL(gl);
}
});
mGLSurfaceView.setRenderer(new SpriteTextRenderer(this));
setContentView(mGLSurfaceView);
}
@Override
protected void onPause() {
super.onPause();
mGLSurfaceView.onPause();
}
@Override
protected void onResume() {
super.onResume();
mGLSurfaceView.onResume();
}
private GLSurfaceView mGLSurfaceView;
}
Related examples in the same category