我已經學會了如何使用OpenGL從各種教程中繪製立方體。現代OpenGL:繪製球體和圓柱體
對於立方體,我們認爲每個面都由兩個三角形組成,然後適當地設置頂點和顏色緩衝區。這些緩衝區然後被髮送到着色器代碼。
我們如何畫一個球體和圓柱體?所有在線教程都專注於繪製立方體。
爲球體或圓柱體設置頂點緩衝區似乎並不重要;我無法像三維立方體那樣從三角形「構造」它們。
我已經學會了如何使用OpenGL從各種教程中繪製立方體。現代OpenGL:繪製球體和圓柱體
對於立方體,我們認爲每個面都由兩個三角形組成,然後適當地設置頂點和顏色緩衝區。這些緩衝區然後被髮送到着色器代碼。
我們如何畫一個球體和圓柱體?所有在線教程都專注於繪製立方體。
爲球體或圓柱體設置頂點緩衝區似乎並不重要;我無法像三維立方體那樣從三角形「構造」它們。
對於氣缸,在cylindrical coordinates中工作很方便:(角度,半徑,高度)。您將計算兩個多邊形(恆定角度增量,固定半徑,兩個高度值),並創建:基礎的兩組三角形和側表面的一組矩形(分成兩部分)。
對於球體,您將使用球面座標:(傾斜,仰角,半徑)。通過改變兩個角度(一次一個),您將描述球體上的平行線和經線。這些定義了一個網格,使每個瓦片是一個四邊形(除了在兩極);沿對角線分割以獲得三角形。
下面是繪製球體時使用的一些代碼。
注意:此代碼使用C++和GLM數學庫。
// Calc The Vertices
for (int i = 0; i <= Stacks; ++i){
float V = i/(float) Stacks;
float phi = V * glm::pi <float>();
// Loop Through Slices
for (int j = 0; j <= Slices; ++j){
float U = j/(float) Slices;
float theta = U * (glm::pi <float>() * 2);
// Calc The Vertex Positions
float x = cosf (theta) * sinf (phi);
float y = cosf (phi);
float z = sinf (theta) * sinf (phi);
// Push Back Vertex Data
vertices.push_back (glm::vec3 (x, y, z) * Radius);
}
}
// Calc The Index Positions
for (int i = 0; i < Slices * Stacks + Slices; ++i){
indices.push_back (i);
indices.push_back (i + Slices + 1);
indices.push_back (i + Slices);
indices.push_back (i + Slices + 1);
indices.push_back (i);
indices.push_back (i + 1);
}
該算法創建所謂的UV球體。 「切片」和「堆棧」是X軸和Y軸上的細分數。
它溢出索引範圍。 – Ruslan 2017-05-10 20:55:59
這發生在哪裏? 代碼從不訪問任何數組元素,只添加到數組中。 它如何溢出索引範圍,如果它從來沒有被訪問過的第一個地方? – 2017-05-11 09:57:20
當'i = Slices * Stacks + Slices-1'時,您可以將'i + Slices + 1'推入索引。由於您有'(Stacks + 1)*(Slices + 1)'頂點的總數,當您有'Slices> Stacks'時,'i + Slices + 1'的索引將指向頂點集合的末尾之外。這不會導致C++代碼中的UB,但會導致在OpenGL代碼中('glDrawElements'等)。在實踐中,你會得到隨機的三角形伸出你的球體。 – Ruslan 2017-05-11 11:38:37