TextManager.java
Go to the documentation of this file.
00001 //package ri.blog.opengl008;
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         /* SHADER Text
00024          * 
00025          * This shader is for rendering 2D text textures straight from a texture
00026          * Color and alpha blended.
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; // 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                 // Create the arrays
00084                 vecs = new float[3 * 10];
00085                 uvs = new float[2 * 10];
00086                 indices = new short[10];
00087                 
00088                 // init as 0 as default
00089                 texturenr = 0;
00090                 
00091                 // Text shader
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);           // add the fragment shader to program
00098                 GLES20.glLinkProgram(TextManager.sp_Text);                  // creates OpenGL ES program executables
00099                 
00100                 // Generate Textures, if more needed, alter these numbers.
00101                 mTextures = new int[1];
00102                 GLES20.glGenTextures(1, mTextures, 0);
00103                 
00104                 // Create an empty, mutable bitmap
00105                 Bitmap bitmap = Bitmap.createBitmap(RI_TEXT_TEXTURE_SIZE, RI_TEXT_TEXTURE_SIZE, Bitmap.Config.ARGB_4444);
00106                 // get a canvas to paint over the bitmap
00107                 Canvas canvas = new Canvas(bitmap);
00108                 bitmap.eraseColor(0);
00109 
00110                 // Draw the text
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                 // compute real maximum height
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                 //Clean up
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             // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
00161             // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
00162             int shader = GLES20.glCreateShader(type);
00163 
00164             // add the source code to the shader and compile it
00165             GLES20.glShaderSource(shader, shaderCode);
00166             GLES20.glCompileShader(shader);
00167             
00168             // return the shader
00169             return shader;
00170         }
00171         
00172         
00173         public void AddCharRenderInformation(float[] vec, float[] cs, float[] uv, short[] indi)
00174         {
00175                 // We need a base value because the object has indices related to 
00176                 // that object and not to this collection so basicly we need to 
00177                 // translate the indices to align with the vertexlocation in ou
00178                 // vecs array of vectors.
00179                 short base = (short) (index_vecs / 3);
00180                         
00181                 // We should add the vec, translating the indices to our saved vector
00182                 for(int i=0;i<vec.length;i++)
00183                 {
00184                         vecs[index_vecs] = vec[i];
00185                         index_vecs++;
00186                 }
00187                 
00188                 // We should add the uvs
00189                 for(int i=0;i<uv.length;i++)
00190                 {
00191                         uvs[index_uvs] = uv[i];
00192                         index_uvs++;
00193                 }
00194 
00195                 // We handle the indices
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                 // Reset the indices.
00206                 index_vecs = 0;
00207                 index_indices = 0;
00208                 index_uvs = 0;
00209                 
00210                 // Get the total amount of characters
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                 // Create the arrays we need with the correct size.
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                 // Setup all the arrays
00236                 PrepareDrawInfo(txtcollection);
00237                 
00238                 // Using the iterator protects for problems with concurrency
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                         // Set the correct shader for our grid object.
00260                         GLES20.glUseProgram(sp_Text);
00261                         
00262                         // The vertex buffer.
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                         // The texture buffer
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                         // initialize byte buffer for the draw list
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                         // get handle to vertex shader's vPosition member
00284                     int mPositionHandle = GLES20.glGetAttribLocation(sp_Text, "vPosition");
00285                     
00286                     // Enable a handle to the triangle vertices
00287                     GLES20.glEnableVertexAttribArray(mPositionHandle);
00288                  
00289                     // Prepare the background coordinate data
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                     // Prepare the texturecoordinates
00297                     GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
00298                         false, 
00299                         0, textureBuffer);
00300         
00301                     GLES20.glEnableVertexAttribArray ( mPositionHandle );
00302                 GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
00303         
00304                     // get handle to shape's transformation matrix
00305                 int mtrxhandle = GLES20.glGetUniformLocation(sp_Text, "uMVPMatrix");
00306                 
00307                 // Apply the projection and view transformation
00308                 GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
00309                 
00310                 // get handle to color value
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                 // Texture activate unit 0
00317                 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
00318                         // Bind the texture to this unit.
00319                 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
00320                 // Set the sampler texture unit to our selected id
00321                     GLES20.glUniform1i ( mSamplerLoc, texturenr);
00322                     
00323                 // Draw the triangle
00324                 GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
00325         
00326                 // Disable vertex array
00327                 GLES20.glDisableVertexAttribArray(mPositionHandle);
00328                 GLES20.glDisableVertexAttribArray(mTexCoordLoc);
00329                 }
00330         }
00331         
00332         private void convertTextToTriangleInfo(TextObject val)
00333         {               
00334                 // Get attributes from text object
00335                 float x = val.x;
00336                 float y = val.y;
00337                 String text = val.text;
00338                 
00339                 // Create 
00340                 for(int j=0; j<text.length(); j++)
00341                 {
00342                         // get ascii value
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                                 // unknown character, we will add a space for it to be save.
00350                                 indx = 0;
00351                         }
00352                         
00353                         int colCount = RI_TEXT_TEXTURE_SIZE/(int)RI_TEXT_HEIGHT_BASE;
00354                         
00355                         // Calculate the uv parts
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                         // Creating the triangle information
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                         // 0.001f = texture bleeding hack/fix
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                         // Add our triangle information to our collection for 1 render call.
00401                         AddCharRenderInformation(vec, colors, uv, inds);
00402                         
00403                         // Calculate the new position
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 }


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jun 6 2019 21:59:31