/**
* Copyright (C) 2013 Gundog Studios LLC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gundogstudios.gl;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.FloatBuffer;
import com.gundogstudios.modules.GLES11Module;
import com.gundogstudios.modules.Modules;
import com.gundogstudios.util.FastMath;
public class TouchPlane {
private final static int FLOAT_SIZE = 4;
private final static int CHAR_SIZE = 2;
private final static int VERTEX_SIZE = 7 * FLOAT_SIZE;
private final static int VERTEX_COLOR_BUFFER_INDEX_OFFSET = 3 * FLOAT_SIZE;
private int vertexBufferObjectId;
private int elementBufferObjectId;
private int indexCount;
private int rows;
private int cols;
private byte[] arr;
private ByteBuffer pixels;
public TouchPlane(int rows, int cols, float size) {
arr = new byte[4];
pixels = ByteBuffer.wrap(arr);
this.rows = rows;
this.cols = cols;
float width = cols * size / 2;
float height = rows * size / 2;
float[] vertices = new float[(rows + 1) * (cols + 1) * 3];
float[] colors = new float[(rows + 1) * (cols + 1) * 4];
int currentVertex = 0;
int currentColor = 0;
float ystart = -height;
for (short r = 0; r <= rows; r++) {
float xstart = -width;
for (short c = 0; c <= cols; c++) {
vertices[currentVertex] = xstart; // X
vertices[currentVertex + 1] = ystart; // Y
vertices[currentVertex + 2] = 0f; // Z
colors[currentColor] = (xstart + width) / (width * 2); // R
colors[currentColor + 1] = (ystart + height) / (height * 2); // G
colors[currentColor + 2] = 0f; // B
colors[currentColor + 3] = 1f; // A
currentVertex += 3;
currentColor += 4;
xstart += size;
}
ystart += size;
}
short[] indices = new short[rows * cols * 6];
int currentIndex = 0;
for (short r = 0; r < rows; r++) {
for (short c = 0; c < cols; c++) {
indices[currentIndex] = (short) (r * (cols + 1) + c);
indices[currentIndex + 1] = (short) (indices[currentIndex] + 1);
indices[currentIndex + 2] = (short) ((r + 1) * (cols + 1) + c);
indices[currentIndex + 3] = indices[currentIndex + 1];
indices[currentIndex + 4] = (short) (indices[currentIndex + 2] + 1);
indices[currentIndex + 5] = indices[currentIndex + 2];
currentIndex += 6;
}
}
ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect((vertices.length + colors.length) * FLOAT_SIZE).order(
ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vertexByteBuffer.asFloatBuffer();
for (int i = 0, j = 0; i < vertices.length && j < colors.length;) {
vertexBuffer.put(vertices[i++]);
vertexBuffer.put(vertices[i++]);
vertexBuffer.put(vertices[i++]);
vertexBuffer.put(colors[j++]);
vertexBuffer.put(colors[j++]);
vertexBuffer.put(colors[j++]);
vertexBuffer.put(colors[j++]);
}
indexCount = indices.length;
ByteBuffer indexByteBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount).order(ByteOrder.nativeOrder());
CharBuffer indexBuffer = indexByteBuffer.asCharBuffer();
for (int x = 0; x < indices.length; x++) {
indexBuffer.put((char) indices[x]);
}
GLES11Module gl = Modules.GL;
int[] vboIds = new int[2];
gl.glGenBuffers(2, vboIds, 0);
vertexBufferObjectId = vboIds[0];
elementBufferObjectId = vboIds[1];
gl.glBindBuffer(GLES11Module.GL_ARRAY_BUFFER, vertexBufferObjectId);
vertexByteBuffer.position(0);
gl.glBufferData(GLES11Module.GL_ARRAY_BUFFER, vertexByteBuffer.capacity(), vertexByteBuffer,
GLES11Module.GL_STATIC_DRAW);
gl.glBindBuffer(GLES11Module.GL_ELEMENT_ARRAY_BUFFER, elementBufferObjectId);
indexByteBuffer.position(0);
gl.glBufferData(GLES11Module.GL_ELEMENT_ARRAY_BUFFER, indexByteBuffer.capacity(), indexByteBuffer,
GLES11Module.GL_STATIC_DRAW);
}
public int[] touch(int x, int y) {
draw();
return readPixels(x, y);
}
private void draw() {
GLES11Module gl = Modules.GL;
gl.glEnableClientState(GLES11Module.GL_VERTEX_ARRAY);
gl.glBindBuffer(GLES11Module.GL_ARRAY_BUFFER, vertexBufferObjectId);
gl.glVertexPointer(3, GLES11Module.GL_FLOAT, VERTEX_SIZE, 0);
gl.glEnableClientState(GLES11Module.GL_COLOR_ARRAY);
gl.glColorPointer(4, GLES11Module.GL_FLOAT, VERTEX_SIZE, VERTEX_COLOR_BUFFER_INDEX_OFFSET);
gl.glBindBuffer(GLES11Module.GL_ELEMENT_ARRAY_BUFFER, elementBufferObjectId);
gl.glDrawElements(GLES11Module.GL_TRIANGLES, indexCount, GLES11Module.GL_UNSIGNED_SHORT, 0);
gl.glDisableClientState(GLES11Module.GL_VERTEX_ARRAY);
gl.glDisableClientState(GLES11Module.GL_COLOR_ARRAY);
gl.glBindBuffer(GLES11Module.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(GLES11Module.GL_ELEMENT_ARRAY_BUFFER, 0);
}
private int[] readPixels(int x, int y) {
GLES11Module gl = Modules.GL;
pixels.position(0);
gl.glReadPixels(x, y, 1, 1, GLES11Module.GL_RGBA, GLES11Module.GL_UNSIGNED_BYTE, pixels);
gl.glClear(GLES11Module.GL_COLOR_BUFFER_BIT | GLES11Module.GL_DEPTH_BUFFER_BIT);
int r = arr[0];
int g = arr[1];
int b = arr[2];
int a = arr[3];
if (r < 0)
r += 256;
if (g < 0)
g += 256;
if (b < 0)
b += 256;
if (a < 0)
a += 256;
float rf = r / 256f;
float gf = g / 256f;
float bf = b / 256f;
// touched off the game board
if (bf > .001f)
return null;
int col = FastMath.floor(rf * cols);
int row = FastMath.floor(gf * rows);
return new int[] { col, row };
}
}