152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project/*
252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project *
452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * you may not use this file except in compliance with the License.
652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * You may obtain a copy of the License at
752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project *
852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project *
1052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * See the License for the specific language governing permissions and
1452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project * limitations under the License.
1552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project */
1652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
1752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectpackage com.android.objviewer;
1852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
1952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.app.Activity;
2052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.AssetManager;
2152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.content.Context;
2252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.graphics.Canvas;
2352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.graphics.OpenGLContext;
2452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.graphics.Paint;
2552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.graphics.glutils.GLView;
2652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.graphics.glutils.Object3D;
2752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.Bundle;
2852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.Handler;
2952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.Message;
3052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.os.SystemClock;
3152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.KeyEvent;
3252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.View;
3352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport android.view.Window;
3452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
3552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.io.IOException;
3652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.io.InputStream;
3752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.util.ArrayList;
3852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport java.util.List;
3952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
4052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectimport javax.microedition.khronos.opengles.GL10;
4152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
4252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectclass OBJView extends View {
4352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
4452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Mathematical constants
4552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static final float PI = (float)Math.PI;
4652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static final float TWO_PI = (float)(2.0*Math.PI);
4752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static final float PI_OVER_TWO = (float)(Math.PI/2.0);
4852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
4952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Ambient light to apply
5052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // private float[] lightModelAmbient = { 0.0f, 0.0f, 0.0f, 1.0f };
5152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float[] lightModelAmbient = { 0.2f, 0.2f, 0.2f, 1.0f };
5252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
5352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Paint object for drawing the FPS display
5452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private Paint paint = new Paint();
5552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
5652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // GLView object to manage drawing
5752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private GLView glView = new GLView();
5852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
5952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private boolean         initialized = false;
6052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
6152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private OpenGLContext   mGLContext;
6252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
6352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Next time to draw
6452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private long            mNextTime;
6552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
6652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // View transformation controlled by UI
6752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mRotAngle = 0.0f;
6852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mRotVelocity = 1.0f;
6952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mTiltAngle = 0.0f;
7052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
7152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Object bounds
7252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mCenterX = 0.0f;
7352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mCenterY = 0.0f;
7452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mCenterZ = 0.0f;
7552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float           mScale   = 1.0f;
7652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
7752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    // Light direction
7852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private float[] mLightDir = { 0.0f, 0.0f, 1.0f, 0.0f };
7952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
8052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    public OBJView(Context context) {
8152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        super(context);
8252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
8352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mGLContext = new OpenGLContext(OpenGLContext.DEPTH_BUFFER);
8452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
8552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        Message msg = mHandler.obtainMessage(INVALIDATE);
8652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mNextTime = SystemClock.uptimeMillis() + 100;
8752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mHandler.sendMessageAtTime(msg, mNextTime);
8852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
8952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        requestFocus();
9052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
9152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
9252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    public void reset() {
9352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        initialized = false;
9452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
9552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mRotAngle = 0.0f;
9652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mRotVelocity = 1.0f;
9752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mTiltAngle = 0.0f;
9852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
9952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mCenterX = 0.0f;
10052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mCenterY = 0.0f;
10152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mCenterZ = 0.0f;
10252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mScale   = 1.0f;
10352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
10452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
10552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
10652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Hand the key to the GLView object first
10752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if (glView.processKey(keyCode)) {
10852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            return true;
10952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
11052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
11152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        switch (keyCode) {
11252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_LEFT:
11352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mRotVelocity -= 1.0f;
11452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
11552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
11652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_RIGHT:
11752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mRotVelocity += 1.0f;
11852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
11952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
12052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_CENTER:
12152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mRotVelocity = 0.0f;
12252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
12352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
12452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
12552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mTiltAngle -= 360.0f/24.0f;
12652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
12752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
12852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
12952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mTiltAngle += 360.0f/24.0f;
13052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
13152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
13252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            case KeyEvent.KEYCODE_U:
13352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                OBJViewer.nextObject();
13452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                reset();
13552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                break;
13652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
13752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            default:
13852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                return super.onKeyDown(keyCode, event);
13952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
14052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
14152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        return true;
14252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
14352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
14452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private void init(GL10 gl) {
14552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.reset();
14652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
14752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        paint.setColor(0xffffffff);
14852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
14952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glEnable(gl.GL_DEPTH_TEST);
15052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
15152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glDisable(gl.GL_SCISSOR_TEST);
15252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
15352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Some quality settings...
15452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glEnable(gl.GL_DITHER);
15552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
15652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glShadeModel(gl.GL_SMOOTH);
15752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
15852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glEnable(gl.GL_CULL_FACE);
15952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glFrontFace(gl.GL_CCW);
16052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
16152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glClearColor(0, 0, 0, 1);
16252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
16352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glLightModelf(gl.GL_LIGHT_MODEL_TWO_SIDE, 0);
16452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glLightModelfv(gl.GL_LIGHT_MODEL_AMBIENT, lightModelAmbient, 0);
16552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
16652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
16752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    @Override
16852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    protected void onDraw(Canvas canvas) {
16952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        GL10 gl = (GL10)mGLContext.getGL();
17052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mGLContext.makeCurrent(this);
17152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
17252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if (!initialized) {
17352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            init(gl);
17452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            initialized = true;
17552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
17652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            // Load the object
17752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            Object3D obj = OBJViewer.getObject();
17852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
17952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            // Compute a scale factor and translation to bring it
18052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            // into view
18152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mCenterX = (obj.getBoundsMinX() + obj.getBoundsMaxX())/2.0f;
18252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mCenterY = (obj.getBoundsMinY() + obj.getBoundsMaxY())/2.0f;
18352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mCenterZ = (obj.getBoundsMinZ() + obj.getBoundsMaxZ())/2.0f;
18452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            float spanX = obj.getBoundsMaxX() - obj.getBoundsMinX();
18552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            float spanY = obj.getBoundsMaxY() - obj.getBoundsMinY();
18652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            float spanZ = obj.getBoundsMaxZ() - obj.getBoundsMinZ();
18752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            float maxSpan = Math.max(spanX, spanY);
18852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            maxSpan = Math.max(maxSpan, spanZ);
18952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mScale = 2.0f/maxSpan;
19052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
19152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
19252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        int w = getWidth();
19352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        int h = getHeight();
19452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glViewport(0, 0, w, h);
19552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
19652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        float ratio = (float)w/h;
19752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.setAspectRatio(ratio);
19852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
19952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Clear buffers
20052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
20152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
20252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Set up the projection and view
20352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.setProjection(gl);
20452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.setView(gl);
20552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
20652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Set up lighting
20752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glMatrixMode(gl.GL_MODELVIEW);
20852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glEnable(gl.GL_LIGHTING);
20952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glEnable(gl.GL_LIGHT0);
21052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, mLightDir, 0);
21152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.setLights(gl, gl.GL_LIGHT0);
21252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
21352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Rotate the viewpoint around the model
21452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glRotatef(mTiltAngle, 1, 0, 0);
21552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glRotatef(mRotAngle, 0, 1, 0);
21652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
21752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Scale object to fit in [-1, 1]
21852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glScalef(mScale, mScale, mScale);
21952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
22052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Center the object at the origin
22152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        gl.glTranslatef(-mCenterX, -mCenterY, -mCenterZ);
22252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
22352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Increment the rotation angle
22452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mRotAngle += mRotVelocity;
22552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if (mRotAngle < 0.0f) {
22652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mRotAngle += 360.0f;
22752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
22852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if (mRotAngle > 360.0f) {
22952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            mRotAngle -= 360.0f;
23052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
23152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
23252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Draw the object
23352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        Object3D object = OBJViewer.getObject();
23452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        object.draw(gl);
23552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
23652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Allow GL to complete
23752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        mGLContext.post();
23852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
23952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Draw GLView messages and/or FPS
24052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.showMessages(canvas);
24152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.setNumTriangles(object.getNumTriangles());
24252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        glView.showStatistics(canvas, w);
24352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
24452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
24552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static final int INVALIDATE = 1;
24652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
24752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private final Handler mHandler = new Handler() {
24852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        public void handleMessage(Message msg) {
24952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            if (msg.what == INVALIDATE) {
25052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                invalidate();
25152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                msg = obtainMessage(INVALIDATE);
25252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                long current = SystemClock.uptimeMillis();
25352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                if (mNextTime < current) {
25452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                    mNextTime = current + 20;
25552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                }
25652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                sendMessageAtTime(msg, mNextTime);
25752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                mNextTime += 20;
25852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            }
25952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
26052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    };
26152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project}
26252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
26352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
26452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Projectpublic class OBJViewer extends Activity {
26552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
26652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static Object3D object = null;
26752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
26852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static List<String> objectFiles = new ArrayList<String>();
26952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private static int objectIndex = 0;
27052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
27152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    static {
27252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("world.gles");
27352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("al.gles");
27452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("apple.gles");
27552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("dolphins.gles");
27652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("f16.gles");
27752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("flowers.gles");
27852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("porsche.gles");
27952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("rosevase.gles");
28052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("shuttle.gles");
28152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        objectFiles.add("soccerball.gles");
28252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
28352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
28452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    private int readInt16(InputStream is) throws Exception {
28552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        return is.read() | (is.read() << 8);
28652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
28752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
28852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    public static Object3D getObject() {
28952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        return object;
29052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
29152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
29252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    public static void nextObject() {
29352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        try {
29452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            objectIndex = (objectIndex + 1) % objectFiles.size();
29552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            object.load(objectFiles.get(objectIndex));
29652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        } catch (IOException e) {
29752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            throw new RuntimeException(e);
29852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
29952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
30052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
30152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    @Override protected void onCreate(Bundle icicle) {
30252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        super.onCreate(icicle);
30352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
30452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Get rid of the title
30552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        requestWindowFeature(Window.FEATURE_NO_TITLE);
30652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        // Make sure we're not drawing a background
30752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        setTheme(R.style.Theme);
30852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        setContentView(new OBJView((Context)getApplication()));
30952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
31052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        if (object == null) {
31152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            try {
31252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                final AssetManager am = getAssets();
31352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                this.object = new Object3D() {
31452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                    public InputStream readFile(String filename)
31552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                    throws IOException {
31652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                        return am.open(filename);
31752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
31852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                    }
31952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                };
32052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                object.load(objectFiles.get(0));
32152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            } catch (Exception e) {
32252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project                throw new RuntimeException(e);
32352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project            }
32452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        }
32552d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
32652d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
32752d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    @Override protected void onResume() {
32852d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        super.onResume();
32952d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
33052d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project
33152d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    @Override protected void onStop() {
33252d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project        super.onStop();
33352d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project    }
33452d4c30ca52320ec92d1d1ddc8db3f07f69c4f98The Android Open Source Project}
335