3D遊戲開發祥解-OpenGL 兩種投影(glFrustumf/glOrthof)結果比較

3D遊戲開發祥解-OpenGL 兩種投影(glFrustumf/glOrthof)結果比較

3D遊戲開發祥解-OpenGL 兩種投影(glFrustumf/glOrthof)結果比較

 

Sample4_5-Layout(Xml)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/main_liner"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<ToggleButton
	android:textOff="正交投影"
	android:textOn="透視投影"
	android:checked="false"
	android:id="@+id/ToggleButton01"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content">
</ToggleButton>
</LinearLayout>

Sample4_5-Code
-MyActivity.java(程式進入點)

 

package wyf.swq;
import wyf.swq.MySurfaceView;				//引入相關套件
import android.app.Activity;				//引入相關套件
import android.os.Bundle;					//引入相關套件
import android.widget.CompoundButton;		//引入相關套件
import android.widget.LinearLayout;			//引入相關套件
import android.widget.ToggleButton;			//引入相關套件
import android.widget.CompoundButton.OnCheckedChangeListener;	//引入相關套件
public class MyActivity extends Activity {
private MySurfaceView mSurfaceView;			//宣告MySurfaceView變數
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);			//設置佈局
mSurfaceView = new MySurfaceView(this);	//建立MySurfaceView物件
mSurfaceView.requestFocus();//獲取焦點	
mSurfaceView.setFocusableInTouchMode(true);//設置為可觸控  
LinearLayout ll=(LinearLayout)findViewById(R.id.main_liner); //獲得佈局引用
ll.addView(mSurfaceView);//在佈局中加入MySurfaceView物件
//控制是否打開背面剪裁的ToggleButton
ToggleButton tb=(ToggleButton)this.findViewById(R.id.ToggleButton01);//獲得按鈕引用
tb.setOnCheckedChangeListener(new MyListener());        //為按鈕設置監聽器
}
class MyListener implements OnCheckedChangeListener{
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
mSurfaceView.isPerspective=!mSurfaceView.isPerspective;//在正交投影與透視投影之間切換
mSurfaceView.requestRender();//重新繪製
}
}
@Override
protected void onResume() {	//
super.onResume();		//
mSurfaceView.onResume();//
}
@Override
protected void onPause() {	//
super.onPause();		//
mSurfaceView.onPause();	//
}
}

-MySurfaceView.java

 
package wyf.swq;
import android.opengl.GLSurfaceView;						//引入相關套件
import android.view.MotionEvent;							//引入相關套件
import javax.microedition.khronos.egl.EGLConfig;			//引入相關套件
import javax.microedition.khronos.opengles.GL10;			//引入相關套件
import android.content.Context;								//引入相關套件
class MySurfaceView extends GLSurfaceView {
private final float TOUCH_SCALE_FACTOR = 180.0f/320;	//角度縮放比例
private SceneRenderer mRenderer;						//場景顯示器
public boolean isPerspective=false;						//投影標誌位元
private float mPreviousY;								//上次的觸控位置Y座標
public float xAngle=0;									//整體繞x軸旋轉的角度  
public MySurfaceView(Context context) {
super(context);
mRenderer = new SceneRenderer();					//建立場景顯示器
setRenderer(mRenderer);								//設置顯示器		
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//主動顯示   
}
//觸控事件回呼方法
@Override
public boolean onTouchEvent(MotionEvent e) {
float y = e.getY();
switch (e.getAction()) {							//獲取動作
case MotionEvent.ACTION_MOVE:						//判斷��否��滑動
float dy = y - mPreviousY;						//計算觸控筆Y位移
xAngle+= dy * TOUCH_SCALE_FACTOR;				//設置沿x軸旋轉角度
requestRender();								//重繪畫面
}
mPreviousY = y;										//作為上一次觸點的Y座標
return true;
}
private class SceneRenderer implements GLSurfaceView.Renderer {
Hexagon[] ha=new Hexagon[]{							//六邊形陣列
new Hexagon(0),
new Hexagon(-2),
new Hexagon(-4),
new Hexagon(-6),
new Hexagon(-8),
new Hexagon(-10),
new Hexagon(-12),
};
public SceneRenderer(){}						//顯示器建構子
@Override
public void onDrawFrame(GL10 gl) {
gl.glMatrixMode(GL10.GL_PROJECTION);		//設置當前矩陣為投影矩陣
gl.glLoadIdentity(); 						//設置當前矩陣為單位矩陣        
float ratio = (float) 320/480;				//計算透視投影的比例
if(isPerspective){
gl.glFrustumf(-ratio, ratio, -1, 1, 1f, 10);//呼叫此方法計算產生透視投影矩陣
}
else{
gl.glOrthof(-ratio, ratio, -1, 1, 1, 10);//呼叫此方法計算產生正交投影矩陣
}
gl.glEnable(GL10.GL_CULL_FACE);				//設置為打開背面剪裁	
gl.glShadeModel(GL10.GL_SMOOTH);    		//設置著色模型為平滑著色       	
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);//清除緩��
gl.glMatrixMode(GL10.GL_MODELVIEW);			//設置當前矩陣為模式矩陣
gl.glLoadIdentity();    			 		//設置當前矩陣為單位矩陣
gl.glTranslatef(0, 0f, -1.4f); 				//沿z軸向遠處推
gl.glRotatef(xAngle, 1, 0, 0);				//繞x軸旋轉制定角度
for(Hexagon th:ha){
th.drawSelf(gl);				//迴圈繪製六邊形陣列中的每個六邊形
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height); //設置視窗大小及位置              
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);								//關閉抗震動 
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);//設置Hint模式
gl.glClearColor(0,0,0,0);									//設置螢幕背景色黑色            
gl.glEnable(GL10.GL_DEPTH_TEST);							//啟用深度測試
}}}
 

-Hexagon.java

 

package wyf.swq;
import java.nio.ByteBuffer;					//引入相關套件
import java.nio.ByteOrder;					//引入相關套件
import java.nio.IntBuffer;					//引入相關套件
import javax.microedition.khronos.opengles.GL10;
public class Hexagon {
private IntBuffer   mVertexBuffer;		//頂點座標資料緩衝
private IntBuffer   mColorBuffer;		//頂點著色資料緩衝
private ByteBuffer  mIndexBuffer;		//頂點建構索引資料緩衝
int vCount=0;							//圖形頂點數量
int iCount=0;							//索引頂點數量
public Hexagon(int zOffset){
//頂點座標資料的初始化
vCount=7;
final int UNIT_SIZE=10000;
int vertices[]=new int[]{
0*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
2*UNIT_SIZE,3*UNIT_SIZE,zOffset*UNIT_SIZE,
4*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
2*UNIT_SIZE,-3*UNIT_SIZE,zOffset*UNIT_SIZE,
-2*UNIT_SIZE,-3*UNIT_SIZE,zOffset*UNIT_SIZE,
-4*UNIT_SIZE,0*UNIT_SIZE,zOffset*UNIT_SIZE,
-2*UNIT_SIZE,3*UNIT_SIZE,zOffset*UNIT_SIZE
};
//建立頂點座標資料緩衝
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());//設置位元組順序
mVertexBuffer = vbb.asIntBuffer();//轉換為int型緩衝
mVertexBuffer.put(vertices);//向緩衝區中放入頂點座標資料
mVertexBuffer.position(0);//設置緩衝區起始位置
//頂點著色數據的初始化
final int one = 65535;
int colors[]=new int[]//頂點顏色值陣列,每個頂點4個色彩值RGBA
{
0,0,one,0,
0,one,0,0,
0,one,one,0,
one,0,0,0,
one,0,one,0,
one,one,0,0,
one,one,one,0
};
//建立頂點著色資料緩衝
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());//設置位元組順序
mColorBuffer = cbb.asIntBuffer();//轉換為int型緩衝
mColorBuffer.put(colors);//向緩衝區中放入頂點著色數據
mColorBuffer.position(0);//設置緩衝區起始位置
//三角形建構索引資料初始化
iCount=18;
byte indices[]=new byte[]{
0,2,1,
0,3,2,
0,4,3,
0,5,4,
0,6,5,
0,1,6
};
//建立三角形構造索引資料緩衝
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);//向緩衝區中放入三角形建構索引資料
mIndexBuffer.position(0);//設置緩衝區起始位置
}
public void drawSelf(GL10 gl){
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//啟用頂點座標陣列
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);//啟用頂點顏色陣列
gl.glVertexPointer(//為畫筆指定頂點座標資料     
3,				//每個頂點的座標數量為3  xyz 
GL10.GL_FIXED,	//頂點座標值的類型為 GL_FIXED
0, 				//連續頂點座標資料之間的間隔
mVertexBuffer	//頂點座標資料
);
gl.glColorPointer(//為畫筆指定頂點著色數據     
4, 				//設置顏色的組成成分,必須為4—RGBA
GL10.GL_FIXED, 	//頂點顏色值的類型為 GL_FIXED
0, 				//連續頂點著色資料之間的間隔
mColorBuffer	//頂點著色數據
);
gl.glDrawElements(//索引法繪製圖形
GL10.GL_TRIANGLES, 		//以三角形方式填充
iCount, 			 	//一共icount/3個三角形,iCount個頂點
GL10.GL_UNSIGNED_BYTE, 	//索引值的尺寸
mIndexBuffer			//索引值資料
);
}}

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *