TextManager.java
Go to the documentation of this file.
1 //package ri.blog.opengl008;
2 package com.introlab.rtabmap;
3 
4 import java.nio.ByteBuffer;
5 import java.nio.ByteOrder;
6 import java.nio.FloatBuffer;
7 import java.nio.ShortBuffer;
8 import java.util.Iterator;
9 import java.util.Vector;
10 
11 import android.content.Context;
12 import android.graphics.Bitmap;
13 import android.graphics.Canvas;
14 import android.graphics.Color;
15 import android.graphics.Rect;
16 import android.graphics.Typeface;
17 import android.opengl.GLES20;
18 import android.opengl.GLUtils;
19 import android.text.TextPaint;
20 
21 public class TextManager {
22 
23  /* SHADER Text
24  *
25  * This shader is for rendering 2D text textures straight from a texture
26  * Color and alpha blended.
27  *
28  */
29  public static final String vs_Text =
30  "uniform mat4 uMVPMatrix;" +
31  "attribute vec4 vPosition;" +
32  "attribute vec2 a_texCoord;" +
33  "varying vec2 v_texCoord;" +
34  "void main() {" +
35  " gl_Position = uMVPMatrix * vPosition;" +
36  " v_texCoord = a_texCoord;" +
37  "}";
38  public static final String fs_Text =
39  "precision mediump float;" +
40  "uniform float uColor;" +
41  "varying vec2 v_texCoord;" +
42  "uniform sampler2D s_texture;" +
43  "void main() {" +
44  " gl_FragColor = texture2D( s_texture, v_texCoord );" +
45  " gl_FragColor.rgb *= uColor;" +
46  "}";
47 
48  public static int sp_Text;
49 
50  public static final int RI_TEXT_TEXTURE_SIZE = 512; // 512
51  public static final float RI_TEXT_HEIGHT_BASE = 32.0f;
52  public static final char RI_TEXT_START = ' ';
53  public static final char RI_TEXT_STOP = '~'+1;
54 
55  public float getMaxTextHeight() {return mTextHeight;}
56 
57  private float mUVWidth;
58  private float mUVHeight;
59  private float mTextHeight;
60  private float mColor;
61 
62  private FloatBuffer vertexBuffer;
63  private FloatBuffer textureBuffer;
64  private ShortBuffer drawListBuffer;
65 
66  private float[] vecs;
67  private float[] uvs;
68  private short[] indices;
69 
70  private int index_vecs;
71  private int index_indices;
72  private int index_uvs;
73 
74  private int texturenr;
75  private int[] mTextures;
76 
77  private float uniformscale = 1.0f;
78 
79  float[] mCharacterWidth;
80 
81  public TextManager(Context context)
82  {
83  // Create the arrays
84  vecs = new float[3 * 10];
85  uvs = new float[2 * 10];
86  indices = new short[10];
87 
88  // init as 0 as default
89  texturenr = 0;
90 
91  // Text shader
92  int vshadert = TextManager.loadShader(GLES20.GL_VERTEX_SHADER, TextManager.vs_Text);
93  int fshadert = TextManager.loadShader(GLES20.GL_FRAGMENT_SHADER, TextManager.fs_Text);
94 
95  TextManager.sp_Text = GLES20.glCreateProgram();
96  GLES20.glAttachShader(TextManager.sp_Text, vshadert);
97  GLES20.glAttachShader(TextManager.sp_Text, fshadert); // add the fragment shader to program
98  GLES20.glLinkProgram(TextManager.sp_Text); // creates OpenGL ES program executables
99 
100  // Generate Textures, if more needed, alter these numbers.
101  mTextures = new int[1];
102  GLES20.glGenTextures(1, mTextures, 0);
103 
104  // Create an empty, mutable bitmap
105  Bitmap bitmap = Bitmap.createBitmap(RI_TEXT_TEXTURE_SIZE, RI_TEXT_TEXTURE_SIZE, Bitmap.Config.ARGB_4444);
106  // get a canvas to paint over the bitmap
107  Canvas canvas = new Canvas(bitmap);
108  bitmap.eraseColor(0);
109 
110  // Draw the text
111  TextPaint textPaint = new TextPaint();
112  textPaint.setTextSize(RI_TEXT_HEIGHT_BASE);
113  textPaint.setColor(Color.WHITE);
114  textPaint.setAntiAlias(true);
115  textPaint.setTypeface(Typeface.create("Arial", Typeface.BOLD));
116 
117  // compute real maximum height
118  mTextHeight=0.0f;
119  for(char c=RI_TEXT_START; c<RI_TEXT_STOP; ++c)
120  {
121  Rect textBounds = new Rect();
122  textPaint.getTextBounds(String.valueOf(c), 0, 1, textBounds);
123  if(textBounds.height() + textBounds.bottom > mTextHeight)
124  {
125  mTextHeight = textBounds.height() + textBounds.bottom;
126  }
127  }
128  mUVWidth = (float)RI_TEXT_HEIGHT_BASE/(float)RI_TEXT_TEXTURE_SIZE;
129  mUVHeight = mTextHeight/(float)RI_TEXT_TEXTURE_SIZE;
130  mColor = 1.0f;
131 
132  int colCount = RI_TEXT_TEXTURE_SIZE/(int)RI_TEXT_HEIGHT_BASE;
133  mCharacterWidth = new float[RI_TEXT_STOP-RI_TEXT_START];
134  int i=0;
135  for(char c=RI_TEXT_START; c<RI_TEXT_STOP; ++c)
136  {
137  Rect textBounds = new Rect();
138  textPaint.getTextBounds(String.valueOf(c), 0, 1, textBounds);
139  canvas.drawText(String.valueOf(c), (i%colCount)*RI_TEXT_HEIGHT_BASE, (i/colCount) * mTextHeight + RI_TEXT_HEIGHT_BASE, textPaint);
140  mCharacterWidth[i] = textPaint.measureText(String.valueOf(c));
141  ++i;
142  }
143 
144  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
145  GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
146  GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
147  GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
148 
149  //Clean up
150  bitmap.recycle();
151  }
152 
153  public void setTextureID(int val)
154  {
155  texturenr = val;
156  }
157 
158  public static int loadShader(int type, String shaderCode){
159 
160  // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
161  // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
162  int shader = GLES20.glCreateShader(type);
163 
164  // add the source code to the shader and compile it
165  GLES20.glShaderSource(shader, shaderCode);
166  GLES20.glCompileShader(shader);
167 
168  // return the shader
169  return shader;
170  }
171 
172 
173  public void AddCharRenderInformation(float[] vec, float[] cs, float[] uv, short[] indi)
174  {
175  // We need a base value because the object has indices related to
176  // that object and not to this collection so basicly we need to
177  // translate the indices to align with the vertexlocation in ou
178  // vecs array of vectors.
179  short base = (short) (index_vecs / 3);
180 
181  // We should add the vec, translating the indices to our saved vector
182  for(int i=0;i<vec.length;i++)
183  {
184  vecs[index_vecs] = vec[i];
185  index_vecs++;
186  }
187 
188  // We should add the uvs
189  for(int i=0;i<uv.length;i++)
190  {
191  uvs[index_uvs] = uv[i];
192  index_uvs++;
193  }
194 
195  // We handle the indices
196  for(int j=0;j<indi.length;j++)
197  {
198  indices[index_indices] = (short) (base + indi[j]);
199  index_indices++;
200  }
201  }
202 
203  public void PrepareDrawInfo(Vector<TextObject> txtcollection)
204  {
205  // Reset the indices.
206  index_vecs = 0;
207  index_indices = 0;
208  index_uvs = 0;
209 
210  // Get the total amount of characters
211  int charcount = 0;
212  for (TextObject txt : txtcollection) {
213  if(txt!=null)
214  {
215  if(!(txt.text==null))
216  {
217  charcount += txt.text.length();
218  }
219  }
220  }
221 
222  // Create the arrays we need with the correct size.
223  vecs = null;
224  uvs = null;
225  indices = null;
226 
227  vecs = new float[charcount * 12];
228  uvs = new float[charcount * 8];
229  indices = new short[charcount * 6];
230 
231  }
232 
233  public void PrepareDraw(Vector<TextObject> txtcollection)
234  {
235  // Setup all the arrays
236  PrepareDrawInfo(txtcollection);
237 
238  // Using the iterator protects for problems with concurrency
239  for( Iterator< TextObject > it = txtcollection.iterator(); it.hasNext() ; )
240  {
241  TextObject txt = it.next();
242  if(txt!=null)
243  {
244  if(!(txt.text==null))
245  {
247  }
248  }
249  }
250  }
251 
252  public void Draw(float[] m)
253  {
254  if(vecs.length > 0)
255  {
256  GLES20.glDisable(GLES20.GL_DEPTH_TEST);
257  GLES20.glEnable(GLES20.GL_BLEND);
258 
259  // Set the correct shader for our grid object.
260  GLES20.glUseProgram(sp_Text);
261 
262  // The vertex buffer.
263  ByteBuffer bb = ByteBuffer.allocateDirect(vecs.length * 4);
264  bb.order(ByteOrder.nativeOrder());
265  vertexBuffer = bb.asFloatBuffer();
266  vertexBuffer.put(vecs);
267  vertexBuffer.position(0);
268 
269  // The texture buffer
270  ByteBuffer bb2 = ByteBuffer.allocateDirect(uvs.length * 4);
271  bb2.order(ByteOrder.nativeOrder());
272  textureBuffer = bb2.asFloatBuffer();
273  textureBuffer.put(uvs);
274  textureBuffer.position(0);
275 
276  // initialize byte buffer for the draw list
277  ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
278  dlb.order(ByteOrder.nativeOrder());
279  drawListBuffer = dlb.asShortBuffer();
280  drawListBuffer.put(indices);
281  drawListBuffer.position(0);
282 
283  // get handle to vertex shader's vPosition member
284  int mPositionHandle = GLES20.glGetAttribLocation(sp_Text, "vPosition");
285 
286  // Enable a handle to the triangle vertices
287  GLES20.glEnableVertexAttribArray(mPositionHandle);
288 
289  // Prepare the background coordinate data
290  GLES20.glVertexAttribPointer(mPositionHandle, 3,
291  GLES20.GL_FLOAT, false,
292  0, vertexBuffer);
293 
294  int mTexCoordLoc = GLES20.glGetAttribLocation(sp_Text, "a_texCoord" );
295 
296  // Prepare the texturecoordinates
297  GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
298  false,
299  0, textureBuffer);
300 
301  GLES20.glEnableVertexAttribArray ( mPositionHandle );
302  GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
303 
304  // get handle to shape's transformation matrix
305  int mtrxhandle = GLES20.glGetUniformLocation(sp_Text, "uMVPMatrix");
306 
307  // Apply the projection and view transformation
308  GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
309 
310  // get handle to color value
311  int colorhandle = GLES20.glGetUniformLocation(sp_Text, "uColor");
312  GLES20.glUniform1f(colorhandle, mColor);
313 
314  int mSamplerLoc = GLES20.glGetUniformLocation (sp_Text, "s_texture" );
315 
316  // Texture activate unit 0
317  GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
318  // Bind the texture to this unit.
319  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
320  // Set the sampler texture unit to our selected id
321  GLES20.glUniform1i ( mSamplerLoc, texturenr);
322 
323  // Draw the triangle
324  GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
325 
326  // Disable vertex array
327  GLES20.glDisableVertexAttribArray(mPositionHandle);
328  GLES20.glDisableVertexAttribArray(mTexCoordLoc);
329  }
330  }
331 
333  {
334  // Get attributes from text object
335  float x = val.x;
336  float y = val.y;
337  String text = val.text;
338 
339  // Create
340  for(int j=0; j<text.length(); j++)
341  {
342  // get ascii value
343  char c = text.charAt(j);
344  int c_val = (int)c;
345 
346  int indx = c_val-RI_TEXT_START;
347 
348  if(indx<0 || indx>=mCharacterWidth.length) {
349  // unknown character, we will add a space for it to be save.
350  indx = 0;
351  }
352 
353  int colCount = RI_TEXT_TEXTURE_SIZE/(int)RI_TEXT_HEIGHT_BASE;
354 
355  // Calculate the uv parts
356  int row = indx / colCount;
357  int col = indx % colCount;
358 
359  float v = row * mUVHeight;
360  float v2 = v + mUVHeight;
361  float u = col * mUVWidth;
362  float u2 = u + mCharacterWidth[indx]/(float)RI_TEXT_TEXTURE_SIZE;
363 
364  // Creating the triangle information
365  float[] vec = new float[12];
366  float[] uv = new float[8];
367  float[] colors = new float[16];
368 
369  vec[0] = x;
370  vec[1] = y + (mTextHeight * uniformscale);
371  vec[2] = 0.99f;
372  vec[3] = x;
373  vec[4] = y;
374  vec[5] = 0.99f;
375  vec[6] = x + (mCharacterWidth[indx] * uniformscale);
376  vec[7] = y;
377  vec[8] = 0.99f;
378  vec[9] = x + (mCharacterWidth[indx] * uniformscale);
379  vec[10] = y + (mTextHeight * uniformscale);
380  vec[11] = 0.99f;
381 
382  colors = new float[]
383  {val.color[0], val.color[1], val.color[2], val.color[3],
384  val.color[0], val.color[1], val.color[2], val.color[3],
385  val.color[0], val.color[1], val.color[2], val.color[3],
386  val.color[0], val.color[1], val.color[2], val.color[3]
387  };
388  // 0.001f = texture bleeding hack/fix
389  uv[0] = u+0.001f;
390  uv[1] = v+0.001f;
391  uv[2] = u+0.001f;
392  uv[3] = v2-0.001f;
393  uv[4] = u2-0.001f;
394  uv[5] = v2-0.001f;
395  uv[6] = u2-0.001f;
396  uv[7] = v+0.001f;
397 
398  short[] inds = {0, 1, 2, 0, 2, 3};
399 
400  // Add our triangle information to our collection for 1 render call.
401  AddCharRenderInformation(vec, colors, uv, inds);
402 
403  // Calculate the new position
404  x += (mCharacterWidth[indx] * uniformscale);
405  }
406  }
407 
408  public float getUniformscale() {
409  return uniformscale;
410  }
411 
412  public void setUniformscale(float uniformscale) {
413  this.uniformscale = uniformscale;
414  }
415 
416  public void setColor(float color) {
417  mColor = color;
418  }
419 }
static int loadShader(int type, String shaderCode)
GLM_FUNC_DECL genType::row_type row(genType const &m, length_t const &index)
void PrepareDrawInfo(Vector< TextObject > txtcollection)
void setUniformscale(float uniformscale)
static final int RI_TEXT_TEXTURE_SIZE
static final float RI_TEXT_HEIGHT_BASE
void AddCharRenderInformation(float[] vec, float[] cs, float[] uv, short[] indi)
void convertTextToTriangleInfo(TextObject val)
void PrepareDraw(Vector< TextObject > txtcollection)


rtabmap
Author(s): Mathieu Labbe
autogenerated on Wed Jun 5 2019 22:43:40