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) ;//畫線帶 } } }