Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android OpenGLES2.0(六)——構建圓錐、圓柱和球體

Android OpenGLES2.0(六)——構建圓錐、圓柱和球體

編輯:關於Android編程

之前的博客中,我們繪制了三角形、正方形、圓形、立方體,今天我們將繪制圓錐、圓柱和球體。能夠繪制這些基本的常規幾何形體後,其他的常見幾何形體的繪制對於我們來說就基本沒問題了。

繪制圓錐

由之前的博客,我們大家也應該都知道了,OpenGL ES2.0中物體的繪制重點就是在於把這個物體表面分解成三角形,分解成功後,繪制自然就不成問題了。圓錐我們很容易就能想到把它拆解成一個圓形和一個錐面,錐面的頂點與圓形的頂點,除了錐面的中心點的坐標有了“高度”,其他的完全相同。圓形在Android OpenGLES2.0(四)——正方形和圓形中我們已經繪制過,那麼錐面其實對於我們來說也是小case了:

ArrayList<float> pos=new ArrayList<>();
pos.add(0.0f);
pos.add(0.0f);
pos.add(height);        //給圓心相對圓邊增加高度,使之形成錐面
float angDegSpan=360f/n;
for(float i=0;i<360+angDegSpan;i+=angDegSpan){
    pos.add((float) (radius*Math.sin(i*Math.PI/180f)));
    pos.add((float)(radius*Math.cos(i*Math.PI/180f)));
    pos.add(0.0f);
}
float[] d=new float[pos.size()];    //所有的頂點
for (int i=0;i<d.length;i++){ pre="">

我們按照繪制圓形的方式,繪制出錐面,然後再在這個錐面的底部繪制一個圓形,這樣我們就得到了一個圓錐了:

圓錐

從圖中我們可以看到,我們繪制的並不是同樣的顏色,如果使用同樣的顏色,很難看出圓錐的立體效果。這種顏色怎麼實現的呢?我們來看它的頂點著色器(片元著色器和之前相同):

uniform mat4 vMatrix;
varying vec4 vColor;
attribute vec4 vPosition;

void main(){
    gl_Position=vMatrix*vPosition;
    if(vPosition.z!=0.0){
        vColor=vec4(0.0,0.0,0.0,1.0);
    }else{
        vColor=vec4(0.9,0.9,0.9,1.0);
    }
}

在頂點著色器中,並沒有傳入顏色,而是在程序中直接判斷進行賦值的,當然也有可以頂點顏色和定邊顏色由外面傳入。在著色器中,我們不再是簡單的賦值,而是加入了流程控制。在下一篇博客中將會專門講解我們使用的著色器語言GLSL——Android OpenGLES 2.0(七)——著色器語言GLSL。

繪制圓柱

圓柱的與圓錐類似,我們可以把圓柱拆解成上下兩個圓面,加上一個圓筒。圓筒我們之前也沒畫過,它怎麼拆解成三角形呢?我們可以如同拆圓的思路來理解圓柱,想想正三菱柱、正八菱柱、正一百菱柱……菱越多,就越圓滑與圓柱越接近了,然後再把每個菱面(矩形)拆解成兩個三角形就OK了,拆解的頂點為:

ArrayList pos=new ArrayList<>();
float angDegSpan=360f/n;
for(float i=0;i<360+angDegSpan;i+=angDegSpan){
    pos.add((float) (radius*Math.sin(i*Math.PI/180f)));
    pos.add((float)(radius*Math.cos(i*Math.PI/180f)));
    pos.add(height);
    pos.add((float) (radius*Math.sin(i*Math.PI/180f)));
    pos.add((float)(radius*Math.cos(i*Math.PI/180f)));
    pos.add(0.0f);
}
float[] d=new float[pos.size()];
for (int i=0;i

這樣我們就可以繪制出一個圓筒了,只需要在頂部繪制一個圓,底部繪制一個圓,就得到了一個圓柱了: 圓柱

繪制球體

相對於圓錐圓柱來說,球體的拆解就復雜了許多,比較常見的拆解方法是將按照經緯度拆解和按照正多面體拆解,下圖分別為正多面體示意和經緯度拆解示意:

正多面體的方法拆解: 多面體 經緯度的方法拆解(每一個小塊看做一個矩形,再拆成三角形。PS:人懶,不想做圖。): 這裡寫圖片描述

由圖我們也能看出來,多面體雖然看起來好看點,但是還是按照經緯度的方式來拆解計算容易點,畢竟規律那麼明顯。

球上點的坐標

無論是按照經緯度拆還是按照多面體拆,都需要知道球上面點的坐標,這算是基本的幾何知識了。以球的中心為坐標中心,球的半徑為R的話,那麼球上點的坐標則為: (R?cos(ψ)?sin(λ),R?sin(ψ),R?cos(ψ)?cos(λ)) 其中,ψ為圓心到點的線段與xz平面的夾角,λ為圓心到點的線段在xz平面的投影與z軸的夾角。用圖形表示如下: 這裡寫圖片描述

拆解頂點

按照經緯度方式拆解球體,得到球體的頂點數組:

ArrayList<float> data=new ArrayList<>();
float r1,r2;
float h1,h2;
float sin,cos;
for(float i=-90;i<90+step;i+=step){
    r1 = (float)Math.cos(i * Math.PI / 180.0);
    r2 = (float)Math.cos((i + step) * Math.PI / 180.0);
    h1 = (float)Math.sin(i * Math.PI / 180.0);
    h2 = (float)Math.sin((i + step) * Math.PI / 180.0);
    // 固定緯度, 360 度旋轉遍歷一條緯線
    float step2=step*2;
    for (float j = 0.0f; j <360.0f+step; j +=step2 ) {
        cos = (float) Math.cos(j * Math.PI / 180.0);
        sin = -(float) Math.sin(j * Math.PI / 180.0);

        data.add(r2 * cos);
        data.add(h2);
        data.add(r2 * sin);
        data.add(r1 * cos);
        data.add(h1);
        data.add(r1 * sin);
    }
}
float[] f=new float[data.size()];
for(int i=0;i<f.length;i++){ pre=""

得到頂點後,剩下的工作就和之前繪制其他圖形一樣了。

修改著色器

如果繼續使用圓錐的著色器,我們會得到這樣一個球:

黑球

看起來都不太像個球了,要不是有條白線,這是不是個球就不好說了。我們需要修改下頂點著色器,讓它有立體感。把頂點著色器修改為:

uniform mat4 vMatrix;
varying vec4 vColor;
attribute vec4 vPosition;

void main(){
    gl_Position=vMatrix*vPosition;
    float color;
    if(vPosition.z>0.0){
        color=vPosition.z;
    }else{
        color=-vPosition.z;
    }
    vColor=vec4(color,color,color,1.0);
}

運行一下,我們得到的運行結果如下,這樣才好意思說是個球嘛。 這裡寫圖片描述

源碼

OK,繪制各種簡單的幾何物體到這裡就結束了,現在應該各種常規的幾何形體都攔不到我們了。後面開始講解其他內容了。 所有的代碼全部在一個項目中,托管在Github上——Android OpenGLES 2.0系列博客的Demo

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved