2012年11月30日 星期五

Android:循環Gallery

public class MainActivity extends Activity {
private ImageAdapter imageAdapter=null;
private Gallery gallery=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gallery=(Gallery)findViewById(R.id.gallery1);
//設定Adapter
gallery.setAdapter(new ImageAdapter(this));
gallery.setGravity(Gravity.CENTER_HORIZONTAL);//效果目前不明     
gallery.setUnselectedAlpha(0.3f);//未選到的圖片比較暗                   
                gallery.setSpacing(20);//圖片與圖片間的間隔 
        
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> adapterView, View view,
int position, long id) {
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
gallery.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
}
});
}


}

package com.briview.mgallery;

import ...

public class ImageAdapter extends BaseAdapter {
private Context context;
int imgArr[]={R.drawable.r0,R.drawable.r100,R.drawable.r150,R.drawable.r20};

public ImageAdapter(Context context){
this.context=context;
}
@Override
public int getCount() {
//修改返回值為無限大
return Integer.MAX_VALUE;
}

@Override
public Object getItem(int position) {
return imgArr[position];
}

@Override
public long getItemId(int position) {
return position;
}

@SuppressWarnings("deprecation")
@Override
public View getView(int position, View v, ViewGroup parent) {
//new a imageview to show pic
ImageView imageview=new ImageView(context);
//參數意義為讓使用者出圖片index範圍時,跳回第一張,Ex:5%4=1
imageview.setImageResource(imgArr[position%imgArr.length]);
//set the layout,determine how the pic to show
imageview.setLayoutParams(new Gallery.LayoutParams(480,800));
imageview.setScaleType(ImageView.ScaleType.CENTER);
imageview.setBackgroundColor(Color.alpha(1)); 
return imageview;
}


}



2012年11月29日 星期四

2012年11月27日 星期二

Android:Service啟動方式,BindService


  1. 建立class並extends android.app.Service, override其需要的method
  2. public IBinder onBind(Intent intent) 需要回傳一個IBinder物件, 在實作上我們回傳一個extends Binder類別的物件, EX: LocalBinder
  3. 在這個LocalBinder類別中, 我們定義一個method, 讓它可以取得一個Service物件, 這也是使用Binder Service最主要的目的
  4. 我們可以將想再背景執行Service的程式碼寫在一個自訂的方法中, 以供之後從Activity呼叫
  5. 在main activity中, 使用ServiceConnection物件類別來進行與Service連線, 並實作需要的method, 在public void onServiceConnected(ComponentName name, IBinder service)中, 使用參數傳進來的service轉型成自定義的LocalBinder後, 呼叫自行定義的方法, 取得Service
  6. 接著在使用Intent物件,設定好main activity以及Service,再來就可以啟動服務啦 bindService(intent, mServConn, BIND_AUTO_CREATE);
  7. 記得不需要服務後,要將Service 連線給Unbind   unbindService(mServConn);
先註冊Service至manifest.xml中


package com.servicedemo;

import ...

public class MyService extends Service {
private LocalBinder myBinder=new LocalBinder();
private MyService myService;
@Override
public IBinder onBind(Intent intent) {
Log.d("MyService", "onBind");
return myBinder;
}

@Override
public void onCreate() {
Log.d("MyService", "onCreate");
super.onCreate();
}

@Override
public void onDestroy() {
Log.d("MyService", "onDestroy");
super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}

@Override
public boolean onUnbind(Intent intent) {
Log.d("MyService", "onUnBind");
return super.onUnbind(intent);
}
//Service自行提供可供操作的方法
public void doSomeThing(TextView textView){
textView.setText("Service提供的方法...");
}
/*
* inner class extends Binder
*/
public class LocalBinder extends Binder{
MyService getService(){
return MyService.this;
}
}

}



package com.servicedemo;

import...
import com.servicedemo.MyService.LocalBinder;

public class Main extends Activity {
private TextView textView;
private MyService mService = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView1);
}
public void bindService_onClick(View v) {
mService = null;
Intent intent = new Intent(Main.this, MyService.class);
this.bindService(intent, mServConn, BIND_AUTO_CREATE);
}

public void unBindService_onClick(View v) {
mService = null;
this.unbindService(mServConn);
}

public void callServiceMethod_onClick(View v) {
if (mService != null)
mService.doSomeThing(textView);
}
/*
* 目的:為了取得Service物件,進而操作其public的方法
* 作法:在這function會接收到由service內的onBinde()所丟出來的Ibinder物件
* 利用這IBinder物件取得Service物件,就可以直接操作Service內各個public 的method
*/
private ServiceConnection mServConn = new ServiceConnection() {
// bind Service過程中,系統會呼叫執行以下程式碼
@Override
public void onServiceConnected(ComponentName name, IBinder service) {

mService = ((LocalBinder) service).getService();
}

// Service發生意外才會執行
@Override
public void onServiceDisconnected(ComponentName name) {

}

};

}




2012年11月26日 星期一

Android: View Bitmap Canvas與Drawable


View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別

 Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂

 Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw()方法自動繪製

 Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)

Android: Reflection效果



 View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別

 Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂

 Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw(Canvas canvas)方法自動繪製

 Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)
  
 

這個例子特別的點是在, 通常我們為了達到彈性需求(不想用內建的容器像ImageView、GridView、ListView、Button、EditText...
所以會是利用一個類別繼承View來當成容器,然後利用Canvas畫完之後,再將他裝到自建的容器中顯示,通常的做法是在@override中的onDraw(Canvas canvas)中,這個參數傳進來的canvas可視為一張撲滿螢幕的大畫布利用各式的Drawable物件將Canvas給畫出




package com.briview.reflection;

import ...
public class MainActivity extends Activity {
private ImageView imageView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imageView = (ImageView) findViewById(R.id.imageView1);
Bitmap bmp = ((BitmapDrawable) getResources().getDrawable(R.drawable.a))
.getBitmap();
imageView.setImageBitmap(createReflectedImage(bmp));

}

/*
* public static Bitmap createBitmap (Bitmap source, int x, int y, int
* width, int height, Matrix m, boolean filter) 須注意以下規則 x + width <=
* bmp.getWidth(); y + height <= bmp.getHeight();
*/

private Bitmap createReflectedImage(Bitmap originalImage) {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
/*
* create bitmap object
*/
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// 創建總圖片(原圖片 + 倒影圖片)
Bitmap finalReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
Paint shaderPaint = new Paint();
// 創建線性漸變LinearGradient物件
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, finalReflection.getHeight() + 1,
0x70ffffff, 0x00ffffff, TileMode.MIRROR);
shaderPaint.setShader(shader);
// 漸層效果!!
shaderPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// 畫布畫出反轉圖片大小區域,然後把漸變效果加到其中,就出現了圖片的倒    
                   影效果。


/*
 * draw on the canvas
 */
// 創建畫布
Canvas canvas = new Canvas(finalReflection);
canvas.drawBitmap(originalImage, 0, 0, null);
canvas.drawBitmap(reflectionImage, 0, height + 1, null);


canvas.drawRect(0, height + 1, width, finalReflection.getHeight(),
           shaderPaint);

return finalReflection;

}

}



2012年11月21日 星期三

Android:[轉]OpenGL 投影方式

Ref: http://fansofjava.iteye.com/blog/1499991

关于android的投影矩阵,一般有两种,一种是矩阵投影,另一种是透视投影。 
矩阵投影主要用于2D画面,但指定此投影的方式却有多种方式,而且对于初入门的人来说,也不容易理解,可以使用glOrthof,此方法使用方式大概如下: 
Java代码  收藏代码
  1. GL10 gl = glGraphics.getGL();  
  2. gl.glViewport(00, glGraphics.getWidth(), glGraphics.getHeight());  
  3. gl.glMatrixMode(GL10.GL_PROJECTION);  
  4. gl.glLoadIdentity();  
  5.   
  6. //以左下角为原点  
  7. gl.glOrthof(0//left  
  8.             width,  //right  
  9.             0//bottom  
  10.             height, //top  
  11.             1, -1);  
  12. gl.glMatrixMode(GL10.GL_MODELVIEW);  
  13. gl.glLoadIdentity();  

上面的glOrthof最后两个参数用于设置Z轴坐标,在2D画面中使用1与-1即可。 

除了这种方式外,还可以通过一个叫GLU的工具类来指定投影的显示,用法如下: 
Java代码  收藏代码
  1. gl.glViewport(00, glGraphics.getWidth(), glGraphics.getHeight());  
  2. gl.glMatrixMode(GL10.GL_PROJECTION);  
  3. gl.glLoadIdentity();  
  4. GLU.gluOrtho2D(gl, left, right, bottom, top);  
  5. gl.glMatrixMode(GL10.GL_MODELVIEW);  
  6. gl.glLoadIdentity();  

上面的gluOrtho2D方法相对来说简化了一下。 

在3D的画面中,也有两种方式,一种是使用glFrustumf方法,用法如下: 
Java代码  收藏代码
  1.        gl.glViewport(00, width, height);  
  2. float ratio = (float) width / height;  
  3. gl.glMatrixMode(GL10.GL_PROJECTION);  
  4. gl.glLoadIdentity();  
  5. gl.glFrustumf(-ratio, ratio, -11120);  

这个ratio表示宽度与高度的比,glFrustumf方法的前两个参数分别代表左右方向,因为高度与宽度不一样,所以这个ratio是为了限制场景宽度而必须存在的。第三四个参数分别代表Y的下上方向,而最后两个参数则代表Z轴的近远方向。这个近与远不是很好理解的话请看下图: 

 
上面这个图也把Viewport与场景区分开了。 

除了使用glFrustumf外,也可以使用工具类GLU里面的方法gluPerspective,此方法参数如下: 
Java代码  收藏代码
  1. GLU.gluPerspective(gl, fovy, aspect, zNear, zFar);  

其中第二个参数表示角度,即视图的角度。而aspect则表示宽度与高度比,即与上面的ratio一样。但这些参数最好还是配上一个图,下面的图来自最后链接文章,个人觉得很形象的说明了这些参数的意思。 
 

引用

我们观察平面的裁剪窗口的大小和屏幕的大小可以一致,也可以有差别. 但为了使得最终的效果基本一致,所以,一般设置成它们具有相同的 aspect(横纵比 w/h), 从而它们的转换关系就是等比例的放大或者缩小,而不会产生扭曲. 

对于3D图形来说,除了设置视图投影以外,还得设置整个游戏模型的浏览角度,这个会涉及到一个很重要的方法GLU.gluLookAt,这个方法的参数形式如下: 
Java代码  收藏代码
  1. void android.opengl.GLU.gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)  

参数很多,但参数作用主要分为三部分(gl不算)。 
eye系列坐标用于设置整个视野所参照的原点坐标。 
center系列坐标用于设置浏览游戏角色的方向,这个方向坐标就是相对于eye系统坐标的。 
up系列坐标则用于设置浏览者(镜头)相对于原点(eye系列)的坐标。 
下图可供参考: 
 
因此在3D环境中,整个游戏的视图设置大概就像下面这样,先设置投影矩阵下整个游戏的面板的显示,再设置为模型矩阵,显示3D模型的轮廓: 
Java代码  收藏代码
  1. public void setMatrices(GL10 gl) {  
  2.   gl.glMatrixMode(GL10.GL_PROJECTION);  
  3.   gl.glLoadIdentity();  
  4.   GLU.gluPerspective(gl, fieldOfView, aspectRatio, near, far);  
  5.   gl.glMatrixMode(GL10.GL_MODELVIEW);  
  6.   gl.glLoadIdentity();  
  7.   GLU.gluLookAt(gl, position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, up.x, up.y, up.z);  
  8. }  

Eclipse:Android專案匯入問題 gen already exists but is not a source folder. Convert to a source folder or rename it"


Try this, it helped me:
  1. Right click on the project and go to "Properties"
  2. Select "Java Build Path" on the left
  3. Open "Source" tab
  4. Click "Add Folder..."
  5. Check "gen" folder and click Ok and Ok again
  6. Again right click on the project and in the "Andriod Tools" click on "Fix Project Properties"

2012年11月19日 星期一

Android:OpenGL Cube


package com.example.opengltest2;

import ...

public class Cube {
// 頂點座標
float cubeVtx[] = { -1.0f, 1.0f, -1.0f, // v0
-1.0f, 1.0f, 1.0f, // v1
1.0f, 1.0f, 1.0f, // v2
1.0f, 1.0f, -1.0f, // v3
-1.0f, -1.0f, -1.0f, // v4
-1.0f, -1.0f, 1.0f, // v5
1.0f, -1.0f, 1.0f, // v6
1.0f, -1.0f, -1.0f }; // v7

private float colors[] = {
             0.0f,  1.0f,  0.0f,  1.0f,
             0.0f,  1.0f,  0.0f,  1.0f,
             1.0f,  0.5f,  0.0f,  1.0f,
             1.0f,  0.5f,  0.0f,  1.0f,
             1.0f,  0.0f,  0.0f,  1.0f,
             1.0f,  0.0f,  0.0f,  1.0f,
             0.0f,  0.0f,  1.0f,  1.0f,
             1.0f,  0.0f,  1.0f,  1.0f
          };
// 頂點索引
short cubeInx[] = { 0, 1, 2, // Top_Face1
0, 2, 3, // Top_Face2
4, 6, 5, // Bottom_Face1
4, 7, 6, // Bottom_Face2
2, 6, 7, // Left_face1
2, 7, 3, // Left_Face2
0, 4, 1, // Right_Face1
1, 4, 5, // Right_Face2
1, 5, 6, // Front_Face1
1, 6, 2, // Front_Face2
0, 3, 4, // Back_Face1
3, 7, 4 }; // Back_Face2

// 點的緩衝區
private FloatBuffer vertexBuffer;
//顏色的緩衝區
private FloatBuffer colorBuffer;
// 索引值緩衝區
private ShortBuffer indexBuffer;

public cube() {
// 初始化頂點緩衝
ByteBuffer bb = ByteBuffer.allocateDirect(cubeVtx.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubeVtx);
vertexBuffer.position(0);

//初始化顏色資料緩衝
ByteBuffer cb = ByteBuffer.allocateDirect(colors.length * 4);
cb.order(ByteOrder.nativeOrder());
colorBuffer = cb.asFloatBuffer();
colorBuffer.put(colors);
colorBuffer.position(0);

// 初始化索引緩衝
ByteBuffer ib = ByteBuffer.allocateDirect(cubeInx.length * 2);
ib.order(ByteOrder.nativeOrder());
indexBuffer = ib.asShortBuffer();
indexBuffer.put(cubeInx);
indexBuffer.position(0);

}

public void draw(GL10 gl) {
// 逆時鐘
 gl.glFrontFace(GL10.GL_CCW);
 // 啟動CULL_FACE
 gl.glEnable(GL10.GL_CULL_FACE);
 // 刪除多邀形的背景
 gl.glCullFace(GL10.GL_BACK);
// 啟動點的緩衝區
 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
 // 為畫筆指定頂點位置和資料格式
//啟動顏色的緩衝區
 gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
 //為畫筆指定頂點顏色資料
 gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
 // 以三點劃出三角形
 gl.glDrawElements(GL10.GL_TRIANGLES, cubeInx.length,
   GL10.GL_UNSIGNED_SHORT, indexBuffer);

}

}



public class OpenGLRenderer implements Renderer {
Cube cube;
public OpenGLRenderer() {
 // 初始化
 cube1=new cube();
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除螢幕和深度緩衝區
 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
 // 以單位矩陣取代目前的矩陣
 gl.glLoadIdentity();
 // Z軸轉置 10單位
 gl.glTranslatef(0, 0, -10);
    //可以加上這段讓Cube不斷旋轉
 long time = SystemClock.uptimeMillis()% 4000L;  
   float angle = 0.090f * ((int)time);  
   gl.glRotatef(angle, 1.0f, 0.0f, 0.0f);  
   gl.glRotatef(angle, 0.0f, 1.0f, 0.0f);  
   gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);  
 
    cube1.draw(gl);


}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// 設定新視域視窗的大小
 gl.glViewport(0, 0, width, height);
 // 選擇投射的陣列模式
 gl.glMatrixMode(GL10.GL_PROJECTION);
 // 重設投射陣
 gl.glLoadIdentity();
 // 計算視窗的寬高比率
 GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
   100.0f);
 //float ratio=(float)width/height;//比例大小
//gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//設定投影模式
 // 選擇MODELVIEW陣列
 gl.glMatrixMode(GL10.GL_MODELVIEW);
 // 重設MODELVIEW陣列
 gl.glLoadIdentity();
}


註;可以透過openGL Transformation函式或是投影操作, 讓Cube效果更顯著

2012年11月13日 星期二

Android:OpenGL 座標變換

*注意要領*

  1. 注意glPushMatrix以及glPopMatrix的交互使用配合以建構出設想的模式
  2. glTranslatef (float x, float y, float z) 平移座標軸
  3. glRotatef(float angle, float x, float y, float z) 旋轉座標軸
  4. glScalef (float x, float y, float z) 縮大或放小
  5. 可以透過不斷的改變角度或其他參數來達到動態的效果
OpenGLRenderer

package com.example.opengltest2;

import ...

public class OpenGLRenderer implements Renderer {
private Square square;
     private float angle=0;
public OpenGLRenderer() {
 // 初始化
 square = new Square();
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
// 清除螢幕和深度緩衝區
 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
 // 以單位矩陣取代目前的矩陣
 gl.glLoadIdentity();
 
 gl.glTranslatef(0, 0, -10);//Z軸轉置10單位
 
 //第一個方形,儲存目前陣列
 gl.glPushMatrix();
 //逆時鐘旋轉
 gl.glRotatef(angle, 0, 0, 1);
 //畫出第一個方形
 square.draw(gl);
 //復原回最後的矩陣
 gl.glPopMatrix();
 
 //第二個方形,儲存目前陣列
 gl.glPushMatrix();
 //先旋轉再移動,旋轉時讓第二個方形繞著第一個方形旋轉
 gl.glRotatef(-angle, 0, 0, 1);
 gl.glTranslatef(2, 0, 0);
 //調整大小為第一個方型的一半
 gl.glScalef(.5f, .5f, .5f);
 square.draw(gl);
 
// 第三個方形
 // 存儲目前陣列
 gl.glPushMatrix();
 // 讓第三個方形圍繞著第二個方形旋轉
 gl.glRotatef(-angle, 0, 0, 1);
 // 移動第三個方形
 gl.glTranslatef(2, 0, 0);
 // 調整其大小為第二個方形的一半
 gl.glScalef(.5f, .5f, .5f);
 // 以自己為中心旋轉,12倍目的是為了自轉比較快的效果
 gl.glRotatef(angle * 12, 0, 0, 1);
 // 畫出第三個方形.
 square.draw(gl);

 // 復原成第三個方形前的矩陣
 gl.glPopMatrix();
 // 復原成第二個方形前的矩陣
 gl.glPopMatrix();
 
 angle++;//讓圖形不斷的旋轉

}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
// 設定新視域視窗的大小
 gl.glViewport(0, 0, width, height);
 // 選擇投射的陣列模式
 gl.glMatrixMode(GL10.GL_PROJECTION);
 // 重設投射陣
 gl.glLoadIdentity();
 // 計算視窗的寬高比率
 GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
   100.0f);
 //float ratio=(float)width/height;//比例大小
//gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);//設定投影模式
 // 選擇MODELVIEW陣列
 gl.glMatrixMode(GL10.GL_MODELVIEW);
 // 重設MODELVIEW陣列
 gl.glLoadIdentity();
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
// 設定背景顏色為黑色, 格式是RGBA
 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
 // 設定流暢的陰影模式
 gl.glShadeModel(GL10.GL_SMOOTH);
 // 深度緩區的設定
 gl.glClearDepthf(1.0f);
 // 啟動深度的測試
 gl.glEnable(GL10.GL_DEPTH_TEST);
 // GL_LEQUAL深度函式測試
 gl.glDepthFunc(GL10.GL_LEQUAL);
 // 設定很好的角度計算模式
 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);

}

}






Android:OpenGL 加上顏色


package com.example.opengltest2;

import ...

public class Square {
// 點的陣列
private float vertices[] = { -1.0f, 1.0f, 0.0f, // 0, 左上角
  -1.0f, -1.0f, 0.0f, // 1, 左下角
  1.0f, -1.0f, 0.0f, // 2, 右下角
  1.0f, 1.0f, 0.0f, // 3, 右上角
};

// 顏色的陣列(RGBA)
float[] color=new float[]{
1.0f,0.0f,0.0f,1.0f,//左上角
0.0f,1.0f,0.0f,1.0f,//左下角
0.0f,0.0f,1.0f,1.0f,//右下角
1.0f,1.0f,0.0f,1.0f //右上角
};

// 連接點的次序
private short[] indices = { 0, 1, 2, 0, 2, 3 };

// 點的緩衝區
private FloatBuffer vertexBuffer;

// 顏色的緩衝區
private FloatBuffer colorBuffer;

// 索引值緩衝區
private ShortBuffer indexBuffer;

public Square() {
//初始化頂點座標暫存
// 浮點數是4位元組因此需要把點陣列長度乘以4
 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
 vbb.order(ByteOrder.nativeOrder());//設定為本機平台的位元組順序
 vertexBuffer = vbb.asFloatBuffer();//轉換為float形式的緩衝,並建立實例
 vertexBuffer.put(vertices);//將頂點座標陣列放進緩衝
 vertexBuffer.position(0);////設定緩衝區的起始位置

 //初始化座標顏色暫存,浮點數是4位元組因此需要把點陣列長度乘以4
 ByteBuffer cbb=ByteBuffer.allocateDirect(color.length*4);
 cbb.order(ByteOrder.nativeOrder());
 colorBuffer=cbb.asFloatBuffer();
 colorBuffer.put(color);
 colorBuffer.position(0);

 ////初始化構造索引資料緩衝
 // 短整數是2位元組因此需要把點陣列長度乘以2
 ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
 ibb.order(ByteOrder.nativeOrder());
 indexBuffer = ibb.asShortBuffer();
 indexBuffer.put(indices);
 indexBuffer.position(0);
}

/**
 * 畫圖函式
 *
 * @param gl
 */
public void draw(GL10 gl) {
 // 逆時鐘
 gl.glFrontFace(GL10.GL_CCW);
 // 啟動CULL_FACE
 gl.glEnable(GL10.GL_CULL_FACE);
 // 刪除多邀形的背景
 gl.glCullFace(GL10.GL_BACK);

 // 啟動點的緩衝區
 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
 // 為畫筆指定頂點位置和資料格式
 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

 //啟動顏色的緩衝區
 gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
 //為畫筆指定頂點顏色資料
 gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);

 // 以三點劃出三角形
 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
   GL10.GL_UNSIGNED_SHORT, indexBuffer);

 // 除能點的緩衝區
 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
 // 除能CULL_FACE
 gl.glDisable(GL10.GL_CULL_FACE);
}

}