如何在使用 triangle_strip 创建的 OpenGL 中对圆柱体进行纹理处理?
这是我创建的圆柱体:
void drawCylinder(float r, float g, float b) {
setMaterialColors(r, g, b);
glColor4f(r, g, b, 1.0);
/* top triangle */
double i, resolution = 0.1;
double height = 1, radius = 0.5;
glPushMatrix();
glTranslatef(0, -0.5, 0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, height, 0); /* center */
for (i = 0; i <= 2 * PI; i += resolution)
glVertex3f(radius * cos(i), height, radius * sin(i));
glEnd();
/* bottom triangle: note: for is in reverse order */
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0, 0, 0); /* center */
for (i = 2 * PI; i >= 0; i -= resolution)
glVertex3f(radius * cos(i), 0, radius * sin(i));
/* close the loop back to 0 degrees */
glVertex3f(radius, height, 0);
glEnd();
/* middle tube */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= 2 * PI; i += resolution)
{
glVertex3f(radius * cos(i), 0, radius * sin(i));
glVertex3f(radius * cos(i), height, radius * sin(i));
}
/* close the loop back to zero degrees */
glVertex3f(radius, 0, 0);
glVertex3f(radius, height, 0);
glEnd();
glPopMatrix();
}
现在,我无法将纹理映射到它.我尝试保持纹理坐标与三角条坐标相同,但没有奏效.
Now, I am unable to map textures to it. I tried keeping texture coordinate same as the triangle strip coordinates, but it didn't work.
PS:我不想使用 gluCylinder.我知道它存在.
PS: I don't want to use gluCylinder. I know it exists.
如果我只能对磁盘进行纹理处理就可以了.四边形不需要纹理.
It's fine if I can only texture the disks. The quad strip needn't be textured.
推荐答案
对于中心:将 i
除以 2 * PI
得到一个在 之间变化的数字>0.0
和 1.0
并将其用作纹理坐标:
For the center: Divide i
by 2 * PI
to get a number that varies between 0.0
and 1.0
and use that as a texture coordinate:
for (i = 0; i <= 2 * PI; i += resolution)
{
const float tc = ( i / (float)( 2 * PI ) );
glTexCoord2f( tc, 0.0 );
glVertex3f(radius * cos(i), 0, radius * sin(i));
glTexCoord2f( tc, 1.0 );
glVertex3f(radius * cos(i), height, radius * sin(i));
}
/* close the loop back to zero degrees */
glTexCoord2f( 0.0, 0.0 );
glVertex3f(radius, 0, 0);
glTexCoord2f( 0.0, 1.0 );
glVertex3f(radius, height, 0);
对于 endcaps:您可以直接使用 sin()
/cos()
输出(几乎):
For the endcaps: You can use the sin()
/cos()
output (almost) directly:
glTexCoord2f( 0.5, 0.5 );
glVertex3f(0, height, 0); /* center */
for (i = 0; i <= 2 * PI; i += resolution)
{
// scale sin/cos range (-1 to 1) by 0.5 to get -0.5 to 0.5
// then shift that range up/right by 0.5 to get 0 to 1:
glTexCoord2f( 0.5f * cos(i) + 0.5f, 0.5f * sin(i) + 0.5f );
glVertex3f(radius * cos(i), height, radius * sin(i));
}
完整示例:
#include <GL/glew.h>
#include <GL/glut.h>
#include <cmath>
void cylinder()
{
const double PI = 3.14159;
/* top triangle */
double i, resolution = 0.1;
double height = 1;
double radius = 0.5;
glPushMatrix();
glTranslatef(0, -0.5, 0);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( 0.5, 0.5 );
glVertex3f(0, height, 0); /* center */
for (i = 2 * PI; i >= 0; i -= resolution)
{
glTexCoord2f( 0.5f * cos(i) + 0.5f, 0.5f * sin(i) + 0.5f );
glVertex3f(radius * cos(i), height, radius * sin(i));
}
/* close the loop back to 0 degrees */
glTexCoord2f( 0.5, 0.5 );
glVertex3f(radius, height, 0);
glEnd();
/* bottom triangle: note: for is in reverse order */
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f( 0.5, 0.5 );
glVertex3f(0, 0, 0); /* center */
for (i = 0; i <= 2 * PI; i += resolution)
{
glTexCoord2f( 0.5f * cos(i) + 0.5f, 0.5f * sin(i) + 0.5f );
glVertex3f(radius * cos(i), 0, radius * sin(i));
}
glEnd();
/* middle tube */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= 2 * PI; i += resolution)
{
const float tc = ( i / (float)( 2 * PI ) );
glTexCoord2f( tc, 0.0 );
glVertex3f(radius * cos(i), 0, radius * sin(i));
glTexCoord2f( tc, 1.0 );
glVertex3f(radius * cos(i), height, radius * sin(i));
}
/* close the loop back to zero degrees */
glTexCoord2f( 0.0, 0.0 );
glVertex3f(radius, 0, 0);
glTexCoord2f( 0.0, 1.0 );
glVertex3f(radius, height, 0);
glEnd();
glPopMatrix();
}
GLuint tex;
void init()
{
unsigned char data[] =
{
128, 128, 128, 255,
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
};
glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_2D, tex );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D, 0,GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
}
float angle = 0;
void timer( int value )
{
angle += 6;
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60, 1.0, 0.1, 100.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -5 );
glEnable( GL_CULL_FACE );
glEnable( GL_DEPTH_TEST );
glRotatef( angle, 0.2, 0.3, 0.1 );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, tex );
cylinder();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
init();
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
相关文章