opengl画圆锥和圆柱体
具体资源欢迎下载:https://download.csdn.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;
}
实现效果
在添加了右键响应菜单后,可看出实现效果如下: