| /* |
| * Authors Name: Jeff Molofee (NeHe) |
| * |
| * Disclaimer: |
| * This program may crash your system or run poorly depending on your |
| * hardware. The program and code contained in this archive was scanned |
| * for virii and has passed all test before it was put online. If you |
| * use this code in project of your own, send a shout out to the author! |
| * |
| * Ported to Android by INsanityDesign: |
| * http://insanitydesign.com/wp/projects/nehe-android-ports/ |
| * |
| * Adapted by 0xlab developers. |
| */ |
| |
| package com.nea.nehe.lesson08; |
| |
| import org.zeroxlab.benchmark.Tester; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.ByteOrder; |
| import java.nio.FloatBuffer; |
| |
| import javax.microedition.khronos.egl.EGLConfig; |
| import javax.microedition.khronos.opengles.GL10; |
| |
| import android.content.Context; |
| import android.opengl.GLSurfaceView; |
| import android.opengl.GLU; |
| import android.opengl.GLSurfaceView.Renderer; |
| import android.view.KeyEvent; |
| import android.view.MotionEvent; |
| |
| /** |
| * This is a port of the {@link http://nehe.gamedev.net} OpenGL |
| * tutorials to the Android 1.5 OpenGL ES platform. Thanks to |
| * NeHe and all contributors for their great tutorials and great |
| * documentation. This source should be used together with the |
| * textual explanations made at {@link http://nehe.gamedev.net}. |
| * The code is based on the original Visual C++ code with all |
| * comments made. It has been altered and extended to meet the |
| * Android requirements. The Java code has according comments. |
| * |
| * If you use this code or find it helpful, please visit and send |
| * a shout to the author under {@link http://www.insanitydesign.com/} |
| * |
| * @DISCLAIMER |
| * This source and the whole package comes without warranty. It may or may |
| * not harm your computer or cell phone. Please use with care. Any damage |
| * cannot be related back to the author. The source has been tested on a |
| * virtual environment and scanned for viruses and has passed all tests. |
| * |
| * |
| * This is an interpretation of "Lesson 08: Blending" |
| * for the Google Android platform. |
| * |
| * @author Savas Ziplies (nea/INsanityDesign) |
| */ |
| public class Lesson08 extends GLSurfaceView implements Renderer { |
| |
| private Tester mTester; |
| |
| /** Cube instance */ |
| private Cube cube; |
| |
| /* Rotation values */ |
| private float xrot; //X Rotation |
| private float yrot; //Y Rotation |
| |
| /* Rotation speed values */ |
| private float xspeed; //X Rotation Speed |
| private float yspeed; //Y Rotation Speed |
| |
| private float z = -5.0f; //Depth Into The Screen |
| |
| private int filter = 0; //Which texture filter? |
| |
| /** Is light enabled */ |
| private boolean light = true; |
| /** Is blending enabled ( NEW ) */ |
| private boolean blend = true; |
| |
| /* The initial light values */ |
| private float[] lightAmbient = {0.5f, 0.5f, 0.5f, 1.0f}; |
| private float[] lightDiffuse = {1.0f, 1.0f, 1.0f, 1.0f}; |
| private float[] lightPosition = {0.0f, 0.0f, 2.0f, 1.0f}; |
| |
| /* The buffers for our light values */ |
| private FloatBuffer lightAmbientBuffer; |
| private FloatBuffer lightDiffuseBuffer; |
| private FloatBuffer lightPositionBuffer; |
| |
| /* Variables and factor for the input handler */ |
| private float oldX; |
| private float oldY; |
| private final float TOUCH_SCALE = 0.2f; //Proved to be good for normal rotation |
| |
| /** The Activity Context */ |
| private Context context; |
| |
| /** |
| * Instance the Cube object and set the Activity Context |
| * handed over. Initiate the light buffers and set this |
| * class as renderer for this now GLSurfaceView. |
| * Request Focus and set if focusable in touch mode to |
| * receive the Input from Screen and Buttons |
| * |
| * @param context - The Activity Context |
| */ |
| public Lesson08(Context context) { |
| super(context); |
| |
| //Set this as Renderer |
| this.setRenderer(this); |
| //Request focus, otherwise buttons won't react |
| this.requestFocus(); |
| this.setFocusableInTouchMode(true); |
| |
| // |
| this.context = context; |
| |
| // |
| ByteBuffer byteBuf = ByteBuffer.allocateDirect(lightAmbient.length * 4); |
| byteBuf.order(ByteOrder.nativeOrder()); |
| lightAmbientBuffer = byteBuf.asFloatBuffer(); |
| lightAmbientBuffer.put(lightAmbient); |
| lightAmbientBuffer.position(0); |
| |
| byteBuf = ByteBuffer.allocateDirect(lightDiffuse.length * 4); |
| byteBuf.order(ByteOrder.nativeOrder()); |
| lightDiffuseBuffer = byteBuf.asFloatBuffer(); |
| lightDiffuseBuffer.put(lightDiffuse); |
| lightDiffuseBuffer.position(0); |
| |
| byteBuf = ByteBuffer.allocateDirect(lightPosition.length * 4); |
| byteBuf.order(ByteOrder.nativeOrder()); |
| lightPositionBuffer = byteBuf.asFloatBuffer(); |
| lightPositionBuffer.put(lightPosition); |
| lightPositionBuffer.position(0); |
| |
| // |
| cube = new Cube(); |
| } |
| |
| public void setSpeedAndTester(int speedX, int speedY, Tester tester) { |
| xspeed = speedX; |
| yspeed = speedY; |
| mTester = tester; |
| } |
| |
| /** |
| * The Surface is created/init() |
| */ |
| public void onSurfaceCreated(GL10 gl, EGLConfig config) { |
| //And there'll be light! |
| gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbientBuffer); //Setup The Ambient Light |
| gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuseBuffer); //Setup The Diffuse Light |
| gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer); //Position The Light |
| gl.glEnable(GL10.GL_LIGHT0); //Enable Light 0 |
| |
| //Blending |
| gl.glColor4f(1.0f, 1.0f, 1.0f, 0.5f); //Full Brightness. 50% Alpha ( NEW ) |
| gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); //Set The Blending Function For Translucency ( NEW ) |
| |
| //Settings |
| gl.glDisable(GL10.GL_DITHER); //Disable dithering |
| gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping |
| gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading |
| gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background |
| gl.glClearDepthf(1.0f); //Depth Buffer Setup |
| gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing |
| gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do |
| |
| //Really Nice Perspective Calculations |
| gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); |
| |
| //Load the texture for the cube once during Surface creation |
| cube.loadGLTexture(gl, this.context); |
| } |
| |
| /** |
| * Here we do our drawing |
| */ |
| public void onDrawFrame(GL10 gl) { |
| //Clear Screen And Depth Buffer |
| gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); |
| gl.glLoadIdentity(); //Reset The Current Modelview Matrix |
| |
| //Check if the light flag has been set to enable/disable lighting |
| if(light) { |
| gl.glEnable(GL10.GL_LIGHTING); |
| } else { |
| gl.glDisable(GL10.GL_LIGHTING); |
| } |
| |
| //Check if the blend flag has been set to enable/disable blending |
| if(blend) { |
| gl.glEnable(GL10.GL_BLEND); //Turn Blending On ( NEW ) |
| gl.glDisable(GL10.GL_DEPTH_TEST); //Turn Depth Testing Off ( NEW ) |
| |
| } else { |
| gl.glDisable(GL10.GL_BLEND); //Turn Blending On ( NEW ) |
| gl.glEnable(GL10.GL_DEPTH_TEST); //Turn Depth Testing Off ( NEW ) |
| } |
| |
| //Drawing |
| gl.glTranslatef(0.0f, 0.0f, z); //Move z units into the screen |
| gl.glScalef(0.8f, 0.8f, 0.8f); //Scale the Cube to 80 percent, otherwise it would be too large for the screen |
| |
| //Rotate around the axis based on the rotation matrix (rotation, x, y, z) |
| gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X |
| gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y |
| |
| cube.draw(gl, filter); //Draw the Cube |
| gl.glFinish(); |
| mTester.decreaseCounter(); |
| //Change rotation factors |
| xrot += xspeed; |
| yrot += yspeed; |
| } |
| |
| |
| /** |
| * If the surface changes, reset the view |
| */ |
| public void onSurfaceChanged(GL10 gl, int width, int height) { |
| if(height == 0) { //Prevent A Divide By Zero By |
| height = 1; //Making Height Equal One |
| } |
| |
| gl.glViewport(0, 0, width, height); //Reset The Current Viewport |
| gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix |
| gl.glLoadIdentity(); //Reset The Projection Matrix |
| |
| //Calculate The Aspect Ratio Of The Window |
| GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f); |
| |
| gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix |
| gl.glLoadIdentity(); //Reset The Modelview Matrix |
| } |
| |
| /* ***** Listener Events ***** */ |
| /** |
| * Override the key listener to receive keyUp events. |
| * |
| * Check for the DPad presses left, right, up, down and middle. |
| * Change the rotation speed according to the presses |
| * or change the texture filter used through the middle press. |
| */ |
| @Override |
| public boolean onKeyUp(int keyCode, KeyEvent event) { |
| // |
| if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { |
| yspeed -= 0.1f; |
| |
| } else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { |
| yspeed += 0.1f; |
| |
| } else if(keyCode == KeyEvent.KEYCODE_DPAD_UP) { |
| xspeed -= 0.1f; |
| |
| } else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { |
| xspeed += 0.1f; |
| |
| } else if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { |
| filter += 1; |
| if(filter > 2) { |
| filter = 0; |
| } |
| } |
| |
| //We handled the event |
| return true; |
| } |
| |
| /** |
| * Override the touch screen listener. |
| * |
| * React to moves and presses on the touchscreen. |
| */ |
| @Override |
| public boolean onTouchEvent(MotionEvent event) { |
| // |
| float x = event.getX(); |
| float y = event.getY(); |
| |
| //If a touch is moved on the screen |
| if(event.getAction() == MotionEvent.ACTION_MOVE) { |
| //Calculate the change |
| float dx = x - oldX; |
| float dy = y - oldY; |
| //Define an upper area of 10% on the screen |
| int upperArea = this.getHeight() / 10; |
| |
| //Zoom in/out if the touch move has been made in the upper |
| if(y < upperArea) { |
| z -= dx * TOUCH_SCALE / 2; |
| |
| //Rotate around the axis otherwise |
| } else { |
| xrot += dy * TOUCH_SCALE; |
| yrot += dx * TOUCH_SCALE; |
| } |
| |
| //A press on the screen |
| } else if(event.getAction() == MotionEvent.ACTION_UP) { |
| //Define an upper area of 10% to define a lower area |
| int upperArea = this.getHeight() / 10; |
| int lowerArea = this.getHeight() - upperArea; |
| |
| // |
| if(y > lowerArea) { |
| //Change the blend setting if the lower area left has been pressed ( NEW ) |
| if(x < (this.getWidth() / 2)) { |
| if(blend) { |
| blend = false; |
| } else { |
| blend = true; |
| } |
| |
| //Change the light setting if the lower area right has been pressed |
| } else { |
| if(light) { |
| light = false; |
| } else { |
| light = true; |
| } |
| } |
| } |
| } |
| |
| //Remember the values |
| oldX = x; |
| oldY = y; |
| |
| //We handled the event |
| return true; |
| } |
| } |