OpenGL ES 2.0 doesn't draw anything - java
I have a problem with OpenGl ES 2.0. I've designed a very simple framework to help me load OBJ files and draw them on my Android phone, but I have 2 bugs that I haven't been able to fix:
My app doesn't show anything until I change the orientation and the Activity gets scraped and reloaded. Until it reloads only GLES20.glClear() can be seen(I've set it to a grayish color).
Sometimes when I load an OBJ and do the orientation trick, half of my faces are missing and I see gaps, but the problem might be with the OBJ files I've used.
package com.ideas.opengl;
import java.io.IOException;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.Matrix;
public class DemoRenderer implements Renderer {
public static int mProgramHandle;
private int mMVPMatrixHandle;
private float[] mModelMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private float[] mMVPMatrix = new float[16];
public Object banana;
private OpenGLDemoActivity activity;
private int angle;
public DemoRenderer(OpenGLDemoActivity activity) throws IOException {
this.activity = activity;
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config){
GLES20.glClearColor(0.65f, 0.65f, 0.65f, 0.65f);
//GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
Shader shader = null;
try {
shader = new Shader(activity, "simple");
} catch (IOException e) {
e.printStackTrace();
}
Vector position = new Vector();
Vector speed = new Vector();
Vector accel = new Vector();
Model model = null;
try {
model = new Model("banana", activity);
} catch (IOException e) {
e.printStackTrace();
}
banana = new Object(position, speed, accel, model);
mProgramHandle = shader.getProgramHandle();
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 3.5f;
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
#Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
angle++;
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, angle, 0.0f, 1.0f, 1.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
banana.draw();
}
}
`
Tried some glGetError() and got to errors, one regarding a variable that had its value unchanged and another was that glGetAttributeLocation() return a -1 if the attribute is not used in the vertex shader. Thaks for the help!
The problem with the geometry is likely due to using the same float array for input and output in the matrix multiplication:
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
According to the multiplyMM() specs the input and output arrays may not have overlapping elements, but you use the same array mMVPMatrix starting with the same index 0. One way to fix the problem is to use another matrix as a buffer for the result of the last multiplication, so instead of:
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
use:
Matrix.multiplyMM(mMatrixFinal, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMatrixFinal, 0);
Related
GP/GPU : ping pong technique with JOGL
I've tried to implement an reaction-diffusion model on GPU with JOGL and GLSL. I use a ping pong technique with 2 FramebufferObject ( I've tried too with one FBO and 2 Colors attachements without success). Shader seems correct since I've tried it in unity (with some adaptations) and it works. After one week of trying many things, i'm completely out of idea to make this code works. I'm really not specialist of JOGL, so maybe i miss something evident. The result is an image which becomes white with time : no reaction-diffusion behaviors and I don't understand why ! Thanks in advance for helps. Here is my code : package gpu2; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.nio.IntBuffer; import java.nio.FloatBuffer; import java.io.File; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.glu.GLU; import com.jogamp.opengl.util.FPSAnimator; import com.jogamp.opengl.GLFBODrawable; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Colorbuffer; import com.jogamp.opengl.FBObject.ColorAttachment; import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.glsl.ShaderUtil; import com.jogamp.opengl.util.GLBuffers; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLOffscreenAutoDrawable; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil; import com.jogamp.opengl.GLDrawableFactory; import static com.jogamp.opengl.GL.*; // GL constants import static com.jogamp.opengl.GL2.*; // GL2 constants import gpu2.ModelParam; /** * JOGL 2.0 Program Template (GLCanvas) * This is a "Component" which can be added into a top-level "Container". * It also handles the OpenGL events to render graphics. */ #SuppressWarnings("serial") public class JOGL2Setup_GLCanvas extends GLCanvas implements GLEventListener { // Define constants for the top-level container private static String TITLE = "JOGL 2.0 Setup (GLCanvas)"; // window's title private static final int CANVAS_WIDTH = 512; // width of the drawable private static final int CANVAS_HEIGHT = 512; // height of the drawable private static final int FPS = 30; // animator's target frames per second private final float[] canvasVertices = { -1f, -1f, 0.0f, -1f, 1f, 0.0f, 1f, -1f, 0.0f, 1f, 1f, 0.0f, }; private final float[] canvasTexCoords = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; /** The entry main() method to setup the top-level container and animator */ public static void main(String[] args) { // Run the GUI codes in the event-dispatching thread for thread safety SwingUtilities.invokeLater(new Runnable() { #Override public void run() { // Create the OpenGL rendering canvas GLCanvas canvas = new JOGL2Setup_GLCanvas(); canvas.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT)); // Create a animator that drives canvas' display() at the specified FPS. final FPSAnimator animator = new FPSAnimator(canvas, FPS, true); // Create the top-level container final JFrame frame = new JFrame(); // Swing's JFrame or AWT's Frame frame.getContentPane().add(canvas); frame.addWindowListener(new WindowAdapter() { #Override public void windowClosing(WindowEvent e) { // Use a dedicate thread to run the stop() to ensure that the // animator stops before program exits. new Thread() { #Override public void run() { if (animator.isStarted()) animator.stop(); System.exit(0); } }.start(); } }); frame.setTitle(TITLE); frame.pack(); frame.setVisible(true); animator.start(); // start the animation loop } }); } // Setup OpenGL Graphics Renderer private GLU glu; // for the GL Utility private GL2 gl; //OpenGl data private int vboVertices; private int vboTextCoord; private Texture textureFile; private FBObject fbo[]; private ShaderProgram shaderCompute; private ShaderProgram shaderVisu; private ShaderProgram shaderComputeInit; private int currentSourceBuffer = 0; private int currentDestBuffer = 1; private int currentFrame = 0; private int maxFrameCount = 5000000; private float clearUniform = 0; ModelParam params = new ModelParam(); public JOGL2Setup_GLCanvas() { this.addGLEventListener(this); } #Override public void init(GLAutoDrawable drawable) { gl = drawable.getGL().getGL2(); // get the OpenGL graphics context glu = new GLU(); // get GL Utilities gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // set background (clear) color gl.glEnable(GL_TEXTURE_2D); gl.glEnable( GL_COLOR_MATERIAL ); gl.glEnable( GL_FRAMEBUFFER ); gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NEAREST); // best perspective correction viewOrtho(gl); gl.glViewport(0,0,CANVAS_WIDTH,CANVAS_HEIGHT); int[] buffers = new int[2]; gl.glGenBuffers(2, buffers, 0); vboVertices = buffers[0]; vboTextCoord = buffers[1]; gl.glBindBuffer(GL_ARRAY_BUFFER, vboVertices); gl.glBufferData(GL_ARRAY_BUFFER, canvasVertices.length*(Float.SIZE/Byte.SIZE)*3, FloatBuffer.wrap(canvasVertices), GL_STATIC_DRAW); gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glBufferData(GL_ARRAY_BUFFER, canvasTexCoords.length*(Float.SIZE/Byte.SIZE)*2, FloatBuffer.wrap(canvasTexCoords), GL_STATIC_DRAW); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); // ------------ create Texture Source------------------------ textureFile = initializeTexture(); if (textureFile==null) { System.out.println("cannot load texture from disk"); } // ------------ load shaders ------------------------ shaderCompute = loadShader(gl, "compute.vsh", "compute.fsh"); shaderComputeInit = loadShader(gl, "compute.vsh", "computeInit.fsh"); shaderVisu = loadShader(gl, "visu.vsh", "visu.fsh"); // ------------ create FBO ------------------------ initFBO(); } /** * Called back by the animator to perform rendering. */ #Override public void display(GLAutoDrawable drawable) { if (currentFrame < maxFrameCount) { prepareNextStep(); renderToFBO(); currentFrame++; } renderFBOToScreen(); } private void prepareNextStep() { currentSourceBuffer = 1 - currentSourceBuffer; currentDestBuffer = 1 - currentDestBuffer; } private void renderToFBO() { fbo[currentDestBuffer].bind(gl); //gl.glClear(GL_COLOR_BUFFER_BIT); viewOrtho(gl); shaderCompute.useProgram(gl, true); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseU", 0.211f); setShaderUniformFloat(gl, shaderCompute.program(), "diffuseV", 0.088f); setShaderUniformFloat(gl, shaderCompute.program(), "feed", 0.007f); setShaderUniformFloat(gl, shaderCompute.program(), "kill", 0.08f); setShaderUniformFloat(gl, shaderCompute.program(), "Tech", 1f); setShaderUniformFloat(gl, shaderCompute.program(), "currentFrame", currentFrame); setShaderUniformFloat2(gl, shaderCompute.program(), "resolution", CANVAS_WIDTH, CANVAS_HEIGHT); drawDataBuffer(shaderCompute, true); shaderCompute.useProgram(gl, false); fbo[currentDestBuffer].unbind(gl); } void drawDataBuffer(ShaderProgram currentShader, boolean sencondImage) { // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER,vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //activate texture data from last fbo final FBObject.Colorbuffer texSource = (FBObject.Colorbuffer) fbo[currentSourceBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, texSource.getName()); setShaderUniform1i(gl, currentShader.program(), "textureData", 0); if (sencondImage) { //activate texture with image from file gl.glActiveTexture(GL_TEXTURE1); gl.glBindTexture(GL_TEXTURE_2D, textureFile.getTextureObject()); textureFile.bind(gl); setShaderUniform1i(gl, currentShader.program(), "textureImage", 1); } //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); //disable texture image if (sencondImage) { gl.glActiveTexture(GL_TEXTURE1); textureFile.disable(gl); } //disable texture data gl.glActiveTexture(GL_TEXTURE0); gl.glDisable(texSource.getName()); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); } public void renderFBOToScreen() { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear color and depth buffers gl.glLoadIdentity(); // reset the model-view matrix viewOrtho(gl); gl.glEnable(GL_TEXTURE_2D); final FBObject.Colorbuffer tex0 = (FBObject.Colorbuffer) fbo[currentDestBuffer].getColorbuffer(0); gl.glActiveTexture(GL_TEXTURE0); gl.glBindTexture(GL_TEXTURE_2D, tex0.getName()); //activate shader shaderVisu.useProgram(gl, true); // --- draw vbo gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); //textcoords gl.glBindBuffer(GL_ARRAY_BUFFER, vboTextCoord); gl.glTexCoordPointer(2, GL_FLOAT, 0, 0); //vertices gl.glBindBuffer( GL_ARRAY_BUFFER, vboVertices ); gl.glVertexPointer(3, GL_FLOAT, 0, 0); //draw buffer on screens gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, canvasVertices.length / 3); gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL_VERTEX_ARRAY); gl.glBindBuffer( GL_ARRAY_BUFFER, 0 ); //desactivate shader shaderVisu.useProgram(gl, false); } private void initFBO() { try { gl.glEnable(GL_TEXTURE_2D); fbo = new FBObject[2]; //first fbo fbo[currentSourceBuffer] = new FBObject(); // Create FrameBuffer fbo[currentSourceBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentSourceBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentSourceBuffer].bind(gl); int tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentSourceBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //gl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); int DrawBuffers[] = {GL_COLOR_ATTACHMENT0}; gl.glDrawBuffers(1, DrawBuffers, 0); // "1" is the size of DrawBuffers fbo[currentSourceBuffer].unbind(gl); //second fbo fbo[currentDestBuffer] = new FBObject(); // Create FrameBuffer fbo[currentDestBuffer].init(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); fbo[currentDestBuffer].reset(gl, CANVAS_WIDTH, CANVAS_HEIGHT, 0); // int width, height - size of FBO, can be resized with the same call fbo[currentDestBuffer].bind(gl); tex = genTexture(gl); gl.glBindTexture(GL_TEXTURE_2D, tex); gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, CANVAS_WIDTH, CANVAS_HEIGHT, 0, GL_RGBA, GL_FLOAT, null); fbo[currentDestBuffer].attachTexture2D(gl, 0, GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); //ogl.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); gl.glDrawBuffers(1, DrawBuffers, 1); // "1" is the size of DrawBuffers fbo[currentDestBuffer].unbind(gl); } catch (Exception e) { System.out.println("Problem with fbo init " + e); e.printStackTrace(); } } private Texture initializeTexture() { Texture t = null; try { t = TextureIO.newTexture(new File("e:/shaders/wiki.jpg"), false); t.setTexParameteri(gl, GL_TEXTURE_MIN_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_MAG_FILTER, GL_LINEAR); t.setTexParameteri(gl, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); t.setTexParameteri(gl, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } catch (Exception e) { System.out.println("Unable to read texture file: " + e); e.printStackTrace(); } return t; } private ShaderProgram loadShader(GL2 gl, String vertexShader, String fragmentShader) { ShaderCode vertShader = ShaderCode.create(gl, GL2.GL_VERTEX_SHADER, 1, getClass(), new String[]{"e:/shaders/"+vertexShader},false); vertShader.compile(gl); ShaderCode fragShader = ShaderCode.create(gl, GL2.GL_FRAGMENT_SHADER, 1, getClass(), new String[]{"e:/shaders/"+fragmentShader},false); fragShader.compile(gl); ShaderProgram newShader = new ShaderProgram(); newShader.init(gl); newShader.add(vertShader); newShader.add(fragShader); newShader.link(gl, System.out); vertShader.destroy(gl); fragShader.destroy(gl); return newShader; } public static void setShaderUniform1i(GL2 inGL,int inProgramID,String inName,int inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1i(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat(GL2 inGL,int inProgramID,String inName,float inValue) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform1f(tUniformLocation, inValue); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } public static void setShaderUniformFloat2(GL2 inGL,int inProgramID,String inName,float inValue1 ,float inValue2) { int tUniformLocation = inGL.glGetUniformLocation(inProgramID,inName); if (tUniformLocation != -1) { inGL.glUniform2f(tUniformLocation, inValue1, inValue2); } else { System.out.println("UNIFORM COULD NOT BE FOUND! NAME="+inName); } } private void viewOrtho(GL2 gl) // Set Up An Ortho View { gl.glMatrixMode(GL_PROJECTION); // Select Projection gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix gl.glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); gl.glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix gl.glPushMatrix(); // Push The Matrix gl.glLoadIdentity(); // Reset The Matrix } private int genTexture(GL2 gl) { final int[] tmp = new int[1]; gl.glGenTextures(1, tmp, 0); return tmp[0]; } /** * Called back before the OpenGL context is destroyed. Release resource such as buffers. */ #Override public void dispose(GLAutoDrawable drawable) { } } And the corresponding GLSL Shader : #version 120 uniform sampler2D textureData; uniform sampler2D textureImage; uniform vec2 resolution; uniform float diffuseU; uniform float diffuseV; uniform float feed; uniform float kill; uniform float Tech = 1.0; uniform float currentFrame = 0.0; void main() { //coords vec2 position = ( gl_FragCoord.xy / resolution.xy ); vec2 pixel = 1./resolution; //get data from texture vec4 imgSource = texture2D(textureImage, gl_TexCoord[0].st); vec2 oldUV = texture2D(textureData, gl_TexCoord[0].st).rg; if(currentFrame<10){ if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.2f) oldUV = vec2(0.0,0.2); else if (distance(position,vec2(0.5,0.5 - currentFrame * 0.01f)) < 0.3f) oldUV = vec2(0.5,0.1); else oldUV = vec2(0.1,0.0); gl_FragColor = vec4(oldUV.rg, 0.0, 1.0); return; } //get neightboors vec2 dataUp = texture2D(textureData, position + pixel * vec2(0., 1.)).rg; vec2 dataDown = texture2D(textureData, position + pixel * vec2(0., -1.)).rg; vec2 dataLeft = texture2D(textureData, position + pixel * vec2(-1., 0.)).rg; vec2 dataRight = texture2D(textureData, position + pixel * vec2(1., 0.)).rg; //adapt parameters vec2 imgParam = imgSource.rg; float dU = diffuseU ;//+ 0.01 * (imgParam - 0.5); float dV = diffuseV ;//+ 0.01 * (imgParam - 0.5); float F = feed ;//+ 0.01 * (imgParam - 0.5); float K = kill ;//+ 0.01 * (imgParam - 0.5); //compute new values vec2 laplace = (dataUp+dataDown+dataLeft+dataRight) - 4.0 * oldUV; float uvv = oldUV.r * oldUV.g * oldUV.g; // calculate delta quantities float du = dU * laplace.r - uvv + F*(1.0 - oldUV.r); float dv = dV * laplace.g + uvv - (F+K)*oldUV.g; vec2 newUV = oldUV + vec2(du, dv)* Tech; gl_FragColor = vec4(newUV.rg, 0.0, 1.0); }
Few considerations: avoid deprecated OpenGL (and GLU), use GL4 (or GL3) unless you need awt/swt/swing, prefer newt, more here prefer Animator instead of FPSAnimator, more here prefer direct buffers instead of arrays, since otherwise jogl has to create them underneath and you can't keep trace (= deallocate when done) of those native allocations GL4 will allow you also to avoid all those uniform overhead (and also potential bugs) you have to deal with (especially during runtime), thanks to explicit locations prefer direct buffer management instead of FBObject for the moment unless you really know what FBObject is doing. Once you get it working, you can move on using that class. This may be (one of the) cause your code is not working, because something is not getting setup up as you need. Moreover, the lines of codes needed to replace FBObject are essentially the same (if you can't use explicit location for any reason) prefer some literal way to define the texture uniform location, it is usually another tricky part causing bugs, something like this prefer also a sampler for the textures, gives you more flexibility don't wait one week next time, let us know earlier! :) Frustation can be a nasty thing that put you down easily. Together we can help you getting it working ;)
Is it possible to draw more than one object using OpenGL ES 2.0
This is an update to a question I recently asked, but with new problems after I tried some stuff. What I want is to draw multiple circles on the screen. I created a class for the circle object. In my renderer class, I created an array list of these circles each with a different position. When called to draw, it only draws one of them. I logged what was going on and each object is being called to get drawn, but it seems only one appears on the screen. It's not just my circles. It appears throughout personal testing OpenGL ES 2.0 will only draw one object on the screen. I have no idea how to fix this. Is there something special I have to do in OpenGL ES 2.0? Here is my code. Ignore the incredibly sloppy and inefficient code right now. I am aware of it and will fix it later. Here is my circle object class: GLCircle: package com.background.gl.objects; import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.glDrawArrays; import static android.opengl.Matrix.multiplyMM; import static android.opengl.Matrix.setIdentityM; import static android.opengl.Matrix.translateM; import static com.background.gl.glcirclebackgroundanimation.Constants.BYTES_PER_FLOAT; import java.util.Random; import android.opengl.Matrix; import android.util.Log; import com.background.gl.data.VertexArray; import com.background.gl.helper.TextureShaderProgram; public class GLCircle { private static final int POSITION_COMPONENT_COUNT = 2; private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2; private static final int STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT; public float x; public float y; protected float[] wallBounds; protected boolean positiveX, positiveY; public boolean nullify; protected float xCounter = 0f; protected float yCounter = 0f; public float[] bounds; protected Random ran; private float[] VERTEX_DATA = { // Order of coordinates: X, Y, S, T // Triangle Fan 0f, 0f, 0.5f, 0.5f, -0.25f, -0.25f, 0f, 0.9f, 0.25f, -0.25f, 1f, 0.9f, 0.25f, 0.25f, 1f, 0.1f, -0.25f, 0.25f, 0f, 0.1f, -0.25f, -0.25f, 0f, 0.9f }; private final VertexArray vertexArray; public GLCircle(float x, float y) { vertexArray = new VertexArray(VERTEX_DATA); ran = new Random(); wallBounds = new float[4]; nullify = false; this.x = x; this.y = y; } public void bindData(TextureShaderProgram textureProgram) { //Bind the position data to the shader attribute vertexArray.setVertexAttribPointer( 0, textureProgram.getPositionAttributeLocation(), POSITION_COMPONENT_COUNT, STRIDE); //Bind the texture coordinate data to the shader attribute vertexArray.setVertexAttribPointer( POSITION_COMPONENT_COUNT, textureProgram.getTextureCoordinatesAttributeLocation(), TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE); } public void drawCircle() { glDrawArrays(GL_TRIANGLE_FAN, 0, 6); } public float getX() { return this.x; } public float getY() { return this.y; } public boolean isPositiveX() { return positiveX; } public boolean isPositiveY() { return positiveY; } public float[] getBounds(float ranX, float ranY) { if(!positiveX) { /*if(ranX >= 0f) { wallBounds[0] = 1.05f + ranX; } else {*/ this.wallBounds[0] = 1.05f + ranX; //} } else { /* if(ranX >= 0f) { wallBounds[0] = 1.05f - ranX; } else {*/ this.wallBounds[1] = 1.05f - ranX; //} } if(!positiveY) { this.wallBounds[2] = 1.75f + ranY; } else { this.wallBounds[3] = 1.75f - ranY; } return this.wallBounds; } public void setPos(float[] modelMatrix, float[] projectionMatrix, TextureShaderProgram textureProgram, int texture, float x, float y, String log) { setIdentityM(modelMatrix, 0); translateM(modelMatrix, 0, 0f, 0.01f, 0f); final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length); textureProgram.useProgram(); textureProgram.setUniforms(projectionMatrix, texture); bindData(textureProgram); drawCircle(); Log.d("Drawing", "Drawing " + log); } public void scaleCircle(float[] modelMatrix, float x, float y, float z) { Matrix.scaleM(modelMatrix, 0, x, y, z); } public void storeResults(float[] results) { this.x = results[0]; this.y = results[1]; } public void translateCircle(float x, float[] modelMatrix, float[] projectionMatrix) { setIdentityM(modelMatrix, 0); translateM(modelMatrix, 0, /*-0.001f*/ x, -3f, -2f); final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length); } } Again, I'm aware of most things I'm doing incorrectly, but currently I just need to figure out why I can't draw multiple objects on the screen. Here is my renderer code: package com.background.gl.glcirclebackgroundanimation; import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; import static android.opengl.GLES20.glClear; import static android.opengl.GLES20.glClearColor; import static android.opengl.GLES20.glViewport; import static android.opengl.Matrix.multiplyMM; import static android.opengl.Matrix.setIdentityM; import static android.opengl.Matrix.translateM; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView.Renderer; import android.util.Log; import com.background.gl.helper.TextureShaderProgram; import com.background.gl.objects.GLCircle; import com.background.gl.objects.Mallet; import com.background.gl.objects.Table; import com.background.gl.util.MatrixHelper; import com.background.gl.util.TextureHelper; public class CircleDynamicBackgroundRenderer implements Renderer { private final Context context; private final float[] projectionMatrix = new float[16]; private final float[] modelMatrix = new float[16]; protected static float ranX, ranY, ranSignX, ranSignY, ranSignVeloX, ranSignVeloY; public boolean logNums; private Table table; private Mallet mallet; private List<GLCircle> circles; private GLCircle circle2; float xPos, yPos; int x = 1; float[] bounds; Random ran; private TextureShaderProgram textureProgram; private int texture; public CircleDynamicBackgroundRenderer(Context context) { this.context = context; circles = new ArrayList<GLCircle>(); xPos = 0.1f; ran = new Random(); logNums = true; } #Override public void onSurfaceChanged(GL10 glUnused, int width, int height) { glViewport(0, 0, width, height); Log.w("Width and height", Integer.toString(width) + ", " + Integer.toString(height)); MatrixHelper.perspectiveM(projectionMatrix, 90, (float) width / (float) height, 1f, 10f); for(int i = 0; i < circles.size(); i++) { circles.get(i).translateCircle(circles.get(i).x, modelMatrix, projectionMatrix); } // /circle2.translateCircle(circle2.x, modelMatrix); /*final float[] temp = new float[16]; multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0); System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);*/ } #Override public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { glClearColor(0.0f, 0.0f, 1.0f, 0.0f); table = new Table(); mallet = new Mallet(); textureProgram = new TextureShaderProgram(context); texture = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface); //texture2 = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface_2); for(int i = 0; i < 3; i++) { GLCircle circle = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]); circles.add(circle); /*circle[i].x = circle[i].getX(); circle[i].y = circle[i].getY(); circle[i].bounds = circle[i].getBounds();*/ } //circle2 = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]); Log.d("Circles size", Integer.toString(circles.size())); Log.d("circles", Float.toString(circles.get(1).getX()) + " " + Float.toString(circles.get(2).getX())); } #Override public void onDrawFrame(GL10 glUnused) { //Clear the rendering surface glClear(GL_COLOR_BUFFER_BIT); for(int i = 0; i < circles.size(); i++) { circles.get(i).setPos(modelMatrix, projectionMatrix, textureProgram, texture, circles.get(i).x, circles.get(i).y, "1"); if(logNums) { Log.d("Circle1, c2", Float.toString(circles.get(i).x) + ", " + Float.toString(circles.get(i).x)); logNums = false; } //Log.d("Circles", Float.toString(circles.get(i).x)); } } public float[] generateRanFloats() { ranSignX = ran.nextFloat(); ranSignY = ran.nextFloat(); ranSignX = ranSignX > 0.5f? -1:1; ranSignY = ranSignY > 0.5f? -1:1; ranSignVeloX = ran.nextFloat(); ranSignVeloY = ran.nextFloat(); ranX = ran.nextFloat() * 1.05f; ranY = ran.nextFloat() * 1.75f; ranX = ranSignX > 0.5? -ranX:ranX; ranY = ranSignY > 0.5? -ranY:ranY; Log.d("Generated", Float.toString(ranX)); return new float[] {ranX, ranY}; } } It's been two days now and I cannot for the live of me figure out what is wrong and how to fix this. I really need to figure out a way to fix this. Any assistance will be greatly appreciated. If you need to see more code, let me know.
Per the last discussion - did you work on the perspective matrix ? I would recommend first starting with the ortho projection, get your code working, then move to working with perspective projection. You can use the below as a starting point for ortho projection. mat4.ortho(-1.0, 1.0, -1, 1.0, -10.0, 100.0, projectionMatrix); Also remove all the z translations in your code, make your code work on xy, then add z translations. PS: Isnt it better to continue in the same thread as (OpenGL ES 2.0 only draws the object once) ?
Android OpenGL ES 2.0: Text aren't showing up
I have adapted the code from Draw Text in OpenGL ES Android into my app, but the text isn't really showing up. Here's what it currently looks like: The green rectangle box is actually a Drawable bitmap. I am expecting some sort of text, either white or black on top of the background, but nothing is ever showing up. Here's the code for the Text class. package gl.es; import java.nio.*; import android.content.Context; import android.graphics.*; import android.graphics.drawable.Drawable; import android.opengl.*; import android.opengl.Matrix; public class Text { public int textTexture; public FloatBuffer textFloatBuffer; public FloatBuffer textureFloatBuffer; public int bufferSize; public int program; private final int textWidth = 112; private final int textHeight = 16; //private float posX; private int aTextPositionLocation; private int aTexturePositionLocation; private int uMatrixLocation; private int uTextureUnitLocation; public Text(Context context) { program = Shader.buildProgram(context, R.raw.text_vert, R.raw.text_frag); aTextPositionLocation = GLES20.glGetAttribLocation(program, "a_textPosition"); aTexturePositionLocation = GLES20.glGetAttribLocation(program, "a_texturePosition"); uMatrixLocation = GLES20.glGetUniformLocation(program, "u_matrix"); uTextureUnitLocation = GLES20.glGetUniformLocation(program, "u_textureUnit"); textTexture = createTexture(context); setBuffer(); //posX = 0f; } public int createTexture(Context context) { //Create empty mutable bitmap. Bitmap bitmap = Bitmap.createBitmap(textWidth, textHeight, Bitmap.Config.ARGB_8888); //Use Canvas to paint over it. Canvas canvas = new Canvas(bitmap); bitmap.eraseColor(0); //Draw background Drawable background = context.getResources().getDrawable(R.drawable.text_bg); background.setBounds(0, 0, 112, 16); background.draw(canvas); //Draw text Paint textPaint = new Paint(); textPaint.setTextSize(6f); textPaint.setAntiAlias(false); textPaint.setARGB(0xff, 0, 0, 0); //Draw text centered. canvas.drawText("Text.", 0, 0, textPaint); int[] texture = new int[1]; GLES20.glGenTextures(1, texture, 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); //Recycle. bitmap.recycle(); return texture[0]; } public void setBuffer() { final float[] vertexData = { 0f, 0f, textWidth, 0f, 0f, textHeight, 0f, textHeight, textWidth, 0f, textWidth, textHeight }; final float[] texData = { 0f, 1f, 1f, 1f, 0f, 0f, 0f, 0f, 1f, 1f, 1f, 0f }; textFloatBuffer = ByteBuffer.allocateDirect(vertexData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); textFloatBuffer.put(vertexData); textureFloatBuffer = ByteBuffer.allocateDirect(texData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); textureFloatBuffer.put(texData); bufferSize = vertexData.length / 2; } public void transform(float[] model, float[] projection, float[] mvp) { Matrix.setIdentityM(model, 0); Matrix.translateM(model, 0, 0f, 0f, -60f); Matrix.translateM(model, 0, -60f, 0f, 0f); Matrix.multiplyMM(mvp, 0, projection, 0, model, 0); //posX = (posX - 0.3f) % 112f; } public void setVertexPointers() { textFloatBuffer.position(0); GLES20.glVertexAttribPointer(aTextPositionLocation, 2, GLES20.GL_FLOAT, false, 2 * 4, textFloatBuffer); GLES20.glEnableVertexAttribArray(aTextPositionLocation); textFloatBuffer.position(0); textureFloatBuffer.position(0); GLES20.glVertexAttribPointer(aTexturePositionLocation, 2, GLES20.GL_FLOAT, false, 2 * 4, textureFloatBuffer); GLES20.glEnableVertexAttribArray(aTexturePositionLocation); textureFloatBuffer.position(0); } public void draw() { GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, bufferSize); } public void useProgram() { GLES20.glUseProgram(program); } public void setUniforms(float[] matrix) { GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textTexture); GLES20.glUniform1i(uTextureUnitLocation, 1); } } Could someone tell me where I'm doing wrong? What should I do in order to fix this? Thanks in advance. UPDATE 1: To answer deathember: This is what happens when I changed the Matrix.transformM() to what you have suggested: And here's the code that shows where I put my view matrix at: package gl.es; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.*; public class MyRenderer implements GLSurfaceView.Renderer { Context context; Text text; float eyeX; float eyeY; float eyeZ; private float[] modelMatrix; private float[] viewMatrix; private float[] projectionMatrix; private float[] modelViewProjectionMatrix; public MyRenderer(Context context) { this.context = context; modelMatrix = new float[16]; projectionMatrix = new float[16]; viewMatrix = new float[16]; modelViewProjectionMatrix = new float[16]; } #Override public void onSurfaceCreated(GL10 p1, EGLConfig config) { // TODO: Implement this method GLES20.glClearColor(0.4f, 0.8f, 1.0f, 1.0f); this.text = new Text(this.context); } #Override public void onSurfaceChanged(GL10 p1, int width, int height) { // TODO: Implement this method GLES20.glViewport(0, 0, width, height); this.setPerspectiveM(45f, (float) (width) / (float) (height), 1f, 200f); // Did not use view matrix at all for transformations of Text textures. Matrix.setLookAtM(viewMatrix, 0, 0, 0, 0, 0, 0, 0, 0, 1f, 0); //Unused. Matrix.setIdentityM(modelMatrix, 0); projectionMatrix, 0, modelMatrix, 0); } #Override public void onDrawFrame(GL10 p1) { // TODO: Implement this method GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); text.transform(modelMatrix, projectionMatrix, modelViewProjectionMatrix); text.useProgram(); text.setUniforms(modelViewProjectionMatrix); text.setVertexPointers(); text.draw(); } private void setPerspectiveM(float fov, float aspectRatio, float near, float far) { final float anglesInRadians = (float) (fov * Math.PI / 180f); final float angle = (float) (1f / Math.atan(anglesInRadians) / 2f); projectionMatrix[0] = angle / aspectRatio; projectionMatrix[1] = 0f; projectionMatrix[2] = 0f; projectionMatrix[3] = 0f; projectionMatrix[4] = 0f; projectionMatrix[5] = angle; projectionMatrix[6] = 0f; projectionMatrix[7] = 0f; projectionMatrix[8] = 0f; projectionMatrix[9] = 0f; projectionMatrix[10] = -((far + near) / (far - near)); projectionMatrix[11] = -1f; projectionMatrix[12] = 0f; projectionMatrix[13] = 0f; projectionMatrix[14] = -((2f * far * near) / (far - near)); projectionMatrix[15] = 0f; } } Hope that helps.
Try to change public void transform(float[] model, float[] projection, float[] mvp) { Matrix.setIdentityM(model, 0); Matrix.translateM(model, 0, 0f, 0f, -60f); Matrix.translateM(model, 0, -60f, 0f, 0f); Matrix.multiplyMM(mvp, 0, projection, 0, model, 0); //posX = (posX - 0.3f) % 112f; } into public void transform(float[] model, float[] projection, float[] mvp) { Matrix.setIdentityM(model, 0); Matrix.translateM(model, 0, 0f, 0f, 0f); Matrix.multiplyMM(mvp, 0, projection, 0, model, 0); //posX = (posX - 0.3f) % 112f; } And also set your view matrix look at center. May be you draw your text, but you can't see him. And where you set view matrix?
Add true inside view.getDrawingCache() as a parameter. Note that on some devices and hardwares, this will never work. I found this out the hard way.
rotate 3D object with finger in Android
her is my code help me how to implement touchlistner and rotate cube with finger.I have created separate class of cube where cube is drawn.And also class of MainActivity where SurfaceView is also declare and Renderer class is called from MainActivity . public class GLCubeRenderer implements Renderer { //private float oldX; //valor anterior de X, para rotaciĆ³n //private float oldY; //valor anterior de Y, para rotaciĆ³n private GLCube cube; static float ratio; private final float[] mAccumulatedRotation = new float[16]; private final float[] mCurrentRotation = new float[16]; float[] mModelMatrix; public GLCubeRenderer(){ cube = new GLCube(); } #Override public void onSurfaceCreated(GL10 gl, EGLConfig eglconfig) { gl.glDisable(GL10.GL_DITHER); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glClearColor(.8f, 0, .7f, 1); gl.glClearDepthf(1f); Matrix.setIdentityM(mAccumulatedRotation, 0); } #Override public void onDrawFrame(GL10 gl) { gl.glDisable(GL10.GL_DITHER); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 2, 0); long time =SystemClock.uptimeMillis() %4000L ; float angle = .090f *((int) time); gl.glRotatef(angle, 1, 0, 2); gl.glRotatef(angle, 0, 0, 1); cube.Draw(gl); } #Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); ratio = (float) width/height ; gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 1, 25); }
You can use jazzy view flipper. Here is the link https://github.com/jfeinstein10/JazzyViewPager
OpenGL ES Object is Displaying Strangely / Distorted - Android
EDIT OK - I grabbed a device and..guess what...it displays correctly ? Does anyone know why this would be happening on the simulator only ? Thank you. I am trying to draw an object using glDrawElements on Android. I am using the code below to read in my vertice and indice data and then draw the object in my render method. I am testing this on the simulator rather than a real device. This is my scene object code : import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; public class SceneObject { public FloatBuffer mVertexBuffer; public FloatBuffer mTextureBuffer; public ShortBuffer indexBuffer; public FloatBuffer mMatriceBuffer; public FloatBuffer mPivotBuffer; public short[] indicesTest = {0,1,2,3,4,5,3,5,6,7,5,8,7,8,9,10,7,9,11,10,9,12,1,0,13,12,14,15,13,14,14,10,11,15,14,11,0,14,12,16,17,18,19,16,18,18,20,19,21,16,19,22,21,19,22,19,23,4,24,25,25,26,27,25,27,28,4,25,28,5,4,28,5,28,8,29,30,31,29,31,19,29,19,20,32,33,31,32,31,30,32,34,33,35,22,23,36,35,23,37,36,23,37,23,38,39,37,38,40,39,38,41,40,38,41,38,1,42,41,1,12,43,1,42,1,43,17,27,26,26,18,17,44,45,46,46,47,44,48,49,50,51,52,53,53,54,51,55,51,54,54,56,55,57,48,50,50,58,57,52,59,60,60,53,52,59,44,47,47,60,59,61,62,63,63,64,61,65,66,67,67,68,65,69,70,71,71,72,69,66,69,72,72,67,66,73,65,68,68,74,73,70,75,76,76,71,70,75,61,64,64,76,75,77,78,79,79,80,77,81,82,62,62,61,81,83,81,61,61,75,83,84,63,62,62,82,84,63,84,85,86,87,88,89,90,91,92,93,87,87,86,92,94,95,96,96,97,94,98,99,100,100,101,98,102,103,104,104,105,102,106,107,108,108,109,106,110,111,112,78,77,113,114,115,78,112,111,116,117,118,115,119,116,120,121,122,123,123,124,121,125,126,127,127,128,125,129,130,131,132,133,5,5,133,6,5,134,135,135,134,136,134,137,136,137,138,136,129,139,130,139,140,141,140,142,141,137,141,138,141,142,138,141,130,139,143,144,145,144,146,145,147,145,146,144,148,146,148,149,146,146,149,150,151,132,152,153,152,154,154,152,155,152,132,155,132,5,155,155,5,135,156,157,158,158,157,146,146,157,147,159,160,158,158,160,156,34,160,159,149,161,150,161,162,150,162,163,150,150,163,164,163,165,164,165,166,164,166,167,164,164,167,129,167,168,129,169,139,129,129,168,169,154,143,153,145,153,143,170,171,172,173,172,171,174,175,176,177,178,179,180,179,178,178,181,180,182,180,181,175,183,176,184,176,183,185,177,186,179,186,177,171,185,173,186,173,185,187,188,189,190,189,188,191,192,193,194,193,192,195,196,197,198,197,196,196,191,198,193,198,191,192,199,194,200,194,199,201,195,202,197,202,195,188,201,190,202,190,201,203,204,205,206,205,204,207,208,187,188,187,208,208,209,188,201,188,209,189,210,187,207,187,210,210,189,211,212,213,214,215,216,217,218,219,220,221,220,219,222,223,224,225,226,227,228,229,230,231,230,229,232,233,234,235,236,237,238,239,240,241,242,243,123,244,124,245,246,203,204,203,246,247,248,203,249,250,251,252,253,247,248,247,253,159,33,34,254,255,256,256,257,254,255,244,123,123,256,255,244,258,121,121,124,244,259,260,125,125,128,259}; public float[] verticeTest = {20360.8f,20679.5f,611.547f,24248.7f,13527f,1074.93f,24207.4f,23005.5f,1503.19f,9819.59f,14845.7f,8.81875f,11126.3f,13982.2f,32.0718f,8379.01f,17678.5f,0.00115749f,8379.01f,15141.6f,0.00111471f,12137.8f,17973.8f,60.0461f,14591.9f,14509.2f,164.113f,15621.5f,15846.6f,223.075f,15136.7f,18549.5f,194.186f,16918.2f,16705.3f,310.215f,21081.8f,15846.6f,687.576f,19789f,16705.3f,554.435f,18467.9f,19868.7f,433.258f,18354.3f,17001.2f,423.539f,14591.9f,7402.34f,164.113f,13930.5f,9087.62f,131.015f,13039.7f,9096.18f,92.3283f,19110.4f,-8011.43f,490.311f,12811.7f,7228.03f,83.5128f,15621.5f,6064.9f,223.074f,16918.2f,5206.21f,310.215f,21807.5f,-426.492f,768.658f,11221.5f,13854f,34.3347f,12150f,12649.6f,60.4329f,12811.7f,10964.3f,83.513f,13702.6f,10955.8f,120.472f,13930.5f,12823.9f,131.015f,12150f,5542.76f,60.4327f,11119f,4205.31f,31.902f,15341.7f,-15792.9f,206.155f,9819.59f,3346.62f,8.81857f,10735.6f,-21752.5f,23.5976f,8379.01f,3050.73f,0.000981022f,18354.3f,4910.32f,423.538f,19789f,5206.21f,554.434f,21081.8f,6064.9f,687.576f,23336.1f,6399.27f,954.364f,22106.6f,7402.34f,803.393f,22764f,9087.62f,882.485f,22990.5f,10955.8f,910.595f,22764f,12823.9f,882.485f,22106.6f,14509.2f,803.393f,24248.7f,8492.36f,-3249.03f,24207.4f,17415.3f,-3297.97f,24207.4f,23005.5f,1503.19f,24248.7f,13527f,1074.93f,12728.3f,-24463.4f,-4243.56f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,19110.4f,-13046f,-3833.65f,21807.5f,-5461.09f,-3555.3f,21807.5f,-426.492f,768.658f,19110.4f,-8011.43f,490.311f,15341.7f,-20827.5f,-4117.81f,15341.7f,-15792.9f,206.155f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,23336.1f,1364.68f,-3369.59f,23336.1f,6399.27f,954.364f,24883.8f,8123.11f,-2819.08f,24859.5f,16025.8f,-2803.12f,24207.4f,17415.3f,-3297.97f,24248.7f,8492.36f,-3249.03f,13363.4f,-24832.7f,-3813.62f,15976.8f,-21196.8f,-3687.86f,15341.7f,-20827.5f,-4117.81f,12728.3f,-24463.4f,-4243.56f,19745.5f,-13415.3f,-3403.7f,22442.7f,-5830.35f,-3125.36f,21807.5f,-5461.09f,-3555.3f,19110.4f,-13046f,-3833.65f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,23222.6f,-2518.03f,-3057.67f,23336.1f,1364.68f,-3369.59f,10301.8f,-40240.8f,-15469.8f,10482f,-40907.1f,-14694f,10915.8f,-27847.5f,-3863.23f,10735.6f,-26787.1f,-4300.36f,25648.8f,8121.58f,-2817.31f,25624.5f,16024.2f,-2801.34f,24056.1f,-2550.94f,-3019.36f,25678.7f,16560.2f,-2907.29f,25594.2f,17951.2f,-3237.71f,25624.5f,-88046.9f,-92182.7f,25678.7f,-87767f,-92508.6f,25678.7f,16560.2f,-2907.29f,25678.7f,16560.2f,-2907.29f,25624.5f,16024.2f,-2801.34f,25624.5f,-88046.9f,-92182.7f,25624.5f,-88413.1f,-92497.2f,25678.7f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,24820f,-88133.2f,-92823.1f,25678.7f,-88133.2f,-92823.1f,25624.5f,-88413.1f,-92497.2f,24765.7f,-89895.8f,-93770.7f,24820f,-89615.9f,-94096.6f,24820f,-88133.2f,-92823.1f,24765.7f,-88413.1f,-92497.2f,25678.7f,-89596.5f,-94079.9f,25678.7f,-88133.2f,-92823.1f,24820f,-88133.2f,-92823.1f,24820f,-89615.9f,-94096.6f,23222.6f,-93458.9f,-81162.2f,24056.1f,-93491.8f,-81123.9f,24056.1f,-2550.94f,-3019.36f,23222.6f,-2518.03f,-3057.67f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-40907.1f,-14694f,10579.6f,-102089f,-68973.2f,10579f,-102925f,-68042.7f,10482f,-41291.8f,-14246f,10579f,-102925f,-68042.7f,10489f,-103571f,-67018.6f,10482f,-41713.9f,-13886.7f,10482f,-41291.8f,-14246f,10489f,-103571f,-67018.6f,8379.01f,-102145f,-69021.7f,10579.6f,-102089f,-68973.2f,10301.8f,-40240.8f,-15469.8f,8379.01f,-68082.6f,-39554.7f,8379.01f,-101057f,-70411.1f,10735.6f,-101057f,-70411.1f,10579.6f,-102089f,-68973.2f,8379.01f,-102145f,-69021.7f,-7490.7f,13527f,1074.93f,-3602.79f,20679.5f,611.547f,-7449.35f,23005.5f,1503.19f,5631.77f,13982.2f,32.0718f,6938.43f,14845.7f,8.81875f,4620.19f,17973.8f,60.0461f,2166.16f,14509.2f,164.113f,1136.48f,15846.6f,223.075f,1621.29f,18549.5f,194.186f,-160.178f,16705.3f,310.215f,-4323.73f,15846.6f,687.576f,-3030.97f,16705.3f,554.435f,-1709.92f,19868.7f,433.258f,-1596.32f,17001.2f,423.539f,2827.51f,9087.62f,131.015f,2166.16f,7402.34f,164.113f,3718.3f,9096.18f,92.3283f,-2352.36f,-8011.43f,490.311f,3946.3f,7228.03f,83.5128f,1136.48f,6064.9f,223.074f,-160.182f,5206.21f,310.215f,-5049.53f,-426.492f,768.658f,5536.51f,13854f,34.3347f,4608.07f,12649.6f,60.4329f,3946.3f,10964.3f,83.513f,3055.44f,10955.8f,120.472f,2827.51f,12823.9f,131.015f,5639.04f,4205.31f,31.902f,4608.07f,5542.76f,60.4327f,1416.3f,-15792.9f,206.155f,6022.45f,-21752.5f,23.5976f,6938.43f,3346.62f,8.81857f,-1596.32f,4910.32f,423.538f,-3030.97f,5206.21f,554.434f,-4323.73f,6064.9f,687.576f,-6578.08f,6399.27f,954.364f,-5348.56f,7402.34f,803.393f,-6006f,9087.62f,882.485f,-6232.44f,10955.8f,910.595f,-6006f,12823.9f,882.485f,-5348.57f,14509.2f,803.393f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,-7449.35f,23005.5f,1503.19f,-7490.7f,13527f,1074.93f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,1416.3f,-15792.9f,206.155f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,-5049.53f,-426.492f,768.658f,-2352.36f,-8011.43f,490.311f,1416.3f,-20827.5f,-4117.81f,1416.3f,-15792.9f,206.155f,6022.45f,-26787.1f,-4300.36f,6022.45f,-21752.5f,23.5976f,-6578.08f,1364.68f,-3369.59f,-6578.08f,6399.27f,954.364f,-8101.47f,16025.8f,-2803.12f,-8125.81f,8123.11f,-2819.08f,-7449.35f,17415.3f,-3297.97f,-7490.7f,8492.36f,-3249.03f,781.19f,-21196.8f,-3687.86f,3394.66f,-24832.7f,-3813.62f,1416.3f,-20827.5f,-4117.81f,4029.77f,-24463.4f,-4243.56f,-5684.64f,-5830.35f,-3125.36f,-2987.47f,-13415.3f,-3403.7f,-5049.53f,-5461.09f,-3555.3f,-2352.36f,-13046f,-3833.65f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-6464.54f,-2518.03f,-3057.67f,-6578.08f,1364.68f,-3369.59f,6276.06f,-40907.1f,-14694f,6456.25f,-40240.8f,-15469.8f,5842.26f,-27847.5f,-3863.23f,6022.45f,-26787.1f,-4300.36f,-8866.45f,16024.2f,-2801.34f,-8890.79f,8121.58f,-2817.31f,-7298.12f,-2550.94f,-3019.36f,-8920.72f,16560.2f,-2907.29f,-8836.13f,17951.2f,-3237.71f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,16560.2f,-2907.29f,-8866.45f,16024.2f,-2801.34f,-8920.72f,16560.2f,-2907.29f,-8866.45f,-88046.9f,-92182.7f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-87767f,-92508.6f,-8866.45f,-88046.9f,-92182.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8866.45f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8061.98f,-89615.9f,-94096.6f,-8007.72f,-89895.8f,-93770.7f,-8061.98f,-88133.2f,-92823.1f,-8007.72f,-88413.1f,-92497.2f,-8920.72f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-8061.98f,-88133.2f,-92823.1f,-8061.98f,-89615.9f,-94096.6f,-8061.98f,-88133.2f,-92823.1f,-8920.72f,-89596.5f,-94079.9f,-7298.12f,-93491.8f,-81123.9f,-6464.54f,-93458.9f,-81162.2f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-2518.03f,-3057.67f,-7298.12f,-2550.94f,-3019.36f,-6464.54f,-93458.9f,-81162.2f,6456.25f,-40240.8f,-15469.8f,6179.01f,-102925f,-68042.7f,6178.41f,-102089f,-68973.2f,6276.06f,-41291.8f,-14246f,6179.01f,-102925f,-68042.7f,6179.01f,-102925f,-68042.7f,6276.06f,-40907.1f,-14694f,6179.01f,-102925f,-68042.7f,6276.06f,-41713.9f,-13886.7f,6269.01f,-103571f,-67018.6f,6022.45f,-21752.5f,23.5976f,6022.45f,-26787.1f,-4300.36f,10735.6f,-26787.1f,-4300.36f,10735.6f,-21752.5f,23.5976f,6178.41f,-102089f,-68973.2f,6178.41f,-102089f,-68973.2f,6022.45f,-101057f,-70411.1f }; public String objectName; public int triangleCount; public int verticeCount; public float[] vertices; public float[] normals; public float[] textures; public short[] indices; public float[] matrices; public float[] pivots; public float[] animations; public void awake() { ByteBuffer vbb = ByteBuffer.allocateDirect(verticeTest.length * 4); vbb.order(ByteOrder.nativeOrder()); mVertexBuffer = vbb.asFloatBuffer(); mVertexBuffer.put(verticeTest); mVertexBuffer.position(0); ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length * 4); tbb.order(ByteOrder.nativeOrder()); mTextureBuffer = tbb.asFloatBuffer(); mTextureBuffer.put(textures); mTextureBuffer.position(0); //short has 2 bytes ByteBuffer ibb = ByteBuffer.allocateDirect(indicesTest.length*2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indicesTest); indexBuffer.position(0); verticeCount = (triangleCount*3); } public void draw(GL10 gl) { System.out.println("Draw Method Called in Object"); gl.glEnable(GL10.GL_TEXTURE_2D); //workaround bug 3623 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); System.out.println("Triangle Vertice Count is "+verticeCount); int x = vertices.length; System.out.println("Rendering following number of vertices "+x); int y = indices.length; System.out.println("Rendering following number of indices "+y); gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); } } And here is the code where I call the draw method : import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Iterator; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; class GLRenderer implements GLSurfaceView.Renderer { private static final String TAG = "GLRenderer"; private final Context context; private final GLCube cube = new GLCube(); private long startTime; private long fpsStartTime; private long numFrames; SceneObject drawObject; SceneObject object; //Used for object position and rotation. float zRotation; float xRotation; float yRotation; float kxRotation = 0.0f; float kyRotation = 0.0f; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); boolean SEE_THRU = false; GLRenderer(Context context) { this.context = context; } public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Setup any OpenGL Options that are required. gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glEnable(GL10.GL_TEXTURE_2D); if (SEE_THRU) { gl.glDisable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); } //Optional - disable dither to boost peformance. //gl.glDisable(GL10.GL_DITHER); //Dithering enabled by default. //Turn on the lights. float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1}; float lightDiffuse[] = new float[] {1, 1, 1, 1}; float[] lightPos = new float[] {1 ,1 ,1 , 1}; gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0); //Specify which materials we should use. float matAmbient[] = new float[] {1, 1, 1, 1}; float matDiffuse[] = new float[] {1, 1, 1, 1}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, matAmbient, 0); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, matDiffuse, 0); } public void onSurfaceChanged(GL10 gl, int width, int height) { //Define the view frustrum gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); float ratio = (float)width/height; gl.glLoadIdentity(); //gl.glOrthof(0, 480f, 800f, 0, 0, 1); GLU.gluPerspective(gl, 45.0f, ratio, 1.0f, 100f); } public void onDrawFrame (GL10 gl) { //Defs for rotation of object. float kzRotation = 0.0f; kyRotation +=1.0f; kxRotation =280.0f; gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); SceneObject object = sceneObjects.get(13); //Get the object //Position the model. gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -30.0f); gl.glScalef(0.0001f, 0.0001f, 0.0001f); zRotation = kzRotation; xRotation = kxRotation; yRotation = kyRotation; gl.glRotatef(yRotation, 0.0f, 1.0f, 0.0f); gl.glRotatef(xRotation, 1.0f, 0.0f, 0.0f); gl.glRotatef(zRotation, 0.0f, 0.0f, 1.0f); object.draw(gl); } } } The problem is that the object is not displaying as it should, but instead looks warped and squashed. Can anyone spot what might be wrong ? EDIT - Changed the onSufaceChanged method as per Tim's answer below, however no improvement. I've added an image of how the object is rendering on Android and the same object rendering correct on the iPhone. The most noticeable problem is that the "legs" should be straight and not bend and overall the object should be much longer. I'm sure the vertices and indices in the code above are correct (they are exactly the same as the iPhone ones). In case it is relevant here is how I am setting up the surfaceview / view: public class SaxParserActivity extends Activity { /** Called when the activity is first created. */ ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); GLView view; view = new GLView(this, sceneObjects); //Pass down our sceneObjects into the view class. //view.sceneObjects = sceneObjects; setContentView(view); } } class GLView extends GLSurfaceView { private final GLRenderer renderer; ArrayList<SceneObject> sceneObjects = new ArrayList<SceneObject>(); GLView(Context context, ArrayList<SceneObject> sceneObjects) { super (context); //Uncomment this to turn on error-checking and logging. //setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); renderer = new GLRenderer(context); //Pass down our sceneObjects. renderer.sceneObjects = sceneObjects; setRenderer(renderer); } }
I'm a bit confused by what you're doing. Why do you wipe on the projection matrix in onDrawFrame, after setting it in onSurfaceChanged? You should set projection in onSurfaceChanged like so: public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); //make sure to reset before glOrthof gl.glOrthof(0, 320f, 480f, 0, 0, 1); } And then change back to modelview and don't disturb the projection matrix during onDrawFrame. You'll probably need to recalibrate your scale and translate in onDrawFrame as well after doing this.