当前位置:文档之家› 计算机图形学上机实验报告

计算机图形学上机实验报告

计算机图形学上机实验报告计算机科学与技术学院

目录

实验一基本图形的绘制 (2)

1.实验目的与要求 (2)

2.实验内容 (2)

3.实验结果 (3)

4.实验体会 (5)

5.源程序 (5)

实验二日地月模型 (15)

1.实验目的与要求 (15)

2.实验内容 (15)

3.实验结果 (15)

4.实验体会 (17)

5.源程序 (17)

实验一:基本图形的绘制

一、实验目的与要求

(1)理解glut程序框架;

(2)理解窗口到视区的变换;

(3)理解OpenGL实现动画的原理;

(4)添加代码实现中点Bresenham算法画直线;

(5)添加代码实现改进Bresenham算法画直线;

(6)添加代码实现圆的绘制(可以适当对框架坐标系进行修改);

(7)添加代码实现椭圆的绘制。

二、实验内容

中点Bresenham 算法画直线思想:先考虑0≤k≤1,由于最大位移方向为x,因此,每次x方向上加1,而y方向上或加1或加0。判别式初值d= dx-2*dy,若d<0,则(x,y)更新为(x+1,y+1),d更新为d+2*dx-2*dy;否则(x,y)更新为(x+1,y),d更新为d -2*dy。

改进Bresenham算法画直线思想:判别式初值e= -dx,e每次加2*dy,判断e的符号,若e>0,则(x,y)更新为(x+1,y+1),同时将e更新为e-2*dx;否则(x,y)更新为(x+1,y)。之后在考虑斜率为其他值的处理办法。对于k>1的直线,我们只需在原来的基础上对给定的两个坐标进行x,y值互换,然后还是按照0<=k<=1的d值来进行更新坐标值,只是在输出坐标点时在将要输出的坐标值按照(y,x)方式输出。同理对于k<-1和-1<=k<0的情况也是按这种方式处理。

Bresenham 算法绘制圆的算法思想:若考虑第一象限内x∈「0,R/2」的1/8圆弧,此时最大位移方向为x,因此,每次x方向上走一步,而y方向上或减1或减0。判别式初值为d= 1-R,若d<0,则先将d更新为d+2*x+3 ,再将(x,y)更新为(x+1,y);否则先将d更新为d+2*(x-y)+5,再将(x,y)更新为(x+1,y-1)。但是,当圆心不在原点时,不妨设圆心为(x0,y0),则此时判别式初值为d= 1-R,若d<0,则先将d更新为d+2*(x-x0)+3;否则先将d更新为d+2*((x-x0)-(y-y0))+5。而且此时8个对称点分别为(x,y)、(x,2*y0-y) 、(y-y0+x0,y0+x0-x)、(x0+y0-y,y0+x0-x)、(2*x0-x,2*y0-y)、(2*x0-x,y)、(x0+y0-y,y0+x-x0)、(x0+y-y0,y0+x-x0)。即在画1/8圆弧上任一点时,需要同时画出另外7个点,最后即可得到整个圆。

由于要实现动画,所以需要创建一个循环,在每次调用显示回调函数之前给当前像素点着色,使其看起来像是在直线上连续的画出一个个像素点。为了不断的调用显示回调函数,需要利用函数glutTimerFunc(unsigned int msecs,(*func) (int value),int value),指定一个定时器回调函数,即经过msecs毫秒后由GLUT调用指定的函数,并将value值传递给他。被定时器调用的函数原型为void TimerFunction(int value),注意,该函数与其他的回调函数不一样的地方在于该函数只会被激发一次。所以为了实现连续的动画,必须在定时器函数中再次重新设置定时器回调函数。

程序操作。程序运行后,会生成一个(1024*768)*0.8大小的绘图窗口,窗口中绘制好了一个个10*10大小的网格,每一个网格即代表一个像素点。共有5种绘制模式:1、DDA 算法画直线(起点(0,0),终点(15,20),k=4/3);2 、中点Bresenham算法画直线(起点(0,20),终点(15,-10),k=-4/3);3 、改进Bresenham算法画直线(起点(0,20),终点(15,10),k=-3/4);

4 、八分法绘制圆(圆点(15,12),半径10);

5 、Bresenham算法画椭圆(中心坐标(15,12),长半轴10,短半周8)。分别通过按键盘上的数字键1~5来调用控制。在画每一个像素点时,同时会显示当前各点坐标和判别式的值。

三、实验结果

实验结果主要通过截图来表示,适当的选几副就可,注意每幅图都要编号,按照1-1,1-2…的方式,并且要有图的名称;图的编号和名称用小五号宋体字。

1、DDA画线算法,各点坐标、以及最终画出的直线

图1-1 DDA画直线,k=4/3

2、中点Bresenham算法画线,各点坐标、以及最终画出的直线

图1-2 中点Bresenham算法画直线,k=-4/3

3、改进的Bresenham算法画线,各点坐标、以及最终画出的直线

图1-3 改进的Bresenham算法画线,k=-3/4 4、中点Bresenham算法画圆,各点坐标、以及最终画出的图形

图1-4中点Bresenham算法画圆,R=10

5、Bresenham算法画椭圆,各点坐标、以及最终画出的图形

图1-5 Bresenham算法画椭圆,a=10,b=8

四、实验体会

这次实验是我第一次用OpenGL编程,在看懂老师给定的代码思路后,按照课本上的算法对剩余的中点Bresenham算法画直线、改进的Bresenham画直线、Bresenham画圆以及Bresenham画椭圆都能顺利完成,不过书本上的算法只能绘制斜率为0<=K<=1的直线。我就在原来的代码基础上将斜率为其他的情况的时候进行了相应的转换,来实现所有斜率的直线绘制。这次实验明显感觉到OpenGL功能很强大,图形显示效果很好。通过本次实验,让我更进一步的理解了几种基本的图形生成算法,包括DDA画线,中点Bresenham画线,改进的Bresenham画线,Bresenham画圆,以及Bresenham画椭圆。

五、源程序

///////////////////////////////////////////////////////////////////////////////////////

//实验要求:(1)理解glut程序框架//

// (2)理解窗口到视区的变换//

// (3)理解OpenGL实现动画的原理//

// (4)添加代码实现中点Bresenham算法画直线//

// (5)添加代码实现改进Bresenham算法画直线//

// (6)添加代码实现圆的绘制(可以适当对框架坐标系进行修改)//

// (7)添加代码实现椭圆的绘制//

///////////////////////////////////////////////////////////////////////////////////////

#include

#include

#include

int m_PointNumber = 0; //用于控制点的输出时的动画效果

/* 不同的m_DrawMode值表示不同的绘制模式。

1、DDA算法画直线;

2、中点Bresenham算法画直线;

3、改进Bresenham算法画直线;

4、八分法绘制圆;

5、四分法绘制椭圆

初始时默认为1

*/

int m_DrawMode = 1;

void DrawCordinateLine(void) //绘制坐标线

{

int i = 0 ;

glColor3f(0.0f, 0.0f ,0.0f); //坐标线为黑色

glBegin(GL_LINES);//准备画笔句柄

for (i=10;i<=500;i=i+10)

{

glVertex2f((float)(i), 0.0f);

glVertex2f((float)(i), 500.0f);

glVertex2f(0.0f, (float)(i));

glVertex2f(500.0f, (float)(i));

}

glEnd();//关闭画笔句柄

}

void putpixel(GLsizei x, GLsizei y) //绘制一个像素点,这里用一个正方形表示一个点

{

glRectf(10*x,10*y,10*x+10,10*y+10);//两个对角点的坐标

}

///////////////////////////////////////////////////////////////////

//DDA(Data Differential Analyzer)画线算法

//

//参数说明:x0,y0 起点坐标//

// x1,y1 终点坐标// //num 扫描转换时从起点开始输出的点的数目,用于动画//

void DDACreateLine(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num)

{

GLsizei dx,dy,epsl,k;

GLfloat x,y,xIncre,yIncre;

glColor3f(1.0f,0.0f,0.0f); //设置颜色

if(num == 1) //对画线动画进行控制

printf("DDA画线算法:各点坐标\n");

else if(num==0)

return;

//以下为画线算法的实现

dx = x1-x0;

dy = y1-y0;

x = x0;

y = y0;

if(abs(dx) > abs(dy)) epsl = abs(dx);

else epsl = abs(dy);

xIncre = (float)dx / epsl ;

yIncre = (float)dy / epsl ;

for(k = 0; k<=epsl; k++)

{

putpixel((int)(x+0.5), (int)(y+0.5));

if (k>=num-1)

{

printf("x=%f,y=%f,取整后x=%d,y=%d,num=%d\n", x, y, (int)(x+0.5),(int)(y+0.5),num);

break;

}

x += xIncre;

y += yIncre;

if(x >= 35 || y >= 35) break;

}

}

///////////////////////////////////////////////////////////////////

//中点Bresenham算法画直线(0<=k<=1) //

//参数说明:x0,y0 起点坐标//

// x1,y1 终点坐标//

// num 扫描转换时从起点开始输出的点的数目,用于动画//

///////////////////////////////////////////////////////////////////

void BresenhamLine1(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num)

{

GLsizei dx,dy,d,UpIncre,DownIncre,x,y;

GLfloat k;

glColor3f(1.0f,0.0f,0.0f);

if(num == 1)

printf("中点Bresenham算法画直线:各点坐标及判别式的值\n");

else if(num==0)

return;

//以下为画线算法的实现

if(x0>x1) //保证点(x0,y0)在点(x1,y1)前面

{

x=x1;x1=x0;x0=x;

y=y1;y1=y0;y0=y;

}

dx=x1-x0;dy=y1-y0;

k = (float)dy/dx;//求斜率k

if(k>1) { //K>1

x=x0;x0=y0;y0=x;

y=x1;x1=y1;y1=y;

}

if(k<-1) {//k<-1

y1=2*y0-y1;

x=x0;x0=y0;y0=x;

y=x1;x1=y1;y1=y;

}

if(k<0 && k>=-1){ // -1<=k<0

y1=2*y0-y1;

}

x=x0;y=y0;

dx=x1-x0;dy=y1-y0;

d=dx-2*dy;

UpIncre=2*dx-2*dy;DownIncre=-2*dy;

while(x<=x1)

{

if(k<=1 && k>0) putpixel(x,y);

else if(k>1) putpixel(y,x);

else if(k<-1) putpixel(y,2*x0-x);

else putpixel(x,2*y0-y);

if(x-x0>=num-1)

{

if(k<=1 && k>0) printf("x=%d,y=%d,d=%d\n", x, y,d);

else if(k>1) printf("x=%d,y=%d,d=%d\n", y, x,d);

else if(k<-1) printf("x=%d,y=%d,d=%d\n",y, 2*x0-x,d);

else printf("x=%d,y=%d,d=%d\n", x,2*y0-y,d);

break;

}

x++;

if(d<0)

{

y++;

d+=UpIncre;

}

else d+=DownIncre;

if(k>=0 && (x >= 30 || y >= 30) ) break;

if(k<0 && (y >=60 || x>= 60) ) break;

}

}

///////////////////////////////////////////////////////////////////

//改进的Bresenham算法画直线(0<=k<=1) //

//参数说明:x0,y0 起点坐标//

// x1,y1 终点坐标// //num 扫描转换时从起点开始输出的点的数目,用于动画//

///////////////////////////////////////////////////////////////////

void BresenhamLine2(GLsizei x0, GLsizei y0, GLsizei x1, GLsizei y1, GLsizei num)

{

GLsizei x,y,dx,dy,e;

GLfloat k;

glColor3f(1.0f,0.0f,0.0f);

if(num == 1)

printf("改进的Bresenham算法画直线:各点坐标及判别式的值\n");

else if(num==0)

return;

dx=x1-x0;dy=y1-y0;

k = (float)dy/dx;//求斜率k

if(k>1) { //K>1

x=x0;x0=y0;y0=x;

y=x1;x1=y1;y1=y;

}

if(k<-1) {//k<-1

y1=2*y0-y1;

x=x0;x0=y0;y0=x;

y=x1;x1=y1;y1=y;

}

if(k<0 && k>=-1){ // -1<=k<0

y1=2*y0-y1;

}

dx=x1-x0;dy=y1-y0;

e=-dx;

x=x0;y=y0;

while(x<=x1)

{

if(k<=1 && k>0) putpixel(x,y);

else if(k>1) putpixel(y,x);

else if(k<-1) putpixel(y,2*x0-x);

else putpixel(x,2*y0-y);

if(x-x0>=num-1)

{

if(k<=1 && k>0) printf("x=%d,y=%d,e=%d\n", x, y,e);

else if(k>1) printf("x=%d,y=%d,e=%d\n", y, x,e);

else if(k<-1) printf("x=%d,y=%d,e=%d\n",y, 2*x0-x,e);

else printf("x=%d,y=%d,e=%d\n", x,2*y0-y,e);

break;

}

x++;

e=e+2*dy;

if(e>0)

{

y++;

e=e-2*dx;

}

}

}

//画出以(x0,y0)为圆心,包括点(x,y)在内的8个对称点

void circlePoint(GLsizei x0,GLsizei y0,GLsizei x,GLsizei y)

{

putpixel(x,y);

putpixel(x,2*y0-y);

putpixel(y-y0+x0,y0+x0-x);

putpixel(x0+y0-y,y0+x0-x);

putpixel(2*x0-x,2*y0-y);

putpixel(2*x0-x,y);

putpixel(x0+y0-y,y0+x-x0);

putpixel(x0+y-y0,y0+x-x0);

}

///////////////////////////////////////////////////////////////////

//Bresenham算法画圆// //参数说明:x,y 圆心坐标// // R 圆半径// //num 扫描转换时从起点开始输出的点的数目,用于动画//

///////////////////////////////////////////////////////////////////

void BresenhamCircle(GLsizei x0, GLsizei y0, GLsizei r, GLsizei num)

{

GLsizei x,y,d;

glColor3f(1.0f,0.0f,0.0f);

if(num == 1)

printf("Bresenham算法画圆:各点坐标及判别式的值\n");

else if(num==0)

return;

x=x0; y=y0+r; d=1-r;

while(x-x0<=y-y0)

{

circlePoint(x0,y0,x,y);

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d=%d\n",x,y,d);

break;

}

if(d<0) d+=2*(x-x0)+3;

else

{

d+=2*((x-x0)-(y-y0))+5;

y--;

}

x++;

}

}

//画出以(x0,y0)为中心,包括点(x,y)在内的4个对称点

void EllipsePoint(GLsizei x0,GLsizei y0,GLsizei x,GLsizei y)

{

putpixel(x,y);

putpixel(x,2*y0-y);

putpixel(2*x0-x,2*y0-y);

putpixel(2*x0-x,y);

}

///////////////////////////////////////////////////////////////////

//Bresenham算法画椭圆//

//参数说明:x,y 圆心坐标//

// a 椭圆长半轴// // b 椭圆短半轴// // num 扫描转换时从起点开始输出的点的数目,用于动画//

///////////////////////////////////////////////////////////////////

void BresenhamEllipse(GLsizei x0, GLsizei y0, GLsizei a, GLsizei b,GLsizei num)

{

GLsizei x,y,d;

GLfloat d1,d2;

glColor3f(1.0f,0.0f,0.0f);

if(num == 1)

printf("Bresenham算法画椭圆:各点坐标及判别式的值\n");

else if(num==0)

return;

x=x0; y=y0+b;

d1=b*b+a*a*(-b+0.25);

EllipsePoint(x0,y0,x,y);

EllipsePoint(x0,y0,-x,-y);

EllipsePoint(x0,y0,-x,y);

EllipsePoint(x0,y0,x,-y);

while(b*b*(x-x0+1)

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d1=%.2f\n",x,y,d1);

break;

}

if(d1<=0){

d1+=b*b*(2*(x-x0)+3);

x++;

}

else{

d1+=b*b*(2*(x-x0)+3)+a*a*(-2*(y-y0)+2);

x++;

y--;

}

EllipsePoint(x0,y0,x,y);

EllipsePoint(x0,y0,-x,-y);

EllipsePoint(x0,y0,-x,y);

EllipsePoint(x0,y0,x,-y);

}

d2=b*b*((x-x0)+0.5)*((x-x0)+0.5)+a*a*(y-y0-1)*(y-y0-1)-a*a*b*b; while((y-y0)>0){

if(x-x0>=num-1)

{

printf("x=%d,y=%d,d2=%.2f\n",x,y,d2);

break;

}

if(d2<=0){

d2+=b*b*(2*(x-x0)+2)+a*a*(-2*(y-y0)+3);

x++;

y--;

}

else{

d2+=a*a*(-2*(y-y0)+3);

y--;

}

EllipsePoint(x0,y0,x,y);

EllipsePoint(x0,y0,-x,-y);

EllipsePoint(x0,y0,-x,y);

EllipsePoint(x0,y0,x,-y);

}

//初始化窗口

void Initial(void)

{

// 设置窗口颜色为蓝色

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

}

// 窗口大小改变时调用的登记函数

void ChangeSize(GLsizei w, GLsizei h)

{

if(h == 0) h = 1;

// 设置视区尺寸

glViewport(0, 0, w, h);

// 重置坐标系统

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// 建立修剪空间的范围

if (w <= h)

glOrtho (0.0f, 250.0f, 0.0f, 250.0f*h/w, 1.0, -1.0);

else

glOrtho (0.0f, 250.0f*w/h, 0.0f, 250.0f, 1.0, -1.0);

}

// 在窗口中绘制图形

void ReDraw(void)

{

//用当前背景色填充窗口

glClear(GL_COLOR_BUFFER_BIT);

//画出坐标线

DrawCordinateLine();

switch(m_DrawMode)

{

case 1: DDACreateLine(0,0,15,20,m_PointNumber);//DDA算法画线k>1

break;

case 2: BresenhamLine1(0,20,15,-10,m_PointNumber);//中点Bresenham算法画线k<-1 break;

case 3: BresenhamLine2(0,20,15,10,m_PointNumber);//改进的中点Bresenham算法画线-1

case 4: BresenhamCircle(15,12,10,m_PointNumber);//Bresenham算法画圆

break;

case 5: BresenhamEllipse(15,12,10,8,m_PointNumber); //Bresenham算法画椭圆

break;

default: break;

glFlush();

}

//设置时间回调函数

void TimerFunc(int value)

{

if(m_PointNumber == 0)

value = 1;

m_PointNumber = value;

glutPostRedisplay();

glutTimerFunc(500, TimerFunc, value+1);

}

//设置键盘回调函数,按键盘1~5,调用不同的画线模式void Keyboard(unsigned char key, int x, int y)

{

if (key == '1') m_DrawMode = 1;

if (key == '2') m_DrawMode = 2;

if (key == '3') m_DrawMode = 3;

if (key == '4') m_DrawMode = 4;

if (key == '5') m_DrawMode = 5;

m_PointNumber = 0;

glutPostRedisplay();

}

//void main(void)

int main(int argc, char* argv[])

{

glutInit(&argc, argv);

//初始化GLUT库OpenGL窗口的显示模式

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(819,614);

glutInitWindowPosition(0,0);

glutCreateWindow("基本图元绘制程序@CS1110_王涛");

glutDisplayFunc(ReDraw);

glutReshapeFunc(ChangeSize);

glutKeyboardFunc(Keyboard);//键盘响应回调函数

glutTimerFunc(500, TimerFunc, 1);

// 窗口初始化

Initial();

glutMainLoop(); //启动主GLUT事件处理循环

return 0;

}

实验二:日地月模型

一、实验目的与要求

(1)理解OpenGL中的变换过程

(2)理解透视投影与平行投影的不同

(3)添加代码实现太阳、地球和月亮的运动模型

(4)了解深度测试

(5)通过变换调整观察的位置与方向

(6)加入光照模型

二、实验内容

首先,我们认定这三个天体都是标准的球形,建立以下坐标系:太阳的中心为原点,地球绕太阳旋转的平面与X轴与Z轴决定的平面平行,即glRotatef(increment1, 0.0f, 1.0f, 0.0f);月亮绕地球旋转的平面与X轴与Y轴决定的平面平行,即glRotatef(increment2, 0.0f, 0.0f, 1.0f)。且每年第一天,地球在X轴正方向上,月亮在地球的正X轴方向。而且根据地球绕太阳转、月亮绕地球转的关系,画图时,可以依次画太阳、地球、月亮,这样可以不必使用连续使用glPushMatrix()、glPopMatrix()来保存当前的模型视图矩阵,同样可以保证地球绕太阳转、月亮绕地球转。

由于月亮绕地球旋转的速度是地球绕太阳旋转速度的12倍,为便于计算角度,可设地球绕太阳旋转角度为increment1, 月亮绕地球旋转角度为increment2,初值均为0,为产生旋转的动画,还应增加旋转步长,increment1每次增加2度,而increment1每次增加24度。

为了得到透视效果,我们使用gluPerspective来设置可视空间。假定可视角为45度,最近可视距离为1.0,最远可视距离为500。

当地球、月亮处于太阳的不同位置时,应该考虑遮挡效果。比如,地球处在太阳背面时,地球不可见。为增强真实感的立体感,应激活光照和深度检测。为以示区别,可假定除太阳外,地球和月亮本身也可发光,就通过设置材质Emission成分使物体看起来有发光效果。为产生光照的视觉效果,可使用glEnable(GL_LIGHTING)、glEnable(GL_LIGHT1)启用光照系统和点光源,点光源可以放置在右上角的位置。在环境中增加漫反射,相应的,使用glMaterialfv()给太阳、地球,月亮设置对漫反射光的反射率的RGBA值,即可达到效果。

三、实验结果

日地月环绕模型运行结果如下:

图2-1 地月在太阳左侧

图2-1 地月在太阳背面

图2-1 地月在太阳前方

四、体会

在前一次实验的基础上,对于这次的实验还是比较容易上手的。因为我之前接触过Ogre 的图形渲染方面的知识,所以对于这个实验中的地球等模型的光照,材质对漫散色光的反射,以及点光源的工作原理都比较熟悉,所以对于这个实验中的可视原理更容易明白。虽然这次是用让OpenGL来编程,但是其原理还是一样的。其中包括坐标轴变换(glLoadIdentity(),glTranslatef()),旋转glRotatef(),透视投影gluPerspective,使用glutSolidSphere ()、glLightfv()画球体,使用glEnable(GL_LIGHTING)启用光照系统,使用glEnable(GL_LIGHT1)启用点光源,使用glMaterialfv()设置材质对漫反射光的反射率,以及在窗口中使用双缓存、RGB颜色和深度测试。其中深度测试就是用来实现各个球体的互相之间的遮盖效果的。

五、源程序

////////////////////////////////////////////////////////////////////////////

//实验要求:(1)理解OpenGL中的变换过程//

// (2)理解透视投影与平行投影的不同//

// (3)添加代码实现太阳、地球和月亮的运动模型//

// (4)了解深度测试//

// (5)通过变换调整观察的位置与方向//

// (6)加入光照模型//

//////////////////////////////////////////////////////////////////////////

#include

#include

#include

#include

void Initial()

{

GLfloat diffuse[]={1.0f,0.5f,0.5f,1.0f};//漫反射分量,三个参数分别为红、绿、蓝光线成分,以及透明度

GLfloat position[]={250.0f,250.0f,-250.0f,1.0f};

glClearColor(0.0f, 0.0f, 0.0f, 0.0f ); //设置背景为黑色

glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);//指定漫反射分量

glLightfv(GL_LIGHT1, GL_POSITION, position);//指定点光源的坐标位置

glEnable(GL_LIGHTING); //启用光照系统

glEnable(GL_LIGHT1); //启用点光源(GL_LIGHT1)

// 启用深度测试,即深度(z值)会影响图形的遮挡关系(外边的会挡住里边的),不启动的话就是后画的挡住先画的(z值不起作用)

glEnable(GL_DEPTH_TEST);

}

void ChangeSize(int w, int h)

{

GLfloat fAspect;

if(h == 0) h = 1;

// 设置视区尺寸

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// 设置修剪空间

fAspect = (float)w/(float)h;

gluPerspective(45.0, fAspect, 1.0, 500.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void RenderScene(void)

{

// 地球绕太阳旋转角度、月亮绕地球旋转角度分别为increment1、increment2,从0到360变化

static float increment1 = 0.0;

static float increment2 = 0.0;

// GLfloat position[]={0.0f,0.0f,1.0f,2.0f};

GLfloat s_diffuse1[]={1.0f,1.0f,1.0f,1.0f};//设置材质对漫反射光的反射率的RGBA GLfloat s_emission1[]={1.0,0.1,0.1,1.0}; //设置材质发光颜色的RGBA值

GLfloat e_diffuse2[]={0.8f,0.8f,0.8f,1.0f};

GLfloat e_emission2[]={0.1,0.1,1.0,1.0};

GLfloat m_diffuse3[]={0.4f,0.4f,0.4f,1.0f};

GLfloat m_emission3[]={0.3,0.3,0.05,1.0};

//清除颜色和深度缓冲区

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 重置模型视图矩阵

glMatrixMode(GL_MODELVIEW);

//将坐标原点定位到屏幕中心

glLoadIdentity();

//将坐标沿Z负轴平移250

glTranslatef(0.0f, 0.0f, -250.0f);

// 以下绘制红色的“太阳”

glMaterialfv(GL_FRONT, GL_DIFFUSE, s_diffuse1);//设置材质对漫反射光的反射率//设置材质对各种光的反光率

glMaterialfv(GL_FRONT, GL_EMISSION, s_emission1);

glutSolidSphere(50.0f, 40, 50);

glEnable(GL_LIGHTING);

// 以下绘制蓝色的“地球”

glMaterialfv(GL_FRONT, GL_DIFFUSE, e_diffuse2);

glMaterialfv(GL_FRONT, GL_EMISSION, e_emission2);

glRotatef(increment1, 0.0f, 1.0f, 0.0f);//地球绕太阳旋转(Y轴)

glTranslatef(80.0f, 0.0f, 0.0f);

glutSolidSphere(15.0f, 40, 50);//设置太阳的半径以及位置

//以下绘制灰色的“月亮”

glMaterialfv(GL_FRONT, GL_DIFFUSE, m_diffuse3);

glMaterialfv(GL_FRONT, GL_EMISSION, m_emission3);

glRotatef(increment2, 0.0f, 0.0f, 1.0f);//月亮绕地球旋转(Z轴)

glTranslatef(20.0f, 0.0f, 0.0f);

glutSolidSphere(5.0f, 40, 50);

// 增加旋转步长

increment1 += 2.0f;

相关主题
文本预览
相关文档 最新文档