看了幾天3D這些天才弄懂些畫圖,現在弄這個紋理煩得很,半懂半不懂的,這個例子是我到網站下載的,感覺不錯,先給大家看看,下期我再和大家討論討論。
package wyf.sj;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 Sample6_2 extends Activity { /** Called when the activity is first created. */ MySurfaceView mGLSurfaceView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mGLSurfaceView = new MySurfaceView(this); mGLSurfaceView.requestFocus();//擷取焦點 mGLSurfaceView.setFocusableInTouchMode(true);//設定為可觸控 LinearLayout ll=(LinearLayout)findViewById(R.id.main_liner); ll.addView(mGLSurfaceView); ToggleButton tb=(ToggleButton)this.findViewById(R.id.ToggleButton01); tb.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { mGLSurfaceView.setSmoothFlag(!mGLSurfaceView.isSmoothFlag());package wyf.sj;import java.io.IOException;import java.io.InputStream;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.opengl.GLSurfaceView;import android.opengl.GLUtils;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座標 private float mPreviousX;//上次的觸控位置Y座標private boolean smoothFlag=true;//是否進行平滑著色private int lightAngleGreen=0;//綠光燈的當前角度private int lightAngleRed=90;//紅光燈的當前角度int textureId;//紋理名稱IDpublic MySurfaceView(Context context) {super(context);mRenderer = new SceneRenderer();//建立情境渲染器 setRenderer(mRenderer);//設定渲染器 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//設定渲染模式為主動渲染 } @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;//設定沿x軸旋轉角度 mRenderer.ball.mAngleZ += dx * TOUCH_SCALE_FACTOR;//設定沿z軸旋轉角度 requestRender();//重繪畫面 } mPreviousY = y;//記錄觸控筆位置 mPreviousX = x;//記錄觸控筆位置 return true; } public void setSmoothFlag(boolean smoothFlag) {this.smoothFlag = smoothFlag;}public boolean isSmoothFlag() {return smoothFlag;}private class SceneRenderer implements GLSurfaceView.Renderer { Ball ball;public SceneRenderer(){ //開啟一個線程自動旋轉球體 new Thread() { public void run() { try { Thread.sleep(1000);//休息1000ms再開始繪製 } catch(Exception e) { e.printStackTrace(); } while(true) { lightAngleGreen+=5;//轉動綠燈 lightAngleRed+=5;//轉動紅燈 requestRender();//重繪畫面 try { Thread.sleep(50);//休息10ms再重繪 } catch(Exception e) { e.printStackTrace(); } } } }.start();} public void onDrawFrame(GL10 gl) { if(smoothFlag) {//進行平滑著色 gl.glShadeModel(GL10.GL_SMOOTH); } else {//不進行平滑著色 gl.glShadeModel(GL10.GL_FLAT); } //設定綠色光源的位置 float lxGreen=(float)(7*Math.cos(Math.toRadians(lightAngleGreen))); float lzGreen=(float)(7*Math.sin(Math.toRadians(lightAngleGreen))); float[] positionParamsGreen={lxGreen,0,lzGreen,1};//最後的1表示使用定位光 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, positionParamsGreen,0); //設定紅色光源的位置 float lyRed=(float)(7*Math.cos(Math.toRadians(lightAngleRed))); float lzRed=(float)(7*Math.sin(Math.toRadians(lightAngleRed))); float[] positionParamsRed={0,lyRed,lzRed,1};//最後的1表示使用定位光 gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionParamsRed,0); //清除顏色緩衝 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //設定當前矩陣為模式矩陣 gl.glMatrixMode(GL10.GL_MODELVIEW); //設定當前矩陣為單位矩陣 gl.glLoadIdentity(); gl.glTranslatef(0, 0f, -1.8f); gl.glPushMatrix();//保護變換矩陣現場 ball.drawSelf(gl);//繪製球 gl.glPopMatrix();//恢複變換矩陣現場 } public void onSurfaceChanged(GL10 gl, int width, int height) { //設定視窗大小及位置 gl.glViewport(0, 0, width, height); //設定當前矩陣為投影矩陣 gl.glMatrixMode(GL10.GL_PROJECTION); //設定當前矩陣為單位矩陣 gl.glLoadIdentity(); //計算透視投影的比例 float ratio = (float) width / height; //調用此方法計算產生透視投影矩陣 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); } public void onSurfaceCreated(GL10 gl, EGLConfig config) { //關閉抗抖動 gl.glDisable(GL10.GL_DITHER); //設定特定Hint項目的模式,這裡為設定為使用快速模式 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); //設定螢幕背景色黑色RGBA gl.glClearColor(0,0,0,0); //設定著色模型為平滑著色 gl.glShadeModel(GL10.GL_SMOOTH);//GL10.GL_SMOOTH GL10.GL_FLAT //啟用深度測試 gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_LIGHTING);//允許光照 initGreenLight(gl);//初始化綠色燈 initRedLight(gl);//初始化紅色燈 initMaterial(gl);//初始化材質 textureId=initTexture(gl,R.drawable.duke);//初始化紋理 ball=new Ball(4,textureId); }}//初始化綠色燈private void initGreenLight(GL10 gl){ gl.glEnable(GL10.GL_LIGHT0);//開啟0號燈 //環境光線設定 float[] ambientParams={0.1f,0.1f,0.1f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientParams,0); //散射光設定 float[] diffuseParams={0f,1f,0f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, diffuseParams,0); //反射光設定 float[] specularParams={1f,1f,1f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, specularParams,0); }//初始化紅色燈private void initRedLight(GL10 gl){ gl.glEnable(GL10.GL_LIGHT1);//開啟1號燈 //環境光線設定 float[] ambientParams={0.2f,0.2f,0.2f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientParams,0); //散射光設定 float[] diffuseParams={1f,0f,0f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseParams,0); //反射光設定 float[] specularParams={1f,1f,1f,1.0f};//光參數 RGBA gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, specularParams,0); }//初始化材質private void initMaterial(GL10 gl){//材質為白色時什麼顏色的光照在上面就將體現出什麼顏色 //環境光線為白色材質 float ambientMaterial[] = {1.0f, 1.0f, 1.0f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambientMaterial,0); //散射光為白色材質 float diffuseMaterial[] = {1.0f, 1.0f, 1.0f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuseMaterial,0); //高光材質為白色 float specularMaterial[] = {1f, 1f, 1f, 1.0f}; gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularMaterial,0); gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 100.0f);}public int initTexture(GL10 gl,int textureId)//textureId{int[] textures = new int[1];gl.glGenTextures(1, textures, 0); int currTextureId=textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT); InputStream is = this.getResources().openRawResource(textureId); Bitmap bitmapTmp; try { bitmapTmp = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) { e.printStackTrace(); } } GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0); bitmapTmp.recycle(); return currTextureId;}}package wyf.sj;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import java.nio.IntBuffer;import java.util.ArrayList;import javax.microedition.khronos.opengles.GL10;public class Ball {private IntBuffer mVertexBuffer;//頂點座標資料緩衝private IntBuffer mNormalBuffer;//頂點法向量資料緩衝 private FloatBuffer mTextureBuffer;//頂點紋理資料緩衝 public float mAngleX;//沿x軸旋轉角度 public float mAngleY;//沿y軸旋轉角度 public float mAngleZ;//沿z軸旋轉角度 int vCount=0;//頂點數量 int textureId;//紋理ID public Ball(int scale,int textureId) { this.textureId=textureId; final int UNIT_SIZE=10000; //實際頂點座標資料的初始化================begin============================ ArrayList<Integer> alVertix=new ArrayList<Integer>();//存放頂點座標的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度一份 {//縱向橫向各到一個角度後計算對應的此點在球面上的座標 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座標加入存放頂點座標的ArrayList alVertix.add(x);alVertix.add(y);alVertix.add(z); } } vCount=alVertix.size()/3;//頂點的數量為座標值數量的1/3,因為一個頂點有3個座標 //將alVertix中的座標值轉存到一個int數組中 int vertices[]=new int[vCount*3]; for(int i=0;i<alVertix.size();i++) { vertices[i]=alVertix.get(i); } //實際頂點座標資料的初始化================end============================ //三角形構造頂點、紋理、法向量資料初始化==========begin========================== alVertix.clear(); ArrayList<Float> alTexture=new ArrayList<Float>();//紋理 int row=(180/angleSpan)+1;//球面切分的行數 int col=360/angleSpan;//球面切分的列數 for(int i=0;i<row;i++)//對每一行迴圈 { if(i>0&&i<row-1) {//中間行 for(int j=-1;j<col;j++){//中間行的兩個相鄰點與下一行的對應點構成三角形int k=i*col+j;//第1個三角形頂點alVertix.add(vertices[(k+col)*3]);alVertix.add(vertices[(k+col)*3+1]);alVertix.add(vertices[(k+col)*3+2]);alTexture.add(0.0f);alTexture.add(0.0f);//第2個三角形頂點alVertix.add(vertices[(k+1)*3]);alVertix.add(vertices[(k+1)*3+1]);alVertix.add(vertices[(k+1)*3+2]);alTexture.add(1.0f);alTexture.add(1.0f);//第3個三角形頂點alVertix.add(vertices[k*3]);alVertix.add(vertices[k*3+1]);alVertix.add(vertices[k*3+2]);alTexture.add(1.0f);alTexture.add(0.0f);} for(int j=0;j<col+1;j++){//中間行的兩個相鄰點與上一行的對應點構成三角形int k=i*col+j;//第1個三角形頂點alVertix.add(vertices[(k-col)*3]);alVertix.add(vertices[(k-col)*3+1]);alVertix.add(vertices[(k-col)*3+2]);alTexture.add(1f);alTexture.add(1f);//第2個三角形頂點alVertix.add(vertices[(k-1)*3]);alVertix.add(vertices[(k-1)*3+1]);alVertix.add(vertices[(k-1)*3+2]);alTexture.add(0.0f);alTexture.add(0.0f);//第3個三角形頂點alVertix.add(vertices[k*3]);alVertix.add(vertices[k*3+1]);alVertix.add(vertices[k*3+2]);alTexture.add(0f);alTexture.add(1f); } } } vCount=alVertix.size()/3;//頂點的數量為座標值數量的1/3,因為一個頂點有3個座標 //將alVertix中的座標值轉存到一個int數組中 vertices=new int[vCount*3]; for(int i=0;i<alVertix.size();i++) { vertices[i]=alVertix.get(i); } //建立繪製頂點資料緩衝 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); vbb.order(ByteOrder.nativeOrder());//設定位元組順序 mVertexBuffer = vbb.asIntBuffer();//轉換為int型緩衝 mVertexBuffer.put(vertices);//向緩衝區中放入頂點座標資料 mVertexBuffer.position(0);//設定緩衝區起始位置 //建立頂點法向量資料緩衝 ByteBuffer nbb = ByteBuffer.allocateDirect(vertices.length*4); nbb.order(ByteOrder.nativeOrder());//設定位元組順序 mNormalBuffer = vbb.asIntBuffer();//轉換為int型緩衝 mNormalBuffer.put(vertices);//向緩衝區中放入頂點座標資料 mNormalBuffer.position(0);//設定緩衝區起始位置 //建立紋理座標緩衝 float textureCoors[]=new float[alTexture.size()];//頂點紋理值數組 for(int i=0;i<alTexture.size();i++) { textureCoors[i]=alTexture.get(i); } ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4); cbb.order(ByteOrder.nativeOrder());//設定位元組順序 mTextureBuffer = cbb.asFloatBuffer();//轉換為int型緩衝 mTextureBuffer.put(textureCoors);//向緩衝區中放入頂點著色資料 mTextureBuffer.position(0);//設定緩衝區起始位置 //三角形構造頂點、紋理、法向量資料初始化==========end============================== } public void drawSelf(GL10 gl) { gl.glRotatef(mAngleZ, 0, 0, 1);//沿Z軸旋轉 gl.glRotatef(mAngleX, 1, 0, 0);//沿X軸旋轉 gl.glRotatef(mAngleY, 0, 1, 0);//沿Y軸旋轉 //允許使用頂點數組 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//為畫筆指定頂點座標資料 gl.glVertexPointer ( 3,//每個頂點的座標數量為3 xyz GL10.GL_FIXED,//頂點座標值的類型為 GL_FIXED 0, //連續頂點座標資料之間的間隔 mVertexBuffer//頂點座標資料 ); //允許使用法向量數組 gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); //為畫筆指定頂點法向量資料 gl.glNormalPointer(GL10.GL_FIXED, 0, mNormalBuffer); //開啟紋理 gl.glEnable(GL10.GL_TEXTURE_2D); //允許使用紋理ST座標緩衝 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); //為畫筆指定紋理ST座標緩衝 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer); //綁定當前紋理 gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); //繪製圖形 gl.glDrawArrays ( GL10.GL_TRIANGLES, //以三角形方式填充 0, //開始點編號 vCount//頂點數量 ); }}} } ); } @Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume(); } @Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause(); } }