免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5305 | 回复: 0
打印 上一主题 下一主题

[转]Android Opengl - Colored 3D Cube [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-20 16:12 |只看该作者 |倒序浏览

                 What is this: This tutorial shows how to create colored 3D Objects using the
OpenGL® ES
cross-platform API.
What you learn: You will learn how easy it is, to create a Colored 3D Cube, using OpenGL® ES.


Problems/Questions: post
here
Difficulty: 1.5 of 5   

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...


          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)
        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

.
         */
        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:
code.google.com
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
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* 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 ) {
                    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)
        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

.
         */
        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  

.
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/85193/showart_1904550.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP