00001
00002 package com.introlab.rtabmap;
00003
00004 import java.nio.ByteBuffer;
00005 import java.nio.ByteOrder;
00006 import java.nio.FloatBuffer;
00007 import java.nio.ShortBuffer;
00008 import java.util.Iterator;
00009 import java.util.Vector;
00010
00011 import android.content.Context;
00012 import android.graphics.Bitmap;
00013 import android.graphics.Canvas;
00014 import android.graphics.Color;
00015 import android.graphics.Rect;
00016 import android.graphics.Typeface;
00017 import android.opengl.GLES20;
00018 import android.opengl.GLUtils;
00019 import android.text.TextPaint;
00020
00021 public class TextManager {
00022
00023
00024
00025
00026
00027
00028
00029 public static final String vs_Text =
00030 "uniform mat4 uMVPMatrix;" +
00031 "attribute vec4 vPosition;" +
00032 "attribute vec2 a_texCoord;" +
00033 "varying vec2 v_texCoord;" +
00034 "void main() {" +
00035 " gl_Position = uMVPMatrix * vPosition;" +
00036 " v_texCoord = a_texCoord;" +
00037 "}";
00038 public static final String fs_Text =
00039 "precision mediump float;" +
00040 "uniform float uColor;" +
00041 "varying vec2 v_texCoord;" +
00042 "uniform sampler2D s_texture;" +
00043 "void main() {" +
00044 " gl_FragColor = texture2D( s_texture, v_texCoord );" +
00045 " gl_FragColor.rgb *= uColor;" +
00046 "}";
00047
00048 public static int sp_Text;
00049
00050 public static final int RI_TEXT_TEXTURE_SIZE = 512;
00051 public static final float RI_TEXT_HEIGHT_BASE = 32.0f;
00052 public static final char RI_TEXT_START = ' ';
00053 public static final char RI_TEXT_STOP = '~'+1;
00054
00055 public float getMaxTextHeight() {return mTextHeight;}
00056
00057 private float mUVWidth;
00058 private float mUVHeight;
00059 private float mTextHeight;
00060 private float mColor;
00061
00062 private FloatBuffer vertexBuffer;
00063 private FloatBuffer textureBuffer;
00064 private ShortBuffer drawListBuffer;
00065
00066 private float[] vecs;
00067 private float[] uvs;
00068 private short[] indices;
00069
00070 private int index_vecs;
00071 private int index_indices;
00072 private int index_uvs;
00073
00074 private int texturenr;
00075 private int[] mTextures;
00076
00077 private float uniformscale = 1.0f;
00078
00079 float[] mCharacterWidth;
00080
00081 public TextManager(Context context)
00082 {
00083
00084 vecs = new float[3 * 10];
00085 uvs = new float[2 * 10];
00086 indices = new short[10];
00087
00088
00089 texturenr = 0;
00090
00091
00092 int vshadert = TextManager.loadShader(GLES20.GL_VERTEX_SHADER, TextManager.vs_Text);
00093 int fshadert = TextManager.loadShader(GLES20.GL_FRAGMENT_SHADER, TextManager.fs_Text);
00094
00095 TextManager.sp_Text = GLES20.glCreateProgram();
00096 GLES20.glAttachShader(TextManager.sp_Text, vshadert);
00097 GLES20.glAttachShader(TextManager.sp_Text, fshadert);
00098 GLES20.glLinkProgram(TextManager.sp_Text);
00099
00100
00101 mTextures = new int[1];
00102 GLES20.glGenTextures(1, mTextures, 0);
00103
00104
00105 Bitmap bitmap = Bitmap.createBitmap(RI_TEXT_TEXTURE_SIZE, RI_TEXT_TEXTURE_SIZE, Bitmap.Config.ARGB_4444);
00106
00107 Canvas canvas = new Canvas(bitmap);
00108 bitmap.eraseColor(0);
00109
00110
00111 TextPaint textPaint = new TextPaint();
00112 textPaint.setTextSize(RI_TEXT_HEIGHT_BASE);
00113 textPaint.setColor(Color.WHITE);
00114 textPaint.setAntiAlias(true);
00115 textPaint.setTypeface(Typeface.create("Arial", Typeface.BOLD));
00116
00117
00118 mTextHeight=0.0f;
00119 for(char c=RI_TEXT_START; c<RI_TEXT_STOP; ++c)
00120 {
00121 Rect textBounds = new Rect();
00122 textPaint.getTextBounds(String.valueOf(c), 0, 1, textBounds);
00123 if(textBounds.height() + textBounds.bottom > mTextHeight)
00124 {
00125 mTextHeight = textBounds.height() + textBounds.bottom;
00126 }
00127 }
00128 mUVWidth = (float)RI_TEXT_HEIGHT_BASE/(float)RI_TEXT_TEXTURE_SIZE;
00129 mUVHeight = mTextHeight/(float)RI_TEXT_TEXTURE_SIZE;
00130 mColor = 1.0f;
00131
00132 int colCount = RI_TEXT_TEXTURE_SIZE/(int)RI_TEXT_HEIGHT_BASE;
00133 mCharacterWidth = new float[RI_TEXT_STOP-RI_TEXT_START];
00134 int i=0;
00135 for(char c=RI_TEXT_START; c<RI_TEXT_STOP; ++c)
00136 {
00137 Rect textBounds = new Rect();
00138 textPaint.getTextBounds(String.valueOf(c), 0, 1, textBounds);
00139 canvas.drawText(String.valueOf(c), (i%colCount)*RI_TEXT_HEIGHT_BASE, (i/colCount) * mTextHeight + RI_TEXT_HEIGHT_BASE, textPaint);
00140 mCharacterWidth[i] = textPaint.measureText(String.valueOf(c));
00141 ++i;
00142 }
00143
00144 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
00145 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
00146 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
00147 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
00148
00149
00150 bitmap.recycle();
00151 }
00152
00153 public void setTextureID(int val)
00154 {
00155 texturenr = val;
00156 }
00157
00158 public static int loadShader(int type, String shaderCode){
00159
00160
00161
00162 int shader = GLES20.glCreateShader(type);
00163
00164
00165 GLES20.glShaderSource(shader, shaderCode);
00166 GLES20.glCompileShader(shader);
00167
00168
00169 return shader;
00170 }
00171
00172
00173 public void AddCharRenderInformation(float[] vec, float[] cs, float[] uv, short[] indi)
00174 {
00175
00176
00177
00178
00179 short base = (short) (index_vecs / 3);
00180
00181
00182 for(int i=0;i<vec.length;i++)
00183 {
00184 vecs[index_vecs] = vec[i];
00185 index_vecs++;
00186 }
00187
00188
00189 for(int i=0;i<uv.length;i++)
00190 {
00191 uvs[index_uvs] = uv[i];
00192 index_uvs++;
00193 }
00194
00195
00196 for(int j=0;j<indi.length;j++)
00197 {
00198 indices[index_indices] = (short) (base + indi[j]);
00199 index_indices++;
00200 }
00201 }
00202
00203 public void PrepareDrawInfo(Vector<TextObject> txtcollection)
00204 {
00205
00206 index_vecs = 0;
00207 index_indices = 0;
00208 index_uvs = 0;
00209
00210
00211 int charcount = 0;
00212 for (TextObject txt : txtcollection) {
00213 if(txt!=null)
00214 {
00215 if(!(txt.text==null))
00216 {
00217 charcount += txt.text.length();
00218 }
00219 }
00220 }
00221
00222
00223 vecs = null;
00224 uvs = null;
00225 indices = null;
00226
00227 vecs = new float[charcount * 12];
00228 uvs = new float[charcount * 8];
00229 indices = new short[charcount * 6];
00230
00231 }
00232
00233 public void PrepareDraw(Vector<TextObject> txtcollection)
00234 {
00235
00236 PrepareDrawInfo(txtcollection);
00237
00238
00239 for( Iterator< TextObject > it = txtcollection.iterator(); it.hasNext() ; )
00240 {
00241 TextObject txt = it.next();
00242 if(txt!=null)
00243 {
00244 if(!(txt.text==null))
00245 {
00246 convertTextToTriangleInfo(txt);
00247 }
00248 }
00249 }
00250 }
00251
00252 public void Draw(float[] m)
00253 {
00254 if(vecs.length > 0)
00255 {
00256 GLES20.glDisable(GLES20.GL_DEPTH_TEST);
00257 GLES20.glEnable(GLES20.GL_BLEND);
00258
00259
00260 GLES20.glUseProgram(sp_Text);
00261
00262
00263 ByteBuffer bb = ByteBuffer.allocateDirect(vecs.length * 4);
00264 bb.order(ByteOrder.nativeOrder());
00265 vertexBuffer = bb.asFloatBuffer();
00266 vertexBuffer.put(vecs);
00267 vertexBuffer.position(0);
00268
00269
00270 ByteBuffer bb2 = ByteBuffer.allocateDirect(uvs.length * 4);
00271 bb2.order(ByteOrder.nativeOrder());
00272 textureBuffer = bb2.asFloatBuffer();
00273 textureBuffer.put(uvs);
00274 textureBuffer.position(0);
00275
00276
00277 ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
00278 dlb.order(ByteOrder.nativeOrder());
00279 drawListBuffer = dlb.asShortBuffer();
00280 drawListBuffer.put(indices);
00281 drawListBuffer.position(0);
00282
00283
00284 int mPositionHandle = GLES20.glGetAttribLocation(sp_Text, "vPosition");
00285
00286
00287 GLES20.glEnableVertexAttribArray(mPositionHandle);
00288
00289
00290 GLES20.glVertexAttribPointer(mPositionHandle, 3,
00291 GLES20.GL_FLOAT, false,
00292 0, vertexBuffer);
00293
00294 int mTexCoordLoc = GLES20.glGetAttribLocation(sp_Text, "a_texCoord" );
00295
00296
00297 GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
00298 false,
00299 0, textureBuffer);
00300
00301 GLES20.glEnableVertexAttribArray ( mPositionHandle );
00302 GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
00303
00304
00305 int mtrxhandle = GLES20.glGetUniformLocation(sp_Text, "uMVPMatrix");
00306
00307
00308 GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
00309
00310
00311 int colorhandle = GLES20.glGetUniformLocation(sp_Text, "uColor");
00312 GLES20.glUniform1f(colorhandle, mColor);
00313
00314 int mSamplerLoc = GLES20.glGetUniformLocation (sp_Text, "s_texture" );
00315
00316
00317 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
00318
00319 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
00320
00321 GLES20.glUniform1i ( mSamplerLoc, texturenr);
00322
00323
00324 GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
00325
00326
00327 GLES20.glDisableVertexAttribArray(mPositionHandle);
00328 GLES20.glDisableVertexAttribArray(mTexCoordLoc);
00329 }
00330 }
00331
00332 private void convertTextToTriangleInfo(TextObject val)
00333 {
00334
00335 float x = val.x;
00336 float y = val.y;
00337 String text = val.text;
00338
00339
00340 for(int j=0; j<text.length(); j++)
00341 {
00342
00343 char c = text.charAt(j);
00344 int c_val = (int)c;
00345
00346 int indx = c_val-RI_TEXT_START;
00347
00348 if(indx<0 || indx>=mCharacterWidth.length) {
00349
00350 indx = 0;
00351 }
00352
00353 int colCount = RI_TEXT_TEXTURE_SIZE/(int)RI_TEXT_HEIGHT_BASE;
00354
00355
00356 int row = indx / colCount;
00357 int col = indx % colCount;
00358
00359 float v = row * mUVHeight;
00360 float v2 = v + mUVHeight;
00361 float u = col * mUVWidth;
00362 float u2 = u + mCharacterWidth[indx]/(float)RI_TEXT_TEXTURE_SIZE;
00363
00364
00365 float[] vec = new float[12];
00366 float[] uv = new float[8];
00367 float[] colors = new float[16];
00368
00369 vec[0] = x;
00370 vec[1] = y + (mTextHeight * uniformscale);
00371 vec[2] = 0.99f;
00372 vec[3] = x;
00373 vec[4] = y;
00374 vec[5] = 0.99f;
00375 vec[6] = x + (mCharacterWidth[indx] * uniformscale);
00376 vec[7] = y;
00377 vec[8] = 0.99f;
00378 vec[9] = x + (mCharacterWidth[indx] * uniformscale);
00379 vec[10] = y + (mTextHeight * uniformscale);
00380 vec[11] = 0.99f;
00381
00382 colors = new float[]
00383 {val.color[0], val.color[1], val.color[2], val.color[3],
00384 val.color[0], val.color[1], val.color[2], val.color[3],
00385 val.color[0], val.color[1], val.color[2], val.color[3],
00386 val.color[0], val.color[1], val.color[2], val.color[3]
00387 };
00388
00389 uv[0] = u+0.001f;
00390 uv[1] = v+0.001f;
00391 uv[2] = u+0.001f;
00392 uv[3] = v2-0.001f;
00393 uv[4] = u2-0.001f;
00394 uv[5] = v2-0.001f;
00395 uv[6] = u2-0.001f;
00396 uv[7] = v+0.001f;
00397
00398 short[] inds = {0, 1, 2, 0, 2, 3};
00399
00400
00401 AddCharRenderInformation(vec, colors, uv, inds);
00402
00403
00404 x += (mCharacterWidth[indx] * uniformscale);
00405 }
00406 }
00407
00408 public float getUniformscale() {
00409 return uniformscale;
00410 }
00411
00412 public void setUniformscale(float uniformscale) {
00413 this.uniformscale = uniformscale;
00414 }
00415
00416 public void setColor(float color) {
00417 mColor = color;
00418 }
00419 }