OpenGL: OpenGL圆柱面绘制贴图
最近看到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圆柱面绘制贴图相关推荐
- OpenGL圆柱面绘制贴图
最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...
- OpenGL: 圆柱面绘制贴图
最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...
- OpenGL总结6-圆柱纹理贴图
圆柱纹理贴图我采用了OpenGL中的函数gluCylinder,这个函数会生成空心的圆柱,这个圆柱固定生成为底面位于xy面,z=0,顶面从z=0开始向z轴正方向,也就是说圆柱体是冲着我们生成的,如果想 ...
- openGL之glsl入门6--画三维图魔方、圆柱体
这一章介绍坐标变换与矩阵相关内容,对应红宝书第5章内容,并通过两个简单的例子展示矩阵变换的效果. 1. 坐标变换 变换的类型有多种,包括视图.模型.投影.视口变换等,概念可以参照红宝书5.1章节,概念 ...
- 计算机图形学实验四 OpenGL的鼠标交互绘制
一.实验目的 1.掌握OpenGL的鼠标按钮响应函数. 2.掌握OpenGL的鼠标移动响应函数. 3.进一步巩固OpenGL的基本图元绘制基础. 二.实验内容 1.鼠标画草图--实现鼠标点到哪,线就画 ...
- android平台下OpenGL ES 3.0绘制圆点、直线和三角形
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- android平台下OpenGL ES 3.0绘制纯色背景
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- OpenGL ES for Android 绘制旋转的地球
No 图 No Code,我们先来欣赏下旋转的地球: 是不是很酷炫,要想绘制出上面酷炫的效果需要3个步骤: 计算球体顶点数据 地球纹理贴图 通过MVP矩阵旋转地球 计算球体顶点数据 我们知道OpenG ...
- android平台下OpenGL ES 3.0绘制立方体的几种方式
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
最新文章
- Neumorphism.io一个神奇的网站,满足各种圆角矩形ICON图表立体化效果要求,这种样式的名称——新拟态
- CentOS7配置防火墙
- 九度OnlineJudge之1004:Median
- 说一说Android事件分发中的requestDisallowInterceptTouchEvent
- python实现局域网攻击_通过python实现DNS欺骗
- Javascript与未来十年的数据编程
- 【java】自定义异常类
- 关于UIScrollViewDelegate协议中每个回调函数的意义及执行
- 上海航芯 | 智能网联汽车终端T-BOX应用方案
- 基于单片机指纹考勤系统设计(论文毕设)全套资料
- 【备忘】Aegisub字幕制作简易方法
- keras使用load_weights遇到报错
- Windows Mobile 6.x 下改Tahoma字体+微软雅黑说明
- 常见编程语言对REPL支持情况小结[转]
- play_win7截图工具
- 简单的前后端交互的案例
- K8s------Metallb实现Load Balancer服务
- multisim秒信号发生器_基于Multisim的简易信号发生器的设计
- ThinkPHP上传图片并压缩为缩略图
- NCH Eyeline Video System