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

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

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

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

效果图如下:

代码:

头文件

#ifndef CYLINDER_H
#define CYLINDER_Hstruct 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;      //纹理IDbool          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 coordinatevertex.x = radius * cosTheta;vertex.y = hgh;vertex.z = radius * sinTheta;// setup normal coordinatevertex.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);// 注意分母为高度段数减1float 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。

http://blog.csdn.net/ryfdizuo/article/details/4926045

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

  1. OpenGL圆柱面绘制贴图

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

  2. OpenGL: 圆柱面绘制贴图

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

  3. OpenGL总结6-圆柱纹理贴图

    圆柱纹理贴图我采用了OpenGL中的函数gluCylinder,这个函数会生成空心的圆柱,这个圆柱固定生成为底面位于xy面,z=0,顶面从z=0开始向z轴正方向,也就是说圆柱体是冲着我们生成的,如果想 ...

  4. openGL之glsl入门6--画三维图魔方、圆柱体

    这一章介绍坐标变换与矩阵相关内容,对应红宝书第5章内容,并通过两个简单的例子展示矩阵变换的效果. 1. 坐标变换 变换的类型有多种,包括视图.模型.投影.视口变换等,概念可以参照红宝书5.1章节,概念 ...

  5. 计算机图形学实验四 OpenGL的鼠标交互绘制

    一.实验目的 1.掌握OpenGL的鼠标按钮响应函数. 2.掌握OpenGL的鼠标移动响应函数. 3.进一步巩固OpenGL的基本图元绘制基础. 二.实验内容 1.鼠标画草图--实现鼠标点到哪,线就画 ...

  6. android平台下OpenGL ES 3.0绘制圆点、直线和三角形

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  7. android平台下OpenGL ES 3.0绘制纯色背景

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  8. OpenGL ES for Android 绘制旋转的地球

    No 图 No Code,我们先来欣赏下旋转的地球: 是不是很酷炫,要想绘制出上面酷炫的效果需要3个步骤: 计算球体顶点数据 地球纹理贴图 通过MVP矩阵旋转地球 计算球体顶点数据 我们知道OpenG ...

  9. android平台下OpenGL ES 3.0绘制立方体的几种方式

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

最新文章

  1. Neumorphism.io一个神奇的网站,满足各种圆角矩形ICON图表立体化效果要求,这种样式的名称——新拟态
  2. CentOS7配置防火墙
  3. 九度OnlineJudge之1004:Median
  4. 说一说Android事件分发中的requestDisallowInterceptTouchEvent
  5. python实现局域网攻击_通过python实现DNS欺骗
  6. Javascript与未来十年的数据编程
  7. 【java】自定义异常类
  8. 关于UIScrollViewDelegate协议中每个回调函数的意义及执行
  9. 上海航芯 | 智能网联汽车终端T-BOX应用方案
  10. 基于单片机指纹考勤系统设计(论文毕设)全套资料
  11. 【备忘】Aegisub字幕制作简易方法
  12. keras使用load_weights遇到报错
  13. Windows Mobile 6.x 下改Tahoma字体+微软雅黑说明
  14. 常见编程语言对REPL支持情况小结[转]
  15. play_win7截图工具
  16. 简单的前后端交互的案例
  17. K8s------Metallb实现Load Balancer服务
  18. multisim秒信号发生器_基于Multisim的简易信号发生器的设计
  19. ThinkPHP上传图片并压缩为缩略图
  20. NCH Eyeline Video System

热门文章

  1. Thinkpad X1 extreme gen2驱动更新相关问题
  2. 从与星瑞格软件的合作看浪潮深化主机生态布局
  3. 黑马程序员20——OC之Fundation(NSValue)
  4. 《语言的本能》很值得一读
  5. nginx webdav模块实现http协议上传文件
  6. 机器人运动学与动力学入门(一)自由度与连杆机构
  7. C 语言结构体之点运算符( . )和箭头运算符( - )的区别
  8. 6----编程计算个人所得税
  9. MySQL拼音首字母查询(支持三个中文以内的查询)
  10. 【Java】IDEA插件推荐,让你的开发效率翻倍