Skip to content

Instantly share code, notes, and snippets.

@vaalentin
Created October 18, 2017 09:36
Show Gist options
  • Save vaalentin/58c6ba67ac84ba55355e28e1e822e517 to your computer and use it in GitHub Desktop.
Save vaalentin/58c6ba67ac84ba55355e28e1e822e517 to your computer and use it in GitHub Desktop.
Java OpenGL classes
package com.breel.gl.utils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Buffer {
private static final String TAG = Buffer.class.getSimpleName();
public static FloatBuffer create(float[] data) {
final FloatBuffer buffer = ByteBuffer.allocateDirect(data.length * Constants.BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
buffer.put(data);
buffer.position(0);
return buffer;
}
public static ShortBuffer create(short[] data) {
final ShortBuffer buffer = ByteBuffer.allocateDirect(data.length * Constants.BYTES_PER_SHORT)
.order(ByteOrder.nativeOrder())
.asShortBuffer();
buffer.put(data);
buffer.position(0);
return buffer;
}
}
package com.breel.gl.utils;
public class Constants {
public static final int BYTES_PER_FLOAT = 4;
public static final int BYTES_PER_SHORT = 2;
}
package com.breel.gl.utils;
import android.graphics.Bitmap;
import static android.opengl.GLES20.*;
public class FrameBuffer {
private static final String TAG = FrameBuffer.class.getSimpleName();
private final int[] mHandler;
private final int[] mTextureHandler;
private final Texture2d mTexture;
private FrameBuffer(int width, int height) {
mHandler = new int[1];
glGenFramebuffers(1, mHandler, 0);
bind();
mTexture = Texture2d.create(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888));
mTextureHandler = mTexture.getHandlers();
mTexture.bind(0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureHandler[0], 0);
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("Error while creating the framebuffer: " + status);
}
unbind();
}
public void bind() {
glBindFramebuffer(GL_FRAMEBUFFER, mHandler[0]);
}
public void unbind() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
public Texture2d getTexture() {
return mTexture;
}
public void dispose() {
glDeleteFramebuffers(GL_FRAMEBUFFER, mHandler, 0);
}
public static FrameBuffer create(int width, int height) {
return new FrameBuffer(width, height);
}
}
package com.breel.gl.utils;
public class Math {
public static boolean isPowerOfTwo(final int value) {
return ((value & -value) == value);
}
}
package com.breel.gl.utils;
import android.util.Log;
public class Matrix {
private static final String TAG = Matrix.class.getSimpleName();
public static float[] createMatrix2() {
return new float[]{
1f, 0f,
0f, 1f
};
}
public static float[] createMatrix3() {
return new float[]{
1f, 0f, 0f,
0f, 1f, 0f,
0f, 0f, 1f
};
}
public static float[] createMatrix4() {
return new float[]{
1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
0f, 0f, 0f, 1f
};
}
public static String toString(final float[] in) {
int itemPerRow;
switch (in.length) {
case 4:
itemPerRow = 2;
break;
case 9:
itemPerRow = 3;
break;
case 16:
itemPerRow = 4;
break;
default:
Log.w(TAG, "Matrix format not recognized");
return "";
}
String out = "(";
int j = 0;
for (int i = 0; i < in.length; ++i) {
out += String.valueOf(in[i]);
if (i != in.length - 1) {
out += ", ";
}
if (j == itemPerRow - 1 && i != in.length - 1) {
out += "\n";
j = 0;
} else {
j++;
}
}
out += ")";
return out;
}
}
package com.breel.gl.utils;
import java.util.ArrayList;
import java.lang.Math;
import static android.opengl.GLES20.*;
// TODO
public class Mesh {
private static final String TAG = Mesh.class.getSimpleName();
public final VertexBuffer positions;
public final VertexBuffer normals;
public final VertexBuffer uvs;
public final VertexBuffer indices;
public final int indicesCount;
private Mesh(VertexBuffer positions, VertexBuffer normals, VertexBuffer uvs, VertexBuffer indices, int indicesCount) {
this.positions = positions;
this.normals = normals;
this.uvs = uvs;
this.indices = indices;
this.indicesCount = indicesCount;
}
public static Mesh create(
VertexBuffer positions,
VertexBuffer normals,
VertexBuffer uvs,
VertexBuffer indices,
int indicesCount
) {
return new Mesh(positions, normals, uvs, indices, indicesCount);
}
public static Mesh createQuad() {
return createQuad(1, 1, 1, 1);
}
public static Mesh createQuad(float totalWidth, float totalHeight, float width, float height) {
float normalizedWidth = width / totalWidth;
float normalizedHeight = height / totalHeight;
float[] positions = {
1f, -1f,
1f, 1f,
-1f, 1f,
-1f, -1f
};
float[] normals = {
0f, 0f -1f,
0f, 0f -1f,
0f, 0f -1f,
0f, 0f -1f
};
float[] uvs = {
1f, 1f,
1f, 0f,
0f, 0f,
0f, 1f
};
short[] indices = {
0, 1, 2,
2, 3, 0
};
VertexBuffer positionsVbo = VertexBuffer.create(GL_ARRAY_BUFFER, Buffer.create(positions), GL_STATIC_DRAW);
VertexBuffer normalsVbo = VertexBuffer.create(GL_ARRAY_BUFFER, Buffer.create(normals), GL_STATIC_DRAW);
VertexBuffer uvsVbo = VertexBuffer.create(GL_ARRAY_BUFFER, Buffer.create(uvs), GL_STATIC_DRAW);
VertexBuffer indicesVbo = VertexBuffer.create(GL_ELEMENT_ARRAY_BUFFER, Buffer.create(indices), GL_STATIC_DRAW);
return Mesh.create(positionsVbo, normalsVbo, uvsVbo, indicesVbo, indices.length);
}
public static void getNormalizedPosition(float[] position, float width, float height, float x, float y) {
position[0] = (x / width) * 2f;
position[1] = -(y / height) * 2f;
position[2] = 0f;
}
public static float[] getNormalizedPosition(float width, float height, float x, float y) {
float[] position = Vector.create();
getNormalizedPosition(position, width, height, x, y);
return position;
}
}
package com.breel.gl.utils;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import static android.opengl.GLES20.*;
public class Program {
private static final String TAG = Program.class.getSimpleName();
private static class Uniform {
private final int location;
private final int type;
private Uniform(final int location, final int type) {
this.location = location;
this.type = type;
}
}
private static class Attribute {
private final int location;
private final int stride;
private final int type;
private Attribute(final int location, final int stride, final int type) {
this.location = location;
this.stride = stride;
this.type = type;
}
}
private int mHandler;
private ArrayList<Uniform> mUniforms;
private ArrayList<Attribute> mAttributes;
protected Program(final int vertexShader, final int fragmentShader) {
mHandler = glCreateProgram();
glAttachShader(mHandler, vertexShader);
glAttachShader(mHandler, fragmentShader);
glLinkProgram(mHandler);
final int[] status = new int[1];
glGetProgramiv(mHandler, GL_LINK_STATUS, status, 0);
if (status[0] != GL_TRUE) {
final String errorMessage = glGetProgramInfoLog(mHandler);
glDeleteProgram(mHandler);
throw new RuntimeException("Error linking program: " + errorMessage);
}
mAttributes = new ArrayList<Attribute>();
mUniforms = new ArrayList<Uniform>();
}
public int registerUniform(final String name, final int type) {
final int location = glGetUniformLocation(mHandler, name);
if (location == -1) {
//throw new RuntimeException("Uniform '" + name + "' can't be registered.");
Log.v( TAG, "Warning: Unused Uniform " + name );
}
final Uniform uniform = new Uniform(location, type);
mUniforms.add(uniform);
return mUniforms.size() - 1;
}
private Uniform getUniform(final int uniformId) {
final Uniform uniform = mUniforms.get(uniformId);
if (uniform == null) {
throw new RuntimeException("Uniform '" + uniformId + "' isn't registered.");
}
return uniform;
}
public void setUniform(final int uniformId, final int value) {
final Uniform uniform = getUniform(uniformId);
final int location = uniform.location;
glUniform1i(location, value);
}
public void setUniform(final int uniformId, final int[] value) {
final Uniform uniform = getUniform(uniformId);
final int location = uniform.location;
final int type = uniform.type;
final int length = value.length;
switch (type) {
case GL_INT_VEC2:
glUniform2iv(location, length / 2, value, 0);
break;
case GL_INT_VEC3:
glUniform3iv(location, length / 3, value, 0);
break;
case GL_INT_VEC4:
glUniform4iv(location, length / 4, value, 0);
break;
}
}
public void setUniform(final int uniformId, final float value) {
final Uniform uniform = getUniform(uniformId);
final int location = uniform.location;
glUniform1f(location, value);
}
public void setUniform(final int uniformId, final float[] value) {
final Uniform uniform = getUniform(uniformId);
final int location = uniform.location;
final int type = uniform.type;
final int length = value.length;
switch (type) {
case GL_FLOAT_VEC2:
glUniform2fv(location, length / 2, value, 0);
break;
case GL_FLOAT_VEC3:
glUniform3fv(location, length / 3, value, 0);
break;
case GL_FLOAT_VEC4:
glUniform4fv(location, length / 4, value, 0);
break;
case GL_FLOAT_MAT2:
glUniformMatrix2fv(location, length / 4, false, value, 0);
break;
case GL_FLOAT_MAT3:
glUniformMatrix3fv(location, length / 9, false, value, 0);
break;
case GL_FLOAT_MAT4:
glUniformMatrix4fv(location, length / 16, false, value, 0);
break;
}
}
public int registerAttribute(final String name, final int stride, final int type) {
final int location = glGetAttribLocation(mHandler, name);
if (location == -1) {
throw new RuntimeException("Attribute '" + name + "' can't be registered.");
}
glEnableVertexAttribArray(location);
final Attribute attribute = new Attribute(location, stride, type);
mAttributes.add(attribute);
return mAttributes.size() - 1;
}
public void setAttributePointer(final int attributeId) {
final Attribute attribute = mAttributes.get(attributeId);
if (attribute == null) {
throw new RuntimeException("Attribute '" + attributeId + "' isn't registered.");
}
final int type = attribute.type;
final int stride = attribute.stride;
final int location = attribute.location;
glVertexAttribPointer(location, stride, type, false, 0, 0);
}
public void use() {
glUseProgram(mHandler);
}
public void dispose() {
mUniforms.clear();
mAttributes.clear();
glDeleteProgram(mHandler);
}
public static Program create(final String vertexShaderSource, final String fragmentShaderSource) {
final int vertexShader = Shader.create(GL_VERTEX_SHADER, vertexShaderSource);
final int framentShader = Shader.create(GL_FRAGMENT_SHADER, fragmentShaderSource);
return new Program(vertexShader, framentShader);
}
public static Program create(final int vertexShader, final int fragmentShader) {
return new Program(vertexShader, fragmentShader);
}
}
package com.breel.gl.utils;
import static android.opengl.GLES20.*;
public class Shader {
private static final String TAG = Shader.class.getSimpleName();
public static int create(final int type, final String source) {
final int handler = glCreateShader(type);
glShaderSource(handler, source);
glCompileShader(handler);
final int[] status = new int[1];
glGetShaderiv(handler, GL_COMPILE_STATUS, status, 0);
if (status[0] != GL_TRUE) {
final String errorMessage = glGetShaderInfoLog(handler);
glDeleteShader(handler);
throw new RuntimeException("Error compiling shader: " + errorMessage);
}
return handler;
}
}
package com.breel.gl.utils;
import android.graphics.Bitmap;
import android.opengl.GLUtils;
import java.nio.IntBuffer;
import static android.opengl.GLES20.*;
// TODO allow to resize the texture
// TODO allow to update parts of the texture
// TODO improve performance when updating texture, read: http://stackoverflow.com/a/21578261
public class Texture2d {
private static final String TAG = Texture2d.class.getSimpleName();
private final int mWidth;
private final int mHeight;
private final int[] mHandlers;
private Texture2d(final int width, final int height) {
mWidth = width;
mHeight = height;
mHandlers = new int[1];
glGenTextures(1, mHandlers, 0);
}
public int bind(final int unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, mHandlers[0]);
return unit;
}
public void unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
public void setParameter(final int parameter, final int value) {
glTexParameterf(GL_TEXTURE_2D, parameter, value);
}
public void setPixels(final Bitmap bitmap) {
GLUtils.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap);
}
public void setPixels(final IntBuffer data) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
public void generateMipmaps() {
glGenerateMipmap(GL_TEXTURE_2D);
}
public int[] getHandlers() {
return mHandlers;
}
public void dispose() {
glDeleteTextures(1, mHandlers, 0);
}
public static Texture2d create(final Bitmap bitmap) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final Texture2d texture = new Texture2d(width, height);
texture.bind(0);
GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
public static Texture2d create(final int width, final int height) {
final Texture2d texture = new Texture2d(width, height);
texture.bind(0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
public static Texture2d create() {
final Texture2d texture = new Texture2d(1, 1);
texture.bind(0);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
}
package com.breel.gl.utils;
import android.graphics.Bitmap;
import android.opengl.GLUtils;
import java.nio.IntBuffer;
import static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
import static android.opengl.GLES20.GL_NEAREST;
import static android.opengl.GLES20.GL_RGBA;
import static android.opengl.GLES20.GL_TEXTURE0;
import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
import static android.opengl.GLES20.GL_UNSIGNED_BYTE;
import static android.opengl.GLES20.glActiveTexture;
import static android.opengl.GLES20.glBindTexture;
import static android.opengl.GLES20.glDeleteTextures;
import static android.opengl.GLES20.glGenTextures;
import static android.opengl.GLES20.glGenerateMipmap;
import static android.opengl.GLES20.glTexImage2D;
import static android.opengl.GLES20.glTexParameterf;
import static android.opengl.GLES20.glTexSubImage2D;
// TODO allow to resize the texture
// TODO allow to update parts of the texture
// TODO improve performance when updating texture, read: http://stackoverflow.com/a/21578261
public class TextureExternal {
private static final String TAG = TextureExternal.class.getSimpleName();
private static int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
private final int mWidth;
private final int mHeight;
private final int[] mHandlers;
private TextureExternal(final int width, final int height) {
mWidth = width;
mHeight = height;
mHandlers = new int[1];
glGenTextures(1, mHandlers, 0);
}
public int bind(final int unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, mHandlers[0]);
return unit;
}
public void unbind() {
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
}
public void setParameter(final int parameter, final int value) {
glTexParameterf(GL_TEXTURE_EXTERNAL_OES, parameter, value);
}
public void setPixels(final Bitmap bitmap) {
GLUtils.texSubImage2D(GL_TEXTURE_EXTERNAL_OES, 0, 0, 0, bitmap);
}
public void setPixels(final IntBuffer data) {
glTexSubImage2D(GL_TEXTURE_EXTERNAL_OES, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
public void generateMipmaps() {
glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
}
public int[] getHandlers() {
return mHandlers;
}
public void dispose() {
glDeleteTextures(1, mHandlers, 0);
}
public static TextureExternal create(final Bitmap bitmap) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
final TextureExternal texture = new TextureExternal(width, height);
texture.bind(0);
GLUtils.texImage2D(GL_TEXTURE_EXTERNAL_OES, 0, bitmap, 0);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
public static TextureExternal create(final int width, final int height) {
final TextureExternal texture = new TextureExternal(width, height);
texture.bind(0);
glTexImage2D(GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
public static TextureExternal create() {
final TextureExternal texture = new TextureExternal(1, 1);
texture.bind(0);
texture.setParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
texture.setParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.unbind();
return texture;
}
}
// Usage sample
package com.breel.gl;
import android.content.Context;
import android.opengl.GLES20;
import com.breel.utils.File;
import com.breel.gl.utils.Mesh;
import com.breel.gl.utils.Program;
import com.breel.gl.utils.Shader;
import com.breel.gl.utils.Texture2d;
public class TextureQuad {
private Context mContext;
private Mesh mQuad;
private Program mProgram;
private int mPositionsId;
private int mUvsId;
private int mTextureId;
public TextureQuad(Context context) {
mContext = context;
}
public void initGL() {
mQuad = Mesh.createQuad();
int vertexShader = Shader.create(GLES20.GL_VERTEX_SHADER, File.readFile(mContext, "shaders/tex.vert"));
int fragmentShader = Shader.create(GLES20.GL_FRAGMENT_SHADER, File.readFile(mContext, "shaders/tex.frag"));
mProgram = Program.create(vertexShader, fragmentShader);
mPositionsId = mProgram.registerAttribute("position", 2, GLES20.GL_FLOAT);
mUvsId = mProgram.registerAttribute("uv", 2, GLES20.GL_FLOAT);
mTextureId = mProgram.registerUniform("map", GLES20.GL_INT);
}
public void draw(Texture2d texture) {
mProgram.use();
mQuad.positions.bind();
mProgram.setAttributePointer(mPositionsId);
mQuad.uvs.bind();
mProgram.setAttributePointer(mUvsId);
mProgram.setUniform(mTextureId, texture.bind(0));
mQuad.indices.bind();
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mQuad.indicesCount, GLES20.GL_UNSIGNED_SHORT, 0);
}
}
package com.breel.gl.utils;
public class Vector {
private static final String TAG = Vector.class.getSimpleName();
public static float[] create() {
return create(0f, 0f, 0f);
}
public static float[] create(final float x, final float y) {
return create(x, y, 0f);
}
public static float[] create(float x, final float y, final float z) {
return new float[]{x, y, z};
}
public static void set(final float[] in, final float x, final float y) {
in[0] = x;
in[1] = y;
}
public static void set(final float[] in, final float x, final float y, final float z) {
set(in, x, y);
in[2] = z;
}
public static float[] clone(final float[] in) {
return create(in[0], in[1], in[2]);
}
public static float magnitude(final float[] in) {
final float x = in[0] * in[0];
final float y = in[1] * in[1];
final float z = in[2] * in[2];
return (float) java.lang.Math.sqrt(x + y + z);
}
public static float magnitudeSqrt(final float[] in) {
final float x = in[0] * in[0];
final float y = in[1] * in[1];
final float z = in[2] * in[2];
return x + y + z;
}
public static void add(final float[] out, final float[] in) {
out[0] += in[0];
out[1] += in[1];
out[2] += in[2];
}
public static void subtract(final float[] out, final float[] in) {
out[0] -= in[0];
out[1] -= in[1];
out[2] -= in[2];
}
public static void multiply(final float[] out, final float scalar) {
out[0] *= scalar;
out[1] *= scalar;
out[2] *= scalar;
}
public static void divide(final float[] out, final float scalar) {
out[0] /= scalar;
out[1] /= scalar;
out[2] /= scalar;
}
static public float distance(final float[] inA, final float[] inB) {
final float dx = inA[0] - inB[0];
final float dy = inA[1] - inB[1];
final float dz = inA[2] - inB[2];
return (float) java.lang.Math.sqrt(dx * dx + dy * dy + dz * dz);
}
public static float dotProduct(final float[] inA, final float[] inB) {
return inA[0] * inB[0] + inA[1] * inB[1] + inA[2] * inB[2];
}
public static void crossProduct(final float[] out, final float[] inA, final float[] inB) {
final float crossX = inA[1] * inB[2] - inB[1] * inA[2];
final float crossY = inA[2] * inB[0] - inB[2] * inA[0];
final float crossZ = inA[0] * inB[1] - inB[0] * inA[1];
out[0] = crossX;
out[1] = crossY;
out[2] = crossZ;
}
public static void normalize(final float[] out) {
divide(out, magnitude(out));
}
public static void limit(final float[] out, final float max) {
if (magnitudeSqrt(out) > max * max) {
normalize(out);
multiply(out, max);
}
}
public static void setMagnitude(final float[] out, final float newMagnitude) {
normalize(out);
multiply(out, newMagnitude);
}
public static boolean equals(final float[] inA, final float[] inB) {
return inA[0] == inB[0] && inA[1] == inB[1] && inA[2] == inB[2];
}
public static String toString(final float[] in) {
final String x = String.valueOf(in[0]);
final String y = String.valueOf(in[1]);
final String z = String.valueOf(in[2]);
return "(" + x + ", " + y + ", " + z + ")";
}
}
package com.breel.gl.utils;
import java.nio.*;
import java.nio.Buffer;
import static android.opengl.GLES20.*;
public class VertexBuffer {
private final int mType;
private final int mMemberByteSize;
private final int mUsage;
private final int[] mHandlers;
private VertexBuffer(final int type, final int memberByteSize, final int usage) {
mType = type;
mMemberByteSize = memberByteSize;
mUsage = usage;
mHandlers = new int[1];
glGenBuffers(1, mHandlers, 0);
}
public void bind() {
glBindBuffer(mType, mHandlers[0]);
}
public void unbind() {
glBindBuffer(mType, 0);
}
public void update(final java.nio.Buffer data, final int offset) {
glBufferSubData(mType, offset, data.capacity() * mMemberByteSize, data);
}
public void dispose() {
glDeleteBuffers(1, mHandlers, 0);
}
public static VertexBuffer create(final int type, final Buffer buffer, final int usage) {
final int memberByteSize = buffer instanceof FloatBuffer ? Constants.BYTES_PER_FLOAT : Constants.BYTES_PER_SHORT;
final int totalByteSize = buffer.capacity() * memberByteSize;
final VertexBuffer vbo = new VertexBuffer(type, memberByteSize, usage);
vbo.bind();
glBufferData(type, totalByteSize, buffer, usage);
return vbo;
}
public static VertexBuffer create(final int type, final int mMemberByteSize, final int totalByteSize, final int usage) {
final VertexBuffer vbo = new VertexBuffer(type, mMemberByteSize, usage);
vbo.bind();
glBufferData(type, totalByteSize, null, usage);
return vbo;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment