哎呀,照着图形学课本上的部分代码画的一个球,用了一个晚上,一个下午的时间,中间还求助了他人,才把这个球画正确了。过程好艰辛,是用汗水与泪水画出来的球啊!
为什么那么难画?
1、我太粗心:抄式子的时候抄错了好几处地方
2、课本太粗心:有几处地方原本就是错的
不过还好,总算是画出来了,很开心!
#include<gl/glut.h>
#include<math.h>
//#include<gl/glu.h>
//#include<gl/gl.h>
// 1 radian = π / 180°
#define PI 3.14159
const float DegreeToRadians = PI / 180.0;
typedef GLfloat point3[3];
point3 quad_data[342];// 8 rows of 18 quads
point3 strip_data[40];
//全局变量
//窗口大小
int width = 600;
int height = 600;
//a point data type
typedef GLfloat point2[2];
//initial triangle
point2 v[] = {{-1.0, -0.58}, {1.0, -0.58}, {0.0, 1.15}};
void sphere_quad()// 计算球体的中间以四边形表示的部分的顶点坐标,并存入数组quad_data中,用GL_QUAD
{
int k = 0;
/*
x(theta, phi) = sin theta cos phi
y(theta, phi) = cos theta sin phi
z(theta, phi) = sin phi
*/
for (float phi = -80.0; phi < 80.0; phi += 20.0) //课本这里写成了phi <= 80.0,结果两极不一样!
{
float phir = phi * DegreeToRadians;
float phir20 = (phi + 20) * DegreeToRadians;
for (float theta = -180.0; theta <= 180.0; theta += 20.0)
{
float thetar = theta * DegreeToRadians;
quad_data[k][0] = sin(thetar) * cos(phir);
quad_data[k][1] = cos(thetar) * cos(phir);// 粗心大意 画出了一件艺术品来!是cos不是sin啊!
quad_data[k][2] = sin(phir);
glVertex3fv(quad_data[k]);
k++;
quad_data[k][0] = sin(thetar) * cos(phir20);//是thetar不是thetar20啊!
quad_data[k][1] = cos(thetar) * cos(phir20);
quad_data[k][2] = sin(phir20);
glVertex3fv(quad_data[k]);
k++;
}
}
}
void sphere_triangle() // 两极部分,用GL_TRIANGLE_FAN
{
int k = 0;
strip_data[k][0] = 0.0;
strip_data[k][1] = 0.0;
strip_data[k][2] = 1.0;
glVertex3fv(strip_data[k]); // 这一点是那个三角形扇的顶点
k++;
float sin80 = sin(80.0 * DegreeToRadians);
float cos80 = cos(80.0 * DegreeToRadians);
for (float theta = -180.0; theta <= 180.0; theta += 20)
{
float thetar = theta * DegreeToRadians; //
strip_data[k][0] = sin(thetar) * cos80;
strip_data[k][1] = cos(thetar) * cos80;
strip_data[k][2] = sin80;
glVertex3fv(strip_data[k]);
k++;
}
glEnd();
glBegin(GL_TRIANGLE_FAN);
strip_data[k][0] = 0.0;
strip_data[k][1] = 0.0;
strip_data[k][2] = -1.0;
glVertex3fv(strip_data[k]); // 这一点是那个三角形扇的顶点
k++;
for (float theta = -180.0; theta <= 180.0; theta += 20)
{
float thetar = theta * DegreeToRadians; //这里课本漏写了" * DegreeToRadians"
strip_data[k][0] = sin(thetar) * cos80;
strip_data[k][1] = cos(thetar) * cos80;
strip_data[k][2] = -sin80;
glVertex3fv(strip_data[k]);
k++;
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);//投影矩阵
glLoadIdentity();
gluPerspective(45, width/height, 1, 1000);
glMatrixMode(GL_MODELVIEW);//模型矩阵
glLoadIdentity();
gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
glRotatef(100, 1, 0, 0);//绕x轴旋转
glEnable(GL_DEPTH_TEST);
// 设置正反面为填充模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//glBegin(GL_TRIANGLE_STRIP);
glBegin(GL_QUAD_STRIP);//把glBegin和glEnd放在显示回调函数中,而不是triangle函数中,绘制整个图形只需要调用一次glBegin和glEnd。
glColor3f(0.0, 1.0, 1.0);
sphere_quad();
glEnd();
glBegin(GL_TRIANGLE_FAN);
//glColor3f(1.0, 0.0, 1.0);
sphere_triangle();
glEnd();
glFlush();//交换两个缓冲区指针
}
void myinit()
{
/*
glMatrixMode(GL_PROJECTION);//投影矩阵
glLoadIdentity();
gluPerspective(45, width/height, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 50, 0, 0, 0, 0, 1, 0);//设置摄像机参数(eye, at, up三个向量)
glColor3f(0.0, 0.0, 0.0);
*/
glClearColor(0.0, 0.0, 0.0, 1.0);
}
void myReshape(int w, int h)
{
if (h == 0) h = 1;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);//投影矩阵
glLoadIdentity();
gluPerspective(45, width/height, 1, 1000);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);//初始化GLUT
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);//设置图形显示模式。GLUT_DEPTH:使用深度缓存;GLUT_DOUBLE:使用双缓存;
glutInitWindowPosition(100, 100);//设置窗口显示位置
glutInitWindowSize(width,height);//设置窗口大小
glutCreateWindow("Approximation of Sphere");//创建带标题的窗口
myinit();
glutDisplayFunc(display);//为当前窗口设置显示回调函数
glutMainLoop();//进入GLUT事件处理循环
return 0;
}