从头开始绘制一个圆锥体

opengl帮助库glu里有一个对象叫做二次几何体,可以用来给球体圆锥体建模,然而在opengles中不能使用glu库,那么我们只能自己写方法替代它了,上次给球体建了模,这次应该给圆锥体建模了.

圆锥体是平面上的一个圆以及它的所有切线和平面外一点确定的平面围成的几何体,圆被称为底面,顶点被称为尖端,定义听上去有些复杂,那么看图:

嗯,懂了吧.其实它是一种特殊情况,如果尖端是一个圆面的话那么它就是一个截头圆锥体,顶面半径为0的截头圆锥体就是圆锥体了.

先来看下头文件是怎么定义的吧:

class Cone {
private:
	GLuint* vboId;
	GLuint vert,texcoord,norm;
	GLfloat* verts;
	GLfloat* texcoords;
	GLfloat* norms;
	int vertNum,topVertNum,sideVertNum;
	float radiusTop,radiusBottom,yHeight;//顶面半径,底面半径,高度
	void calculateSideNormal(float& x,float& y,float& z);//计算侧面法线
public:
	Cone(float rt,float rb,int m,float height);
	~Cone();
	void render();
};

侧面法线的计算方法,先取底面任意一点,求得圆心到该点的向量,然后沿着此向量把该截头圆锥体劈开,如图所示

然后把红色的向量沿着它的方向平移到圆周上的点,如图所示:

利用相似三角形即可求出紫色的法线N,具体代码如下:

void Cone::calculateSideNormal(float& x,float& y,float& z) {
	y=(radiusBottom-radiusTop)/yHeight*sqrtf(x*x+z*z);
	if(x==0.0&&z==0.0)
		y=1.0;
}

这边的(x,y,z)就是法向量了,x和z都是圆周上那点的坐标(x,z),y依靠相似三角形可以求出

接着是具体的建模代码:

Cone::Cone(float rt,float rb,int m,float height) {
	radiusTop=rt;
	radiusBottom=rb;
	yHeight=height;

	vertNum=m*3*2+m*4;
	topVertNum=m*3*2;
	sideVertNum=m*4;

	verts=new GLfloat[vertNum*3];
	norms=new GLfloat[vertNum*3];
	texcoords=new GLfloat[vertNum*2];

	float stepAngZ=PI2/m;
	float angZ=0.0;

	int index=0;
	int indexNorm=0;
	int indexTex=0;
	for(int i=0;i<m;i++) {
		//bottom
		float x1=cos(angZ)*rb;
		float y1=0.0;
		float z1=sin(angZ)*rb;
		verts[index]=x1; index++;
		verts[index]=y1; index++;
		verts[index]=z1; index++;
		float nx1=0.0;
		float ny1=-1.0;
		float nz1=0.0;
		norms[indexNorm]=nx1; indexNorm++;
		norms[indexNorm]=ny1; indexNorm++;
		norms[indexNorm]=nz1; indexNorm++;
		float u1=angZ/PI2;
		float v1=1.0;
		texcoords[indexTex]=u1; indexTex++;
		texcoords[indexTex]=v1; indexTex++;

		float x2=cos(angZ+stepAngZ)*rb;
		float y2=0.0;
		float z2=sin(angZ+stepAngZ)*rb;
		verts[index]=x2; index++;
		verts[index]=y2; index++;
		verts[index]=z2; index++;
		norms[indexNorm]=nx1; indexNorm++;
		norms[indexNorm]=ny1; indexNorm++;
		norms[indexNorm]=nz1; indexNorm++;
		float u2=(angZ+stepAngZ)/PI2;
		float v2=1.0;
		texcoords[indexTex]=u2; indexTex++;
		texcoords[indexTex]=v2; indexTex++;

		float x3=0.0;
		float y3=0.0;
		float z3=0.0;
		verts[index]=x3; index++;
		verts[index]=y3; index++;
		verts[index]=z3; index++;
		norms[indexNorm]=nx1; indexNorm++;
		norms[indexNorm]=ny1; indexNorm++;
		norms[indexNorm]=nz1; indexNorm++;
		float u3=0.0;
		float v3=0.0;
		texcoords[indexTex]=u3; indexTex++;
		texcoords[indexTex]=v3; indexTex++;

		//top
		float x4=cos(angZ+stepAngZ)*rt;
		float y4=height;
		float z4=sin(angZ+stepAngZ)*rt;
		verts[index]=x4; index++;
		verts[index]=y4; index++;
		verts[index]=z4; index++;
		float nx4=0.0;
		float ny4=1.0;
		float nz4=0.0;
		norms[indexNorm]=nx4; indexNorm++;
		norms[indexNorm]=ny4; indexNorm++;
		norms[indexNorm]=nz4; indexNorm++;
		float u4=(angZ+stepAngZ)/PI2;
		float v4=1.0;
		texcoords[indexTex]=u4; indexTex++;
		texcoords[indexTex]=v4; indexTex++;

		float x5=cos(angZ)*rt;
		float y5=height;
		float z5=sin(angZ)*rt;
		verts[index]=x5; index++;
		verts[index]=y5; index++;
		verts[index]=z5; index++;
		norms[indexNorm]=nx4; indexNorm++;
		norms[indexNorm]=ny4; indexNorm++;
		norms[indexNorm]=nz4; indexNorm++;
		float u5=angZ/PI2;
		float v5=1.0;
		texcoords[indexTex]=u5; indexTex++;
		texcoords[indexTex]=v5; indexTex++;

		float x6=0.0;
		float y6=height;
		float z6=0.0;
		verts[index]=x6; index++;
		verts[index]=y6; index++;
		verts[index]=z6; index++;
		norms[indexNorm]=nx4; indexNorm++;
		norms[indexNorm]=ny4; indexNorm++;
		norms[indexNorm]=nz4; indexNorm++;
		float u6=0.0;
		float v6=0.0;
		texcoords[indexTex]=u6; indexTex++;
		texcoords[indexTex]=v6; indexTex++;

		angZ+=stepAngZ;
	}

	angZ=0.0;
	for(int i=0;i<m;i++) {
		//side
		float x7=cos(angZ+stepAngZ)*rb;
		float y7=0.0;
		float z7=sin(angZ+stepAngZ)*rb;
		verts[index]=x7; index++;
		verts[index]=y7; index++;
		verts[index]=z7; index++;
		float nx7=x7;
		float ny7=0;
		float nz7=z7;
		calculateSideNormal(nx7,ny7,nz7);
		norms[indexNorm]=nx7; indexNorm++;
		norms[indexNorm]=ny7; indexNorm++;
		norms[indexNorm]=nz7; indexNorm++;
		float u7=(angZ+stepAngZ)/PI2;
		float v7=1.0;
		texcoords[indexTex]=u7; indexTex++;
		texcoords[indexTex]=v7; indexTex++;

		float x8=cos(angZ)*rb;
		float y8=0.0;
		float z8=sin(angZ)*rb;
		verts[index]=x8; index++;
		verts[index]=y8; index++;
		verts[index]=z8; index++;
		float nx8=x8;
		float ny8=0;
		float nz8=z8;
		calculateSideNormal(nx8,ny8,nz8);
		norms[indexNorm]=nx8; indexNorm++;
		norms[indexNorm]=ny8; indexNorm++;
		norms[indexNorm]=nz8; indexNorm++;
		float u8=angZ/PI2;
		float v8=1.0;
		texcoords[indexTex]=u8; indexTex++;
		texcoords[indexTex]=v8; indexTex++;

		float x10=cos(angZ)*rt;
		float y10=height;
		float z10=sin(angZ)*rt;
		verts[index]=x10; index++;
		verts[index]=y10; index++;
		verts[index]=z10; index++;
		float nx10=x10;
		float ny10=0;
		float nz10=z10;
		calculateSideNormal(nx10,ny10,nz10);
		norms[indexNorm]=nx10; indexNorm++;
		norms[indexNorm]=ny10; indexNorm++;
		norms[indexNorm]=nz10; indexNorm++;
		float u10=angZ/PI2*rt/rb;
		float v10=0.0;
		texcoords[indexTex]=u10; indexTex++;
		texcoords[indexTex]=v10; indexTex++;

		float x11=cos(angZ+stepAngZ)*rt;
		float y11=height;
		float z11=sin(angZ+stepAngZ)*rt;
		verts[index]=x11; index++;
		verts[index]=y11; index++;
		verts[index]=z11; index++;
		float nx11=x11;
		float ny11=0;
		float nz11=z11;
		calculateSideNormal(nx11,ny11,nz11);
		norms[indexNorm]=nx11; indexNorm++;
		norms[indexNorm]=ny11; indexNorm++;
		norms[indexNorm]=nz11; indexNorm++;
		float u11=(angZ+stepAngZ)/PI2*rt/rb;
		float v11=0.0;
		texcoords[indexTex]=u11; indexTex++;
		texcoords[indexTex]=v11; indexTex++;

		angZ+=stepAngZ;
	}

	vboId=new GLuint[3];
	vert=0;
	texcoord=1;
	norm=2;
	glGenBuffers(3,vboId);
	glBindBuffer(GL_ARRAY_BUFFER_ARB, vboId[vert]);
	glBufferData(GL_ARRAY_BUFFER_ARB, vertNum*3*sizeof(GLfloat),
			verts, GL_STATIC_DRAW_ARB);
	glBindBuffer(GL_ARRAY_BUFFER_ARB, vboId[texcoord]);
	glBufferData(GL_ARRAY_BUFFER_ARB, vertNum*2*sizeof(GLfloat),
			texcoords, GL_STATIC_DRAW_ARB);
	glBindBuffer(GL_ARRAY_BUFFER_ARB, vboId[norm]);
	glBufferData(GL_ARRAY_BUFFER_ARB, vertNum*3*sizeof(GLfloat),
			norms, GL_STATIC_DRAW_ARB);
	delete[] verts;
	delete[] texcoords;
	delete[] norms;
}

和上次球体的代码很像,纹理坐标底面与顶面的变化程度一致以防贴图分布不均匀.

这样模型就建立完成了,渲染效果如下所示:

时间: 2024-08-25 21:25:36

从头开始绘制一个圆锥体的相关文章

怎么使用CAD编辑器绘制一个圆锥体?

怎么使用CAD编辑器绘制一个圆锥体?在我们需要使用CAD编辑器绘制一张CAD图纸文件的时候,如果需要绘制一份三维立体图形的时候我们应该如何进行此项操作呢?会不会很难呢?今天小编就要来教教大家CAD中如何绘制一个三维的圆锥体,以下为全部操作步骤,希望大家进行采纳!第一步:首先要先打开你们电脑上面的迅捷CAD编辑器软件,或是您还可以去到官网上面进行下载安装然后进行使用,之后打开进入软件的首页面,选择上方属性栏上面的"绘图"-"三维网格"-"圆锥体"然

怎么在CAD编辑器中绘制一个圆锥体?

怎么在CAD编辑器中绘制一个圆锥体? 从事CAD相关工作的人,经常会需要绘制一些立体图形,那么这对于刚从事CAD方面的人来说,是一件不太容易的事情,我们应该如何进行操作呢?今天小编就要来教教大家怎么在CAD编辑器中绘制一个圆锥体的全部操作步骤,希望进行采纳!第一步:首先要打开电脑上面的CAD编辑器软件,如果您电脑上面没有这样一款软件的话,您就需要打开浏览器去到官网上进行下载安装了!或是直接去到软件商店上面进行搜索也可!第二步:点击下载完成之后,将软件安装到你们的电脑说面上,然后双击鼠标左键将CA

从头开始绘制一个球体

好久都没有更新博客了,最近在研究OpenGL图形编程,写了一些有趣的程序,分享一下. 废话少说,开始吧. 球体作为基本的几何图形在游戏程序中应用广泛,其中最为人所知的是可以作为Sky Dome模拟天空,比起Sky Box来说更加细致一些,即使加上别的特殊效果也不容易穿帮. 我们在中学的数学课上应该学过球体的参数方程 x = r * sin(angZ) * cos(angXY) y = r * sin(angZ) * sin(angXY) z = r * cos(angZ) angZ是纵向夹角,a

从头开始搭建一个dubbo+zookeeper平台 【转】

本篇主要是来分享从头开始搭建一个dubbo+zookeeper平台的过程,其中会简要介绍下dubbo服务的作用.   注册中心的选择   dubbo支持多种类型的注册中心: 这里我们选择zookeeper,其实类型的优点缺点可详细查看文档. 1:zookeeper的安装,还是采用docker这一招鲜的run命令来安装zookeeper docker run -dit --name zookeeper --hostname zookeeper-host -v /data:/data -p 2181

从头开始搭建一个dubbo+zookeeper平台

本篇主要是来分享从头开始搭建一个dubbo+zookeeper平台的过程,其中会简要介绍下dubbo服务的作用. 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后的常规方案演进历程. 其次,当服务越来越多之后,我们需要做哪些服务治理? 最后,是dubbo的架构图   注册中心的选择   dubbo支持多种类型的注册中心: Multicast注册中心 Zookeeper注册中心 Redis注册中心 Simple注册中心 这里我们选择zookeeper,其实类型

OpenGl 绘制一个立方体

OpenGl 绘制一个立方体 为了绘制六个正方形,我们为每个正方形指定四个顶点,最终我们需要指定6*4=24个顶点.但是我们知道,一个立方体其实总共只有八个顶点,要指定24次,就意味着每个顶点其实重复使用了三次,这样可不是好的现象.最起码,像上面这样重复烦琐的代码,是很容易出错的.稍有不慎,即使相同的顶点也可能被指定成不同的顶点了. 如果我们定义一个数组,把八个顶点都放到数组里,然后每次指定顶点都使用指针,而不是使用直接的数据,这样就避免了在指定顶点时考虑大量的数据,于是减少了代码出错的可能性.

四、绘制一个点

上次我们介绍了如何在<canvas>中使用WebGL,以及几个基础的WebGL函数:实现了背景色的重置:为了扩展方便,我们把上次的代码做了些改动,将绘制图形的js独立成文件,这样我们只关注与这个js文件的编写:以后除非HTML文件发生变化,我们就跳过它,直接讨论JavaScript代码. 1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <met

GDI+学习笔记(五)绘制一个正方体

本文将介绍如何利用GDI+绘制一个正方体. (一)准备阶段 想象一下,高中的时候,我们在学立体几何的时候是怎样画一个正方体的,我们在一张纸上利用投影的思路将其绘制在一张纸上,对吧,这计算投影的部分,我们暂且忽略.下图是我用windows的画图绘制的一个正方体: 我们计算出这些点在平面上的坐标如下: Point A(100,200); Point B(200,200); Point C(100,300); Point D(200,300); Point E(100+50*1.414, 200-50

学习WebGL:着色器、绘制一个点

WebGL使用着色器信息绘图,着色器使用OpenGL ES(GLSL)编写 着色器分为顶点着色器(Vertex shader)和片元着色器(Fragment shader),顶点着色器描述位置信息,片元着色器描述颜色信息 //顶点着色器 void main(){ gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_PointSize = 10.0; } //片元着色器 void main(){ gl_FragColor = vec4(1.0, 0.0, 0.0,