欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

opengl 绘制圆柱体、圆锥体等并使用四元数旋转

最编程 2024-07-05 22:00:56
...

opengl画圆锥和圆柱体

具体资源欢迎下载:https://download.****.net/download/qq_32563773/13077923

画圆锥

如要画出想画的立方体,必须计算出来顶点数组对象,并且根据顶点定义的位置,简历索引关系,进而使用CreateGLResources函数完成绘画。

第一步计算出顶点位置:

我们可以将底面的圆看成是一条直线绕一个顶点旋转,这样旋转一定的角度后,另一个定点的位置即所要求的顶点坐标。若我们分的够多,即旋转角度设立的越小,越相似于圆形。(类似于古代割圆术的思想)
即,问题可以转换为:
A点(x, y)按顺时针旋转 theta 角度后点的坐标为A1点(x1,y1) ,求x1 y1坐标用(x,y)和 theta 来表示。
解题方法:
设 OA 向量和x轴的角度为 alpha ,那么顺时针转过 theta后 ,OA1 向量和x轴的角度为 (alpha - theta) 。使用圆的参数方程来表示点坐标。A的坐标可以表示为:

在这里插入图片描述

A1的坐标可以表示为(带入A点坐标进行化简)

在这里插入图片描述

在代码中,我们设定一个函数,传入参数为底面圆的半径、割圆的线段个数、圆锥高度,之后通过上述的公式计算出顶点的坐标,我使用的是【原点+底面圆上顶点+圆锥上边的点】的顺序构建的。

第二步构建三角形索引

为了提升性能,因此要少使用循环。在计算顶点坐标的过程中即可以完成对顶点索引的构建。

即在计算所得圆上顶点数为1时,1与最后一个顶点,即输入的割圆最后一个点,这两个顶点和底面圆中心点构建一个三角形,和圆锥顶点构建第二个三角形;

顶点数超过2时,以此两个顶点,加上底面圆中心点构建第一个三角形,加上圆锥顶点构建第二个三角形,以此类推,没加一个顶点就加两个三角形的索引。最后完成索引构建。

具体代码如下:

void CMesh::CreateCone(float radius, int num_stacks, float height)
{
	double angle = 2 * M_PI / num_stacks;
	num_vertices = num_stacks + 2;
	num_indices = num_stacks * 2 * 3;

	CMeshVertex* vertices = new CMeshVertex[num_vertices];
	GLuint* indices = new GLuint[num_indices];

	vertices[0].pos = vec3{ 0,0,0 };
	vertices[0].color = { 1.0f,0.0f,0.0f,0.0f };
	vertices[1].color = { 0.0f,1.0f,0.0f,0.0f };

	vertices[num_vertices - 1].pos = vec3{ 0,0,height };
	int num_angle = 1;
	for (int i = 0; i < num_stacks; ++i) {
		vertices[i+1].pos.x = cos(angle * i)*radius;
		vertices[i+1].pos.y = -sin(angle * i)*radius;
		vertices[i+1].pos.z = 0;
		if (i > 0) {
			indices[i * 6] = 0;
			indices[i * 6 + 1] = i;
			indices[i * 6 + 2] = i + 1;
			indices[i * 6 + 3] = num_vertices - 1;
			indices[i * 6 + 4] = i;
			indices[i * 6 + 5] = i + 1;
		}
		else if(i == 0)
		{
			indices[0] = 0;
			indices[1] = num_stacks;
			indices[2] = 1;
			indices[3] = num_vertices - 1;
			indices[4] = num_stacks;
			indices[5] = 1;
		}
	}

	CreateGLResources(vertices, indices);

	delete[] vertices;
	delete[] indices;
}

实现效果

在添加了右键响应菜单后,可看出实现效果如下:
在这里插入图片描述

实现时遇到的问题:
在实现的过程中,要注意索引的顺序,如果某一个三角形索引顺序出现问题,可能相出现如下的画不出的问题。

在这里插入图片描述

画圆柱

画圆柱和圆锥类似,只不过是添加了一组z方向为高度的顶点,并且以圆锥顶点为中心,和新加顶点画出三角,以此完成两个圆,之后再降上下圆的顶点联系起来,画出侧面。

实现原理

具体实现原理与圆锥类似,不同点为:在生成每个顶点时,依托此顶点要完成12条索引,即上下圆生成的三角形、侧面生成的两个三角形,共4个三角形12个顶点索引。

具体实现:

void CMesh::CreateCylinder(float radius, int num_stacks, float height)
{
	double angle = 2 * M_PI / num_stacks;
	num_vertices = num_stacks * 2 + 2;
	num_indices = num_stacks * 2 * 3 * 4;

	CMeshVertex* vertices = new CMeshVertex[num_vertices];
	GLuint* indices = new GLuint[num_indices];

	vertices[0].pos = vec3{ 0,0,0 };
	vertices[0].color = { 1.0f,0.0f,0.0f,0.0f };
	vertices[1].color = { 0.0f,1.0f,0.0f,0.0f };

	vertices[num_vertices - 1].pos = vec3{ 0,0,height };
	int num_angle = 1;
	for (int i = 0; i < num_stacks; ++i) {
		vertices[i + 1].pos.x = cos(angle * i)*radius;
		vertices[i + 1].pos.y = -sin(angle * i)*radius;
		vertices[i + 1].pos.z = 0;
		vertices[i + 1 + num_stacks].pos.x = vertices[i + 1].pos.x;
		vertices[i + 1 + num_stacks].pos.y = vertices[i + 1].pos.y;
		vertices[i + 1 + num_stacks].pos.z = height;
		if (i > 0) {
			indices[i * 12] = 0;
			indices[i * 12 + 1] = i;
			indices[i * 12 + 2] = i + 1;
			indices[i * 12 + 3] = num_vertices - 1;
			indices[i * 12 + 4] = i+num_stacks;
			indices[i * 12 + 5] = i + 1+num_stacks;
			indices[i * 12 + 6] = i;
			indices[i * 12 + 7] = i+1;
			indices[i * 12 + 8] = i + num_stacks;
			indices[i * 12 + 9] = i+1;
			indices[i * 12 + 10] = i +1+ num_stacks;
			indices[i * 12 + 11] = i+num_stacks;
		}
		else if (i == 0)
		{
			indices[0] = 0;
			indices[1] = num_stacks;
			indices[2] = 1;
			indices[3] = num_vertices-1;
			indices[4] = num_stacks*2;
			indices[5] = num_stacks + 1;
			indices[6] = num_stacks;
			indices[7] = 1;
			indices[8] = 2 * num_stacks;
			indices[9] = 1;
			indices[10] = 1+num_stacks;
			indices[11] = 2 * num_stacks;
		}
	}

	CreateGLResources(vertices, indices);

	delete[] vertices;
	delete[] indices;
}

实现效果
在添加了右键响应菜单后,可看出实现效果如下:
在这里插入图片描述