OpenGL: 圆柱面绘制贴图
2014-02-26 10:51
281 查看
最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序。于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标。构造圆柱体的参数主要有:水平分段数(就是上下圆的分段数目),
高度上的分段数目,(至少有两段:上下两个圆面)
半径,
高度。
顶点生成的原理:将圆柱面展开就是一个矩形。而纹理也是一个矩形区域,需要注意的是圆柱面是一个首尾相接的封闭面。效果图如下:
![](http://p.blog.csdn.net/images/p_blog_csdn_net/dizuo/EntryImages/20091202/1.jpg)
代码:头文件
高度上的分段数目,(至少有两段:上下两个圆面)
半径,
高度。
顶点生成的原理:将圆柱面展开就是一个矩形。而纹理也是一个矩形区域,需要注意的是圆柱面是一个首尾相接的封闭面。效果图如下:
![](http://p.blog.csdn.net/images/p_blog_csdn_net/dizuo/EntryImages/20091202/1.jpg)
代码:头文件
#ifndef CYLINDER_H #define CYLINDER_H struct Vertex3f { float x; float y; float z; float nx; float ny; float nz; float u; float v; void setValue(float x_, float y_, float z_) { x = x_; y = y_; z = z_; } void setNormal(float x_, float y_, float z_) { nx = x_; ny = y_; nz = z_; } void setTexture(float u_, float v_) { u = u_; v = v_; } }; enum REND_MODE { SOLID = 3000, WIRE = 3001 }; /* * Cylinder created by RYF. [11/25/2009] */ class Cylinder { public: Cylinder(float r, float h, int l, int v); ~Cylinder(); void Render(REND_MODE mode); void PrintMatrices(); protected: Cylinder(){}; void RenderSlice( const Vertex3f& v1, const Vertex3f& v2, const Vertex3f& v3, const Vertex3f& v4, int i, int j, REND_MODE mode ); void RenderSliceNormal( const Vertex3f& v1, const Vertex3f& v2, const Vertex3f& v3, const Vertex3f& v4 ); void _getMatrices(); void _setupVertexTexcoord(); void _getVertex(float alpha, float hgh, Vertex3f& vertex); unsigned int texId; //纹理ID bool isHasTex; //是否加载纹理 float radius; //半径 float height; //高度 int lSlice; //水平分段数 int vSlice; //垂直分段数 Vertex3f* pVertexBuffer; //顶点数据 float* pTexcoord; //最后一列的纹理坐标 }; #endifcpp文件:
#include "Cylinder.h" #include <gl/glut.h> #include <iostream> #include <iomanip> #include <cmath> // ---------------------------------------------------------------- // Description: 重载构造函数 // Para info: r为上下圆的半径 // h为高度 // l为上下圆的分段数 // v为高度上圆柱的段数v>=2 // ---------------------------------------------------------------- Cylinder::Cylinder(float r, float h, int l, int v) : radius(r) , height(h) , lSlice(l) , vSlice(v) , texId(0) , isHasTex(false) , pVertexBuffer(0) , pTexcoord(0) { pVertexBuffer = new Vertex3f[vSlice*lSlice]; pTexcoord = new float[vSlice]; _setupVertexTexcoord(); _getMatrices(); PrintMatrices(); } Cylinder::~Cylinder() { if (pVertexBuffer) { delete pVertexBuffer; pVertexBuffer = 0; } } // ---------------------------------------------------------------- // Description: 圆柱体绘制函数 // 绘制按照逆时钟: // v4 v3 // // v1 v2 // ---------------------------------------------------------------- void Cylinder::Render(REND_MODE mode) { int i(0); int j(0); // 绘制圆柱体 for (i=0; i<vSlice-1; i++) { for (j=0; j<lSlice-1; j++) { RenderSlice( pVertexBuffer[(i+1)*lSlice+j], pVertexBuffer[(i+1)*lSlice+j+1], pVertexBuffer[i*lSlice+j+1], pVertexBuffer[i*lSlice+j], i, j, mode ); } RenderSlice( pVertexBuffer[(i+1)*lSlice+j], //第二行末端 pVertexBuffer[(i+1)*lSlice], //第二行始端 pVertexBuffer[i*lSlice], //第一行始端 pVertexBuffer[i*lSlice+j], //第一行末端 i, j+1, mode ); } } // ---------------------------------------------------------------- // Description: 绘制四边形函数 // 函数参数顺序: 1 2 3 4 // GL_TRIANGLE_STRIP的绘制顺序:1 2 4 3 // 四个v参数提供:位置和法线数据 // i,j提供纹理坐标数据 // 1, 4为要特殊处理的点 // ---------------------------------------------------------------- void Cylinder::RenderSlice( const Vertex3f& v1, const Vertex3f& v2, const Vertex3f& v3, const Vertex3f& v4, int i, int j, REND_MODE mode ) { glDisable(GL_LIGHTING); switch(mode) { case SOLID: glBegin(GL_TRIANGLE_STRIP); //glBegin(GL_POLYGON); break; case WIRE: glBegin(GL_LINE_LOOP); break; } glTexCoord2f( v1.u, v1.v ); glVertex3f(v1.x, v1.y, v1.z); /*glNormal3f(v1.nx, v1.ny, v1.nz);*/ //特殊处理v2的配置 if (j==lSlice) { glTexCoord2f( 1.0f, pTexcoord[i+1] ); glVertex3f(v2.x, v2.y, v2.z); /*glNormal3f(v2.nx, v2.ny, v2.nz);*/ } else { glTexCoord2f( v2.u, v2.v ); glVertex3f(v2.x, v2.y, v2.z); /*glNormal3f(v2.nx, v2.ny, v2.nz);*/ } glTexCoord2f( v4.u, v4.v ); glVertex3f(v4.x, v4.y, v4.z); /*glNormal3f(v4.nx, v4.ny, v4.nz);*/ //特殊处理v3的配置 if (j==lSlice) { glTexCoord2f( 1.0f, pTexcoord[i] ); glVertex3f(v3.x, v3.y, v3.z); /*glNormal3f(v3.nx, v3.ny, v3.nz);*/ } else { glTexCoord2f( v3.u, v3.v ); glVertex3f(v3.x, v3.y, v3.z); /*glNormal3f(v3.nx, v3.ny, v3.nz);*/ } glEnd(); // 显示法线 // RenderSliceNormal( v1, v2, v3, v4 ); glEnable(GL_LIGHTING); } void Cylinder::RenderSliceNormal( const Vertex3f& v1, const Vertex3f& v2, const Vertex3f& v3, const Vertex3f& v4 ) { glBegin(GL_LINES); glVertex3f(v1.x, v1.y, v1.z); glVertex3f(v1.nx + v1.x, v1.ny+v1.y, v1.nz+v1.z); glEnd(); glBegin(GL_LINES); glVertex3f(v2.x, v2.y, v2.z); glVertex3f(v2.nx + v2.x, v2.ny+v2.y, v2.nz+v2.z); glEnd(); glBegin(GL_LINES); glVertex3f(v3.x, v3.y, v3.z); glVertex3f(v3.nx + v3.x, v3.ny+v3.y, v3.nz+v3.z); glEnd(); glBegin(GL_LINES); glVertex3f(v4.x, v4.y, v4.z); glVertex3f(v4.nx + v4.x, v4.ny+v4.y, v4.nz+v4.z); glEnd(); } // ---------------------------------------------------------------- // Description: 根据vSlice和lSlice生成纹理坐标 // // ---------------------------------------------------------------- void Cylinder::_setupVertexTexcoord() { if (!pVertexBuffer || !pTexcoord) return; float ds = 1.0f / lSlice; //x,u 方向 float dt = 1.0f / (vSlice-1); //y,v 方向 for (int i=0; i<vSlice; i++) { for (int j=0; j<lSlice; j++) { pVertexBuffer[j + i*lSlice].u = j*ds; pVertexBuffer[j + i*lSlice].v = i*dt; } // 最后一列的纹理横坐标全部为:1.0 // pTexcoord中只是纵坐标 pTexcoord[i] = i * dt; } } // ---------------------------------------------------------------- // Description: 根据角度和高度求取顶点的坐标 // Para info: theta为弧度数,圆中的角度 // hgh为高度 // ---------------------------------------------------------------- void Cylinder::_getVertex(float theta, float hgh, Vertex3f& vertex) { float cosTheta = cos(theta); float sinTheta = sin(theta); // setup position coordinate vertex.x = radius * cosTheta; vertex.y = hgh; vertex.z = radius * sinTheta; // setup normal coordinate vertex.nx = cosTheta; vertex.ny = 0; vertex.nz = sinTheta; } // ---------------------------------------------------------------- // Description: 求取圆柱的顶点阵列 // ---------------------------------------------------------------- void Cylinder::_getMatrices() { const float pi = 3.1415926; float angle = 2.0f * pi / static_cast<float>(lSlice); // 注意分母为高度段数减1 float span = height / static_cast<float>(vSlice-1); for (int v=0; v<vSlice; v++) { float y = span * v; for (int l=0; l<lSlice; l++) { float x = angle * static_cast<float>(l); _getVertex(x, y, pVertexBuffer[l + v*lSlice]); } } } // ---------------------------------------------------------------- // Description: 打印matrices中的元素 // ---------------------------------------------------------------- void Cylinder::PrintMatrices() { using namespace std; for (int i=0; i<vSlice*lSlice; i++) { cout << "//---------------------------------------------------------------------" << endl; cout << "row = " << i / lSlice << "."; cout << "coll = " << i % lSlice << endl; cout << "position(x, y, z) = " << setprecision (7) << pVertexBuffer[i].x << " " << setprecision (7) << pVertexBuffer[i].y << " " << setprecision (7) << pVertexBuffer[i].z << endl; cout << "texture(u, v) = " << setprecision (7) << pVertexBuffer[i].u << " " << setprecision (7) << pVertexBuffer[i].v << endl; cout << "//---------------------------------------------------------------------" << endl; } }测试程序如下,要运行起来,还必须加一个bmpLoader的程序库,可以到这里下载一个简单的,里面有自带的bmp图片。http://users.ox.ac.uk/~orie1330/bmploader.html代码:
#include <GL/glut.h> #include <cstdio> #include <cstdlib> #include "Cylinder.h" #include "BMPLoader.h" /* Create checkerboard texture */ #define checkImageWidth 64 #define checkImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; static GLuint texName; Cylinder g_cylinder(0.5f, 1.3f, 30, 5); static float angleX = 0.0f; static float angleY = 0.0f; ////////////////////////////////////////////////////////////////////////// void makeCheckImage(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i&0x8)==0)^((j&0x8))==0))*255; checkImage[i][j][0] = (GLubyte) c; checkImage[i][j][1] = (GLubyte) c; checkImage[i][j][2] = (GLubyte) c; checkImage[i][j][3] = (GLubyte) 255; } } } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); //makeCheckImage(); BMPClass bmp; BMPLoad("bmp16.bmp", bmp); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 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, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, / *checkImage* /bmp.bytes); */ glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName); glPushMatrix(); { glRotatef(angleX, 1.0f, 0.0f, 0.0f); glRotatef(angleY, 0.0f, 1.0f, 0.0f); g_cylinder.Render(SOLID); }glPopMatrix(); glutSwapBuffers(); glDisable(GL_TEXTURE_2D); glutPostRedisplay(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -3.6f); } void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; case 'x': angleX += 5.0f; break; case 's': angleX -= 5.0f; case 'y': angleY += 4.0f; break; case 'h': angleY -= 4.0f; break; default: break; } glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }PS:OpenGL绘制什么都得DIY。/article/1342262.html
相关文章推荐
- OpenGL圆柱面绘制贴图
- OpenGL圆柱面绘制贴图
- OpenGL: OpenGL圆柱面绘制贴图
- WinCE OpenGL绘制立方体和纹理贴图
- 在OpenGL中如何根据空间两点绘制圆柱?(www.c3dn.net)
- OpenGL: 平面圆绘制与贴图
- opengl 绘制简单的带纹理贴图的立方体
- OpenGL_ES|WinCE纹理贴图的方式绘制字符串
- OpenGL: OpenGL中的平面圆绘制与贴图
- OpenGL_ES|WinCE纹理贴图的方式绘制字符串
- OpenGL中的平面圆绘制与贴图
- 在OpenGL中如何根据空间两点绘制圆柱
- 在OpenGL中如何根据空间两点绘制圆柱?
- MFC+OpenGL 纹理贴图后再绘制线条两个颜色相互影响
- OPENGL 贴图影响绘制 OR 绘图影响贴图
- 【OpenGL】理解GL_TRIANGLE_STRIP等绘制三角形序列的三种方式
- Opengl_13_纹理贴图
- Android移动开发-使用OpenGL来绘制3D纹理图的实现
- OpenGL国民党党徽、共青团团徽、花型的绘制
- WIN32 opengl绘制一个点