/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * 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 2 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, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.jogl.old; import static org.andork.jogl.util.JoglUtils.checkGLError; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.andork.jogl.JoglBuffer; import org.andork.jogl.JoglDrawContext; import org.andork.jogl.util.JoglUtils; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GL3; public class BasicJOGLObject implements JOGLObject { public abstract class Attribute { protected String name; protected int bufferIndex; protected int divisor; public int getBufferIndex() { return bufferIndex; } public int getDivisor() { return divisor; } public String getName() { return name; } public abstract int getNumBytes(); public abstract void put(GL2ES2 gl, int stride, int offset); } public class Attribute1fv extends Attribute { public Attribute1fv bufferIndex(int bufferIndex) { this.bufferIndex = bufferIndex; return this; } @Override public int getNumBytes() { return 4; } public Attribute1fv name(String name) { this.name = name; return this; } public void put(float x) { vertexBuffers[bufferIndex].buffer().putFloat(x); } @Override public void put(GL2ES2 gl, int stride, int offset) { int location = gl.glGetAttribLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glEnableVertexAttribArray(location); checkGLError(gl); gl.glVertexAttribPointer(location, 1, GL.GL_FLOAT, false, stride, offset); checkGLError(gl); } } public class Attribute2fv extends Attribute { boolean normalized; public Attribute2fv bufferIndex(int bufferIndex) { this.bufferIndex = bufferIndex; return this; } public Attribute2fv divisor(int divisor) { this.divisor = divisor; return this; } @Override public int getNumBytes() { return 8; } public Attribute2fv name(String name) { this.name = name; return this; } public Attribute2fv normalized(boolean normalized) { this.normalized = normalized; return this; } public void put(float x, float y) { vertexBuffers[bufferIndex].buffer().putFloat(x).putFloat(y); } public void put(float[] values, int offset) { vertexBuffers[bufferIndex].buffer().putFloat(values[offset++]).putFloat(values[offset++]); } @Override public void put(GL2ES2 gl, int stride, int offset) { int location = gl.glGetAttribLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glEnableVertexAttribArray(location); checkGLError(gl); gl.glVertexAttribPointer(location, 2, GL.GL_FLOAT, normalized, stride, offset); checkGLError(gl); if (divisor > 0) { ((GL3) gl).glVertexAttribDivisor(location, divisor); } } } public class Attribute3fv extends Attribute { boolean normalized; public Attribute3fv bufferIndex(int bufferIndex) { this.bufferIndex = bufferIndex; return this; } public Attribute3fv divisor(int divisor) { this.divisor = divisor; return this; } @Override public int getNumBytes() { return 12; } public Attribute3fv name(String name) { this.name = name; return this; } public Attribute3fv normalized(boolean normalized) { this.normalized = normalized; return this; } public void put(float x, float y, float z) { vertexBuffers[bufferIndex].buffer().putFloat(x).putFloat(y).putFloat(z); } public void put(float[] values, int offset) { vertexBuffers[bufferIndex].buffer().putFloat(values[offset++]).putFloat(values[offset++]) .putFloat(values[offset++]); } @Override public void put(GL2ES2 gl, int stride, int offset) { int location = gl.glGetAttribLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glEnableVertexAttribArray(location); checkGLError(gl); gl.glVertexAttribPointer(location, 3, GL.GL_FLOAT, normalized, stride, offset); checkGLError(gl); if (divisor > 0) { ((GL3) gl).glVertexAttribDivisor(location, divisor); checkGLError(gl); } } } public class Attribute4fv extends Attribute { boolean normalized; public Attribute4fv bufferIndex(int bufferIndex) { this.bufferIndex = bufferIndex; return this; } @Override public int getNumBytes() { return 16; } public Attribute4fv name(String name) { this.name = name; return this; } public Attribute4fv normalized(boolean normalized) { this.normalized = normalized; return this; } public void put(float x, float y, float z, float w) { vertexBuffers[bufferIndex].buffer().putFloat(x).putFloat(y).putFloat(z).putFloat(w); } public void put(float[] values, int offset) { vertexBuffers[bufferIndex].buffer().putFloat(values[offset++]).putFloat(values[offset++]) .putFloat(values[offset++]).putFloat(values[offset++]); } @Override public void put(GL2ES2 gl, int stride, int offset) { int location = gl.glGetAttribLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glEnableVertexAttribArray(location); checkGLError(gl); gl.glVertexAttribPointer(location, 4, GL.GL_FLOAT, normalized, stride, offset); checkGLError(gl); } } public static class BasicVertexShader { int posDim = 3; boolean passPosToFragmentShader = false; public BasicVertexShader passPosToFragmentShader(boolean passPosToFragmentShader) { this.passPosToFragmentShader = passPosToFragmentShader; return this; } public BasicVertexShader posDim(int posDim) { this.posDim = posDim; return this; } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("uniform mat4 m;"); sb.append("uniform mat4 v;"); sb.append("uniform mat4 p;"); sb.append("attribute vec").append(posDim).append(" a_pos;"); if (passPosToFragmentShader) { sb.append("varying vec").append(posDim).append(" v_pos;"); } sb.append("void main() {"); sb.append(" mat4 mvp = p*v*m;"); switch (posDim) { case 2: sb.append(" gl_Position = mvp * vec4(a_pos, 0.0, 1.0);"); break; case 3: sb.append(" gl_Position = mvp * vec4(a_pos, 1.0);"); break; case 4: sb.append(" gl_Position = mvp * a_pos;"); break; } sb.append(" gl_Position.z += 0.05;"); if (passPosToFragmentShader) { sb.append(" v_pos = vec3(a_pos);"); } sb.append("}"); return sb.toString(); } } /** * Shades according to normal, u, and v vectors on the object. Normals * facing the camera are red, facing away are cyan. u facing the camera are * green, facing away are magenta. v facing the camera are blue, facing away * are yellow. * * @author Andy */ public static class DebugUVNFragmentShader { @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("varying vec3 v_vmpos;"); sb.append("varying vec3 v_norm;"); sb.append("varying vec3 v_u;"); sb.append("varying vec3 v_v;"); sb.append("void main() {"); sb.append(" vec3 topos = normalize(v_vmpos);"); sb.append(" float norm = dot(v_norm, topos);"); sb.append(" float u = dot(v_u, topos);"); sb.append(" float v = dot(v_v, topos);"); sb.append(" vec4 color = vec4(0.0, 0.0, 0.0, 1.0);"); sb.append(" if (norm > 0.0) {"); sb.append(" color += vec4(norm, 0.0, 0.0, 0.0);"); sb.append(" }"); sb.append(" else {"); sb.append(" color += vec4(0.0, -norm, -norm, 0.0);"); sb.append(" }"); sb.append(" if (u > 0.0) {"); sb.append(" color += vec4(0.0, u, 0.0, 0.0);"); sb.append(" }"); sb.append(" else {"); sb.append(" color += vec4(-u, 0.0, -u, 0.0);"); sb.append(" }"); sb.append(" if (v > 0.0) {"); sb.append(" color += vec4(0.0, 0.0, v, 0.0);"); sb.append(" }"); sb.append(" else {"); sb.append(" color += vec4(-v, -v, 0.0, 0.0);"); sb.append(" }"); sb.append(" gl_FragColor = color;"); sb.append("}"); return sb.toString(); } } public static class DebugUVNVertexShader { @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("uniform mat4 m, v, p;"); sb.append("uniform mat3 n;"); sb.append("attribute vec3 a_pos;"); sb.append("attribute vec3 a_norm;"); sb.append("attribute vec3 a_u;"); sb.append("attribute vec3 a_v;"); sb.append("varying vec3 v_vmpos;"); sb.append("varying vec3 v_norm;"); sb.append("varying vec3 v_u;"); sb.append("varying vec3 v_v;"); sb.append("void main(void)"); sb.append("{"); sb.append(" v_vmpos = (v * m * vec4(a_pos, 1.0)).xyz;"); sb.append(" v_norm = (v * vec4(n * a_norm, 0.0)).xyz;"); sb.append(" v_u = (v * vec4(n * a_u, 0.0)).xyz;"); sb.append(" v_v = (v * vec4(n * a_v, 0.0)).xyz;"); sb.append(" gl_Position = p * v * m * vec4(a_pos, 1.0);"); sb.append("}"); return sb.toString(); } } public static class DepthFragmentShader { final float[] farColor = { 0.1f, 0.1f, 0.1f, 1f }; final float[] nearColor = { 1f, 1f, 1f, 1f }; final float[] center = { 0, 0, 0 }; float radius = 1; public DepthFragmentShader center(float x, float y, float z) { center[0] = x; center[1] = y; center[2] = z; return this; } public DepthFragmentShader farColor(float r, float g, float b, float a) { farColor[0] = r; farColor[1] = g; farColor[2] = b; farColor[3] = a; return this; } public DepthFragmentShader nearColor(float r, float g, float b, float a) { nearColor[0] = r; nearColor[1] = g; nearColor[2] = b; nearColor[3] = a; return this; } public DepthFragmentShader radius(float radius) { if (radius < 0) { throw new IllegalArgumentException("radius must be >= 0"); } this.radius = radius; return this; } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("uniform mat4 m;"); sb.append("uniform mat4 v;"); sb.append("uniform mat4 p;"); sb.append("varying vec3 v_pos;"); sb.append("void main() {"); sb.append(" float center_depth = (v * m * vec4("); sb.append(format("%.4f", center[0], center[1], center[2], 1f)).append(")).z;"); sb.append(" float radius = ").append(format("%.4f", radius)).append(";"); sb.append(" float frag_depth = (v * m * vec4(v_pos, 1.0)).z;"); sb.append(" float f;"); sb.append(" if (frag_depth > center_depth + radius) { f = 1.0; }"); sb.append(" else if (frag_depth < center_depth - radius) { f = 0.0; }"); sb.append(" else { f = (frag_depth - center_depth + radius) / (radius * 2.0); }"); sb.append(" gl_FragColor = mix(vec4(").append(format("%.4f", farColor)).append("), "); sb.append("vec4(").append(format("%.4f", nearColor)).append("), f);"); sb.append("}"); return sb.toString(); } } public static class DistanceFragmentShader { @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("uniform mat4 m;"); sb.append("uniform mat4 v;"); sb.append("uniform mat4 p;"); sb.append("uniform float nearDist;"); sb.append("uniform vec4 nearColor;"); sb.append("uniform float farDist;"); sb.append("uniform vec4 farColor;"); sb.append("varying vec3 v_pos;"); sb.append("void main() {"); sb.append(" float frag_depth = -(v * m * vec4(v_pos, 1.0)).z;"); sb.append(" float f;"); sb.append(" if (frag_depth > farDist) { f = 1.0; }"); sb.append(" else if (frag_depth < nearDist) { f = 0.0; }"); sb.append(" else { f = (frag_depth - nearDist) / (farDist - nearDist); }"); sb.append(" gl_FragColor = mix(nearColor, farColor, f); "); sb.append("}"); return sb.toString(); } } public static class FlatFragmentShader { final float[] color = { 1f, 1f, 1f, 1f }; public FlatFragmentShader color(float r, float g, float b, float a) { color[0] = r; color[1] = g; color[2] = b; color[3] = a; return this; } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("void main() {"); sb.append(" gl_FragColor = vec4("); sb.append(String.format("%.4f", color[0])); for (int i = 1; i < 4; i++) { sb.append(String.format(", %.4f", color[i])); } sb.append(");"); sb.append("}"); return sb.toString(); } } public static class PerVertexDiffuseVertexShader { int nlights = 1; @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("uniform mat4 m, v, p;"); sb.append("uniform mat3 n;"); sb.append("attribute vec3 a_pos;"); sb.append("attribute vec3 a_norm;"); sb.append("uniform vec4 u_color;"); sb.append("varying vec4 v_color;"); sb.append("uniform int u_nlights;"); sb.append("uniform vec4 u_lightpos[").append(nlights).append("];"); sb.append("uniform vec4 u_lightcolor[").append(nlights).append("];"); sb.append("uniform float u_constantAttenuation[").append(nlights).append("];"); sb.append("uniform float u_linearAttenuation[").append(nlights).append("];"); sb.append("uniform float u_quadraticAttenuation[").append(nlights).append("];"); sb.append("void main(void)"); sb.append("{"); sb.append(" mat4 mvp = p*v*m;"); sb.append(" vec3 normalDirection = normalize(n * a_norm);"); sb.append(" vec3 lightDirection;"); sb.append(" float attenuation;"); sb.append(" v_color = vec4(0.0, 0.0, 0.0, 1.0);"); sb.append(" for (int i = 0; i < u_nlights; i++) {"); sb.append(" if (u_lightpos[i].w == 0.0)"); sb.append(" {"); sb.append(" attenuation = 1.0;"); sb.append(" lightDirection = normalize(vec3(u_lightpos[i]));"); sb.append(" }"); sb.append(" else"); sb.append(" {"); sb.append(" vec3 vertexToLightSource = vec3(u_lightpos[i] - m * vec4(a_pos, 1.0));"); sb.append(" float distance = length(vertexToLightSource);"); sb.append(" lightDirection = normalize(vertexToLightSource);"); sb.append(" attenuation = 1.0 / (u_constantAttenuation[i]"); sb.append(" + u_linearAttenuation[i] * distance"); sb.append(" + u_quadraticAttenuation[i] * distance * distance);"); sb.append(" }"); sb.append(" vec3 diffuseReflection = attenuation"); sb.append(" * vec3(u_lightcolor[i]) * vec3(u_color)"); sb.append(" * max(0.0, dot(normalDirection, lightDirection));"); sb.append(" v_color += vec4(diffuseReflection, 0.0);"); sb.append(" }"); sb.append(" gl_Position = mvp * vec4(a_pos, 1.0);"); sb.append("}"); return sb.toString(); } } public class PlaceholderAttribute extends Attribute { int numBytes; public PlaceholderAttribute(int numBytes) { super(); this.numBytes = numBytes; } @Override public int getNumBytes() { return numBytes; } @Override public void put(GL2ES2 gl, int stride, int offset) { } } public static abstract class Uniform { protected String name; public String getName() { return name; } public abstract void put(GL2ES2 gl, int program, boolean ignoreMissingLocations); } public static class Uniform1fv extends Uniform { int count = 1; float[] value; int value_offset; public int count() { return count; } public Uniform1fv count(int count) { this.count = count; return this; } public Uniform1fv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniform1fv(location, count, value, value_offset); checkGLError(gl); } public float[] value() { return value; } public Uniform1fv value(float... value) { this.value = value; return this; } public Uniform1fv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class Uniform1iv extends Uniform { int count = 1; int[] value; int value_offset; public Uniform1iv count(int count) { this.count = count; return this; } public Uniform1iv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniform1iv(location, count, value, value_offset); checkGLError(gl); } public Uniform1iv value(int... value) { this.value = value; return this; } public Uniform1iv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class Uniform2fv extends Uniform { int count = 1; float[] value; int value_offset; public int count() { return count; } public Uniform2fv count(int count) { this.count = count; return this; } public Uniform2fv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniform2fv(location, count, value, value_offset); checkGLError(gl); } public float[] value() { return value; } public Uniform2fv value(float... value) { this.value = value; return this; } public Uniform2fv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class Uniform3fv extends Uniform { int count = 1; float[] value; int value_offset; public int count() { return count; } public Uniform3fv count(int count) { this.count = count; return this; } public Uniform3fv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniform3fv(location, count, value, value_offset); checkGLError(gl); } public float[] value() { return value; } public Uniform3fv value(float... value) { this.value = value; return this; } public Uniform3fv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class Uniform4fv extends Uniform { int count = 1; float[] value; int value_offset; public int count() { return count; } public Uniform4fv count(int count) { this.count = count; return this; } public Uniform4fv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniform4fv(location, count, value, value_offset); checkGLError(gl); } public float[] value() { return value; } public Uniform4fv value(float... value) { this.value = value; return this; } public Uniform4fv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class UniformMatrix4fv extends Uniform { int count; boolean transpose; float[] value; int value_offset; public UniformMatrix4fv count(int count) { this.count = count; return this; } public UniformMatrix4fv name(String name) { this.name = name; return this; } @Override public void put(GL2ES2 gl, int program, boolean ignoreMissingLocations) { int location = gl.glGetUniformLocation(program, name); checkGLError(gl); if (ignoreMissingLocations && location < 0) { return; } gl.glUniformMatrix4fv(location, count, transpose, value, value_offset); checkGLError(gl); } public UniformMatrix4fv transpose(boolean transpose) { this.transpose = transpose; return this; } public UniformMatrix4fv value(float[] value) { this.value = value; return this; } public UniformMatrix4fv value_offset(int value_offset) { this.value_offset = value_offset; return this; } } public static class VaryingColorFragmentShader { @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("varying vec4 v_color;"); sb.append("void main() {"); sb.append(" gl_FragColor = v_color;"); sb.append("}"); return sb.toString(); } } private static String format(String valueFormat, float... values) { StringBuffer sb = new StringBuffer(); if (values.length > 0) { sb.append(String.format(valueFormat, values[0])); } for (int i = 1; i < values.length; i++) { sb.append(", "); sb.append(String.format(valueFormat, values[i])); } return sb.toString(); } JoglBuffer[] vertexBuffers = new JoglBuffer[0]; int[] offsets; int[] strides; int vertexCount; JoglBuffer indexBuffer; int indexCount; int indexType; int program; int vertexShader; int fragmentShader; String vertexShaderCode; String fragmentShaderCode; String modelMatrixName = "m"; String normalMatrixName = null; String viewMatrixName = "v"; String projMatrixName = "p"; boolean transpose = false; final List<Uniform> uniforms = new ArrayList<Uniform>(); final List<Attribute> attributes = new ArrayList<Attribute>(); final List<JOGLModifier> modifiers = new ArrayList<JOGLModifier>(); int drawMode; private boolean initialized = false; boolean ignoreMissingLocations = false; public BasicJOGLObject add(Attribute attribute) { attributes.add(attribute); return this; } public BasicJOGLObject add(JOGLModifier modifier) { modifiers.add(modifier); return this; } public BasicJOGLObject add(Uniform uniform) { uniforms.add(uniform); return this; } public BasicJOGLObject addVertexBuffer(ByteBuffer newBuffer) { return addVertexBuffer(new JoglBuffer().buffer(newBuffer)); } public ByteBuffer addVertexBuffer(int capacity) { ByteBuffer newBuffer = ByteBuffer.allocateDirect(capacity); newBuffer.order(ByteOrder.nativeOrder()); addVertexBuffer(newBuffer); return newBuffer; } public BasicJOGLObject addVertexBuffer(JoglBuffer newBuffer) { vertexBuffers = Arrays.copyOf(vertexBuffers, vertexBuffers.length + 1); vertexBuffers[vertexBuffers.length - 1] = newBuffer; return this; } @Override public void destroy(GL2ES2 gl) { if (initialized) { for (JoglBuffer buffer : vertexBuffers) { buffer.dispose(gl); } if (indexBuffer != null) { indexBuffer.dispose(gl); } if (vertexShaderCode != null && fragmentShaderCode != null) { gl.glDetachShader(program, vertexShader); gl.glDetachShader(program, fragmentShader); gl.glDeleteShader(vertexShader); gl.glDeleteShader(fragmentShader); gl.glDeleteProgram(program); } initialized = false; } } @Override public void draw(GL2ES2 gl, float[] m, float[] n, float[] v, float[] p) { gl.glUseProgram(program); for (JOGLModifier modifier : modifiers) { modifier.beforeDraw(gl, this); } for (Uniform uniform : uniforms) { uniform.put(gl, program, ignoreMissingLocations); } if (modelMatrixName != null) { int m_location = gl.glGetUniformLocation(program, modelMatrixName); gl.glUniformMatrix4fv(m_location, 1, transpose, m, 0); } if (viewMatrixName != null) { int m_location = gl.glGetUniformLocation(program, viewMatrixName); gl.glUniformMatrix4fv(m_location, 1, transpose, v, 0); } if (projMatrixName != null) { int m_location = gl.glGetUniformLocation(program, projMatrixName); gl.glUniformMatrix4fv(m_location, 1, transpose, p, 0); } if (normalMatrixName != null) { int n_location = gl.glGetUniformLocation(program, normalMatrixName); gl.glUniformMatrix3fv(n_location, 1, transpose, n, 0); } Arrays.fill(offsets, 0); for (Attribute attribute : attributes) { int bi = attribute.getBufferIndex(); int bytes = attribute.getNumBytes(); gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexBuffers[bi].id()); checkGLError(gl); attribute.put(gl, strides[bi], offsets[bi]); offsets[bi] += bytes; } if (indexBuffer != null) { gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.id()); gl.glDrawElements(drawMode, indexCount, indexType, 0); gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); } else { gl.glDrawArrays(drawMode, 0, vertexCount); } gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); for (JOGLModifier modifier : modifiers) { modifier.afterDraw(gl, this); } } @Override public void draw(JoglDrawContext context, GL2ES2 gl, float[] m, float[] n) { draw(gl, m, n, context.viewXform(), context.projXform()); } public BasicJOGLObject drawMode(int drawMode) { this.drawMode = drawMode; return this; } public BasicJOGLObject fragmentShaderCode(String fragmentShaderCode) { this.fragmentShaderCode = fragmentShaderCode; return this; } public int getProgram() { return program; } public BasicJOGLObject ignoreMissingLocations(boolean ignoreMissingLocations) { this.ignoreMissingLocations = ignoreMissingLocations; return this; } public JoglBuffer indexBuffer() { return indexBuffer; } public BasicJOGLObject indexBuffer(ByteBuffer newBuffer) { return indexBuffer(new JoglBuffer().target(GL.GL_ELEMENT_ARRAY_BUFFER).buffer(newBuffer)); } public BasicJOGLObject indexBuffer(JoglBuffer newBuffer) { indexBuffer = newBuffer; return this; } public BasicJOGLObject indexCount(int indexCount) { this.indexCount = indexCount; return this; } public BasicJOGLObject indexType(int indexType) { this.indexType = indexType; return this; } @Override public void init(GL2ES2 gl) { if (initialized) { return; } initialized = true; if (vertexShaderCode != null && fragmentShaderCode != null) { vertexShader = JoglUtils.loadShader(gl, GL2ES2.GL_VERTEX_SHADER, vertexShaderCode); fragmentShader = JoglUtils.loadShader(gl, GL2ES2.GL_FRAGMENT_SHADER, fragmentShaderCode); program = JoglUtils.loadProgram(gl, vertexShader, fragmentShader); } int[] temp = new int[1]; for (JoglBuffer buffer : vertexBuffers) { buffer.init(gl); } rebufferVertices(gl); offsets = new int[vertexBuffers.length]; strides = new int[vertexBuffers.length]; for (Attribute attribute : attributes) { int bi = attribute.getBufferIndex(); int bytes = attribute.getNumBytes(); strides[bi] += bytes; } // for( Attribute attribute : attributes ) // { // int bi = attribute.getBufferIndex( ); // int bytes = attribute.getNumBytes( ); // // gl.glBindBuffer( GL2ES2.GL_ARRAY_BUFFER , vertexBuffers[ bi ].id( ) // ); // // attribute.put( gl , strides[ bi ] , offsets[ bi ] ); // // offsets[ bi ] += bytes; // } if (indexBuffer != null) { indexBuffer.init(gl); } gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); } public BasicJOGLObject modelMatrixName(String modelMatrixName) { this.modelMatrixName = modelMatrixName; return this; } public BasicJOGLObject normalMatrixName(String normalMatrixName) { this.normalMatrixName = normalMatrixName; return this; } public BasicJOGLObject program(int program) { this.program = program; return this; } public BasicJOGLObject projMatrixName(String projMatrixName) { this.projMatrixName = projMatrixName; return this; } public void rebufferVertices(GL2ES2 gl) { for (JoglBuffer buffer : vertexBuffers) { buffer.rebuffer(gl); } } public BasicJOGLObject transpose(boolean transpose) { this.transpose = transpose; return this; } public ByteBuffer vertexBuffer(int index) { return vertexBuffers[index].buffer(); } public BasicJOGLObject vertexBuffer(int index, ByteBuffer newBuffer) { vertexBuffers[index].buffer(newBuffer); return this; } public BasicJOGLObject vertexCount(int vertexCount) { this.vertexCount = vertexCount; return this; } public BasicJOGLObject vertexShaderCode(String vertexShaderCode) { this.vertexShaderCode = vertexShaderCode; return this; } public BasicJOGLObject viewMatrixName(String viewMatrixName) { this.viewMatrixName = viewMatrixName; return this; } }