OpenGL ES 1.0 on Android – Triangle Example

Android LogoSince I spent quite a few hours trying to get my first OpenGL ES triangle on the Android phone’s screen I thought I should share the code with everyone to ease a bit the pain. Hopefully this will help someone get going on Android.


MainActivity.java

package com.ruibm;

import android.app.Activity;
import android.graphics.PointF;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class MainActivity extends Activity {

  private PointF touchStart;
  private GLSurfaceView glSurfaceView;
  private TriangleRenderer renderer;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    touchStart = new PointF();
    glSurfaceView = new GLSurfaceView(this);
    renderer = new TriangleRenderer();
    glSurfaceView.setRenderer(renderer);
    setContentView(glSurfaceView);
  }

  @Override
  protected void onResume() {
    super.onResume();
    glSurfaceView.onResume();
  }

  @Override
  protected void onPause() {
    super.onPause();
    glSurfaceView.onPause();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
      case MotionEvent.ACTION_MOVE:
        renderer.move(event.getX() - touchStart.x, touchStart.y - event.getY());
        touchStart.set(event.getX(), event.getY());
        glSurfaceView.requestRender();
        return true;

      case MotionEvent.ACTION_DOWN:
        touchStart.set(event.getX(), event.getY());
        return true;

      default:
        return super.onTouchEvent(event);
    }
  }

  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
      case KeyEvent.KEYCODE_DPAD_UP:
        renderer.move(0, 1);
        glSurfaceView.requestRender();
        return true;

      case KeyEvent.KEYCODE_DPAD_DOWN:
        renderer.move(0, -1);
        glSurfaceView.requestRender();
        return true;

      case KeyEvent.KEYCODE_DPAD_LEFT:
        renderer.move(-1, 0);
        glSurfaceView.requestRender();
        return true;

      case KeyEvent.KEYCODE_DPAD_RIGHT:
        renderer.move(1, 0);
        glSurfaceView.requestRender();
        return true;

      default:
        return super.onKeyDown(keyCode, event);
    }
  }
}

TriangleRenderer.java

package com.ruibm;

import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.graphics.PointF;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

public class TriangleRenderer implements Renderer {
  
  private PointF surfaceSize;
  private PointF offset;
  private ShortBuffer triangleBuffer;
  
  public TriangleRenderer() {
    surfaceSize = new PointF();
    offset = new PointF();
  }

  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  }
  
  public void onSurfaceChanged(GL10 gl, int width, int height) {
    surfaceSize.set(width, height);

    // Create our triangle.
    final int div = 1;
    short[] triangles = { 
        0, 0, 0,
        0, (short) (surfaceSize.y / div), 0,
        (short) (surfaceSize.x / div), (short) (surfaceSize.y / div), 0,
    };    
    triangleBuffer = ShortBuffer.wrap(triangles);
    
    // Disable a few things we are not going to use.
    gl.glDisable(GL10.GL_LIGHTING);
    gl.glDisable(GL10.GL_CULL_FACE);
    gl.glDisable(GL10.GL_DEPTH_BUFFER_BIT);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glClearColor(.5f, .5f, .8f, 1.f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    
    float ratio = surfaceSize.x / surfaceSize.y;
    gl.glViewport(0, 0, (int) surfaceSize.x, (int) surfaceSize.y);
            
    // Set our field of view.
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glFrustumf(
        -surfaceSize.x / 2, surfaceSize.x / 2, 
        -surfaceSize.y / 2, surfaceSize.y / 2,
        1, 3);
    
    // Position the camera at (0, 0, -2) looking down the -z axis.
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
    // Points rendered to z=0 will be exactly at the frustum's 
    // (farZ - nearZ) / 2 so the actual dimension of the triangle should be
    // half
    gl.glTranslatef(0, 0, -2);
  }

  public void onDrawFrame(GL10 gl) {    
    gl.glPushMatrix();
    
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glTranslatef(offset.x, offset.y, 0);
    
    gl.glColor4f(1.0f, 0.3f, 0.0f, .5f);    
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_SHORT, 0, triangleBuffer);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);    
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    
    gl.glPopMatrix();
  }

  public void move(float xDelta, float yDelta) {
    offset.x += xDelta;
    offset.y += yDelta;
    Log.d("TriangleRenderer", "offset=[" + offset.x + " ," + offset.y + "]");
  }
}
Advertisements

AppleScripts for Finder

I found recently this amazing Mac application called Spark that allows you to define global shortcuts keys (hotkeys). Here are some utility scripts I conjured to make my life easier.

Copy the current Finder path to the clipboard.

tell application "Finder"
	set theWindow to window 1
	set thePath to (POSIX path of (target of theWindow as alias))
	set the clipboard to thePath
end tell

Open an iTerm in the current Finder location.

tell application "Finder"
	if ((count the window) < 1) then
		return
	end if
	set theWindow to window 1
	set thePath to (POSIX path of (target of theWindow as alias))
	my openTerminal(thePath)
end tell

on openTerminal(path)
	tell application "iTerm"
		activate
		if not (exists current terminal) then
			launch session "Default Session"
		end if
		set mysession to current session of current terminal
		select mysession
		set cmd to "pushd " & path
		write mysession text cmd
	end tell
end openTerminal

Quick python socket server that stdouts all input

And here’s a simple python script that allows you to connect to your machine and debug your client output. It basically echoes to stdout everything that gets passed to it. Specially useful to debug HTTP GET requests.

#!/usr/bin/env python
#  Disconnect the client.
#  Stop the server.

import socket
import sys

host = ''
# host = 'localhost' # to restrict to localhost connections only.
port = 3434
pending_connections = 1
buffer_size = 1

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(pending_connections)
try:
  while True:
      print "nnWaiting for connection..."
      client, address = s.accept()
      print "Client connected: " + str(address)
      while True:
        data = client.recv(buffer_size)
        if not data or chr(3) in data:
          break
        elif chr(24) in data:
          sys.exit(0)
        sys.stdout.write(data)
      client.close()
      print "nClient disconnected: " + str(address)
finally:
  s.close()