Home | History | Annotate | Download | only in objviewer
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.objviewer;
     18 
     19 import android.app.Activity;
     20 import android.content.AssetManager;
     21 import android.content.Context;
     22 import android.graphics.Canvas;
     23 import android.graphics.OpenGLContext;
     24 import android.graphics.Paint;
     25 import android.graphics.glutils.GLView;
     26 import android.graphics.glutils.Object3D;
     27 import android.os.Bundle;
     28 import android.os.Handler;
     29 import android.os.Message;
     30 import android.os.SystemClock;
     31 import android.view.KeyEvent;
     32 import android.view.View;
     33 import android.view.Window;
     34 
     35 import java.io.IOException;
     36 import java.io.InputStream;
     37 import java.util.ArrayList;
     38 import java.util.List;
     39 
     40 import javax.microedition.khronos.opengles.GL10;
     41 
     42 class OBJView extends View {
     43 
     44     // Mathematical constants
     45     private static final float PI = (float)Math.PI;
     46     private static final float TWO_PI = (float)(2.0*Math.PI);
     47     private static final float PI_OVER_TWO = (float)(Math.PI/2.0);
     48 
     49     // Ambient light to apply
     50     // private float[] lightModelAmbient = { 0.0f, 0.0f, 0.0f, 1.0f };
     51     private float[] lightModelAmbient = { 0.2f, 0.2f, 0.2f, 1.0f };
     52 
     53     // Paint object for drawing the FPS display
     54     private Paint paint = new Paint();
     55 
     56     // GLView object to manage drawing
     57     private GLView glView = new GLView();
     58 
     59     private boolean         initialized = false;
     60 
     61     private OpenGLContext   mGLContext;
     62 
     63     // Next time to draw
     64     private long            mNextTime;
     65 
     66     // View transformation controlled by UI
     67     private float           mRotAngle = 0.0f;
     68     private float           mRotVelocity = 1.0f;
     69     private float           mTiltAngle = 0.0f;
     70 
     71     // Object bounds
     72     private float           mCenterX = 0.0f;
     73     private float           mCenterY = 0.0f;
     74     private float           mCenterZ = 0.0f;
     75     private float           mScale   = 1.0f;
     76 
     77     // Light direction
     78     private float[] mLightDir = { 0.0f, 0.0f, 1.0f, 0.0f };
     79 
     80     public OBJView(Context context) {
     81         super(context);
     82 
     83         mGLContext = new OpenGLContext(OpenGLContext.DEPTH_BUFFER);
     84 
     85         Message msg = mHandler.obtainMessage(INVALIDATE);
     86         mNextTime = SystemClock.uptimeMillis() + 100;
     87         mHandler.sendMessageAtTime(msg, mNextTime);
     88 
     89         requestFocus();
     90     }
     91 
     92     public void reset() {
     93         initialized = false;
     94 
     95         mRotAngle = 0.0f;
     96         mRotVelocity = 1.0f;
     97         mTiltAngle = 0.0f;
     98 
     99         mCenterX = 0.0f;
    100         mCenterY = 0.0f;
    101         mCenterZ = 0.0f;
    102         mScale   = 1.0f;
    103     }
    104 
    105     public boolean onKeyDown(int keyCode, KeyEvent event) {
    106         // Hand the key to the GLView object first
    107         if (glView.processKey(keyCode)) {
    108             return true;
    109         }
    110 
    111         switch (keyCode) {
    112             case KeyEvent.KEYCODE_DPAD_LEFT:
    113                 mRotVelocity -= 1.0f;
    114                 break;
    115 
    116             case KeyEvent.KEYCODE_DPAD_RIGHT:
    117                 mRotVelocity += 1.0f;
    118                 break;
    119 
    120             case KeyEvent.KEYCODE_DPAD_CENTER:
    121                 mRotVelocity = 0.0f;
    122                 break;
    123 
    124             case KeyEvent.KEYCODE_DPAD_UP:
    125                 mTiltAngle -= 360.0f/24.0f;
    126                 break;
    127 
    128             case KeyEvent.KEYCODE_DPAD_DOWN:
    129                 mTiltAngle += 360.0f/24.0f;
    130                 break;
    131 
    132             case KeyEvent.KEYCODE_U:
    133                 OBJViewer.nextObject();
    134                 reset();
    135                 break;
    136 
    137             default:
    138                 return super.onKeyDown(keyCode, event);
    139         }
    140 
    141         return true;
    142     }
    143 
    144     private void init(GL10 gl) {
    145         glView.reset();
    146 
    147         paint.setColor(0xffffffff);
    148 
    149         gl.glEnable(gl.GL_DEPTH_TEST);
    150 
    151         gl.glDisable(gl.GL_SCISSOR_TEST);
    152 
    153         // Some quality settings...
    154         gl.glEnable(gl.GL_DITHER);
    155 
    156         gl.glShadeModel(gl.GL_SMOOTH);
    157 
    158         gl.glEnable(gl.GL_CULL_FACE);
    159         gl.glFrontFace(gl.GL_CCW);
    160 
    161         gl.glClearColor(0, 0, 0, 1);
    162 
    163         gl.glLightModelf(gl.GL_LIGHT_MODEL_TWO_SIDE, 0);
    164         gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT, lightModelAmbient, 0);
    165     }
    166 
    167     @Override
    168     protected void onDraw(Canvas canvas) {
    169         GL10 gl = (GL10)mGLContext.getGL();
    170         mGLContext.makeCurrent(this);
    171 
    172         if (!initialized) {
    173             init(gl);
    174             initialized = true;
    175 
    176             // Load the object
    177             Object3D obj = OBJViewer.getObject();
    178 
    179             // Compute a scale factor and translation to bring it
    180             // into view
    181             mCenterX = (obj.getBoundsMinX() + obj.getBoundsMaxX())/2.0f;
    182             mCenterY = (obj.getBoundsMinY() + obj.getBoundsMaxY())/2.0f;
    183             mCenterZ = (obj.getBoundsMinZ() + obj.getBoundsMaxZ())/2.0f;
    184             float spanX = obj.getBoundsMaxX() - obj.getBoundsMinX();
    185             float spanY = obj.getBoundsMaxY() - obj.getBoundsMinY();
    186             float spanZ = obj.getBoundsMaxZ() - obj.getBoundsMinZ();
    187             float maxSpan = Math.max(spanX, spanY);
    188             maxSpan = Math.max(maxSpan, spanZ);
    189             mScale = 2.0f/maxSpan;
    190         }
    191 
    192         int w = getWidth();
    193         int h = getHeight();
    194         gl.glViewport(0, 0, w, h);
    195 
    196         float ratio = (float)w/h;
    197         glView.setAspectRatio(ratio);
    198 
    199         // Clear buffers
    200         gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
    201 
    202         // Set up the projection and view
    203         glView.setProjection(gl);
    204         glView.setView(gl);
    205 
    206         // Set up lighting
    207         gl.glMatrixMode(gl.GL_MODELVIEW);
    208         gl.glEnable(gl.GL_LIGHTING);
    209         gl.glEnable(gl.GL_LIGHT0);
    210         gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, mLightDir, 0);
    211         glView.setLights(gl, gl.GL_LIGHT0);
    212 
    213         // Rotate the viewpoint around the model
    214         gl.glRotatef(mTiltAngle, 1, 0, 0);
    215         gl.glRotatef(mRotAngle, 0, 1, 0);
    216 
    217         // Scale object to fit in [-1, 1]
    218         gl.glScalef(mScale, mScale, mScale);
    219 
    220         // Center the object at the origin
    221         gl.glTranslatef(-mCenterX, -mCenterY, -mCenterZ);
    222 
    223         // Increment the rotation angle
    224         mRotAngle += mRotVelocity;
    225         if (mRotAngle < 0.0f) {
    226             mRotAngle += 360.0f;
    227         }
    228         if (mRotAngle > 360.0f) {
    229             mRotAngle -= 360.0f;
    230         }
    231 
    232         // Draw the object
    233         Object3D object = OBJViewer.getObject();
    234         object.draw(gl);
    235 
    236         // Allow GL to complete
    237         mGLContext.post();
    238 
    239         // Draw GLView messages and/or FPS
    240         glView.showMessages(canvas);
    241         glView.setNumTriangles(object.getNumTriangles());
    242         glView.showStatistics(canvas, w);
    243     }
    244 
    245     private static final int INVALIDATE = 1;
    246 
    247     private final Handler mHandler = new Handler() {
    248         public void handleMessage(Message msg) {
    249             if (msg.what == INVALIDATE) {
    250                 invalidate();
    251                 msg = obtainMessage(INVALIDATE);
    252                 long current = SystemClock.uptimeMillis();
    253                 if (mNextTime < current) {
    254                     mNextTime = current + 20;
    255                 }
    256                 sendMessageAtTime(msg, mNextTime);
    257                 mNextTime += 20;
    258             }
    259         }
    260     };
    261 }
    262 
    263 
    264 public class OBJViewer extends Activity {
    265 
    266     private static Object3D object = null;
    267 
    268     private static List<String> objectFiles = new ArrayList<String>();
    269     private static int objectIndex = 0;
    270 
    271     static {
    272         objectFiles.add("world.gles");
    273         objectFiles.add("al.gles");
    274         objectFiles.add("apple.gles");
    275         objectFiles.add("dolphins.gles");
    276         objectFiles.add("f16.gles");
    277         objectFiles.add("flowers.gles");
    278         objectFiles.add("porsche.gles");
    279         objectFiles.add("rosevase.gles");
    280         objectFiles.add("shuttle.gles");
    281         objectFiles.add("soccerball.gles");
    282     }
    283 
    284     private int readInt16(InputStream is) throws Exception {
    285         return is.read() | (is.read() << 8);
    286     }
    287 
    288     public static Object3D getObject() {
    289         return object;
    290     }
    291 
    292     public static void nextObject() {
    293         try {
    294             objectIndex = (objectIndex + 1) % objectFiles.size();
    295             object.load(objectFiles.get(objectIndex));
    296         } catch (IOException e) {
    297             throw new RuntimeException(e);
    298         }
    299     }
    300 
    301     @Override protected void onCreate(Bundle icicle) {
    302         super.onCreate(icicle);
    303 
    304         // Get rid of the title
    305         requestWindowFeature(Window.FEATURE_NO_TITLE);
    306         // Make sure we're not drawing a background
    307         setTheme(R.style.Theme);
    308         setContentView(new OBJView((Context)getApplication()));
    309 
    310         if (object == null) {
    311             try {
    312                 final AssetManager am = getAssets();
    313                 this.object = new Object3D() {
    314                     public InputStream readFile(String filename)
    315                     throws IOException {
    316                         return am.open(filename);
    317 
    318                     }
    319                 };
    320                 object.load(objectFiles.get(0));
    321             } catch (Exception e) {
    322                 throw new RuntimeException(e);
    323             }
    324         }
    325     }
    326 
    327     @Override protected void onResume() {
    328         super.onResume();
    329     }
    330 
    331     @Override protected void onStop() {
    332         super.onStop();
    333     }
    334 }
    335