2016-06-21 182 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中的默认顺序是逆时针。 –