android 3D-紋理——球的紋理 – Android移動開發技術文章_手機開發 Android移動開發教學課程

 

看瞭幾天3D這些天才弄懂些畫圖,現在弄這個紋理煩得很,半懂半不懂的,這個例子是我到網站下載的,感覺不錯,先給大傢看看,下期我再和大傢討論討論。

<span style="font-family:FangSong_GB2312;"></span><p><img style="width: 331px; height: 305px;" src="file:///D:\Users\nate\AppData\Roaming\Tencent\Users\397319689\QQ\WinTemp\RichOle\EUJB][9W]%TQK]_]43IED}2.jpg" width="299" height="30" alt="" /></p> 

 

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()); 

<pre class="html" name="code">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;//紋理名稱ID 

 

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(); 

        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; 

 

view plain

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;vAnglevAngle=vAngle+angleSpan)//垂直方向angleSpan度一份 

        { 

            for(int hAngle=0;hAngle<360;hAnglehAngle=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(); } }

 

摘自 dlnuchunge的專欄

發佈留言