public class MyGLRenderer implements GLSurfaceView.Renderer { private GameClock gameClock; private float elapsedTime; private Context context; private Camera camera; private ArrayList maze; private Player player; private int mazeTexture; private int playerTexture; private TextureShaderProgram textureShaderProgram; private float[] projectionMatrix = new float[16]; private float[] modelMatrix = new float[16]; private float[] viewMatrix = new float[16]; private float[] worldView = new float[16]; private float[] worldViewProjection = new float[16]; private float[] scalingMatrix = new float[16]; private float[] rotationMatrix = new float[16]; private float[] translationMatrix = new float[16]; private float rotate = 0; public MyGLRenderer(Context context) { this.context = context; gameClock = new GameClock(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_CULL_FACE); //Enables cull face GLES20.glCullFace(GLES20.GL_BACK); //specifies whether front- or back-facing polygons can be culled GLES20.glFrontFace(GLES20.GL_CCW); //defines the font facing polygon, whether they are drawn in CW order or CCW order. LoadShaderPrograms(); LoadObjects(); playerTexture = TextureHelper.loadTexture(context, R.drawable.chararacter); player = new Player(context, R.raw.character); camera = new Camera(player); gameClock.Initialize(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0, 0, width, height); Matrix.setIdentityM(worldViewProjection, 0); float aspectRatio; if(width > height) { aspectRatio = (float)width/(float)height; //Matrix.frustumM(projectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1, 0.1f, 150); Matrix.perspectiveM(projectionMatrix, 0, 90, aspectRatio, 0.1f, 150); } else { aspectRatio = (float)height/(float)width; Matrix.perspectiveM(projectionMatrix, 0, 90, aspectRatio, 0.1f, 150); //Matrix.frustumM(projectionMatrix, 0, -1, 1, -aspectRatio, aspectRatio, 1, 150); } viewMatrix = camera.getViewMatrix(); } @Override public void onDrawFrame(GL10 gl) { elapsedTime = gameClock.CalculateElapsedTime(); System.out.println(elapsedTime); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); drawPlayer(); drawMaze(); updateCamera(); } private void drawMaze() { for(int a = 0; a < maze.size(); a++) { Matrix.setIdentityM(modelMatrix, 0); Matrix.multiplyMM(worldView, 0, viewMatrix, 0, modelMatrix, 0); Matrix.multiplyMM(worldViewProjection, 0, projectionMatrix, 0, worldView, 0); textureShaderProgram.useProgram(); textureShaderProgram.setUniforms(worldViewProjection, mazeTexture); maze.get(a).bindData(textureShaderProgram); maze.get(a).draw(); } } private void drawPlayer() { Matrix.setIdentityM(translationMatrix, 0); Vector3 playerWorldMidPoint = player.getWorldMidPoint(); Matrix.translateM(translationMatrix, 0, playerWorldMidPoint.x, playerWorldMidPoint.y, playerWorldMidPoint.z); rotationMatrix = player.getIncrementalRotationMatrix(); Matrix.multiplyMM(modelMatrix, 0, translationMatrix, 0, rotationMatrix, 0); Matrix.multiplyMM(worldView, 0, viewMatrix, 0, modelMatrix, 0); Matrix.multiplyMM(worldViewProjection, 0, projectionMatrix, 0, worldView, 0); textureShaderProgram.useProgram(); textureShaderProgram.setUniforms(worldViewProjection, playerTexture); player.bindData(textureShaderProgram); player.draw(); player.updatePlayerPosition(elapsedTime); } private void updateCamera() { camera.updateCamera(); viewMatrix = camera.getViewMatrix(); } private void LoadShaderPrograms() { textureShaderProgram = new TextureShaderProgram(context); } private void LoadObjects() { LoadMaze(); } //I am loading in a wavefront file and the maze consists of several objects so I have to load them all since I stored them //separately. private void LoadMaze() { mazeTexture = TextureHelper.loadTexture(context, R.drawable.dark_texture); InputStream path = context.getResources().openRawResource(R.raw.maze); LoadOBJModel mazeOBJLoader = new LoadOBJModel(); ArrayList mazeOBJFileData = mazeOBJLoader.LoadData(path); maze = new ArrayList<>(); for(int a = 0; a < mazeOBJFileData.size(); a++) { maze.add(new StaticObject(mazeOBJFileData.get(a))); } } }