最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序。于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标。

构造圆柱体的参数主要有:

  • 水平分段数(就是上下圆的分段数目),
  • 高度上的分段数目,(至少有两段:上下两个圆面)
  • 半径,
  • 高度。

顶点生成的原理:将圆柱面展开就是一个矩形。而纹理也是一个矩形区域,需要注意的是圆柱面是一个首尾相接的封闭面。

效果图如下:

代码:

头文件

#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; //最后一列的纹理坐标 }; #endif

cpp文件:

#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。

OpenGL圆柱面绘制贴图相关推荐

  1. OpenGL: 圆柱面绘制贴图

    最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...

  2. OpenGL: OpenGL圆柱面绘制贴图

    最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...

  3. 如何在opengl用代码绘制英文_如何用AIPS直接绘制服装款式图(线稿)

    AI 1.首先创建文件 2.将服装效果图/模特人体图(本示例用成衣图替代)添加到图层中. 3. 在示例图层(图层1)之上创建新的透明图层. 4. 可适当调节底层图片透明度,方便查看款式图效果. 5. ...

  4. 计算机函数图象,信息技术应用用计算机绘制函数图象

    <信息技术应用用计算机绘制函数图象>由会员分享,可在线阅读,更多相关<信息技术应用用计算机绘制函数图象(15页珍藏版)>请在人人文库网上搜索. 1.柱体.锥体. 台体的体积,锥 ...

  5. 【OpenGL ES】凸镜贴图

    1 前言 正方形图片贴到圆形上 中将正方形图片上的纹理映射到圆形模型上,同理,也可以将圆形上的纹理映射到凸镜的球形曲面上.如下图,最左边的竖条是原图片的截面(纹理坐标),最右边的竖条是变换后的顶点模型 ...

  6. 【OpenGL ES】立方体贴图(6张图)

    1 前言 本文通过一个立方体贴图的例子,讲解三维纹理贴图的应用,案例中使用 6 张不同的图片给立方体贴图,图片如下: 本文涉及到的知识点主要包含:三维绘图.MVP 矩阵变换.纹理贴图,读者如果对 Op ...

  7. OpenGL ES之三——绘制纯色背景

    概述 这是一个系列的Android平台下OpenGl ES介绍,从最基本的使用最终到VR图的展示的实现,属于基础篇.(后面针对VR视频会再有几篇文章,属于进阶篇) OpenGL ES之一--概念扫盲 ...

  8. Qt OpenGL(三十六)——Qt OpenGL 核心模式-绘制雷达坐标系

    提示:本系列文章的索引目录在下面文章的链接里(点击下面可以跳转查看): Qt OpenGL 核心模式版本文章目录 Qt OpenGL(三十六)--Qt OpenGL 核心模式-绘制雷达坐标系 一.场景 ...

  9. Android+JNI+OpenGL开发自己的美图秀秀

    https://blog.csdn.net/oshunz/article/details/50537631 Android+JNI+OpenGL开发自己的美图秀秀 2016年01月18日 16:39: ...

最新文章

  1. 2022-2028年中国ITO薄膜行业市场全景调查及投资前景趋势报告
  2. python编程到底难不难_养成下面几个编程习惯,学习python并不难!
  3. hdoj Last non-zero Digit in N! 【数论】
  4. jsp内置对象与el内置对象
  5. 【Python基础】python必会的10个知识点
  6. 矩阵低秩张量分解_TKDE 2020 | CTRR:组稀疏约束的紧凑张量环回归
  7. leetcode412. Fizz Buzz
  8. CENTOS 7 踢用户_CentOS服务器及MySQL数据库性能测试-乐搏软件测试
  9. 圆环和环形是一样的吗_Excel不知道还可以这样做圆环图
  10. java 正则高级应用_JAVA正则表白式高级用法(分组与捉拿).
  11. Java核心技术11 | Java IO
  12. php抽奖实现-概率算法
  13. png图片如何在线转换成jpg格式的
  14. org/w3c/dom/ElementTraversal 错误解决办法
  15. 台式计算机红外线端口,台式电脑的红外线端口在哪?
  16. 推动区块链技术应用创新河南开展区块链应用场景需求和典型应用案例征集工作
  17. 图形2d,3d加速简介
  18. IT信息技术-1.1 信息系统与信息化
  19. MODBUS通讯协议解析及实例
  20. CTF-日常密码泄露分析溯源

热门文章

  1. python公式计算_Python Numpy计算各类距离的方法
  2. 迷宫(深度优先搜索)
  3. plt.style绘图风格展示(matplotlib)
  4. 手机号登录和微信登录
  5. 联想服务器开机滴一下不显示,电脑开机没有滴的一声显示器不亮怎么办 电脑开机故障解决方法【图文】...
  6. “放心消费”宣言传递正品心智,网易考拉8.16大促首日获用户好评
  7. Archlinux 安装Yaourt的方式
  8. Appium 按压元素进行滑动
  9. 红米K40 面具root教程
  10. 农村信用贷款要具备什么条件,有哪些要求