Note that there are some explanatory texts on larger screens.

plurals
  1. POTransformations are weird in OpenGL ES 2.0
    primarykey
    data
    text
    <p>I'm developing an application for Android that uses OpenGL ES 2.0</p> <p>Since it's my first time with OpenGL (I used to use WebGL), I made a custom and pretty simple API like THREE.js, which consists of a <code>Object3D</code> and <code>Geometry</code> objects.</p> <p>Basicaly, what I did was: Store shapes inside the <code>Geometry</code> object, and create <code>Mesh</code> objects with the the geometry instance inside. Also, inside <code>Mesh</code>, I have: <code>Vector3</code> object for: <code>position</code>, <code>scale</code>, <code>rotation</code>.</p> <p>I created a circle to test, and here is what is happening</p> <p>If I don't change ANY thing, the circle is perfect on the screen. If I change the vertices positions on the creation of the circle, the circle is still Ok also.</p> <p>But, when I do some transformation (change the attribute position, scale or rotation) or Object3D (in this case, Mesh), the circle becomes "strech".</p> <p>So, I think that there is some problem with the projectionMatrix, but the circle it's ok if I don't transform it.</p> <p>Is there a problem with my matrix code? Should I send the Rotation, Translation and Scale matrix to the GPU? </p> <p>Perhaps I'm complicating things, but since this is the first time I use OpenGL after reading lot's of information, it's acceptable...</p> <p>Here is the Object3D code:</p> <pre><code>public class Object3D { public Vector3 position = new Vector3(); public Vector3 rotation = new Vector3(); public Vector3 scale = new Vector3(); public Color color = new Color(); public float[] getMVMatrix(){ // Initialize matrix with Identity float[] mvMatrix = new float[16]; Matrix.setIdentityM(mvMatrix, 0); // apply scale Matrix.scaleM(mvMatrix, 0, scale.x, scale.y, scale.z); // set rotation Matrix.setRotateM(mvMatrix, 0, rotation.x, 1f, 0, 0); Matrix.setRotateM(mvMatrix, 0, rotation.y, 0, 1f, 0); Matrix.setRotateM(mvMatrix, 0, rotation.z, 0, 0, 1f); // apply translation Matrix.translateM(mvMatrix, 0, position.x, position.y, position.z); return mvMatrix; } } </code></pre> <p>This is the Geometry class, that simplifies the use of Triangles:</p> <pre><code>public class Geometry { // Public, to allow modifications public ArrayList&lt;Vector3&gt; vertices; public ArrayList&lt;Face3&gt; faces; // Type of Geometry public int triangleType = GLES20.GL_TRIANGLES; [...] public FloatBuffer getVerticesBuffer(){ if(verticesBuffer == null || verticesBufferNeedsUpdate){ /* * Cache faces */ int size = vertices.size(); // (size of Vector3 list) * (3 for each object) * (4 bytes per float) ByteBuffer bb = ByteBuffer.allocateDirect( size * 3 * 4 ); // use the device hardware's native byte order bb.order(ByteOrder.nativeOrder()); // Get the ByteBuffer as a floatBuffer verticesBuffer = bb.asFloatBuffer(); for(int i = 0; i &lt; size; i++) verticesBuffer.put(vertices.get(i).toArray()); verticesBufferNeedsUpdate = false; } verticesBuffer.position(0); return verticesBuffer; } public ShortBuffer getFacesBuffer(){ if(facesBuffer == null || facesBufferNeedsUpdate){ /* * Cache faces */ int size = faces.size(); // Log.i(TAG, "FACES Size: "+size); // (size of Vector3 list) * (3 for each object) * (2 bytes per short) ByteBuffer bb = ByteBuffer.allocateDirect( size * 3 * 2 ); // use the device hardware's native byte order bb.order(ByteOrder.nativeOrder()); // Get the ByteBuffer as a floatBuffer facesBuffer = bb.asShortBuffer(); for(int i = 0; i &lt; size; i++) facesBuffer.put(faces.get(i).toArray()); facesBufferNeedsUpdate = false; } facesBuffer.position(0); return facesBuffer; } } </code></pre> <p>Also, The Mesh class, responsable for resndering <code>Geometry</code> objects:</p> <pre><code>public class Mesh extends Object3D{ [...] public void draw(float[] projectionMatrix, int shaderProgram){ float[] MVMatrix = getMVMatrix(); Matrix.multiplyMM(projectionMatrix, 0, projectionMatrix, 0, MVMatrix, 0); // Check if geometry is set if(geometry == null){ Log.i(TAG, "Geometry is null. skiping"); return; } // Add program to OpenGL environment GLES20.glUseProgram(shaderProgram); // Get, enable and Set the position attribute positionHandle = GLES20.glGetAttribLocation(shaderProgram, "vPosition"); GLES20.glEnableVertexAttribArray(positionHandle); // Prepare the triangles coordinate data Buffer vertexBuffer = geometry.getVerticesBuffer(); GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, COORDS_PER_VERTEX*4, vertexBuffer); // get handle to fragment shader's vColor member int mColorHandle = GLES20.glGetUniformLocation(shaderProgram, "vColor"); // Set color for drawing the triangle GLES20.glUniform4fv(mColorHandle, 1, color.toArray(), 0); // get handle to shape's transformation matrix int mMVPMatrixHandle = GLES20.glGetUniformLocation(shaderProgram, "uMVPMatrix"); ChwaziSurfaceView.checkGlError("glGetUniformLocation"); // Apply the projection and view transformation GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, projectionMatrix, 0); ChwaziSurfaceView.checkGlError("glUniformMatrix4fv"); // Draw the triangles if(geometry.triangleType == GLES20.GL_TRIANGLES){ Buffer indexesBuffer = geometry.getFacesBuffer(); GLES20.glDrawElements( GLES20.GL_TRIANGLES, geometry.faces.size()*3, GL10.GL_UNSIGNED_SHORT, indexesBuffer); }else{ GLES20.glDrawArrays(geometry.triangleType, 0, geometry.vertices.size()); ChwaziSurfaceView.checkGlError("glDrawArrays"); } // Disable vertex array GLES20.glDisableVertexAttribArray(positionHandle); } } </code></pre> <p>This is the sample code I made to test if it's working properly (just translation)</p> <pre><code>// Inside my Renderer... @Override public void onDrawFrame(GL10 unused) { // Draw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glCullFace(GLES20.GL_FRONT_AND_BACK); // Set the camera position (View matrix) Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Calculate the projection and view transformation Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); // Create a rotation for the triangle long time = SystemClock.uptimeMillis();// % 4000L; myMesh.position.x = (time%4000)/4000f; myMesh.draw(mMVPMatrix, shaderProgram.getProgram()); } @Override public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; // this projection matrix is applied to object coordinates Matrix.orthoM(mProjMatrix, 0, -1, 1, -1, 1, 0, 10); } </code></pre> <p><strong>EDIT</strong></p> <p>Shader code:</p> <pre><code> private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of the objects that use this vertex shader "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + // the matrix must be included as a modifier of gl_Position " gl_Position = vPosition * uMVPMatrix;" + "}"; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload