Android應(yīng)用: 3D旋轉(zhuǎn)球
package?com.example.android_sample_5_2;
import?java.nio.ByteBuffer;
import?java.nio.ByteOrder;
import?java.nio.IntBuffer;
import?java.util.ArrayList;
import?javax.microedition.khronos.opengles.GL10;
public?class?Ball?{
private?IntBuffer???mVertexBuffer;//頂點坐標(biāo)數(shù)據(jù)緩沖
private?IntBuffer???mNormalBuffer;//頂點法向量數(shù)據(jù)緩沖
????private?ByteBuffer??mIndexBuffer;//頂點構(gòu)建索引數(shù)據(jù)緩沖
????public?float?mAngleX;//沿x軸旋轉(zhuǎn)角度
????public?float?mAngleY;//沿y軸旋轉(zhuǎn)角度?
????public?float?mAngleZ;//沿z軸旋轉(zhuǎn)角度?
????int?vCount=0;
????int?iCount=0;
????public?Ball(int?scale)
????{
???? //頂點坐標(biāo)數(shù)據(jù)的初始化================begin============================
???? final?int?UNIT_SIZE=10000;
???? ArrayListalVertix=new?ArrayList();//存放頂點坐標(biāo)的ArrayList
???? final?int?angleSpan=18;//將球進行單位切分的角度
????????for(int?vAngle=-90;vAngle<=90;vAngle=vAngle+angleSpan)//垂直方向angleSpan度一份
????????{
???????? for(int?hAngle=0;hAngle<360;hAngle=hAngle+angleSpan)//水平方向angleSpan度一份
???????? {//縱向橫向各到一個角度后計算對應(yīng)的此點在球面上的坐標(biāo)
???????? double?xozLength=scale*UNIT_SIZE*Math.cos(Math.toRadians(vAngle));
???????? int?x=(int)(xozLength*Math.cos(Math.toRadians(hAngle)));
???????? int?z=(int)(xozLength*Math.sin(Math.toRadians(hAngle)));
???????? int?y=(int)(scale*UNIT_SIZE*Math.sin(Math.toRadians(vAngle)));
???????? //將計算出來的XYZ坐標(biāo)加入存放頂點坐標(biāo)的ArrayList
???????? alVertix.add(x);alVertix.add(y);alVertix.add(z);
???????? }
????????}?
????????vCount=alVertix.size()/3;//頂點的數(shù)量為坐標(biāo)值數(shù)量的1/3,因為一個頂點有3個坐標(biāo)
????
????????//將alVertix中的坐標(biāo)值轉(zhuǎn)存到一個int數(shù)組中
????????int?vertices[]=new?int[vCount*3];
???? for(int?i=0;i<alVertix.size();i++)
???? {
???? vertices[i]=alVertix.get(i);
???? }
????????//創(chuàng)建頂點坐標(biāo)數(shù)據(jù)緩沖
????????//vertices.length*4是因為一個整數(shù)四個字節(jié)
????????ByteBuffer?vbb?=?ByteBuffer.allocateDirect(vertices.length*4);
????????vbb.order(ByteOrder.nativeOrder());//設(shè)置字節(jié)順序
????????mVertexBuffer?=?vbb.asIntBuffer();//轉(zhuǎn)換為int型緩沖
????????mVertexBuffer.put(vertices);//向緩沖區(qū)中放入頂點坐標(biāo)數(shù)據(jù)
????????mVertexBuffer.position(0);//設(shè)置緩沖區(qū)起始位置?????
????????
????????
????????//創(chuàng)建頂點法向量數(shù)據(jù)緩沖
????????//vertices.length*4是因為一個float四個字節(jié)
????????ByteBuffer?nbb?=?ByteBuffer.allocateDirect(vertices.length*4);
????????nbb.order(ByteOrder.nativeOrder());//設(shè)置字節(jié)順序
????????mNormalBuffer?=?vbb.asIntBuffer();//轉(zhuǎn)換為int型緩沖
????????mNormalBuffer.put(vertices);//向緩沖區(qū)中放入頂點坐標(biāo)數(shù)據(jù)
????????mNormalBuffer.position(0);//設(shè)置緩沖區(qū)起始位置
????????
????????
????????//特別提示:由于不同平臺字節(jié)順序不同數(shù)據(jù)單元不是字節(jié)的一定要經(jīng)過ByteBuffer
????????//轉(zhuǎn)換,關(guān)鍵是要通過ByteOrder設(shè)置nativeOrder(),否則有可能會出問題
????????//頂點坐標(biāo)數(shù)據(jù)的初始化================end============================
????????
???????????????
????????//三角形構(gòu)造索引數(shù)據(jù)初始化==========begin==========================
????????ArrayListalIndex=new?ArrayList();
????????int?row=(180/angleSpan)+1;//球面切分的行數(shù)
????????int?col=360/angleSpan;//球面切分的列數(shù)
????????for(int?i=0;i0&&i<row-1)
???????? {//中間行
???????? for(int?j=-1;j<col;j++)
{//中間行的兩個相鄰點與下一行的對應(yīng)點構(gòu)成三角形
int?k=i*col+j;
alIndex.add(k+col);
alIndex.add(k+1);
alIndex.add(k);
}
???????? for(int?j=0;j<col+1;j++)
{//中間行的兩個相鄰點與上一行的對應(yīng)點構(gòu)成三角形
int?k=i*col+j;
alIndex.add(k-col);
alIndex.add(k-1);
alIndex.add(k);
}
???????? }
????????}
????????iCount=alIndex.size();
????????byte?indices[]=new?byte[alIndex.size()];
????????for(int?i=0;i<alIndex.size();i++)
????????{
???????? indices[i]=alIndex.get(i).byteValue();
????????}?
????????//創(chuàng)建三角形構(gòu)造索引數(shù)據(jù)緩沖
????????mIndexBuffer?=?ByteBuffer.allocateDirect(indices.length);
????????mIndexBuffer.put(indices);//向緩沖區(qū)中放入三角形構(gòu)造索引數(shù)據(jù)
????????mIndexBuffer.position(0);//設(shè)置緩沖區(qū)起始位置
??????//三角形構(gòu)造索引數(shù)據(jù)初始化==========end==============================
????}
????public?void?drawSelf(GL10?gl)
????{
???? gl.glRotatef(mAngleZ,?0,?0,?1);//沿Z軸旋轉(zhuǎn)
???? gl.glRotatef(mAngleX,?1,?0,?0);//沿X軸旋轉(zhuǎn)
????????gl.glRotatef(mAngleY,?0,?1,?0);//沿Y軸旋轉(zhuǎn)
????????
????????gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
????????gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
????????
//為畫筆指定頂點坐標(biāo)數(shù)據(jù)
????????gl.glVertexPointer
????????(
???????? 3, //每個頂點的坐標(biāo)數(shù)量為3??xyz?
???????? GL10.GL_FIXED, //頂點坐標(biāo)值的類型為?GL_FIXED
???????? 0,? //連續(xù)頂點坐標(biāo)數(shù)據(jù)之間的間隔
???????? mVertexBuffer //頂點坐標(biāo)數(shù)據(jù)
????????);
????????
????????//為畫筆指定頂點法向量數(shù)據(jù)
????????gl.glNormalPointer(GL10.GL_FIXED,?0,?mNormalBuffer);
????????//繪制圖形
????????gl.glDrawElements
????????(
???????? GL10.GL_TRIANGLES,? //以三角形方式填充
???????? iCount,? ? //一共icount/3個三角形,iCount個頂點
???????? GL10.GL_UNSIGNED_BYTE,? //索引值的尺寸
???????? mIndexBuffer //索引值數(shù)據(jù)
????????);?
????}
}MySyrfaceView類
package?com.example.android_sample_5_2;
import?javax.microedition.khronos.egl.EGLConfig;
import?javax.microedition.khronos.opengles.GL10;
import?android.content.Context;
import?android.opengl.GLSurfaceView;
import?android.view.MotionEvent;
public?class?MySurfaceView?extends?GLSurfaceView{
????private?final?float?TOUCH_SCALE_FACTOR?=?180.0f/320;//角度縮放比例
????private?SceneRenderer?mRenderer;//場景渲染器
????private?float?mPreviousY;//上次的觸控位置Y坐標(biāo)
????private?float?mPreviousX;//上次的觸控位置Y坐標(biāo)
????boolean?openLightFlag=true;//開燈標(biāo)記,false為關(guān)燈,true為開燈
????int?openLightNum=1; //開燈數(shù)量標(biāo)記,1為一盞燈,2,為兩盞燈...
public?MySurfaceView(Context?context)?{
????????super(context);
????????mRenderer?=?new?SceneRenderer(); //創(chuàng)建場景渲染器
????????setRenderer(mRenderer); //設(shè)置渲染器
????????setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//設(shè)置渲染模式為主動渲染???
????}
????//觸摸事件回調(diào)方法
????@Override?public?boolean?onTouchEvent(MotionEvent?e)?{
????????float?y?=?e.getY();
????????float?x?=?e.getX();
????????switch?(e.getAction())?{
????????case?MotionEvent.ACTION_MOVE:
????????????float?dy?=?y?-?mPreviousY;//計算觸控筆Y位移
????????????float?dx?=?x?-?mPreviousX;//計算觸控筆Y位移
????????????mRenderer.ball.mAngleX?+=?dy?*?TOUCH_SCALE_FACTOR;//設(shè)置沿x軸旋轉(zhuǎn)角度
????????????mRenderer.ball.mAngleZ?+=?dx?*?TOUCH_SCALE_FACTOR;//設(shè)置沿z軸旋轉(zhuǎn)角度
????????????requestRender();//重繪畫面
????????}
????????mPreviousY?=?y;//記錄觸控筆位置
????????mPreviousX?=?x;//記錄觸控筆位置
????????return?true;
????}
private?class?SceneRenderer?implements?GLSurfaceView.Renderer?
????{???
???? Ball?ball=new?Ball(4);
????
???? public?SceneRenderer(){
???? }
????????public?void?onDrawFrame(GL10?gl){???
???????? gl.glShadeModel(GL10.GL_SMOOTH);
???????? gl.glEnable(GL10.GL_LIGHTING);//允許光照??
???????? initMaterialWhite(gl);//初始化材質(zhì)為白色
???????? float[]?positionParams0={2,1,0,1};//最后的1表示是定位光,此為0號燈位置參數(shù)。
???????? float[]?positionParams1={-2,1,0,1};//最后的1表示是定位光,此為1號燈位置參數(shù)。
???????? float[]?positionParams2={0,0,2,1};//最后的1表示是定位光,此為2號燈位置參數(shù)。
???????? float[]?positionParams3={1,1,2,1};//最后的1表示是定位光,此為3號燈位置參數(shù)。
???????? float[]?positionParams4={-1,-1,2,1};//最后的1表示是定位光,此為4號燈位置參數(shù)。
???????? gl.glDisable(GL10.GL_LIGHT0); //每次繪制前,取消已開啟的燈光效果
???????? gl.glDisable(GL10.GL_LIGHT1); //每次繪制前,取消已開啟的燈光效果
???????? gl.glDisable(GL10.GL_LIGHT2); //每次繪制前,取消已開啟的燈光效果
???????? gl.glDisable(GL10.GL_LIGHT3); //每次繪制前,取消已開啟的燈光效果
???????? gl.glDisable(GL10.GL_LIGHT4); //每次繪制前,取消已開啟的燈光效果
????????
???????? switch(openLightNum){
???????? case?1: //開啟一盞燈
???????? initLight0(gl);//初始化0號燈
????????
????????????????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_POSITION,?positionParams0,0);?
???????? break;
???????? case?2: //開啟兩盞燈
???????? initLight0(gl);//初始化0號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_POSITION,?positionParams0,0);?
????????????????????
????????????????????initLight1(gl);//初始化1號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_POSITION,?positionParams1,0);?
???????? break;
???????? case?3: //開啟三盞燈
???????? initLight0(gl);//初始化0號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_POSITION,?positionParams0,0);?
????????????????????
????????????????????initLight1(gl);//初始化1號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_POSITION,?positionParams1,0);?
????????????????????
????????????????????initLight2(gl);//初始化2號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_POSITION,?positionParams2,0);?
???????? break;
???????? case?4: //開啟四盞燈
???????? initLight0(gl);//初始化0號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_POSITION,?positionParams0,0);?
????????????????????
????????????????????initLight1(gl);//初始化1號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_POSITION,?positionParams1,0);?
????????????????????
????????????????????initLight2(gl);//初始化2號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_POSITION,?positionParams2,0);?
????????
????????????????????initLight3(gl);//初始化3號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT3,?GL10.GL_POSITION,?positionParams3,0);?
????????????????????break;
???????? case?5: //開啟五盞燈
???????? initLight0(gl);//初始化0號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_POSITION,?positionParams0,0);?
????????????????????
????????????????????initLight1(gl);//初始化1號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_POSITION,?positionParams1,0);?
????????????????????
????????????????????initLight2(gl);//初始化2號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_POSITION,?positionParams2,0);?
????????
????????????????????initLight3(gl);//初始化3號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT3,?GL10.GL_POSITION,?positionParams3,0);?
????????????????????
????????????????????initLight4(gl);//初始化4號燈
????????????????????gl.glLightfv(GL10.GL_LIGHT4,?GL10.GL_POSITION,?positionParams4,0);?
????????????????????break;
???????? }
???????? //清除顏色緩存
???????? gl.glClear(GL10.GL_COLOR_BUFFER_BIT?|?GL10.GL_DEPTH_BUFFER_BIT);
???????? //設(shè)置當(dāng)前矩陣為模式矩陣
????????????gl.glMatrixMode(GL10.GL_MODELVIEW);
????????????//設(shè)置當(dāng)前矩陣為單位矩陣
????????????gl.glLoadIdentity();?????
????????????
????????????gl.glTranslatef(0,?0f,?-1.8f);??
????????????ball.drawSelf(gl);
????????????gl.glLoadIdentity();
????????}
????????public?void?onSurfaceChanged(GL10?gl,?int?width,?int?height)?{
????????????//設(shè)置視窗大小及位置?
???????? gl.glViewport(0,?0,?width,?height);
???????? //設(shè)置當(dāng)前矩陣為投影矩陣
????????????gl.glMatrixMode(GL10.GL_PROJECTION);
????????????//設(shè)置當(dāng)前矩陣為單位矩陣
????????????gl.glLoadIdentity();
????????????//計算透視投影的比例
????????????float?ratio?=?(float)?width?/?height;
????????????//調(diào)用此方法計算產(chǎn)生透視投影矩陣
????????????gl.glFrustumf(-ratio,?ratio,?-1,?1,?1,?10);
????????}
????????public?void?onSurfaceCreated(GL10?gl,?EGLConfig?config)?{
????????????//關(guān)閉抗抖動?
???????? gl.glDisable(GL10.GL_DITHER);
???????? //設(shè)置特定Hint項目的模式,這里為設(shè)置為使用快速模式
????????????gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
????????????//設(shè)置屏幕背景色黑色RGBA
????????????gl.glClearColor(0,0,0,0);
????????????//設(shè)置著色模型為平滑著色???
????????????gl.glShadeModel(GL10.GL_SMOOTH);//GL10.GL_SMOOTH??GL10.GL_FLAT
????????????//啟用深度測試
????????????gl.glEnable(GL10.GL_DEPTH_TEST);
????????}
????}
private?void?initLight0(GL10?gl){
????????gl.glEnable(GL10.GL_LIGHT0);//打開0號燈??,白色
????????//環(huán)境光設(shè)置
????????float[]?ambientParams={0.1f,0.1f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_AMBIENT,?ambientParams,0);????????????
????????//散射光設(shè)置
????????float[]?diffuseParams={0.5f,0.5f,0.5f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_DIFFUSE,?diffuseParams,0);?
????????//反射光設(shè)置
????????float[]?specularParams={1.0f,1.0f,1.0f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT0,?GL10.GL_SPECULAR,?specularParams,0);?????
}
private?void?initLight1(GL10?gl)
{
????????gl.glEnable(GL10.GL_LIGHT1);//打開1號燈??,紅色
????????//環(huán)境光設(shè)置
????????float[]?ambientParams={0.2f,0.03f,0.03f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_AMBIENT,?ambientParams,0);????????????
????????//散射光設(shè)置
????????float[]?diffuseParams={0.5f,0.1f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_DIFFUSE,?diffuseParams,0);?
????????//反射光設(shè)置
????????float[]?specularParams={1.0f,0.1f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT1,?GL10.GL_SPECULAR,?specularParams,0);?????
}
private?void?initLight2(GL10?gl)
{
????????gl.glEnable(GL10.GL_LIGHT2);//打開1號燈??,藍色
????????//環(huán)境光設(shè)置
????????float[]?ambientParams={0.03f,0.03f,0.2f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_AMBIENT,?ambientParams,0);????????????
????????//散射光設(shè)置
????????float[]?diffuseParams={0.1f,0.1f,0.5f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_DIFFUSE,?diffuseParams,0);?
????????//反射光設(shè)置
????????float[]?specularParams={0.1f,0.1f,1.0f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT2,?GL10.GL_SPECULAR,?specularParams,0);?????
}
private?void?initLight3(GL10?gl)
{
????????gl.glEnable(GL10.GL_LIGHT3);//打開3號燈??,綠色
????????//環(huán)境光設(shè)置
????????float[]?ambientParams={0.03f,0.2f,0.03f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT3,?GL10.GL_AMBIENT,?ambientParams,0);????????????
????????//散射光設(shè)置
????????float[]?diffuseParams={0.1f,0.5f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT3,?GL10.GL_DIFFUSE,?diffuseParams,0);?
????????//反射光設(shè)置
????????float[]?specularParams={0.1f,1.0f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT3,?GL10.GL_SPECULAR,?specularParams,0);?????
}
private?void?initLight4(GL10?gl)
{
????????gl.glEnable(GL10.GL_LIGHT4);//打開3號燈??,黃色
????????//環(huán)境光設(shè)置
????????float[]?ambientParams={0.2f,0.2f,0.03f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT4,?GL10.GL_AMBIENT,?ambientParams,0);????????????
????????//散射光設(shè)置
????????float[]?diffuseParams={0.5f,0.5f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT4,?GL10.GL_DIFFUSE,?diffuseParams,0);?
????????//反射光設(shè)置
????????float[]?specularParams={1.0f,1.0f,0.1f,1.0f};//光參數(shù)?RGBA
????????gl.glLightfv(GL10.GL_LIGHT4,?GL10.GL_SPECULAR,?specularParams,0);?????
}
private?void?initMaterialWhite(GL10?gl)
{//材質(zhì)為白色時什么顏色的光照在上面就將體現(xiàn)出什么顏色
????????//環(huán)境光為白色材質(zhì)
????????float?ambientMaterial[]?=?{0.4f,?0.4f,?0.4f,?1.0f};
????????gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,?GL10.GL_AMBIENT,?ambientMaterial,0);
????????//散射光為白色材質(zhì)
????????float?diffuseMaterial[]?=?{0.8f,?0.8f,?0.8f,?1.0f};
????????gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,?GL10.GL_DIFFUSE,?diffuseMaterial,0);
????????//高光材質(zhì)為白色
????????float?specularMaterial[]?=?{1.0f,?1.0f,?1.0f,?1.0f};
????????gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,?GL10.GL_SPECULAR,?specularMaterial,0);
????????//高光反射區(qū)域,數(shù)越大高亮區(qū)域越小越暗
????????float?shininessMaterial[]?=?{1.5f};
????????gl.glMaterialfv(GL10.GL_FRONT_AND_BACK,?GL10.GL_SHININESS,?shininessMaterial,0);
}
}
MainActivity類
package?com.example.android_sample_5_2;
import?android.os.Bundle;
import?android.app.Activity;
import?android.view.Menu;
import?android.widget.LinearLayout;
import?android.widget.RatingBar;
import?android.widget.Toast;
public?class?MainActivity?extends?Activity?{
MySurfaceView?msv;
RatingBar?rb;
@Override
protected?void?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
msv?=?new?MySurfaceView(this);
setContentView(R.layout.activity_main);
rb?=?(RatingBar)?findViewById(R.id.RatingBar01);
msv.requestFocus();
msv.setFocusableInTouchMode(true);
LinearLayout?lla?=?(LinearLayout)?findViewById(R.id.lla);
lla.addView(msv);
rb.setOnRatingBarChangeListener(new?RatingBar.OnRatingBarChangeListener()?{
@Override
public?void?onRatingChanged(RatingBar?ratingBar,?float?rating,
boolean?fromUser)?{
//?TODO?Auto-generated?method?stub
if?(rating?>=?0?&&?rating??1?&&?rating??2?&&?rating??3?&&?rating??4?&&?rating?<=?5){
msv.openLightNum?=?5;
}
Toast.makeText(MainActivity.this,?"開啟了"?+?msv.openLightNum?+?"盞燈",?Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected?void?onPause()?{
//?TODO?Auto-generated?method?stub
super.onPause();
msv.onPause();
}
@Override
protected?void?onResume()?{
//?TODO?Auto-generated?method?stub
super.onResume();
msv.onResume();
}
@Override
public?boolean?onCreateOptionsMenu(Menu?menu)?{
//?Inflate?the?menu;?this?adds?items?to?the?action?bar?if?it?is?present.
getMenuInflater().inflate(R.menu.main,?menu);
return?true;
}
}




