2016-06-21 111 views
0

我正在嘗試向圓柱體中添加紋理以便很好地繪製一塊石頭。我先從一個圓柱體開始,然後繪製一塊石頭紋理,我發現它有here,但我得到了一些奇怪的結果。下面是我使用的功能:OpenGL:環繞圓柱體的紋理

void draw_well(double x, double y, double z, 
    double dx, double dy, double dz, 
    double th) 
{ 
    // Set specular color to white 
    float white[] = {1,1,1,1}; 
    float black[] = {0,0,0,1}; 
    glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shinyvec); 
    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,white); 
    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,black); 

    glPushMatrix(); 

    // Offset 
    glTranslated(x,y,z); 
    glRotated(th,0,1,0); 
    glScaled(dx,dy,dz); 

    // Enable textures 
    glEnable(GL_TEXTURE_2D); 
    glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); 

    glBindTexture(GL_TEXTURE_2D,texture[0]); // Stone texture 

    glBegin(GL_QUAD_STRIP); 
    for (int i = 0; i <= 359; i++) 
    { 
     glNormal3d(Cos(i), 1, Sin(i)); 

     glTexCoord2f(0,0); glVertex3f(Cos(i), -1, Sin(i)); 
     glTexCoord2f(0,1); glVertex3f(Cos(i), 1, Sin(i)); 
     glTexCoord2f(1,1); glVertex3f(Cos(i + 1), 1, Sin(i + 1)); 
     glTexCoord2f(1,0); glVertex3f(Cos(i + 1), -1, Sin(i + 1)); 
    } 
    glEnd(); 

    glPopMatrix(); 
    glDisable(GL_TEXTURE_2D); 
} 


// Later down in the display function 
draw_well(0, 0, 0, 1, 1, 1, 0); 

,我收到輸出

enter image description here

我還是很新的OpenGL和更具體的紋理,所以我的理解是相當有限。我的思考過程是將紋理映射到用於製作圓柱體的每個QUAD,但顯然我做錯了什麼。任何解釋是什麼導致這個奇怪的輸出,以及如何解決它將不勝感激。

+0

你應用你的紋理座標每一個四邊形的方式有整個紋理應用到它。這當然不是你想要的。 – datenwolf

回答

2

您的繪圖程序可能有三個主要問題。四條帶索引,過於頻繁地重複紋理座標以及可能不正確地使用trig函數;

三角函數函數通常接受表示以弧度而不是度表示的角度的值。仔細檢查你正在使用的Sin和Cos功能的參數。

四角片索引是不正確的。索引應該是這樣的......

enter image description here

注意四是如何在一個時鐘式的方式定義,但是對角頂點,依次確定。您將四邊形定義爲v0,v1,v3,v2而不是v0,v1,v2,v3,以便交換四個中的最後兩個頂點。這也導致不正確共享頂點的另一個錯誤。由於您在一個循環中繪製了同一組頂點(i + 1),因此您在每個垂直邊緣複製它們,就像您在下一個循環中那樣(即現在我已經增加1)。

對於每個四邊形,紋理座標都在0,1的範圍內,這意味着您要定義一個分割360次的圓柱體,並且該圓形體圍繞圓柱體重複360次。我假設紋理應該1:1映射到Cylinder並且不重複?

以下是使用您提供的一些示例代碼。如果您希望仍然有360,那麼我已將分段數減少到64個,然後相應地修改numberOfSegments

float pi = 3.141592654f; 

unsigned int numberOfSegments = 64; 
float angleIncrement = (2.0f * pi)/static_cast<float>(numberOfSegments); 
float textureCoordinateIncrement = 1.0f/static_cast<float>(numberOfSegments); 

glBegin(GL_QUAD_STRIP); 
for (unsigned int i = 0; i <= numberOfSegments; ++i) 
{ 
    float c = cos(angleIncrement * i); 
    float s = sin(angleIncrement * i); 

    glTexCoord2f(textureCoordinateIncrement * i, 0); glVertex3f(c, -1.0f, s); 
    glTexCoord2f(textureCoordinateIncrement * i, 1.0f); glVertex3f(c, 1.0f, s); 
} 
glEnd(); 

N.BYou使用舊版本的OpenGL(使用glBegin/glVertex等)。

+0

好的,非常感謝你。座標的重複是有意義的,我忘記了OpenGL只需要2個新點就可以做出下一個「QUAD」。至於索引的座標,我不知道它從(0,1)跳到(1,0),我認爲它會跟蹤它,類似於連接點。我其實只是交換了我的循環中的兩條線,並獲得了圓柱形狀,但紋理仍然很奇怪。你的代碼雖然工作。 – steveclark

+0

很高興「更好」;)關於紋理映射。紋理被映射爲0,0(紋理的左下角)到1,1(紋理的右上角),所以爲了正確地將紋理映射到柱體周圍一次(以便紋理不重複),需要繪製紋理的x分量座標與頂點所在圓柱體周圍的距離相匹配。這就是爲什麼存在與角度增量不同的紋理座標增量。要重複紋理,請增加我提供的代碼中textureCoordinateIncrement定義中的分子。 – lfgtm

+0

quadstrip圖是不幸的。雖然拓撲結構正確,但它顯示順時針順序的頂點,而OpenGL中的默認順序是逆時針。 –