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:

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

I hope you succeeded and understood this tutorial.

Please vote and/or leave a comment .

原文地址 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 .
*/

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

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个顶点):

更多相关文章

  1. Android图形显示系统——概述
  2. Android OpenGL学习笔记(二)--三角形的绘制.
  3. Android OpenGL学习笔记(二)之----三角形的绘制.

随机推荐

  1. Android中的样式和主题(Styles and Themes
  2. Android中利用“反射”动态加载R文件中的
  3. Android异步任务的处理方法
  4. 【已解决】Android真机设备调试时LogCat
  5. 将Android(安卓)Studio的设置恢复到初始
  6. 用android实现GB28181前端设备接入平台
  7. 组件化:腾讯 T3 Android(安卓)高级开发岗
  8. Android(安卓)消息循环知识
  9. android中如何让一个不知道高度的控件正
  10. 今天体会最深的一点就是android的生命周