291 lines
9.3 KiB
Java
291 lines
9.3 KiB
Java
package com.homelinux.holtrop.opengltest;
|
|
|
|
import android.opengl.GLSurfaceView;
|
|
import android.opengl.GLES20;
|
|
import javax.microedition.khronos.opengles.GL10;
|
|
import javax.microedition.khronos.egl.EGLConfig;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.FloatBuffer;
|
|
import java.nio.IntBuffer;
|
|
import java.nio.ByteOrder;
|
|
import android.util.Log;
|
|
import android.content.res.AssetManager;
|
|
import android.content.res.Resources;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import android.opengl.Matrix;
|
|
import android.os.SystemClock;
|
|
import android.view.MotionEvent;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.Bitmap;
|
|
import android.opengl.GLUtils;
|
|
import java.lang.Math;
|
|
|
|
public class MyRenderer implements GLSurfaceView.Renderer
|
|
{
|
|
class Tile
|
|
{
|
|
public boolean flipping;
|
|
public boolean side;
|
|
public float rotation;
|
|
public int axis;
|
|
};
|
|
|
|
private int m_program;
|
|
private final String DBGTAG = "JoshsOpenGL";
|
|
private FloatBuffer m_quad_attrib_buffer;
|
|
private AssetManager m_asset_manager;
|
|
private Resources m_resources;
|
|
private float m_proj_matrix[] = new float[16];
|
|
private float m_modelview[] = new float[16];
|
|
private int m_width;
|
|
private int m_height;
|
|
private final int GRID_WIDTH = 16;
|
|
private final int GRID_HEIGHT = 9;
|
|
private Tile[][] m_tiles = new Tile[GRID_WIDTH][GRID_HEIGHT];
|
|
private float m_aspect = 1.0f;
|
|
private final float DISTANCE =
|
|
(float) (GRID_HEIGHT / 2.0 / Math.tan(Math.toRadians(30)));
|
|
private long m_last_time = SystemClock.uptimeMillis();
|
|
private final float[][] AXES = {
|
|
{1, 0, 0},
|
|
{0, 1, 0},
|
|
{-1, 0, 0},
|
|
{0, -1, 0}
|
|
};
|
|
|
|
public MyRenderer(AssetManager am, Resources resources)
|
|
{
|
|
m_asset_manager = am;
|
|
m_resources = resources;
|
|
for (int x = 0; x < GRID_WIDTH; x++)
|
|
{
|
|
for (int y = 0; y < GRID_HEIGHT; y++)
|
|
{
|
|
m_tiles[x][y] = new Tile();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void checkGLError(String glOperation)
|
|
{
|
|
int error;
|
|
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
|
|
{
|
|
Log.e(DBGTAG, glOperation + ": glError " + error);
|
|
}
|
|
}
|
|
|
|
private String read_asset(String fname)
|
|
{
|
|
String result = "";
|
|
try
|
|
{
|
|
InputStream is = m_asset_manager.open(fname);
|
|
InputStreamReader isr = new InputStreamReader(is);
|
|
BufferedReader br = new BufferedReader(isr);
|
|
String line;
|
|
while ((line = br.readLine()) != null)
|
|
{
|
|
result += line + "\n";
|
|
}
|
|
}
|
|
catch (IOException ioe)
|
|
{
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private int load_shader(int type, String source)
|
|
{
|
|
int shader = GLES20.glCreateShader(type);
|
|
|
|
GLES20.glShaderSource(shader, source);
|
|
GLES20.glCompileShader(shader);
|
|
|
|
IntBuffer ib = IntBuffer.allocate(1);
|
|
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, ib);
|
|
if (ib.get(0) != 1)
|
|
{
|
|
String info_log = GLES20.glGetShaderInfoLog(shader);
|
|
Log.e(DBGTAG, "Error compiling shader: " + info_log);
|
|
}
|
|
|
|
return shader;
|
|
}
|
|
|
|
public void onSurfaceCreated(GL10 unused, EGLConfig config)
|
|
{
|
|
final float attribs[] = {
|
|
0.5f, 0.5f, 0.8f, 0.8f, 1,
|
|
-0.5f, 0.5f, 0, 0, 1,
|
|
-0.5f, -0.5f, 0.8f, 0.8f, 1,
|
|
0.5f, -0.5f, 0, 0, 1
|
|
};
|
|
checkGLError("onSurfaceCreated");
|
|
ByteBuffer bb = ByteBuffer.allocateDirect(attribs.length * 4);
|
|
bb.order(ByteOrder.nativeOrder());
|
|
m_quad_attrib_buffer = bb.asFloatBuffer();
|
|
m_quad_attrib_buffer.put(attribs);
|
|
m_quad_attrib_buffer.position(0);
|
|
|
|
final String v_shader_src = read_asset("shaders/vertex.glsl");
|
|
final String f_shader_src = read_asset("shaders/fragment.glsl");
|
|
int v_shader = load_shader(GLES20.GL_VERTEX_SHADER, v_shader_src);
|
|
int f_shader = load_shader(GLES20.GL_FRAGMENT_SHADER, f_shader_src);
|
|
m_program = GLES20.glCreateProgram();
|
|
GLES20.glAttachShader(m_program, v_shader);
|
|
GLES20.glAttachShader(m_program, f_shader);
|
|
GLES20.glLinkProgram(m_program);
|
|
checkGLError("glLinkProgram");
|
|
IntBuffer ib = IntBuffer.allocate(1);
|
|
GLES20.glGetProgramiv(m_program, GLES20.GL_LINK_STATUS, ib);
|
|
if (ib.get(0) != 1)
|
|
{
|
|
String info_log = GLES20.glGetProgramInfoLog(m_program);
|
|
Log.e(DBGTAG, "Program log: " + info_log);
|
|
}
|
|
|
|
/*
|
|
Bitmap texture = BitmapFactory.decodeResource(m_resources,
|
|
R.drawable.texture);
|
|
int[] textures = new int[1];
|
|
GLES20.glGenTextures(1, textures, 0);
|
|
checkGLError("glGenTextures");
|
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
|
|
checkGLError("glBindTexture");
|
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR_MIPMAP_LINEAR);
|
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
|
checkGLError("glTexParameterf");
|
|
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, texture, 0);
|
|
checkGLError("GLUtils.texImage2D");
|
|
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
|
|
checkGLError("glGenerateMipmap");
|
|
texture.recycle();
|
|
*/
|
|
|
|
GLES20.glClearColor(1.0f, 0.6f, 0.1f, 1.0f);
|
|
}
|
|
|
|
private void update_tiles(long elapsed)
|
|
{
|
|
for (int x = 0; x < GRID_WIDTH; x++)
|
|
{
|
|
for (int y = 0; y < GRID_HEIGHT; y++)
|
|
{
|
|
Tile t = m_tiles[x][y];
|
|
if (t.flipping)
|
|
{
|
|
t.rotation += elapsed * (180.0f / 2000.0f);
|
|
if (t.rotation >= 180.0f)
|
|
{
|
|
t.flipping = false;
|
|
t.side = !t.side;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void onDrawFrame(GL10 unused)
|
|
{
|
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
|
|
|
long time = SystemClock.uptimeMillis();
|
|
update_tiles(time - m_last_time);
|
|
|
|
int attr_pos = GLES20.glGetAttribLocation(m_program, "pos");
|
|
int attr_color = GLES20.glGetAttribLocation(m_program, "color");
|
|
checkGLError("glGetAttribLocation");
|
|
|
|
GLES20.glEnableVertexAttribArray(attr_pos);
|
|
GLES20.glEnableVertexAttribArray(attr_color);
|
|
checkGLError("glEnableVertexAttribArray");
|
|
|
|
m_quad_attrib_buffer.position(0);
|
|
GLES20.glVertexAttribPointer(attr_pos, 2, GLES20.GL_FLOAT, false,
|
|
5 * 4, m_quad_attrib_buffer);
|
|
m_quad_attrib_buffer.position(2);
|
|
GLES20.glVertexAttribPointer(attr_color, 3, GLES20.GL_FLOAT, false,
|
|
5 * 4, m_quad_attrib_buffer);
|
|
checkGLError("glVertexAttribPointer");
|
|
|
|
for (int y = 0; y < GRID_HEIGHT; y++)
|
|
{
|
|
for (int x = 0; x < GRID_WIDTH; x++)
|
|
{
|
|
Tile t = m_tiles[x][y];
|
|
Matrix.setIdentityM(m_modelview, 0);
|
|
Matrix.translateM(m_modelview, 0,
|
|
x + 0.5f - GRID_WIDTH / 2.0f,
|
|
y + 0.5f - GRID_HEIGHT / 2.0f,
|
|
-DISTANCE);
|
|
if (t.flipping)
|
|
{
|
|
Matrix.rotateM(m_modelview, 0,
|
|
t.rotation,
|
|
AXES[t.axis][0], AXES[t.axis][1], AXES[t.axis][2]);
|
|
}
|
|
GLES20.glUniformMatrix4fv(
|
|
GLES20.glGetUniformLocation(m_program, "modelview"),
|
|
1, false, m_modelview, 0);
|
|
|
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
|
|
checkGLError("glDrawArrays");
|
|
}
|
|
}
|
|
|
|
GLES20.glDisableVertexAttribArray(attr_pos);
|
|
GLES20.glDisableVertexAttribArray(attr_color);
|
|
checkGLError("glDisableVertexAttribArray");
|
|
|
|
m_last_time = time;
|
|
}
|
|
|
|
public void onSurfaceChanged(GL10 unused, int width, int height)
|
|
{
|
|
m_width = width;
|
|
m_height = height;
|
|
m_aspect = width / (float) height;
|
|
|
|
GLES20.glViewport(0, 0, width, height);
|
|
|
|
Matrix.perspectiveM(m_proj_matrix, 0, 60.0f, 16.0f/9.0f, 0.1f, 10.0f);
|
|
|
|
GLES20.glUseProgram(m_program);
|
|
|
|
GLES20.glUniformMatrix4fv(
|
|
GLES20.glGetUniformLocation(m_program, "projection"),
|
|
1, false, m_proj_matrix, 0);
|
|
}
|
|
|
|
public boolean onTouchEvent(MotionEvent e)
|
|
{
|
|
if (e.getAction() == MotionEvent.ACTION_DOWN ||
|
|
e.getAction() == MotionEvent.ACTION_MOVE)
|
|
{
|
|
int x = (int) (GRID_WIDTH * e.getX() / (float) m_width);
|
|
int y = (int) (GRID_HEIGHT * (m_height - e.getY()) / (float) m_height);
|
|
|
|
if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT)
|
|
{
|
|
Tile t = m_tiles[x][y];
|
|
if (!t.flipping)
|
|
{
|
|
t.flipping = true;
|
|
t.rotation = 0.0f;
|
|
t.axis = (int) (Math.random() * 4);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|