最近看到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: 圆柱面绘制贴图相关推荐

  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. Alibaba Cloud Linux 2.1903 LTS 64位服务器yum源下载404,Alibaba Cloud Linux 2实例中使用docker-ce、epel等YUM源安装软件失败
  2. 通信产业5G迭代,万亿机遇一触即发
  3. 2011,我的IT我的梦
  4. 华为首款Harmonyos摄像头,掀起家居安防大变革 华为首款HarmonyOS智能摄像头发布...
  5. 第五章项目 体检套餐管理系统
  6. 理解ATL中的一些汇编代码
  7. Actor-ES框架:Ray--事件(Event)编写说明
  8. Android WebView https白屏、Http和Https混合问题、证书配置和使用
  9. 偏微分方程的正问题和逆问题(inverse problem)
  10. CVE-2020-16875: Microsoft Exchange远程代码执行漏洞通告
  11. python标准库——time模块
  12. saas商业级的小程序商城(已开源)
  13. matlab 工具箱 comsol 联,基于MATLAB与COMSOL联合仿真的电磁优化设计
  14. android 9图工具位子,Android自定义9宫格图片视图
  15. Delphi中多库关联查询
  16. 一个刚入行而又不甘于平庸的程序猿2019个人总结
  17. mapboxgl - 用webgl展示海量数据,是否可行?
  18. python slots魔法
  19. 手机端也能免费转换CAD图纸啦!
  20. linux opengl配置编译,Linux下OpenGL的安装与cmake编译OpenGL程序

热门文章

  1. windows10 freeswitch soundtouch 变声
  2. 无人值守安装系统完整(CentOS7)
  3. 量化交易python 文件_python数据分析与量化交易
  4. 通过运营界面上传图片失败,浏览器提示上传文件时发生HTTP错误(错误代码:500)
  5. 《深入理解计算机系统》Lab3 Bomblab
  6. 第四次工业革命,人工智能革命真的来了
  7. Axure 9 收录不同效果的制作过程
  8. 香坊区开启“三位一体”智慧城管新模式
  9. 【linux 释放内存】linux释放内存骚操作
  10. 计算机word保存如何操作,怎么开启电脑word中的自动保存功能