Chinaunix首页 | 论坛 | 博客
  • 博客访问: 538913
  • 博文数量: 150
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 1705
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-11 23:29
文章分类

全部博文(150)

文章存档

2011年(9)

2010年(25)

2009年(94)

2008年(22)

我的朋友

分类: LINUX

2009-04-20 16:12:05

What is this: This tutorial shows how to create colored 3D Objects using the cross-platform API.

What you learn: You will learn how easy it is, to create a Colored 3D Cube, using OpenGL® ES.

Question Problems/Questions: post here

Difficulty: 1.5 of 5 Smile

What it will look like:


Introduction:
Lets quote wikipedia first:
Quote:
OpenGL ES (OpenGL for Embedded Systems) is a subset of the OpenGL 3D graphics API designed for embedded devices such as mobile phones, PDAs, and video game consoles. It is defined and promoted by the Khronos Group, a graphics hardware and software industry consortium interested in open APIs for graphics and multimedia.


Description:

What we will do is, create a custom view and using OpenGL ES in it to draw a colored cube.
The Main steps are:
    1. Setup the view and create a cube
    (1.1. Start/Stop the animation if we are (not) viewing it)
    2. Do some trigonometry (rotation)
    3. Make the Cube paint itself


Most interesting:
What the heck do those values in the Cube-Constructor mean... Question
Java:
       int one = 0x10000;
        /* Every vertex got 3 values, for
         * x / y / z position in the kartesian space.
         */

        int vertices[] = {
               -one, -one, -one, // Vertex Zero
                one, -one, -one, // Vertex Two
                one,  one, -one, // Vertex ...
               -one,  one, -one,
               -one, -one,  one,
                one, -one,  one,
                one,  one,  one,
               -one,  one,  one, // Vertex Seven
            };


That is pretty easy, each row stands for a single vertex, consisting of three values (x,y,z) which simply result in a point in the cartesian space.
So if you think of each codeline as one vertex you get something like this:
(Note: We only created the vertices, not the edges. I just added them, that the cube-structure becomes better visible.)
(Note2: You will see that the blue coordinate-system is located right in the middle of the cube)


Java:
       /* Every vertex has got its own color, described by 4 values
         * R(ed)
         * G(green)
         * B(blue)
         * A(lpha) <-- Opticacy
         */

        int colors[] = {
                  0,    0,    0,  one,
                one,    0,    0,  one,
                one,  one,    0,  one,
                  0,  one,    0,  one,
                  0,    0,  one,  one,
                one,    0,  one,  one,
                one,  one,  one,  one,
                  0,  one,  one,  one,
            };


In this code-block the color of all the 8 vertices are described, as '4' each: R(ed) G(reen) B(lue) A(lpha). (Alpha means Opticacy)
OpenGL SE will create the color-flows automatically!

Java:
       /* The last thing is that we need to describe some Triangles.
         * A triangle got 3 vertices.
           * The confusing thing is, that it is important in which order
           * the vertices of each triangle are described.
           * So describing a triangle through the vertices: "0, 4, 5"
           * will not result in the same triangle as: "0, 5, 4"
           * You probably ask: Why the hell isn't that the same ???
           * The reason for that is the call of: "gl.glFrontFace(gl.GL_CW);"
           * which means, that we have to describe the "visible" side of the
           * triangles by naming its vertices in a ClockWise order!
           * From the other side, the triangle will be 100% lookthru!
           * You can create a kind of magic mirror with that Wink.
         */

        byte indices[] = {
                0, 4, 5,
                0, 5, 1,
                1, 5, 6,
                1, 6, 2,
                2, 6, 7,
                2, 7, 3,
                3, 7, 4,
                3, 4, 0,
                4, 7, 6,
                4, 6, 5,
                3, 0, 1,
                3, 1, 2
        };


This is the tricky part. I think that I described it good enough in them comment.
Lets take a look at two example triangles:


The Code
Original Source:


Modified by: Nicolas 'plusminus' Gramlich
Java:
/*
 * Copyright (C) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.google.android.samples.graphics;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.OpenGLContext;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.view.View;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;


/**
 * Example of how to use OpenGL|ES in a custom view
 *
 */


public class GLView1 extends Activity {

    @Override
        protected void onCreate(Bundle icicle)
    {
        super.onCreate(icicle);    
        setContentView(new GLView( getApplication() ));
    }

    @Override
        protected void onResume()
    {
        super.onResume();
        //android.os.Debug.startMethodTracing("/tmp/trace/GLView1.dmtrace",
        //  8 * 1024 * 1024);
    }

    @Override
        protected void onStop()
    {
        super.onStop();
        //android.os.Debug.stopMethodTracing();
    }
}

class GLView extends View
{
    /**
     * The View constructor is a good place to allocate our OpenGL context
     */

    public GLView(Context context)
    {
        super(context);

        /*
         * Create an OpenGL|ES context. This must be done only once, an
         * OpenGL contex is a somewhat heavy object.
         */

        mGLContext = new OpenGLContext(0);
        mCube = new Cube();
        mAnimate = false;
    }

    /*
     * Start the animation only once we're attached to a window
     * @see android.view.View#onAttachedToWindow()
     */

    @Override
    protected void onAttachedToWindow() {
        mAnimate = true;
        Message msg = mHandler.obtainMessage(INVALIDATE);
        mNextTime = SystemClock.uptimeMillis();
        mHandler.sendMessageAtTime(msg, mNextTime);
        super.onAttachedToWindow();
    }

    /*
     * Make sure to stop the animation when we're no longer on screen,
     * failing to do so will cause most of the view hierarchy to be
     * leaked until the current process dies.
     * @see android.view.View#onDetachedFromWindow()
     */

    @Override
    protected void onDetachedFromWindow() {
        mAnimate = false;
        super.onDetachedFromWindow();
    }

    /**
     * Draw the view content
     *
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */

    @Override
    protected void onDraw(Canvas canvas) {
        if (true) {
        /*
         * First, we need to get to the appropriate GL interface.
         * This is simply done by casting the GL context to either
         * GL10 or GL11.
         */

        GL10 gl = (GL10)(mGLContext.getGL());

        /*
         * Before we can issue GL commands, we need to make sure all
         * native drawing commands are completed. Simply call
         * waitNative() to accomplish this. Once this is done, no native
         * calls should be issued.
         */

        mGLContext.waitNative(canvas, this);

            int w = getWidth();
            int h = getHeight();

            /*
             * Set the viewport. This doesn't have to be done each time
             * draw() is called. Typically this is called when the view
             * is resized.
             */



            gl.glViewport(0, 0, w, h);

            /*
             * Set our projection matrix. This doesn't have to be done
             * each time we draw, but usualy a new projection needs to be set
             * when the viewport is resized.
             */


            float ratio = (float)w / h;
            gl.glMatrixMode(gl.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glFrustumf(-ratio, ratio, -1, 1, 2, 12);

            /*
             * dithering is enabled by default in OpenGL, unfortunattely
             * it has a significant impact on performace in software
             * implementation. Often, it's better to just turn it off.
             */

             gl.glDisable(gl.GL_DITHER);

            /*
             * Usually, the first thing one might want to do is to clear
             * the screen. The most efficient way of doing this is to use
             * glClear(). However we must make sure to set the scissor
             * correctly first. The scissor is always specified in window
             * coordinates:
             */


            gl.glClearColor(1,1,1,1);
            gl.glEnable(gl.GL_SCISSOR_TEST);
            gl.glScissor(0, 0, w, h);
            gl.glClear(gl.GL_COLOR_BUFFER_BIT);


            /*
             * Now we're ready to draw some 3D object
             */


            gl.glMatrixMode(gl.GL_MODELVIEW);
            gl.glLoadIdentity();
            gl.glTranslatef(0, 0, -3.0f);
            gl.glScalef(0.5f, 0.5f, 0.5f);
            gl.glRotatef(mAngle,        0, 1, 0);
            gl.glRotatef(mAngle*0.25f,  1, 0, 0);

            gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
            gl.glEnableClientState(gl.GL_COLOR_ARRAY);
            gl.glEnable(gl.GL_CULL_FACE);

            mCube.draw(gl);

            mAngle += 1.2f;

        /*
         * Once we're done with GL, we need to flush all GL commands and
         * make sure they complete before we can issue more native
         * drawing commands. This is done by calling waitGL().
         */

        mGLContext.waitGL();
        }
    }


    // ------------------------------------------------------------------------

    private static final int INVALIDATE = 1;

    private final Handler mHandler = new Handler() {
        @Override
                public void handleMessage(Message msg) {
            if (mAnimate && msg.what == INVALIDATE) {
                invalidate();
                msg = obtainMessage(INVALIDATE);
                long current = SystemClock.uptimeMillis();
                if (mNextTime < current) {
                    mNextTime = current + 20;
                }
                sendMessageAtTime(msg, mNextTime);
                mNextTime += 20;
            }
        }
    };

    private OpenGLContext   mGLContext;
    private Cube            mCube;
    private float           mAngle;
    private long            mNextTime;
    private boolean         mAnimate;
}


class Cube
{
    public Cube()
    {
        int one = 0x10000;
        /* Every vertex got 3 values, for
         * x / y / z position in the kartesian space.
         */

        int vertices[] = {
               -one, -one, -one,
                one, -one, -one,
                one,  one, -one,
               -one,  one, -one,
               -one, -one,  one,
                one, -one,  one,
                one,  one,  one,
               -one,  one,  one,
            };

        /* Every vertex has got its own color, described by 4 values
         * R(ed)
         * G(green)
         * B(blue)
         * A(lpha) <-- Opticacy
         */

        int colors[] = {
                  0,    0,    0,  one,
                one,    0,    0,  one,
                one,  one,    0,  one,
                  0,  one,    0,  one,
                  0,    0,  one,  one,
                one,    0,  one,  one,
                one,  one,  one,  one,
                  0,  one,  one,  one,
            };

        /* The last thing is that we need to describe some Triangles.
         * A triangle got 3 vertices.
           * The confusing thing is, that it is important in which order
           * the vertices of each triangle are described.
           * So describing a triangle through the vertices: "0, 4, 5"
           * will not result in the same triangle as: "0, 5, 4"
           * You probably ask: Why the hell isn't that the same ???
           * The reason for that is the call of: "gl.glFrontFace(gl.GL_CW);"
           * which means, that we have to describe the "visible" side of the
           * triangles by naming its vertices in a ClockWise order!
           * From the other side, the triangle will be 100% lookthru!
           * You can create a kind of magic mirror with that Wink.
         */

        byte indices[] = {
                0, 4, 5,
                0, 5, 1,
                1, 5, 6,
                1, 6, 2,
                2, 6, 7,
                2, 7, 3,
                3, 7, 4,
                3, 4, 0,
                4, 7, 6,
                4, 6, 5,
                3, 0, 1,
                3, 1, 2
        };

        // Buffers to be passed to gl*Pointer() functions
        // must be direct, i.e., they must be placed on the
        // native heap where the garbage collector cannot
        // move them.
    //
    // Buffers with multi-byte datatypes (e.g., short, int, float)
    // must have their byte order set to native order

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
    vbb.order(ByteOrder.nativeOrder());
    mVertexBuffer = vbb.asIntBuffer();
        mVertexBuffer.put(vertices);
        mVertexBuffer.position(0);

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
    cbb.order(ByteOrder.nativeOrder());
        mColorBuffer = cbb.asIntBuffer();
        mColorBuffer.put(colors);
        mColorBuffer.position(0);

        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
        mIndexBuffer.put(indices);
        mIndexBuffer.position(0);
    }

    public void draw(GL10 gl)
    {
        gl.glFrontFace(gl.GL_CW);
        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
        gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);
        gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
    }

    private IntBuffer   mVertexBuffer;
    private IntBuffer   mColorBuffer;
    private ByteBuffer  mIndexBuffer;
}


I hope you succeeded and understood this tutorial.

Please vote and/or leave a comment Smile .
阅读(4121) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~