1. 程式人生 > >openGL之圓環---openGL學習筆記(七)

openGL之圓環---openGL學習筆記(七)

畫圓環的想法與畫球體的想法大致相同,不同的是,圓環中間為空,而環體的直徑又相同,所以通過設定兩個半徑,用兩個半徑和角度就可以確定每個點的x,y,z座標。

首先,還是先把環體切成幾個部分,每個部分開啟之後都是一個矩形,把每個矩形都用畫三角形帶的方式繪製出來的話,那麼圓環就可以實現。

接下來就是座標的計算:

假定以圓環中心為座標圓心,想要確定每個點的座標,就需要設定兩個半徑,一個內圈半徑r1,一個環體半徑r2,再設定一個alpha角和alpha角的步長(alphaStep),用來取到環體上的每個圓,還要設定一個beta角和beta角的步長(betaStep),用來取到每一個圓上的點。


那麼假定兩點(x0,y0,z0)(x1,y1,z1),可以得出x0 = [(r1+r2)+r2 * cos(beta)] * cos(alpha),

y0 = [(r1+r2)+r2 * cos(beta)] * sin(alpha),z0 = -r2 * sin(beta).

而x1,y1,z1與x0,y0,z0不同的地方只有alpha的角度,給alpha加一個步長,就得到x1,y1,z1.

x1 = [(r1+r2)+r2 * cos(beta)] * cos(alpha+alphaStep),

y1 = [(r1+r2)+r2 * cos(beta)] * sin(alpha+alphaStep),

因為圓環環體的直徑處處相等,所以圓環向Z軸負方向的延伸值不變。

所以,z1 = z0 = -r2 * sin(beta).

需要注意的是,z軸座標需要取反,因為是向z軸負方向延伸。

取到了兩點座標之後,接下來就可以用兩層迴圈取到圓環上的各個點。

for( int i = 0;i < count;i ++ ){
        alpha = i * alphaStep;for( int j = 0;j <= count0;j ++ ){
        beta = j * betaStep;
x0 = (float) (Math.cos(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
y0 = (float) (Math.sin(alpha) * (Rring + Rinner + Rinner * Math.cos
(beta))); z0 = (float) -(Rring * Math.sin(beta)); x1 = (float) (Math.cos(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta))); y1 = (float) (Math.sin(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta))); z1 = (float) (-Rring * Math.sin(beta));}
取到了圓環上的各個點的座標後,剩下的就簡單了,設定清屏色,設定繪圖顏色,然後指定模型檢視矩陣,載入單位矩陣,放置眼球位置,設定旋轉角度。最後再指定頂點指標,繪製三角形帶。

執行效果圖:(為觀察方便起見,效果圖還是以畫線帶的方式繪製)

附程式碼:

public class MyRingRenderer extends AbstractRenderer{
    @Override
public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//設定清屏色
gl.glColor4f(1f, 1f, 1f, 1f);//設定繪圖顏色
gl.glMatrixMode(GL10.GL_MODELVIEW);//模型檢視矩陣
gl.glLoadIdentity();//載入單位矩陣
GLU.gluLookAt(gl, 0, 0, 5, 0, 0, 0, 0, 1, 0);//放置眼球位置
gl.glRotatef(xRotate, 1, 0, 0);//x軸旋轉角度
gl.glRotatef(yRotate,0,1,0);//y軸旋轉角度
List<Float> coords = new ArrayList<Float>();
        float Rinner = 0.2f;//內圓半徑
float Rring = 0.3f;//環半徑
int count = 20;//迴圈次數
float alpha = 0;//外圓角度
float x0,x1,y0,y1,z0,z1;
        float alphaStep = (float) (2 * Math.PI / count);//alpha角的步長(外部圓環)
float betaStep = (float) (2 * Math.PI / count);//beta角的步長(每個切片)
float beta = 0;//切片迴圈角度
int count0 = 20;//迴圈次數
/***************************外層迴圈主要負責把圓環切成幾個部分*******************************/
for( int i = 0;i < count;i ++ ){
                alpha = i *alphaStep;
/***************************內層迴圈主要負責把每個部分畫出來*******************************/
for( int j = 0;j <= count0;j ++ ){
                beta = j * betaStep;
x0 = (float) (Math.cos(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
y0 = (float) (Math.sin(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
z0 = (float) -(Rring * Math.sin(beta));
x1 = (float) (Math.cos(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
y1 = (float) (Math.sin(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
z1 = (float) (-Rring * Math.sin(beta));
coords.add(x0);
coords.add(y0);
coords.add(z0);
coords.add(x1);
coords.add(y1);
coords.add(z1);
}

            gl.glVertexPointer(3,GL10.GL_FLOAT,0, BufferUtils.list2FloatBuffer(coords));//頂點指標
gl.glDrawArrays(GL10.GL_LINE_STRIP,0,coords.size() / 3) ;//畫線帶
}
    }
}