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圆柱面绘制贴图
最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...
- OpenGL: OpenGL圆柱面绘制贴图
最近看到dx中的sample中有用顶点数组实现的圆柱体贴图的程序.于是自己写了一个圆柱体的类,支持生成纹理坐标,法线,坐标. 构造圆柱体的参数主要有: 水平分段数(就是上下圆的分段数目), 高度上的分 ...
- 如何在opengl用代码绘制英文_如何用AIPS直接绘制服装款式图(线稿)
AI 1.首先创建文件 2.将服装效果图/模特人体图(本示例用成衣图替代)添加到图层中. 3. 在示例图层(图层1)之上创建新的透明图层. 4. 可适当调节底层图片透明度,方便查看款式图效果. 5. ...
- 计算机函数图象,信息技术应用用计算机绘制函数图象
<信息技术应用用计算机绘制函数图象>由会员分享,可在线阅读,更多相关<信息技术应用用计算机绘制函数图象(15页珍藏版)>请在人人文库网上搜索. 1.柱体.锥体. 台体的体积,锥 ...
- 【OpenGL ES】凸镜贴图
1 前言 正方形图片贴到圆形上 中将正方形图片上的纹理映射到圆形模型上,同理,也可以将圆形上的纹理映射到凸镜的球形曲面上.如下图,最左边的竖条是原图片的截面(纹理坐标),最右边的竖条是变换后的顶点模型 ...
- 【OpenGL ES】立方体贴图(6张图)
1 前言 本文通过一个立方体贴图的例子,讲解三维纹理贴图的应用,案例中使用 6 张不同的图片给立方体贴图,图片如下: 本文涉及到的知识点主要包含:三维绘图.MVP 矩阵变换.纹理贴图,读者如果对 Op ...
- OpenGL ES之三——绘制纯色背景
概述 这是一个系列的Android平台下OpenGl ES介绍,从最基本的使用最终到VR图的展示的实现,属于基础篇.(后面针对VR视频会再有几篇文章,属于进阶篇) OpenGL ES之一--概念扫盲 ...
- Qt OpenGL(三十六)——Qt OpenGL 核心模式-绘制雷达坐标系
提示:本系列文章的索引目录在下面文章的链接里(点击下面可以跳转查看): Qt OpenGL 核心模式版本文章目录 Qt OpenGL(三十六)--Qt OpenGL 核心模式-绘制雷达坐标系 一.场景 ...
- Android+JNI+OpenGL开发自己的美图秀秀
https://blog.csdn.net/oshunz/article/details/50537631 Android+JNI+OpenGL开发自己的美图秀秀 2016年01月18日 16:39: ...
最新文章
- Alibaba Cloud Linux 2.1903 LTS 64位服务器yum源下载404,Alibaba Cloud Linux 2实例中使用docker-ce、epel等YUM源安装软件失败
- 通信产业5G迭代,万亿机遇一触即发
- 2011,我的IT我的梦
- 华为首款Harmonyos摄像头,掀起家居安防大变革 华为首款HarmonyOS智能摄像头发布...
- 第五章项目 体检套餐管理系统
- 理解ATL中的一些汇编代码
- Actor-ES框架:Ray--事件(Event)编写说明
- Android WebView https白屏、Http和Https混合问题、证书配置和使用
- 偏微分方程的正问题和逆问题(inverse problem)
- CVE-2020-16875: Microsoft Exchange远程代码执行漏洞通告
- python标准库——time模块
- saas商业级的小程序商城(已开源)
- matlab 工具箱 comsol 联,基于MATLAB与COMSOL联合仿真的电磁优化设计
- android 9图工具位子,Android自定义9宫格图片视图
- Delphi中多库关联查询
- 一个刚入行而又不甘于平庸的程序猿2019个人总结
- mapboxgl - 用webgl展示海量数据,是否可行?
- python slots魔法
- 手机端也能免费转换CAD图纸啦!
- linux opengl配置编译,Linux下OpenGL的安装与cmake编译OpenGL程序
热门文章
- windows10 freeswitch soundtouch 变声
- 无人值守安装系统完整(CentOS7)
- 量化交易python 文件_python数据分析与量化交易
- 通过运营界面上传图片失败,浏览器提示上传文件时发生HTTP错误(错误代码:500)
- 《深入理解计算机系统》Lab3 Bomblab
- 第四次工业革命,人工智能革命真的来了
- Axure 9 收录不同效果的制作过程
- 香坊区开启“三位一体”智慧城管新模式
- 【linux 释放内存】linux释放内存骚操作
- 计算机word保存如何操作,怎么开启电脑word中的自动保存功能