Good morning,
I'm rather new to OpenGL programming, so please forgive me if this is easy to answer.
My goal is to display 3 line segments of unit lenght at the origin that each point down an axis.
Everything in my app looks translated and / or scaled along the Z axis, but I cannot find the cause.
Here's my rendering code:
Note that the code refers to "Tunnel Sections". Those are for later and currently don't do anything.
I'm rather new to OpenGL programming, so please forgive me if this is easy to answer.
My goal is to display 3 line segments of unit lenght at the origin that each point down an axis.
Everything in my app looks translated and / or scaled along the Z axis, but I cannot find the cause.
Here's my rendering code:
Code:
package nl.wernerkroneman.tunnel.flyer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.SystemClock;
public class GameManager implements GLSurfaceView.Renderer {
private float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private int mGLProgram;
private int mColorHandle;
private int muMVPMatrixHandle;
static final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
final float[] axismarkerPoints = {0f,0f,0f, 1f,0f,0f, 0f,0f,0f, 0f,1f,0f, 0f,0f,0f, 0f,0f,1f};
FloatBuffer axitMarkBuf;
float[] speed;
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;" +
"}";
private ArrayList<TunnelSection> mTunnelSections;
private long lastUpdate;
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
lastUpdate = System.currentTimeMillis();
speed = new float[]{0f,0f,0f};
// prepare shaders and OpenGL program
int vertexShader = GameManager.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = GameManager.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mGLProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mGLProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mGLProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mGLProgram); // create OpenGL program executables
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mTunnelSections = new ArrayList<TunnelSection>(1);
TunnelSection previous = null;
for (int index=0;index<4;index++){
TunnelSection newSection = new TunnelSection(this,previous);
mTunnelSections.add(newSection);
previous = newSection;
}
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
axismarkerPoints.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
axitMarkBuf = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
axitMarkBuf.put(axismarkerPoints);
// set the buffer to read the first coordinate
axitMarkBuf.position(0);
}
@Override
public void onDrawFrame(GL10 unused) {
update();
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
float offsetX = android.util.FloatMath.sin(SystemClock.uptimeMillis()/1000.f) * 10f;
float offsetY = android.util.FloatMath.cos(SystemClock.uptimeMillis()/1000.f) * 10f;
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix,0, offsetX, 0f, offsetY, 0f, 0f, 0f, 0f, 1f, 0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mViewMatrix, 0);
//mMVPMatrix = mViewMatrix;
drawAxisMarker();
//for (int index=0; index<mTunnelSections.size(); index++){
//mTunnelSections.get(index).draw(mGLProgram,mMVPMatrix);
//}
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
// Adjust the viewport based on geometry changes,
// such as screen rotation
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 2, 50);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
void update(){
float deltaSecs = (lastUpdate - System.currentTimeMillis())/1000f;
lastUpdate = System.currentTimeMillis();
//speed = new float[]{speed[0],speed[1],speed[2]};
for (int index=0; index<mTunnelSections.size(); index++){
mTunnelSections.get(index).translate(speed[0],speed[1],speed[2]);
}
}
void drawAxisMarker(){
// Add program to OpenGL environment
GLES20.glUseProgram(mGLProgram);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mGLProgram, "vPosition");
// get handle to shape's transformation matrix
int muMVPMatrixHandle = GLES20.glGetUniformLocation(mGLProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
/* ---------- RING ---------- */
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, axitMarkBuf);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mGLProgram, "vColor");
float[] color = new float[]{1f,0,1f,1f};
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_LINES, 0, 6);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}