package com.asha.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.asha.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);
}
}