content: package com.gamatechno.vrlib.common;
  
  import android.app.ActivityManager;
  import android.content.Context;
  import android.content.pm.ConfigurationInfo;
  import android.opengl.GLES20;
  import android.opengl.Matrix;
  import android.util.Log;
  
  import com.gamatechno.vrlib.objects.MDAbsObject3D;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  import java.util.ArrayList;
  
  /**
   * Created by nitro888 on 15. 4. 5..
   *
   * modify by hzqiujiadi on 16/1/22.
   * hzqiujiadi ashqalcn@gmail.com
   */
  public class GLUtil {
  
      private static final String TAG = "GLUtil";
  
      public static final float[] sIdentityMatrix = new float[16];
  
      static {
          Matrix.setIdentityM(sIdentityMatrix, 0);
      }
  
      public static float[] identityMatrix() {
          return sIdentityMatrix;
      }
  
      /**
       * Check if the system supports OpenGL ES 2.0.
       *
       * @param context
       * @return true:supported
       */
      public static boolean supportsEs2(Context context){
          final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
          final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
          return configurationInfo.reqGlEsVersion >= 0x20000;
      }
  
      public static void glCheck(String op) {
          int error;
          while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
              Log.e(TAG, op + ": glError " + android.opengl.GLUtils.getEGLErrorString(error));
          }
      }
  
      public static String readTextFileFromRaw(final Context context, final int resourceId) {
          final InputStream inputStream = context.getResources().openRawResource(
                  resourceId);
          final InputStreamReader inputStreamReader = new InputStreamReader(
                  inputStream);
          final BufferedReader bufferedReader = new BufferedReader(
                  inputStreamReader);
  
          String nextLine;
          final StringBuilder body = new StringBuilder();
  
          try {
              while ((nextLine = bufferedReader.readLine()) != null) {
                  body.append(nextLine);
                  body.append('\n');
              }
          } catch (IOException e) {
              return null;
          }
  
          return body.toString();
      }
  
      /**
       * Helper function to compile a shader.
       *
       * @param shaderType   The shader type.
       * @param shaderSource The shader source code.
       * @return An OpenGL handle to the shader.
       */
      public static int compileShader(final int shaderType, final String shaderSource) {
          int shaderHandle = GLES20.glCreateShader(shaderType);
  
          if (shaderHandle != 0) {
              // Pass in the shader source.
              GLES20.glShaderSource(shaderHandle, shaderSource);
  
              // Compile the shader.
              GLES20.glCompileShader(shaderHandle);
  
              // Get the compilation status.
              final int[] compileStatus = new int[1];
              GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
  
              // If the compilation failed, delete the shader.
              if (compileStatus[0] == 0) {
                  Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
                  GLES20.glDeleteShader(shaderHandle);
                  shaderHandle = 0;
              }
          }
  
          if (shaderHandle == 0) {
              throw new RuntimeException("Error creating shader.");
          }
  
          return shaderHandle;
      }
  
      /**
       * Helper function to compile and link a program.
       *
       * @param vertexShaderHandle   An OpenGL handle to an already-compiled vertex shader.
       * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
       * @param attributes           Attributes that need to be bound to the program.
       * @return An OpenGL handle to the program.
       */
      public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) {
          int programHandle = GLES20.glCreateProgram();
  
          if (programHandle != 0) {
              // Bind the vertex shader to the program.
              GLES20.glAttachShader(programHandle, vertexShaderHandle);
  
              // Bind the fragment shader to the program.
              GLES20.glAttachShader(programHandle, fragmentShaderHandle);
  
              // Bind attributes
              if (attributes != null) {
                  final int size = attributes.length;
                  for (int i = 0; i < size; i++) {
                      GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
                  }
              }
  
              // Link the two shaders together into a program.
              GLES20.glLinkProgram(programHandle);
  
              // Get the link status.
              final int[] linkStatus = new int[1];
              GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
  
              // If the link failed, delete the program.
              if (linkStatus[0] == 0) {
                  Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
                  GLES20.glDeleteProgram(programHandle);
                  programHandle = 0;
              }
          }
  
          if (programHandle == 0) {
              throw new RuntimeException("Error creating program.");
          }
  
          return programHandle;
      }
  
      public static void loadObject3D(final Context context, final int resourceId, final MDAbsObject3D output) {
          ArrayList<String> vertexes  = new ArrayList<String>();
          ArrayList<String> textures  = new ArrayList<String>();
          ArrayList<String> faces     = new ArrayList<String>();
  
          InputStream iStream         = context.getResources().openRawResource(resourceId);
          InputStreamReader isr       = new InputStreamReader(iStream);
          BufferedReader bReader      = new BufferedReader(isr);
          String line;
          try {
              while ((line = bReader.readLine()) != null) {
                  if (line.startsWith("v "))  vertexes.add(line.substring(2));
                  if (line.startsWith("vt ")) textures.add(line.substring(3));
                  if (line.startsWith("f "))  faces.add(line.substring(2));
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          final float[] vertexBuffer  = new float[faces.size() * 3 * 3];
          final float[] textureBuffer = new float[faces.size() * 3 * 2];
          final short[] indexBuffer   = new short[faces.size() * 3];
  
          int vertexIndex = 0;
          int textureIndex= 0;
          // int normalIndex = 0;
          int faceIndex   = 0;
  
          for (String i : faces) {
              for (String j : i.split(" ")) {
                  indexBuffer[faceIndex] = (short)faceIndex++;
                  String[] faceComponent = j.split("/");
  
                  // only support f v/t/n mode
                  String vertex   = vertexes.get(Integer.parseInt(faceComponent[0]) - 1);
                  String texture  = textures.get(Integer.parseInt(faceComponent[1]) - 1);
                  //String normal   = normals.get(Integer.parseInt(faceComponent[2]) - 1);
  
                  String vertexComp[]     = vertex.split(" ");
                  String textureComp[]    = texture.split(" ");
                  //String normalComp[]     = normal.split(" ");
  
                  for (String v : vertexComp)     vertexBuffer[vertexIndex++]= Float.parseFloat(v);
                  for (String t : textureComp)    textureBuffer[textureIndex++]  = Float.parseFloat(t);
                  //for (String n : normalComp)     normalBuffer[normalIndex++]= Float.parseFloat(n);
              }
          }
  
          // Vertex
          FloatBuffer vertex = ByteBuffer.allocateDirect(vertexBuffer.length * 4)
                  .order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexBuffer);
          vertex.position(0);
  
          // Texture Coordinate
          FloatBuffer texture = ByteBuffer.allocateDirect(textureBuffer.length * 4).
                  order(ByteOrder.nativeOrder()).asFloatBuffer().put(textureBuffer);
          texture.position(0);
  
          output.setVerticesBuffer(0,vertex);
          output.setVerticesBuffer(1,vertex);
          output.setTexCoordinateBuffer(0,texture);
          output.setTexCoordinateBuffer(1,texture);
          output.setNumIndices(indexBuffer.length);
  
          //ByteBuffer.allocateDirect(normalBuffer.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(normalBuffer).position(0);
      }
  
  }
  