[转]Android Opengl - Colored 3D Cube

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.

Question Problems/Questions: post here

Difficulty: 1.5 of 5 Smile

What it will look like:

Introduction:
Lets quote wikipedia first:

  • 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

I hope you succeeded and understood this tutorial.

Please vote and/or leave a comment Smile .

 

原文地址 http://www.anddev.org/colored_3d_cube-t4.html

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.

 

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
            };

 

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,
            };

 

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
        };

 

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 < 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;
}



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



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!



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)



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(根据要绘制的图形设置图形的定点,如果是屏幕的正方形,需要设置4个顶点(x、y、

z的坐标)如果是立方体,则要设置8个顶点):

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值