图形学实验报告 OpenGL中基本图形的绘制

时间:2024.5.2

《计算机图形学基础》

实验4  OpenGL中基本图形的绘制


一、实验目的及要求

1.       掌握OpenGL中点的绘制方法

2.       掌握OpenGL中直线的绘制方法

3.       掌握OpenGL中多边形面的绘制方法

4.  掌握OpenGL中字符函数的绘制方法

二、实验环境

主要是软件开发环境 vc 6.0

三、实验内容

OpenGL实现直线段的反走样。

四、实验结果

     

五、程序代码

#include <gl/glut.h>

GLuint lineList; //指定显示列表ID

void Initial()

{

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

      glLineWidth(12.0f);

      glColor4f (0.0, 0.6, 1.0, 1.0);

      lineList = glGenLists(1);

      glNewList(lineList, GL_COMPILE);  //定义显示列表

            glBegin(GL_LINE_LOOP);

                  glVertex2f(1.0f, 1.0f);

                  glVertex2f(4.0f, 2.0f);

                  glVertex2f(2.0f, 5.0f);

            glEnd();

      glEndList();

}

void ChangeSize(GLsizei w, GLsizei h)

{

      if(h == 0)        h = 1;

   glViewport(0, 0, w, h);

      glMatrixMode(GL_PROJECTION);

      glLoadIdentity();

      if(w<=h)

            gluOrtho2D(0.0, 5.0, 0.0, 6.0*(GLfloat)h/(GLfloat)w);

      else

            gluOrtho2D(0.0, 5.0*(GLfloat)w/(GLfloat)h, 0.0, 6.0);

      glMatrixMode(GL_MODELVIEW);

      glLoadIdentity();

}

void Displayt(void)

{   

      glClear(GL_COLOR_BUFFER_BIT);

      glCallList(lineList);

    glFlush();

}

void Displayw(void)

{

      glClear(GL_COLOR_BUFFER_BIT);

      glEnable(GL_LINE_SMOOTH);      //使用反走样

      glEnable (GL_BLEND);             //启用混合函数

      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  //指定混合函数

      glCallList(lineList);

    glFlush();

}

void main(void)

{

      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

      glutInitWindowSize(300, 300);

      glutCreateWindow("原始图形");

      glutDisplayFunc(Displayt);

    glutReshapeFunc(ChangeSize);

   Initial();

      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

      glutInitWindowPosition(300, 300);

      glutInitWindowSize(300, 300);

      glutCreateWindow("反走样图形");

      glutDisplayFunc(Displayw);

    glutReshapeFunc(ChangeSize);

      Initial();

      glutMainLoop();

}

六、心得体会

    在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观。这是因为直线、多边形、色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显示设备上表现直线、多边形等,必须在离散位置采样。由于采样不充分重建后造成的信息失真,就叫走样。而用于减少或消除这种效果的技术,就称为反走样。OpenGL实现反走样需要满足两个条件,一是启用混合,二是启用针对几何图元的反走样处理。

    要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND)。
    要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND)。


第二篇:交互式图形学-基于OPenGL自顶向下(第五版)课后实例程序全


怎么上传不了啊!!!!!

A.1 Sierpinski

镂垫程序

/* two-dimensional Sierpinski gasket */

/* generated using randomly selected vertices */

/* and bisection */

#include <GL/glut.h>

/*you may have to change the include to<glut.h> or

elsewhere depending on where it is stored on your system */

/* glut.h usually has included for gl.h and glu.h */

void myinit(void)

{

/* attributes */

glClearColor(1.0, 1.0, 1.0, 1.0); /* white background */

glColor3f(1.0, 0.0, 0.0); /* draw in red */

/* set up viewing */

/* 50.0 × 50.0 camera coordinate window with origin lower left */ glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0, 50.0, 0.0, 50.0);

glMatrixMode(GL_MODELVIEW);

}

void display(void)

{

/* A triangle */

GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0},{50.0,0.0}};

int i, j, k;

int rand(); /* standard random number generator */

GLfloat p[2] ={7.5,5.0}; /* an arbitrary initial point inside traingle */ glClear(GL_COLOR_BUFFER_BIT); /* clear the window */

586 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glBegin(GL_POINTS);

/* compute and plots 5000 new points */

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

{

j=rand()%3; /* pick a vertex at random */

/* Compute point halfway between selected vertex and old point */

p[0] = (p[0]+vertices[j][0])/2.0;

p[1] = (p[1]+vertices[j][1])/2.0;

/* plot new point */

glVertex2fv(p);

}

glEnd();

glFlush(); /* clear buffers */

}

void main(int argc, char** argv)

{

/* Standard GLUT initialization */

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); /* default, not needed */ glutInitWindowSize(500,500); /* 500 × 500 pixel window */

glutInitWindowPosition(0,0); /* place window top left on display */ glutCreateWindow("Sierpinski Gasket"); /* window title */

glutDisplayFunc(display);

/* display callback invoked when window opened */

myinit(); /* set attributes */

glutMainLoop(); /* enter event loop */

}

A.2 生成Sierpinski镂垫的递归程序

/* Recursive subdivision of triangle to form Sierpinski gasket */ /* number of recursive steps given on command line */

#include <GL/glut.h>

#include<stdlib.h>

/* initial triangle */

GLfloat v[3][2]={{-1.0, -0.58}, {1.0, -0.58}, {0.0, 1.15}};

附录A 实 例 程 序

int n;

void triangle( GLfloat *a, GLfloat *b, GLfloat *c)

/* display one triangle */

{

glVertex2fv(a);

glVertex2fv(b);

glVertex2fv(c);

}

void divide_triangle(GLfloat *a, GLfloat *b, GLfloat *c, int m) {

/* triangle subdivision using vertex numbers */

GLfloat v0[2], v1[2], v2[2];

int j;

if(m>0)

{

for(j=0; j<2; j++) v0[j]=(a[j]+b[j])/2;

for(j=0; j<2; j++) v1[j]=(a[j]+c[j])/2;

for(j=0; j<2; j++) v2[j]=(b[j]+c[j])/2;

divide_triangle(a, v0, v1, m-1);

divide_triangle(c, v1, v2, m-1);

divide_triangle(b, v2, v0, m-1);

}

else triangle(a,b,c); /* draw triangle at end of recursion */ }

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT);

glBegin(GL_TRIANGLES);

divide_triangle(v[0], v[1], v[2], n);

glEnd();

glFlush();

}

void myinit()

{

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(-2.0, 2.0, -2.0, 2.0);

glMatrixMode(GL_MODELVIEW);

glClearColor(1.0, 1.0, 1.0, 1.0);

glColor3f(0.0,0.0,0.0);

}

void main(int argc, char **argv)

{

n=atoi(argv[1]); /* or set number of subdivision steps here */ 587

588 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(500, 500);

glutCreateWindow("Sierpinski Gasket");

glutDisplayFunc(display);

myinit();

glutMainLoop();

}

A.3 三维Sierpinski镂垫的递归程序

/* Recursive subdivision of a tetrahedron to form 3D Sierpinski gasket */ /* number of recursive steps given on command line */

#include <stdlib.h>

#include <GL/glut.h>

/* initial tetrahedron */

GLfloat v[4][3]={{0.0, 0.0, 1.0},{0.0, 0.942809, -0.33333},

{-0.816497, -0.471405, -0.333333},{0.816497, -0.471405, -0.333333}};

GLfloat colors[4][3]={{1.0,0.0,0.0},{0.0,1.0,0.0},

{0.0,0.0,1.0},{0.0,0.0,0.0}};

int n;

void triangle( GLfloat *va, GLfloat *vb, GLfloat *vc)

{

glVertex3fv(va);

glVertex3fv(vb);

glVertex3fv(vc);

}

void tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d)

{

glColor3fv(colors[0]);

triangle(a,b,c);

glColor3fv(colors[1]);

triangle(a,c,d);

glColor3fv(colors[2]);

triangle(a,d,b);

glColor3fv(colors[3]);

triangle(b,d,c);

}

void divide_tetra(GLfloat *a, GLfloat *b, GLfloat *c, GLfloat *d, int m) {

GLfloat mid[6][3];

int j;

附录A 实 例 程 序

if(m>0)

{

/* compute six midpoints */

for(j=0; j<3; j++) mid[0][j]=(a[j]+b[j])/2;

for(j=0; j<3; j++) mid[1][j]=(a[j]+c[j])/2;

for(j=0; j<3; j++) mid[2][j]=(a[j]+d[j])/2;

for(j=0; j<3; j++) mid[3][j]=(b[j]+c[j])/2;

for(j=0; j<3; j++) mid[4][j]=(c[j]+d[j])/2;

for(j=0; j<3; j++) mid[5][j]=(b[j]+d[j])/2;

/* create 4 tetrahedrons by subdivision */

divide_tetra(a,mid[0],mid[1],mid[2], m-1);

divide_tetra(mid[0],b,mid[3],mid[5], m-1);

divide_tetra(mid[1],mid[3],c,mid[4], m-1);

divide_tetra(mid[2],mid[4],d,mid[5], m-1);

}

else tetra(a,b,c,d); /* draw tetrahedron at end of recursion */ }

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBegin(GL_TRIANGLES);

divide_tetra(v[0],v[1],v[2],v[3],n);

glEnd();

glFlush();

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);

else

glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,

2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW);

glutPostRedisplay();

}

void main(int argc, char **argv)

{

n=atoi(argv[1]); /* or enter number of subdivision steps here */ 589

590 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("3D Gasket");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glEnable(GL_DEPTH_TEST);

glClearColor (1.0, 1.0, 1.0, 1.0);

glutMainLoop();

}

A.4 Marching-Square程序

/* generates contours using marching squares */

/* region size */

#define X_MAX 1.0

#define Y_MAX 1.0

#define X_MIN -1.0

#define Y_MIN -1.0

/* number of cells */

#define N_X 50

#define N_Y 50

/* contour value */

#define THRESHOLD 0.0

#include<gl/glut.h>

void display()

{

double f(double,double);

int cell(double,double,double,double);

void lines(int,int,int,double,double,double,double);

double data[N_X][N_Y];

int i,j;

int c;

glClear(GL_COLOR_BUFFER_BIT);

/* form data array from function */

for(i=0;i<N_X;i++)

for(j=0;j<N_Y;j++)

data[i][j]=f(X_MIN+i*(X_MAX-X_MIN) /(N_X-1.0),

附录A 实 例 程 序

Y_MIN+j*(Y_MAX-Y_MIN)/(N_Y-1.0));

/* process each cell */

for(i=0;i<N_X;i++)

for(j=0;j<N_Y;j++)

{

c=cell(data[i][j],data[i+1][j],data[i+1][j+1],data[i][j+1]);

lines(c,i,j,data[i][j],data[i+1][j],data[i+1][j+1],data[i][j+1]); }

glFlush();

}

/* define function f(x,y) */

double f(double x, double y)

{

double a=0.49, b=0.5;

/* ovals of Cassini */

return (x*x+y*y+a*a)*(x*x+y*y+a*a)-4*a*a*x*x-b*b*b*b;

}

/* define cell vertices */

int cell(double a,double b,double c, double d)

{

int n=0;

if(a>THRESHOLD) n+=1;

if(b>THRESHOLD) n+=8;

if(c>THRESHOLD) n+=4;

if(d>THRESHOLD) n+=2;

return n ;

}

/* draw line segments for each case */

void lines(int num,int i,int j,double a ,double b,double c,double d) {

void draw_one(int,int,int,double,double,double,double);

void draw_adjacent(int,int,int, double,double,double,double); void draw_opposite(int,int,int,double,double,double,double);

switch(num)

{

case 1 : case 2: case 4 : case 7: case 8: case 11: case 13: case 14: 591

592 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

draw_one(num,i,j,a,b,c,d);

break;

case 3: case 6: case 9: case 12:

draw_adjacent(num,i,j,a,b,c,d);

break;

case 5: case 10:

draw_opposite(num,i,j,a,b,c,d);

break;

case 0: case 15:

break;

}

}

void draw_one(int num,int i,int j,double a,double b,double c,double d) {

double x1,y1,x2,y2;

double ox,oy;

double dx,dy;

dx=(X_MAX-X_MIN)/(N_X-1.0);

dy=(Y_MAX-Y_MIN)/(N_Y-1.0);

ox=X_MIN+i*(X_MAX-X_MIN)/(N_X-1.0);

oy=Y_MIN+j*(Y_MAX-Y_MIN)/(N_Y-1.0);

switch(num)

{

case 1 : case 14:

x1=ox;

y1=oy+dy*(THRESHOLD-a)/(d-a);

x2=ox+dx*(THRESHOLD-a)/(b-a);

y2=oy;

break;

case 2: case 13:

x1=ox;

y1=oy+dy*(THRESHOLD-a)/(d-a);

x2=ox+dx*(THRESHOLD-d)/(c-d);

y2=oy+dy;

break;

case 4: case 11:

x1=ox+dx*(THRESHOLD-d)/(c-d);

y1=oy+dy;

x2=ox+dx;

y2=oy+dy*(THRESHOLD-b)/(c-b);

break;

case 7: case 8:

x1=ox+dx*(THRESHOLD-a)/(b-a);

y1=oy;

x2=ox+dx;

y2=oy+dy*(THRESHOLD-b)/(c-b);

附录A 实 例 程 序

break;

}

glBegin(GL_LINES);

glVertex2d(x1,y1);

glVertex2d(x2,y2);

glEnd();

}

void draw_adjacent(int num,int i,int j,double a,double b,double c ,double d) {

double x1,y1,x2,y2;

double ox,oy;

double dx,dy;

dx=(X_MAX-X_MIN)/(N_X-1.0);

dy=(Y_MAX-Y_MIN)/(N_Y-1.0);

ox=X_MIN+i*(X_MAX-X_MIN)/(N_X-1.0);

oy=Y_MIN+j*(Y_MAX-Y_MIN)/(N_Y-1.0);

switch(num)

{

case 3 : case 12:

x1=ox+dx*(THRESHOLD-a)/(b-a);

y1=oy;

x2=ox+dx*(THRESHOLD-d)/(c-d);

y2=oy+dy;

break;

case 6: case 9:

x1=ox;

y1=oy+dy*(THRESHOLD-a)/(d-a);

x2=ox+dx;

y2=oy+dy*(THRESHOLD-b)/(c-b);

break;

}

glBegin(GL_LINES);

glVertex2d(x1,y1);

glVertex2d(x2,y2);

glEnd();

}

void draw_opposite(int num,int i,int j,double a,double b,double c ,double d) {

double x1,y1,x2,y2,x3,y3,x4,y4;

double ox,oy;

double dx,dy;

dx=(X_MAX-X_MIN)/(N_X-1.0);

dy=(Y_MAX-Y_MIN)/(N_Y-1.0);

ox=X_MIN+i*(X_MAX-X_MIN)/(N_X-1.0);

oy=Y_MIN+j*(Y_MAX-Y_MIN)/(N_Y-1.0);

switch(num)

{ 593

594 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

case 5 :

x1=ox;

y1=oy+dy*(THRESHOLD-a)/(d-a);

x2=ox+dx*(THRESHOLD-a)/(b-a);

y2=oy;

x3=ox+dx*(THRESHOLD-d)/(c-d);

y3=oy+dy;

x4=ox+dx;

y4=oy+dy*(THRESHOLD-b)/(c-b);

break;

case 10:

x1=ox;

y1=oy+dy*(THRESHOLD-a)/(d-a);

x2=ox+dx*(THRESHOLD-d)/(c-d);

y2=oy+dy;

x3=ox+dx*(THRESHOLD-d)/(c-d);

y3=oy;

x4=ox+dx;

y4=oy+dy*(THRESHOLD-b)/(c-b);

break;

}

glBegin(GL_LINES);

glVertex2d(x1,y1);

glVertex2d(x2,y2);

glVertex2d(x3,y3);

glVertex2d(x4,y4);

glEnd();

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

gluOrtho2D(X_MIN, X_MAX, Y_MIN * (GLfloat) h / (GLfloat) w, Y_MAX * (GLfloat) h / (GLfloat) w);

else

gluOrtho2D(X_MIN * (GLfloat) w / (GLfloat) h,

X_MAX * (GLfloat) w / (GLfloat) h, Y_MIN, Y_MAX); glMatrixMode(GL_MODELVIEW);

}

void main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitWindowSize(500, 500);

glutCreateWindow("contour plot");

附录A 实 例 程 序

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glClearColor(0.0, 0.0, 0.0, 1.0);

glColor3f(1.0,1.0,1.0);

glutMainLoop();

}

595

A.5 生成正方形的程序

/* This program illustrates the use of the GLUT library for

interfacing with a Window System */

/* The program opens a window, clears it to black,

then draws a box at the location of the mouse each time the

left button is clicked. The right button exits the program.

The program also reacts correctly when the window is

moved or resized by clearing the new window to black. */

#include <GL/glut.h>

#include <stdlib.h>

/* globals */

GLsizei wh = 500, ww = 500; /* initial window size */

GLfloat size = 3.0; /* half side length of square */

void drawSquare(int x, int y)

{

y=wh-y;

glColor3ub( (char) rand()%256, (char) rand()%256, (char) rand()%256); glBegin(GL_POLYGON);

glVertex2f(x+size, y+size);

glVertex2f(x-size, y+size);

glVertex2f(x-size, y-size);

glVertex2f(x+size, y-size);

glEnd();

glFlush();

}

/* reshaping routine called whenever window is resized

or moved */

void myReshape(GLsizei w, GLsizei h)

{

596 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

/* adjust clipping box */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

/* adjust viewport and clear */

glViewport(0,0,w,h);

glClear(GL_COLOR_BUFFER_BIT);

glFlush();

/* set global size for use by drawing routine */

ww = w;

wh = h;

}

void myinit(void)

{

glViewport(0,0,ww,wh);

/* Pick 2D clipping window to match size of screen window. This choice avoids having to scale object coordinates each time window is resized. */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, (GLdouble) ww, 0.0, (GLdouble) wh, -1.0, 1.0);

/* set clear color to black and clear window */

glClearColor (0.0, 0.0, 0.0, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

glFlush();

}

void mouse(int btn,int state,int x,int y)

{

if(btn==GLUT_RIGHT_BUTTON &&state==GLUT_DOWN) exit(0) }

/* display callback required by GLUT*/

viod display()

{}

int main(int argc,char** argv)

{

附录A 实 例 程 序

glutInit(&argc,argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutCreateWindow("square");

myinit();

glutReshapeFunc (my Reshape);

glutMouseFunc (mouse)

glutMotionFunc (drawSqure);

glutDisp layFunc (display);

glutMainLoop();

} 597

A.6 画图程序

/* simple painting program with text, lines, triangles, rectangles,and points */

#define NULL 0

#define LINE 1

#define RECTANGLE 2

#define TRIANGLE 3

#define POINTS 4

#define TEXT 5

#include <stdlib.h>

#include <GL/glut.h>

void mouse(int, int, int, int);

void key(unsigned char, int, int);

void display(void);

void drawSquare(int, int);

void myReshape(GLsizei, GLsizei);

void myinit(void);

void screen_box(int, int, int);

void right_menu(int);

void middle_menu(int);

void color_menu(int);

void pixel_menu(int);

void fill_menu(int);

int pick(int, int);

/* globals */

GLsizei wh = 500, ww = 500; /* initial window size */ GLfloat size = 3.0; /* half side length of square */ int draw_mode = 0; /* drawing mode */

int rx, ry; /* raster position */

598 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

GLfloat r = 1.0, g = 1.0, b = 1.0; /* drawing color */

int fill = 0; /* fill flag */

void drawSquare(int x, int y)

{

y=wh-y;

glColor3ub( (char) rand()%256, (char) rand()%256, (char) rand()%256); glBegin(GL_POLYGON);

glVertex2f(x+size, y+size);

glVertex2f(x-size, y+size);

glVertex2f(x-size, y-size);

glVertex2f(x+size, y-size);

glEnd();

}

/* rehaping routine called whenever window is resized

or moved */

void myReshape(GLsizei w, GLsizei h)

{

/* adjust clipping box */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

/* adjust viewport and clear */

glViewport(0,0,w,h);

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

display();

glFlush();

/* set global size for use by drawing routine */

ww = w;

wh = h;

}

void myinit(void)

{

glViewport(0,0,ww,wh);

附录A 实 例 程 序

/* Pick 2D clipping window to match size of X window.

This choice avoids having to scale object coordinates

each time window is resized.*/

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, (GLdouble) ww , 0.0, (GLdouble) wh , -1.0, 1.0);

/* set clear color to black and clear window */

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

glFlush();

}

void mouse(int btn, int state, int x, int y)

{

static int count;

int where;

static int xp[2],yp[2];

if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN)

{

glPushAttrib(GL_ALL_ATTRIB_BITS);

where = pick(x,y);

glColor3f(r, g, b);

if(where != 0)

{

count = 0;

draw_mode = where;

}

else switch(draw_mode)

{

case(LINE):

if(count==0)

{

count++;

xp[0] = x;

yp[0] = y;

}

else

{

glBegin(GL_LINES);

glVertex2i(x,wh-y);

glVertex2i(xp[0],wh-yp[0]);

glEnd();

draw_mode=0;

count=0;

}

break; 599

600 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

case(RECTANGLE):

if(count == 0)

{

count++;

xp[0] = x;

yp[0] = y;

}

else

{

if(fill) glBegin(GL_POLYGON); else glBegin(GL_LINE_LOOP); glVertex2i(x,wh-y);

glVertex2i(x,wh-yp[0]);

glVertex2i(xp[0],wh-yp[0]); glVertex2i(xp[0],wh-y);

glEnd();

draw_mode=0;

count=0;

}

break;

case (TRIANGLE):

switch(count)

{

case(0):

count++;

xp[0] = x;

yp[0] = y;

break;

case(1):

count++;

xp[1] = x;

yp[1] = y;

break;

case(2):

if(fill) glBegin(GL_POLYGON); else glBegin(GL_LINE_LOOP); glVertex2i(xp[0],wh-yp[0]); glVertex2i(xp[1],wh-yp[1]); glVertex2i(x,wh-y);

glEnd();

draw_mode=0;

count=0;

}

break;

case(POINTS):

{

drawSquare(x,y);

count++;

}

break;

附录A 实 例 程 序

case(TEXT):

{

rx=x;

ry=wh-y;

glRasterPos2i(rx,ry);

count=0;

}

}

glPopAttrib();

glFlush();

}

}

int pick(int x, int y)

{

y = wh - y;

if(y < wh-ww/10) return 0;

else if(x < ww/10) return LINE;

else if(x < ww/5) return RECTANGLE; else if(x < 3*ww/10) return TRIANGLE; else if(x < 2*ww/5) return POINTS; else if(x < ww/2) return TEXT;

else return 0;

}

void screen_box(int x, int y, int s ) {

glBegin(GL_QUADS);

glVertex2i(x, y);

glVertex2i(x+s, y);

glVertex2i(x+s, y+s);

glVertex2i(x, y+s);

glEnd();

}

void right_menu(int id)

{

if(id == 1) exit(0);

else display();

}

void middle_menu(int id)

{

}

void color_menu(int id)

{

if(id == 1) {r = 1.0; g = 0.0; b = 0.0;} 601

602 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

else if(id == 2) {r = 0.0; g = 1.0; b = 0.0;} else if(id == 3) {r = 0.0; g = 0.0; b = 1.0;} else if(id == 4) {r = 0.0; g = 1.0; b = 1.0;} else if(id == 5) {r = 1.0; g = 0.0; b = 1.0;} else if(id == 6) {r = 1.0; g = 1.0; b = 0.0;} else if(id == 7) {r = 1.0; g = 1.0; b = 1.0;} else if(id == 8) {r = 0.0; g = 0.0; b = 0.0;} }

void pixel_menu(int id)

{

if (id == 1) size = 2 * size;

else if (size > 1) size = size/2;

}

void fill_menu(int id)

{

if (id == 1) fill = 1;

else fill = 0;

}

void key(unsigned char k, int xx, int yy) {

if(draw_mode!=TEXT) return;

glColor3f(0.0,0.0,0.0);

glRasterPos2i(rx,ry);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, k); /* glutStrokeCharacter(GLUT_STROKE_ROMAN,i); */ rx+=glutBitmapWidth(GLUT_BITMAP_9_BY_15,k);

}

void display(void)

{

int shift=0;

glPushAttrib(GL_ALL_ATTRIB_BITS);

glClearColor (0.8, 0.8, 0.8, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

glColor3f(1.0, 1.0, 1.0);

screen_box(0,wh-ww/10,ww/10);

glColor3f(1.0, 0.0, 0.0);

screen_box(ww/10,wh-ww/10,ww/10);

glColor3f(0.0, 1.0, 0.0);

screen_box(ww/5,wh-ww/10,ww/10);

glColor3f(0.0, 0.0, 1.0);

screen_box(3*ww/10,wh-ww/10,ww/10);

glColor3f(1.0, 1.0, 0.0);

screen_box(2*ww/5,wh-ww/10,ww/10);

glColor3f(0.0, 0.0, 0.0);

附录A 实 例 程 序

screen_box(ww/10+ww/40,wh-ww/10+ww/40,ww/20); glBegin(GL_LINES);

glVertex2i(wh/40,wh-ww/20);

glVertex2i(wh/40+ww/20,wh-ww/20);

glEnd();

glBegin(GL_TRIANGLES);

glVertex2i(ww/5+ww/40,wh-ww/10+ww/40); glVertex2i(ww/5+ww/20,wh-ww/40);

glVertex2i(ww/5+3*ww/40,wh-ww/10+ww/40); glEnd();

glPointSize(3.0);

glBegin(GL_POINTS);

glVertex2i(3*ww/10+ww/20, wh-ww/20);

glEnd();

glRasterPos2i(2*ww/5,wh-ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'A'); shift=glutBitmapWidth(GLUT_BITMAP_9_BY_15, 'A'); glRasterPos2i(2*ww/5+shift,wh-ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'B'); shift+=glutBitmapWidth(GLUT_BITMAP_9_BY_15, 'B'); glRasterPos2i(2*ww/5+shift,wh-ww/20);

glutBitmapCharacter(GLUT_BITMAP_9_BY_15, 'C'); glFlush();

glPopAttrib();

}

int main(int argc, char** argv)

{

int c_menu, p_menu, f_menu;

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500);

glutCreateWindow("square");

glutDisplayFunc(display);

c_menu = glutCreateMenu(color_menu);

glutAddMenuEntry("Red",1);

glutAddMenuEntry("Green",2);

glutAddMenuEntry("Blue",3);

glutAddMenuEntry("Cyan",4);

glutAddMenuEntry("Magenta",5);

glutAddMenuEntry("Yellow",6);

glutAddMenuEntry("White",7);

glutAddMenuEntry("Black",8);

p_menu = glutCreateMenu(pixel_menu);

glutAddMenuEntry("increase pixel size", 1); glutAddMenuEntry("decrease pixel size", 2); f_menu = glutCreateMenu(fill_menu); 603

604 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glutAddMenuEntry("fill on", 1);

glutAddMenuEntry("fill off", 2);

glutCreateMenu(right_menu);

glutAddMenuEntry("quit",1);

glutAddMenuEntry("clear",2);

glutAttachMenu(GLUT_RIGHT_BUTTON);

glutCreateMenu(middle_menu);

glutAddSubMenu("Colors", c_menu);

glutAddSubMenu("Pixel Size", p_menu);

glutAddSubMenu("Fill", f_menu);

glutAttachMenu(GLUT_MIDDLE_BUTTON);

myinit ();

glutReshapeFunc (myReshape);

glutKeyboardFunc(key);

glutMouseFunc (mouse);

glutMainLoop();

}

A.7 使用双缓存的程序

/*

* double.c

* This program demonstrates double buffering for

* flicker-free animation. The left and middle mouse

* buttons start and stop the spinning motion of the square. */

#include <GL/glut.h>

#include <stdlib.h>

#include <math.h>

#define DEGREES_TO_RADIANS 3.14159/180.0

static GLfloat spin = 0.0;

GLfloat x,y;

int singleb, doubleb;

void square()

{

glBegin(GL_QUADS);

glVertex2f(x,y);

glVertex2f(-y,x);

glVertex2f(-x,-y);

glVertex2f(y,-x);

glEnd();

}

void displayd(void)

附录A 实 例 程 序

{

glClear(GL_COLOR_BUFFER_BIT);

square();

glutSwapBuffers();

}

void displays(void)

{

glClear(GL_COLOR_BUFFER_BIT);

square();

glFlush();

}

void spinDisplay(void)

{

spin = spin + 2.0;

if (spin > 360.0) spin = spin - 360.0;

x=25.0 * cos(DEGREES_TO_RADIANS*spin);

y=25.0 * sin(DEGREES_TO_RADIANS*spin);

glutSetWindow(singleb);

glutPostRedisplay();

glutSetWindow(doubleb);

glLoadIdentity();

glutPostRedisplay();

}

void myinit(void)

{

glClearColor(0.0, 0.0, 0.0, 1.0);

glColor3f(1.0, 1.0, 1.0);

glShadeModel(GL_FLAT);

}

void mouse(int btn, int state, int x, int y)

{

if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) glutIdleFunc(spinDisplay);

if(btn==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN) glutIdleFunc(NULL);

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-50.0, 50.0, -50.0*(GLfloat)h/(GLfloat)w, 50.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0); else 605

606 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glOrtho(-50.0*(GLfloat)w/(GLfloat)h,

50.0*(GLfloat)w/(GLfloat)h, -50.0, 50.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

/* Main Loop

* Open window with initial window size, title bar, * RGBA display mode, and handle input events.

*/

int main(int argc, char** argv)

{

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

singleb=glutCreateWindow("single buffered");

myinit();

glutDisplayFunc(displays);

glutReshapeFunc(myReshape);

glutIdleFunc(spinDisplay);

glutMouseFunc(mouse);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

doubleb=glutCreateWindow("double buffered");

myinit();

glutDisplayFunc(displayd);

glutReshapeFunc(myReshape);

glutIdleFunc(spinDisplay);

glutMouseFunc(mouse);

glutMainLoop();

}

A.8 选择模式拾取程序

/* demonstrates picking used selection mode */

#include <stdlib.h>

#include <stdio.h>

#include <GL/glut.h>

void init()

{

glClearColor(0.0, 0.0, 0.0, 0.0);

}

void drawObjects(GLenum mode)

附录A 实 例 程 序

{

if(mode == GL_SELECT) glLoadName(1);

glColor3f(1.0, 0.0, 0.0);

glRectf(-0.5, -0.5, 1.0, 1.0);

if(mode == GL_SELECT) glLoadName(2);

glColor3f(0.0, 0.0, 1.0);

glRectf(-1.0, -1.0, 0.5, 0.5);

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT);

drawObjects(GL_RENDER);

glFlush();

}

/* processHits prints out the contents of the

* selection array.

*/

void processHits (GLint hits, GLuint buffer[])

{

unsigned int i, j;

GLuint ii, jj, names, *ptr;

printf("hits = %d\n", hits);

ptr=(GLuint *) buffer;

for (i = 0; i < hits; i++) { /* for each hit */ names = *ptr;

ptr+=3;

for (j = 0; j < names; j++)

{ /* for each name */

if(*ptr==1) printf ("red rectangle\n");

else printf ("blue rectangle\n");

ptr++;

}

printf ("\n");

}

}

#define SIZE 512

void mouse(int button, int state, int x, int y)

{

GLuint selectBuf[SIZE];

GLint hits;

GLint viewport[4];

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {

glGetIntegerv(GL_VIEWPORT, viewport); 607

608 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glSelectBuffer (SIZE, selectBuf);

glRenderMode(GL_SELECT);

glInitNames();

glPushName(0);

glMatrixMode(GL_PROJECTION);

glPushMatrix();

glLoadIdentity();

/* create 5×5 pixel picking region near cursor location */ gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y), 5.0, 5.0, viewport);

gluOrtho2D(-2.0, 2.0, -2.0, 2.0);

drawObjects(GL_SELECT);

glMatrixMode(GL_PROJECTION);

glPopMatrix();

glFlush();

hits = glRenderMode(GL_RENDER);

processHits(hits, selectBuf);

glutPostRedisplay();

}

}

void reshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D (-2.0, 2.0, -2.0, 2.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void keyboard(unsigned char key, int x, int y)

{

switch (key)

{

case 27:

exit(0);

break;

}

}

/* Main Loop */

附录A 实 例 程 序

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize(500, 500);

glutInitWindowPosition(100, 100);

glutCreateWindow(argv[0]);

init();

glutReshapeFunc(reshape);

glutDisplayFunc(display);

glutMouseFunc(mouse);

glutKeyboardFunc(keyboard);

glutMainLoop();

return 0;

} 609

A.9 立方体旋转程序

/* Rotating cube with color interpolation */

/* Demonstration of use of homogeneous coordinate

transformations and simple data structure for representing cube from Chapter 4 */

/* Colors are assigned to the vertices */

/* cube is centered at orign*/

#include <stdlib.h>

#include <GL/glut.h>

GLfloat vertices[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}};

GLfloat colors[][3] = {{0.0,0.0,0.0},{1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}};

void polygon(int a, int b, int c, int d)

{

/* draw a polygon via list of vertices */

glBegin(GL_POLYGON);

glColor3fv(colors[a]);

glVertex3fv(vertices[a]);

glColor3fv(colors[b]);

glVertex3fv(vertices[b]);

610 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

glColor3fv(colors[c]);

glVertex3fv(vertices[c]);

glColor3fv(colors[d]);

glVertex3fv(vertices[d]);

glEnd();

}

void colorcube(void)

{

/* map vertices to faces */

polygon(0,3,2,1);

polygon(2,3,7,6);

polygon(0,4,7,3);

polygon(1,2,6,5);

polygon(4,5,6,7);

polygon(0,1,5,4);

}

static GLfloat theta[] = {0.0,0.0,0.0};

static GLint axis = 2;

void display(void)

{

/* display callback, clear frame buffer and z buffer, rotate cube and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity();

glRotatef(theta[0], 1.0, 0.0, 0.0);

glRotatef(theta[1], 0.0, 1.0, 0.0);

glRotatef(theta[2], 0.0, 0.0, 1.0);

colorcube();

glFlush();

glutSwapBuffers();

}

void spinCube()

{

/* Idle callback, spin cube 2 degrees about selected axis */

theta[axis] += 2.0;

if( theta[axis] > 360.0 ) theta[axis] -= 360.0;

/* display(); */

glutPostRedisplay();

}

附录A 实 例 程 序

void mouse(int btn, int state, int x, int y)

{

/* mouse callback, selects an axis about which to rotate */

if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;

if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2; }

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,

2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);

else

glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,

2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW);

}

void main(int argc, char **argv)

{

glutInit(&argc, argv);

/* need both double buffering and z buffer */

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("colorcube");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutIdleFunc(spinCube);

glutMouseFunc(mouse);

glEnable(GL_DEPTH_TEST); /* Enable hidden-surface removal */ glutMainLoop();

} 611

A.10 利用顶点数组旋转立方体程序

/* rotating cube with vertex arrays */

#include <stdlib.h>

#include <GL/glut.h>

612 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

GLfloat vertices[] = {-1.0,-1.0,-1.0,1.0,-1.0,-1.0,

1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,

1.0,-1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0};

GLfloat colors[] = {0.0,0.0,0.0,1.0,0.0,0.0,

1.0,1.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0,

1.0,0.0,1.0, 1.0,1.0,1.0, 0.0,1.0,1.0};

GLubyte cubeIndices[]={0,3,2,1,2,3,7,6,0,4,7,3,1,2,6,5,4,5,6,7,0,1,5,4};

static GLfloat theta[] = {0.0,0.0,0.0};

static GLint axis = 2;

void display(void)

{

/* display callback, clear frame buffer and z buffer,

rotate cube and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(1.0,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0);

glTranslatef(0.0, 3.0, 0.0);

glRotatef(theta[0], 1.0, 0.0, 0.0);

glRotatef(theta[1], 0.0, 1.0, 0.0);

glRotatef(theta[2], 0.0, 0.0, 1.0);

glColorPointer(3,GL_FLOAT, 0, colors);

glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cubeIndices);

glutSwapBuffers();

}

void spinCube()

{

/* Idle callback, spin cube 2 degrees about selected axis */

theta[axis] += 2.0;

if( theta[axis] > 360.0 ) theta[axis] -= 360.0;

glutPostRedisplay();

}

void mouse(int btn, int state, int x, int y)

{

/* mouse callback, selects an axis about which to rotate */

附录A 实 例 程 序

if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0;

if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2; }

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-4.0, 4.0, -3.0 * (GLfloat) h / (GLfloat) w,

5.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);

else

glOrtho(-4.0 * (GLfloat) w / (GLfloat) h,

4.0 * (GLfloat) w / (GLfloat) h, -3.0, 5.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW);

}

void main(int argc, char **argv)

{

/* need both double buffering and z buffer */

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("colorcube");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutIdleFunc(spinCube);

glutMouseFunc(mouse);

glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

glEnableClientState(GL_COLOR_ARRAY);

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, vertices);

glColorPointer(3,GL_FLOAT, 0, colors);

glClearColor(1.0,1.0,1.0,1.0);

glColor3f(1.0,1.0,1.0);

glutMainLoop();

} 613

A.11 用虚拟跟踪球实现立方体旋转程序

/* Rotating cube demo with trackball */

#include <math.h>

#include <GL/glut.h>

614 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

#define bool int

#define false 0

#define true 1

int winWidth, winHeight;

float angle = 0.0, axis[3], trans[3];

bool trackingMouse = false;

bool redrawContinue = false;

bool trackballMove = false;

/* Draw the cube */

GLfloat vertices[][3] = {

{-1.0,-1.0,-1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0} };

GLfloat colors[][3] = {

{0.0,0.0,0.0}, {1.0,0.0,0.0}, {1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}

};

void polygon(int a, int b, int c , int d, int face)

{

/* draw a polygon via list of vertices */

glBegin(GL_POLYGON);

glColor3fv(colors[a]);

glVertex3fv(vertices[a]);

glVertex3fv(vertices[b]);

glVertex3fv(vertices[c]);

glVertex3fv(vertices[d]);

glEnd();

}

void colorcube(void)

{

/* map vertices to faces */

polygon(1,0,3,2,0);

polygon(3,7,6,2,1);

polygon(7,3,0,4,2);

polygon(2,6,5,1,3);

polygon(4,5,6,7,4);

polygon(5,4,0,1,5);

附录A 实 例 程 序

}

/* These functions implement a simple trackball-like motion control */

float lastPos[3] = {0.0F, 0.0F, 0.0F};

int curx, cury;

int startX, startY;

void trackball_ptov(int x, int y, int width, int height, float v[3]) {

float d, a;

/* project x,y onto a hemisphere centered within width, height */ v[0] = (2.0F*x - width) / width;

v[1] = (height - 2.0F*y) / height;

d = (float) sqrt(v[0]*v[0] + v[1]*v[1]);

v[2] = (float) cos((M_PI/2.0F) * ((d < 1.0F) ? d : 1.0F));

a = 1.0F / (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); v[0] *= a;

v[1] *= a;

v[2] *= a;

}

void mouseMotion(int x, int y)

{

float curPos[3], dx, dy, dz;

trackball_ptov(x, y, winWidth, winHeight, curPos);

if(trackingMouse)

{

dx = curPos[0] - lastPos[0];

dy = curPos[1] - lastPos[1];

dz = curPos[2] - lastPos[2];

if (dx || dy || dz) {

angle = 90.0F * sqrt(dx*dx + dy*dy + dz*dz);

axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];

axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];

axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];

lastPos[0] = curPos[0];

lastPos[1] = curPos[1];

lastPos[2] = curPos[2];

}

}

glutPostRedisplay();

}

void startMotion(int x, int y)

615

616 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

{

trackingMouse = true;

redrawContinue = false;

startX = x; startY = y;

curx = x; cury = y;

trackball_ptov(x, y, winWidth, winHeight, lastPos); trackballMove=true;

}

void stopMotion(int x, int y)

{

trackingMouse = false;

if (startX != x || startY != y) {

redrawContinue = true;

} else {

angle = 0.0F;

redrawContinue = false;

trackballMove = false;

}

}

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

/* view transform */

if (trackballMove)

{

glRotatef(angle, axis[0], axis[1], axis[2]);

}

colorcube();

glutSwapBuffers();

}

void mouseButton(int button, int state, int x, int y) {

if(button==GLUT_RIGHT_BUTTON) exit(0);

if(button==GLUT_LEFT_BUTTON) switch(state)

{

case GLUT_DOWN:

y=winHeight-y;

startMotion(x,y);

break;

case GLUT_UP:

stopMotion(x,y);

附录A 实 例 程 序

break;

}

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

winWidth = w;

winHeight = h;

}

void spinCube()

{

if (redrawContinue) glutPostRedisplay();

}

int main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("colorcube");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutIdleFunc(spinCube);

glutMouseFunc(mouseButton);

glutMotionFunc(mouseMotion);

glEnable(GL_DEPTH_TEST);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);

glMatrixMode(GL_MODELVIEW);

glutMainLoop();

} 617

A.12 观察者漫游程序

/*rotating cube with viewer movement from Chapter 5*/

/*cube definition and display similar to rotating-cube program*/

/* We use the Lookat function in the display callback to point the viewer, whose position can be altered by the x,X,y,Y,z, and Z keys */

The perspective view is set in the reshape callback */

#include <stdlib.h>

#include <GL/glut.h>

618 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

GLfloat vertices[][3] = {{-1.0,-1.0,-1.0},{1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0},

{1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}};

GLfloat colors[][3] = {{0.0,0.0,0.0},{1.0,0.0,0.0},

{1.0,1.0,0.0}, {0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0}, {0.0,1.0,1.0}};

void polygon(int a, int b, int c, int d)

{

glBegin(GL_POLYGON);

glColor3fv(colors[a]);

glVertex3fv(vertices[a]);

glVertex3fv(vertices[b]);

glVertex3fv(vertices[c]);

glVertex3fv(vertices[d]);

glEnd();

}

void colorcube()

{

polygon(0,3,2,1);

polygon(2,3,7,6);

polygon(0,4,7,3);

polygon(1,2,6,5);

polygon(4,5,6,7);

polygon(0,1,5,4);

}

static GLfloat theta[] = {0.0,0.0,0.0};

static GLint axis = 2;

static GLdouble viewer[]= {0.0, 0.0, 5.0}; /* initial viewer

location */

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* Update viewer position in modelview matrix */

glLoadIdentity();

gluLookAt(viewer[0],viewer[1],viewer[2], 0.0, 0.0, 0.0,

0.0, 1.0, 0.0);

/* rotate cube */

glRotatef(theta[0], 1.0, 0.0, 0.0);

glRotatef(theta[1], 0.0, 1.0, 0.0);

附录A 实 例 程 序

glRotatef(theta[2], 0.0, 0.0, 1.0);

colorcube();

glFlush();

glutSwapBuffers();

}

void mouse(int btn, int state, int x, int y)

{

if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2; theta[axis] += 2.0;

if( theta[axis] > 360.0 ) theta[axis] -= 360.0;

display();

}

void keys(unsigned char key, int x, int y)

{

/* Use x, X, y, Y, z, and Z keys to move viewer */

if(key == 'x') viewer[0]-= 1.0;

if(key == 'X') viewer[0]+= 1.0;

if(key == 'y') viewer[1]-= 1.0;

if(key == 'Y') viewer[1]+= 1.0;

if(key == 'z') viewer[2]-= 1.0;

if(key == 'Z') viewer[2]+= 1.0;

display();

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

/* Use a perspective view */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if(w<=h)

glFrustum( -2.0, 2.0, -2.0 * (GLfloat) h/ (GLfloat) w, 2.0* (GLfloat) h / (GLfloat) w, 2.0, 20.0);

else glFrustum(-2.0, 2.0, -2.0 * (GLfloat) w/ (GLfloat) h, 2.0* (GLfloat) w / (GLfloat) h, 2.0, 20.0);

/* Or we can use gluPerspective */

/* gluPerspective(45.0, w/h, -10.0, 10.0); */

glMatrixMode(GL_MODELVIEW);

} 619

620 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

void main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

glutInitWindowSize(500, 500);

glutCreateWindow("colorcube");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutMouseFunc(mouse);

glutKeyboardFunc(keys);

glEnable(GL_DEPTH_TEST);

glutMainLoop();

}

A.13 球体的细分逼近程序

/* Recursive subdivision of tetrahedron (Chapter 6). Three display modes: wire frame, constant, and interpolative shading */

/* Program also illustrates defining materials and light sources int init() */

/* mode 0 = wire frame, mode 1 = constant shading,

mode 3 = interpolative shading */

#include <stdlib.h>

#include<math.h>

#include <GL/glut.h>

typedef float point[3];

/* initial tetrahedron */

point v[]={{0.0, 0.0, 1.0}, {0.0, 0.942809, -0.33333},

{-0.816497, -0.471405, -0.333333}, {0.816497, -0.471405, -0.333333}};

static GLfloat theta[] = {0.0,0.0,0.0};

int n;

int mode;

void triangle( point a, point b, point c)

/* display one triangle using a line loop for wire frame, a single

normal for constant shading, or three normals for interpolative shading */ {

附录A 实 例 程 序

if (mode==0) glBegin(GL_LINE_LOOP);

else glBegin(GL_POLYGON);

if(mode==1) glNormal3fv(a);

if(mode==2) glNormal3fv(a);

glVertex3fv(a);

if(mode==2) glNormal3fv(b);

glVertex3fv(b);

if(mode==2) glNormal3fv(c);

glVertex3fv(c);

glEnd();

}

void normal(point p)

{

/* normalize a vector */

float d =0.0;

int i;

for(i=0; i<3; i++) d+=p[i]*p[i];

d=sqrt(d);

if(d>0.0) for(i=0; i<3; i++) p[i]/=d;

}

void divide_triangle(point a, point b, point c, int m)

{

/* triangle subdivision using vertex numbers

righthand rule applied to create outward pointing faces */

point v1, v2, v3;

int j;

if(m>0)

{

for(j=0; j<3; j++) v1[j]=a[j]+b[j];

normal(v1);

for(j=0; j<3; j++) v2[j]=a[j]+c[j];

normal(v2);

for(j=0; j<3; j++) v3[j]=b[j]+c[j];

normal(v3);

divide_triangle(a, v1, v2, m-1);

divide_triangle(c, v2, v3, m-1);

divide_triangle(b, v3, v1, m-1);

divide_triangle(v1, v3, v2, m-1);

}

else(triangle(a,b,c)); /* draw triangle at end of recursion */ }

void tetrahedron(int m)

{ 621

622 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

/* apply triangle subdivision to faces of tetrahedron */

divide_triangle(v[0], v[1], v[2], m);

divide_triangle(v[3], v[2], v[1], m);

divide_triangle(v[0], v[3], v[1], m);

divide_triangle(v[0], v[2], v[3], m);

}

void display(void)

{

/* Displays all three modes, side by side */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

mode=0;

tetrahedron(n);

mode=1;

glTranslatef(-2.0, 0.0,0.0);

tetrahedron(n);

mode=2;

glTranslatef(4.0, 0.0,0.0);

tetrahedron(n);

glFlush();

}

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-4.0, 4.0, -4.0 * (GLfloat) h / (GLfloat) w,

4.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);

else

glOrtho(-4.0 * (GLfloat) w / (GLfloat) h,

4.0 * (GLfloat) w / (GLfloat) h, -4.0, 4.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW);

display();

}

void myinit()

{

GLfloat mat_specular[]={1.0, 1.0, 1.0, 1.0};

GLfloat mat_diffuse[]={1.0, 1.0, 1.0, 1.0};

GLfloat mat_ambient[]={1.0, 1.0, 1.0, 1.0};

附录A 实 例 程 序

GLfloat mat_shininess={100.0};

GLfloat light_ambient[]={0.0, 0.0, 0.0, 1.0};

GLfloat light_diffuse[]={1.0, 1.0, 1.0, 1.0};

GLfloat light_specular[]={1.0, 1.0, 1.0, 1.0};

/* set up ambient, diffuse, and specular components for light 0 */

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);

glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);

glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

/* define material proerties for front face of all polygons */

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

glShadeModel(GL_SMOOTH); /* enable smooth shading */

glEnable(GL_LIGHTING); /* enable lighting */

glEnable(GL_LIGHT0); /* enable light 0 */

glEnable(GL_DEPTH_TEST); /* enable z buffer */

glClearColor (1.0, 1.0, 1.0, 1.0);

glColor3f (0.0, 0.0, 0.0);

}

void main(int argc, char **argv)

{

n=atoi(argv[1]);

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("sphere");

myinit();

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutMainLoop();

} 623

A.14 Mandelbrot集程序

#include<stdio.h>

#include<stdlib.h>

#include<gl/glut.h>

/* default data */

#define CENTERX -0.5

624 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

#define CENTERY 0.5

#define HEIGHT 0.5

#define WIDTH 0.5

#define MAX_ITER 100

/* N * M array to be generated */

#define N 500

#define M 500

float height=HEIGHT;

float width = WIDTH;

float cx = CENTERX;

float cy = CENTERY;

int max = MAX_ITER;

int n=N;

int m=M;

/* use unsigned bytes for image */

GLubyte image[N][M];

/* complex data type and complex add,mult,and magnitude functions probably not worth overloaded */

typedef float complex[2];

void add(complex a,complex b,complex p)

{

p[0]=a[0]+b[0];

p[1]=a[1]+b[1];

}

void mult(complex a,complex b,complex p)

{

p[0]=a[0]*b[0]-a[1]*b[1];

p[1]=a[0]*b[1]+a[1]*b[0];

}

float mag2(complex a)

{

return (a[0]*a[0]+a[1]*a[1]);

}

void form(float a,float b,complex p)

{

p[0]=a;

p[1]=b;

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT);

附录A 实 例 程 序

glDrawPixels(n,m,GL_COLOR_INDEX,GL_UNSIGNED_BYTE,image); }

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

gluOrtho2D(0.0, 0.0, (GLfloat) n,(GLfloat)m* (GLfloat ) h /

(GLfloat) w);

else

gluOrtho2D(0.0, 0.0, (GLfloat)n*(GLfloat) w / (GLfloat) h, (GLfloat) m);

glMatrixMode(GL_MODELVIEW);

glutPostRedisplay();

}

void myinit()

{

float redmap[256],greenmap[256],bluemap[256];

int i;

glClearColor (1.0, 1.0, 1.0, 1.0);

gluOrtho2D(0.0, 0.0, (GLfloat)n, (GLfloat)m);

/* define pseudocolor maps,ramps for red and blue,

random for green */

for(i=0;i<256;i++)

{

redmap[i]=i/255.0;

greenmap[i]=rand()%255/255.0;

bluemap[i]=1.0-i/255;

}

glPixelMapfv(GL_PIXEL_MAP_I_TO_R,256,redmap);

glPixelMapfv(GL_PIXEL_MAP_I_TO_G,256,greenmap);

glPixelMapfv(GL_PIXEL_MAP_I_TO_B,256,bluemap);

}

main(int argc, char **argv)

{

int i,j,k;

float x,y,v;

complex c0,c,d;

scanf("%f",&cx);/*center x*/

scanf("%f",&cy); /*center y*/

scanf("%f",&width); /*rectangle width*/

height = width; /*rectangle height*/

625

626 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

scanf("%d",&max); /*maximum iteration*/

for(i=0;i<n;i++)for(j=0;j<m;j++)

{

/* starting point */

x=i*(width/(n-1))+cx-width/2;

y=j*(height/(m-1))+cy-height/2;

form(0,0,c);

form(x,y,c0);

/* complex iteration */

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

{

mult(c,c,d);

add(d,c0,c);

v=mag2(c);

if(v>4.0) break ;/* assume not in set if mag>4 */ }

/*assign gray level to point based on its magnitude*/

if(v>1.0) v=1.0; /* clamp if v>1 */

image[i][j]=255*v;

}

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );

glutInitWindowSize(N,M);

glutCreateWindow("Mandelbrot set");

myinit();

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutMainLoop();

}

A.15 Bresenham画线算法

#include<GL/glut.h>

#include<stdio.h>

#define BLACK 0

void draw_pixel(int ix,int iy,int value)

{

glBegin(GL_POINTS);

glVertex2i(ix,iy);

glEnd();

}

附录A 实 例 程 序

bres(int x1,int y1,int x2,int y2) {

int dx,dy,i,e;

int incx,incy,inc1,inc2; int x,y;

dx=x2-x1;

dy=y2-y1;

if(dx<0) dx=-dx;

if(dy<0) dy=-dy;

incx=1;

if(x2<x1) incx=-1;

incy=1;

if(y2<y1) incy=-1;

x=x1;

y=y1;

if(dx>dy)

{

draw_pixel(x,y,BLACK); e=2*dy-dx;

inc1 = 2*(dy-dx);

inc2 = 2*dy;

for(i=0;i<dx;i++)

{

if(e>=0)

{

y+=incy;

e+=inc1;

}

else

e+=inc2;

x+=incx;

draw_pixel(x,y,BLACK); }

}

else

{

draw_pixel(x,y,BLACK); e=2*dx-dy;

inc1=2*(dx-dy);

inc2=2*dx;

for(i=0;i<dy;i++)

{

if(e>=0)

{

x+=incx;

e+=inc1; 627

628 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

}

else

e+=inc2;

y+=incy;

draw_pixel(x,y,BLACK);

}

}

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT);

bres(200,200,100,50);

glFlush();

}

void myinit()

{

glClearColor(1.0,1.0,1.0,1.0);

glColor3f(1.0,0.0,0.0);

glPointSize(1.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0,499.0,0.0,499.0);

}

void main(int argc,char **argv)

{

/* standard GLUT initialization */

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );/*default,not needed*/ glutInitWindowSize(500,500); /* 500×500 pixel window */

glutInitWindowPosition(0,0);/* place window top left on display */ glutCreateWindow("Bresenham's algorithm ");/* window title */

glutDisplayFunc(display); /* display callback invoked when window opened */

myinit(); /*set attributes */

glutMainLoop(); /* enter event loop */

}

A.16 带纹理立方体的旋转程序

#include <stdlib.h>

#include <GL/glut.h>

附录A 实 例 程 序

GLfloat planes[]= {-1.0, 0.0, 1.0, 0.0};

GLfloat planet[]= {0.0, -1.0, 0.0, 1.0};

GLfloat vertices[][3] = {{-1.0,-1.0,-1.0}, {1.0,-1.0,-1.0}, {1.0,1.0,-1.0}, {-1.0,1.0,-1.0}, {-1.0,-1.0,1.0}, {1.0,-1.0,1.0}, {1.0,1.0,1.0}, {-1.0,1.0,1.0}};

GLfloat colors[][4] = {{0.0,0.0,0.0,0.5}, {1.0,0.0,0.0,0.5},

{1.0,1.0,0.0,0.5}, {0.0,1.0,0.0,0.5}, {0.0,0.0,1.0,0.5}, {1.0,0.0,1.0,0.5}, {1.0,1.0,1.0,0.5}, {0.0,1.0,1.0,0.5}};

void polygon(int a, int b, int c, int d)

{

glBegin(GL_POLYGON);

glColor4fv(colors[a]);

glTexCoord2f(0.0,0.0);

glVertex3fv(vertices[a]);

glColor4fv(colors[b]);

glTexCoord2f(0.0,1.0);

glVertex3fv(vertices[b]);

glColor4fv(colors[c]);

glTexCoord2f(1.0,1.0);

glVertex3fv(vertices[c]);

glColor4fv(colors[d]);

glTexCoord2f(1.0,0.0);

glVertex3fv(vertices[d]);

glEnd();

}

void colorcube(void)

{

/* map vertices to faces */

polygon(0,3,2,1);

polygon(2,3,7,6);

polygon(0,4,7,3);

polygon(1,2,6,5);

polygon(4,5,6,7);

polygon(0,1,5,4);

}

static GLfloat theta[] = {0.0,0.0,0.0};

static GLint axis = 2;

void display(void)

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity();

glRotatef(theta[0], 1.0, 0.0, 0.0);

glRotatef(theta[1], 0.0, 1.0, 0.0);

glRotatef(theta[2], 0.0, 0.0, 1.0); 629

630 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

colorcube();

glutSwapBuffers();

}

void spinCube()

{

theta[axis] += 2.0;

if( theta[axis] > 360.0 ) theta[axis] -= 360.0;

glutPostRedisplay();

}

void mouse(int btn, int state, int x, int y)

{

if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) axis = 0; if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) axis = 1; if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) axis = 2; }

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,

2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);

else

glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,

2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW);

}

void key(unsigned char k, int x, int y)

{

if(k == '1') glutIdleFunc(spinCube);

if(k == '2') glutIdleFunc(NULL);

if(k == 'q') exit(0);

}

void main(int argc, char **argv)

{

GLubyte image[64][64][3];

int i, j, r, c;

for(i=0;i<64;i++)

{

for(j=0;j<64;j++)

{

c = ((((i&0x8)==0)^((j&0x8))==0))*255;

image[i][j][0]= (GLubyte) c;

附录A 实 例 程 序

image[i][j][1]= (GLubyte) c;

image[i][j][2]= (GLubyte) c;

}

}

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500);

glutCreateWindow("colorcube");

glutReshapeFunc(myReshape);

glutDisplayFunc(display);

glutIdleFunc(spinCube);

glutMouseFunc(mouse);

glEnable(GL_DEPTH_TEST);

glEnable(GL_TEXTURE_2D);

glTexImage2D(GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE, image);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glutKeyboardFunc(key);

glClearColor(1.0,1.0,1.0,1.0);

glutMainLoop();

} 631

A.17 GLSL程序

/* display teapot with vertex and fragment shaders */

/* sets up elapsed time parameter for use by shaders */

#include<stdio.h>

#include<stdlib.h>

#include<gl/glut.h>

const float nearVal =1.0f;

const float farVal =300.0f ;

const float lightPos[3] ={3.0f,3.0f,3.0f};

int width =512;

int height =512;

GLint program =0;

GLint timeParam;

/* shader reader */

/* create nulll terminated string from file */

char *readShaderSource(const char *shaderFile)

{

632 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

struct stat statBuf;

FILE *fp =fopen(shaderFile,"r");

char *buf;

stat(shaderFile,&statBuf);

buf=(char *)malloc(statBuf.st_size+1*sizeof(char)); fread(buf,1,statBuf.st_size,fp);

buf[statBuf.st_size]=' ';

fclose(fp);

return buf;

}

/* error printing function */

static void chechError(GLint status,const char *msg) {

if(!status)

{

printf("%s\n",msg);

exit(EXIT_FAILURE);

}

}

/* standard OpenGL initialization */

static void init()

{

const float teapotColor[] ={0.3f,0.5f,0.4f,1.0f};

const float teapotSpecular[] ={0.8f,0.8f,0.8f,1.0f}; const float teapotShininess[] ={80.0f};

glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,teapotColor); glMaterialfv(GL_FRONT,GL_SPECULAR,teapotSpecular); glMaterialfv(GL_FRONT,GL_SHININESS,teapotShininess);

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

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glTranslatef(0.0f,0.0f,10.0f);

glLightfv(GL_LIGHT0,GL_POSITION,lightPos);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glEnable(GL_DEPTH_TEST);

}

附录A 实 例 程 序

/* GLSL initialization */

static void initShader(const char *vShaderFile,const char *fShaderFile) {

GLint vShader =0;

GLint fShader =0;

GLint status =0;

/* read shader file */

char *vSource = readShaderSource(vShaderFile);

char *fSource = readShaderSource(fShaderFile);

/* created program and shader objects */

vShader = glCreateShaderObject(GL_VERTEX_SHADER);

fShader = glCreateShaderObject(GL_FRAGMENT_SHADER);

program = glCreateProgramObject();

/* attach shaders to the program object */

glAttachObject(program,vShader);

glAttachObject(program,fShader);

/* read shaders */

glShaderSource(vShader,1,&vShaderFile,NULL);

checkError(status,"Fail to read vertex shader");

glShaderSource(fShader,1,&fShaderFile,NULL);

checkError(status,"Fail to read vertex shader");

/* compile shaders */

glCompileShader(vShader);

glCompileShader(fShader);

/* error check */

glGetObjectParameteriv(vShader,GL_OBJECT_COMPILE_STATUS,&status); checkError(status,"Failed to compile the vertx shader");

glGetObjectParameteriv(fShader,GL_OBJECT_COMPILE_STATUS,&status); checkError(status,"Failed to compile the fragment shader.");

/* link */

glLinkProgam(program);

glGetObjectParameteriv(program,GL_OBJECT_LINK_STATUS,&status); 633

634 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

checkError(status,"Failed to link the shader program object.");

/* use program object */

glUseProgramObject(program);

/* set up uniform parameter */

timeParam = glGetUniformLocation(program,"time");

}

static void draw()

{

/* send elapsed time to shaders */

glUniform1f(timeParam,gltuGet(GL_ELAPSED_TIME));

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

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

glutSolidTeapot(2.0);

glutSwapBuffers();

}

static void reshape(int w,int h)

{

width =w;

height =h;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(45.0,(double)width/(double)height,nearVal,farVal); glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glViewport(0,0,width,height);

glutPostRedisplay();

}

static void keyboard(unsigned char key,int x,int y)

{

switch(key)

{

case 27 :

case 'Q':

case 'q':

exit(EXIT_SUCCESS);

break;

附录A 实 例 程 序

default:

break;

}

}

void main(int argc, char** argv)

{

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);

glutInitWindowSize(width,height);

glutCreateWindow("Simple GLSL example");

glutDisplayFunc(draw);

glutReshapeFunc(reshape);

glutKeyboardFunc(keyboard);

init();

initShader("vPhong.glsl","fPassThrough.glsl");

glutMainLoop();

}

/* the following code is for the vertex and fragment shaders */

/* shader code is assumed to be in separate files */

//Vphong.glsl

//modified Phong vertex shader

uniform float time;

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

{

gl_Position = gl_ModelviewProjectionMatrix * gl_Vertex;

vec4 eyePosition =gl_ModelVewMatrix * gl_Vertex;

vec4 eyeLightPos = gl_LightSource[0].postion;

vec3 eyeNormalVec = normalize(gl_NormalMatrix * gl_Normal);

vec3 eyeLightVec = normalize(eyeLightPos.xyz-eyePosition.xyz); vec3 eyeViewVec = -normalize(eyePosition.xyz);

vec3 eyeHalfVec = normalize(eyeLightVec+eyeViewVec);

float Kd = max(dot(eyeLightVec,eyeNormalVec),0.0);

float Ks = pow(dot(eyeNormalVec,eyeHalfVec),gl_FrontMaterial.shininess); float Ka = 1.0;

gl_FrontColor = Kd * gl_FrontLightProduct[0].diffuse+

Ks * gl_FrontLightProduct[0].specular+

gl_FrontLightModelProduct.sceneColor;

} 635

636 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

// fPassThrough.glsl

// Pass through fragment shader.

void main()

{

gl_FragColor = gl_Color;

}

A.18 场景图形示例

//scene.cc

#include "Scene.h"

#define BaseRadius 0.2

#define Radius 0.08

#define BaseLen 1

#define UpLen 0.6

#define LowLen 0.6

#define EyeRadius 0.04

#define ChairLegLen 0.55

int main(int argc, char **argv)

{

float v[][3]={{-0.3,-0.2,0.0},{0.3, -0.2, 0.0}, {0.3, 0.2, 0.0},{-0.3, 0.2, 0.0} };

//Light nodes

Light *Light1=new Light;

Light *Light2=new Light;

TurnOff *Off1=new TurnOff(Light1);

TurnOff *Off2=new TurnOff(Light2);

//Setting Light Values :

Light1->SetValue(POSITION, -2, -3, 1.5, 1); Light1->SetValue(SPOT_DIRECTION, 2, 3, -1.5); Light1->SetValue(CUTOFFANGLE, 40.0);

Light1->TurnOn();

Light2->SetValue(POSITION, 5, 5, 5, 0);

Light2->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0); Light2->SetValue(DIFFUSE, 1.0, 1.0, 1.0, 1.0); Light2->TurnOn();

//Nodes for Camera:

附录A 实 例 程 序

Camera *Camera1=new Camera(PERSPECTIVE);

Camera1->SetValue(POSITION, 2.2, 0.9, 3); Camera1->SetValue(AIMAT, 0, 0, 0);

Camera1->SetValue(UPDIRECTION, 0, 1, 0);

Camera1->SetValue(ASPECT, 1);

Camera1->SetValue(NEAR, 1);

Camera1->SetValue(FAR, 20);

Camera1->SetValue(YANGLE, 50);

//Nodes for Robot:

Material *RobotMat=new Material;

Material *EyeMat=new Material;

Cylinder *Base=new Cylinder;

Sphere *Head=new Sphere;

Sphere *EyeL=new Sphere;

Sphere *EyeR=new Sphere;

Cylinder *UpperArmL=new Cylinder;

Cylinder *UpperArmR=new Cylinder;

Cylinder *LowerArmL=new Cylinder;

Cylinder *LowerArmR=new Cylinder;

Cylinder *UpperLegL=new Cylinder;

Cylinder *UpperLegR=new Cylinder;

Cylinder *LowerLegL=new Cylinder;

Cylinder *LowerLegR=new Cylinder;

Polygon *Paper=new Polygon;

Transformation *EyeLTrans=new Transformation; Transformation *EyeRTrans=new Transformation; Transformation *HeadTrans=new Transformation; Transformation *UpArmLTrans=new Transformation; Transformation *UpArmRTrans=new Transformation; Transformation *LowArmTrans=new Transformation; Transformation *UpLegLTrans=new Transformation; Transformation *UpLegRTrans=new Transformation; Transformation *LowLegTrans=new Transformation; Transformation *BaseTrans=new Transformation;

//Robot Value:

RobotMat->SetValue(DIFFUSE, 0.0, 0.0, 1.0, 1.0); RobotMat->SetValue(AMBIENT, 0.0, 0.0, 1.0, 1.0); RobotMat->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0); RobotMat->SetValue(SHININESS, 100.0);

EyeMat->SetValue(DIFFUSE, 1.0, 1.0, 1.0, 1.0); EyeMat->SetValue(AMBIENT, 1.0, 1.0, 1.0, 1.0); EyeMat->SetValue(SPECULAR, 1.0, 1.0, 1.0, 1.0); EyeMat->SetValue(SHININESS, 100.0);

637

638 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

Base->SetValue(HEIGHT, BaseLen);

Base->SetValue(RADIUS, BaseRadius);

Head->SetValue(RADIUS, BaseRadius);

EyeL->SetValue(RADIUS, EyeRadius);

EyeR->SetValue(RADIUS, EyeRadius);

UpperArmL->SetValue(HEIGHT, UpLen);

UpperArmL->SetValue(RADIUS, Radius);

LowerArmL->SetValue(HEIGHT, LowLen);

LowerArmL->SetValue(RADIUS, Radius);

UpperArmR->SetValue(HEIGHT, UpLen);

UpperArmR->SetValue(RADIUS, Radius);

LowerArmR->SetValue(HEIGHT, LowLen);

LowerArmR->SetValue(RADIUS, Radius);

UpperLegL->SetValue(HEIGHT, UpLen);

UpperLegL->SetValue(RADIUS, Radius);

LowerLegL->SetValue(HEIGHT, LowLen);

LowerLegL->SetValue(RADIUS, Radius);

UpperLegR->SetValue(HEIGHT, UpLen);

UpperLegR->SetValue(RADIUS, Radius);

LowerLegR->SetValue(HEIGHT, LowLen);

LowerLegR->SetValue(RADIUS, Radius);

Paper->SetVerticesv(v, 4);

Paper->SetMaterial(EyeMat);

EyeLTrans->SetValue(TRANSLATION, BaseRadius-EyeRadius/2, 0, 0, 0); EyeLTrans->SetValue(ROTATION, 30, 0, 0, 1, 1);

EyeRTrans->SetValue(TRANSLATION, BaseRadius-EyeRadius/2, 0, 0, 0); EyeRTrans->SetValue(ROTATION, -30, 0, 0, 1, 1);

HeadTrans->SetValue(TRANSLATION, 0, 0, BaseLen+BaseRadius+BaseRadius/3, 0); UpArmLTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

UpArmLTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);

UpArmLTrans->SetValue(TRANSLATION, 0, BaseRadius+Radius, BaseLen, 2); UpArmRTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

UpArmRTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);

UpArmRTrans->SetValue(TRANSLATION, 0, -(BaseRadius+Radius), BaseLen, 2); LowArmTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

LowArmTrans->SetValue(ROTATION, -45, 0, 1, 0, 1);

UpLegLTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

UpLegLTrans->SetValue(ROTATION, -90, 0, 1, 0, 1);

UpLegLTrans->SetValue(TRANSLATION, 0, BaseRadius+Radius, 0, 2); UpLegRTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

UpLegRTrans->SetValue(ROTATION, -100, 0, 1, 0, 1);

UpLegRTrans->SetValue(TRANSLATION, 0, -(BaseRadius+Radius), 0, 2); LowLegTrans->SetValue(TRANSLATION, 0, 0, -UpLen, 0);

LowLegTrans->SetValue(ROTATION, 95, 0, 1, 0, 1);

BaseTrans->SetValue(ROTATION, -90, 1, 0, 0, 0);

BaseTrans->SetValue(ROTATION, -10, 0, 0, 1, 1);

Head->SetTransform(HeadTrans);

附录A 实 例 程 序

EyeL->SetTransform(EyeLTrans);

EyeR->SetTransform(EyeRTrans);

EyeR->SetMaterial(EyeMat);

EyeL->SetMaterial(EyeMat);

UpperArmL->SetTransform(UpArmLTrans);

LowerArmL->SetTransform(LowArmTrans);

UpperArmR->SetTransform(UpArmRTrans);

LowerArmR->SetTransform(LowArmTrans);

UpperLegL->SetTransform(UpLegLTrans);

LowerLegL->SetTransform(LowLegTrans);

UpperLegR->SetTransform(UpLegRTrans);

LowerLegR->SetTransform(LowLegTrans);

Base->SetTransform(BaseTrans);

Paper->SetTransform(ROTATION, 20, 0, 1, 0, 0);

Paper->SetTransform(TRANSLATION, 0.05, -0.15, -0.2, 1);

//Set Relationship in Robot:

RobotMat->AddChild(Light1);

Light1->AddChild(Base);

Base->AddChild(Off1);

Off1->AddChild(Light2);

Light2->AddChild(Head);

Head->AddChild(Off2);

Head->AddChild(EyeL);

Head->AddChild(EyeR);

Base->AddChild(UpperArmL);

UpperArmL->AddChild(LowerArmL);

Base->AddChild(UpperArmR);

UpperArmR->AddChild(LowerArmR);

Base->AddChild(UpperLegL);

UpperLegL->AddChild(LowerLegL);

Base->AddChild(UpperLegR);

UpperLegR->AddChild(LowerLegR);

LowerArmR->AddChild(Paper);

//Nodes for Chair:

Cube *Seat=new Cube(0.7, 0.06, 0.7);

Line *Leg1=new Line;

Line *Leg2=new Line;

Line *Leg3=new Line;

Line *Leg4=new Line;

DrawStyle *LegStyle=new DrawStyle;

Color *ChairColor=new Color;

//Chair Value:

float v1[][3]={{-0.3, 0, 0.3},{-0.35, -1*ChairLegLen, 0.3}}; float v2[][3]={{0.3, 0, 0.3},{0.35, -1*ChairLegLen, 0.3}}; 639

640 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

float v3[][3]={{0.3, 0, -0.3},{0.35, -1*ChairLegLen, -0.3}}; float v4[][3]={{-0.3, 0, -0.3},{-0.35, -1*ChairLegLen, -0.3}};

ChairColor->SetValue(RED);

Seat->SetTransform(TRANSLATION, 0, -0.15, 0, 0);

LegStyle->SetValue(LINEWIDTH, 7);

Leg1->SetStyle(LegStyle);

Leg1->SetVerticesv(v1);

Leg2->SetStyle(LegStyle);

Leg2->SetVerticesv(v2);

Leg3->SetStyle(LegStyle);

Leg3->SetVerticesv(v3);

Leg4->SetStyle(LegStyle);

Leg4->SetVerticesv(v4);

Seat->AddChild(Leg1);

Seat->AddChild(Leg2);

Seat->AddChild(Leg3);

Seat->AddChild(Leg4);

ChairColor->AddChild(Seat);

//Transformation Nodes for both Robot and Chair:

Transformation *Trans1=new Transformation;

Trans1->SetValue(TRANSLATION, -0.5, 0, 0, 2);

Trans1->AddChild(ChairColor);

Trans1->AddChild(RobotMat);

//Root Node:

Node *Root=new Node;

Root->AddChild(Trans1);

Root->AddChild(Camera1);

//Viewer:

GLViewer *MyViewer=new GLViewer;

MyViewer->Init(argc, argv);

MyViewer->SetValue(BACKCOLOR, GREY);

MyViewer->SetValue(BUFFER, DOUBLE);

MyViewer->CreateWin("Working Hard", 500, 500);

GLViewer *MyViewer2=new GLViewer;

MyViewer2->Init(argc, argv);

MyViewer2->SetValue(BACKCOLOR, MAGENTA);

MyViewer2->CreateWin("Working Hard2", 200, 200);

MyViewer2->SetValue(BUFFER, DOUBLE);

MyViewer->Show(Root);

附录A 实 例 程 序

MyViewer2->Show(Root);

return 0;

}

641

A.19 Bezier曲线程序

/* curves.c */

/*

**

** Bezier curve drawing program.

**

** q - Quit the program

** c - Clear the screen

** e - Erase the curves

** b - Draw Bezier curves

**

*/

#include <GL/glut.h>

void keyboard(unsigned char key, int x, int y);

#define MAX_CPTS 25 /* Fixed maximum number of control points */

GLfloat cpts[MAX_CPTS][3];

int ncpts = 0;

static int width = 500, height = 500; /* Window width and height */

static void drawCurves()

{

int i;

for(i=0;i<ncpts-3;i+=3)

{

/* draw the curve using OpenGL evaluators */

glMap1f(GL_MAP1_VERTEX_3,0.0,1.0,3,4,cpts[i]);

glMapGrid1f(30,0.0,1.0);

glEvalMesh1(GL_LINE,0,30);

}

glFlush();

}

static void display(void)

{

int i;

glClear(GL_COLOR_BUFFER_BIT);

glBegin(GL_POINTS);

642 交互式计算机图形学—— 基于OpenGL的自顶向下方法(第4版)

for (i = 0; i < ncpts; i++)

glVertex3fv(cpts[i]);

glEnd();

glFlush();

}

void mouse(int button, int state, int x, int y)

{

float wx, wy;

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {

/* Translate back to our coordinate system */

wx = (2.0 * x) / (float)(width - 1) - 1.0;

wy = (2.0 * (height - 1 - y)) / (float)(height - 1) - 1.0;

/* See if we have room for any more control points */

if (ncpts == MAX_CPTS)

return;

/* Save the point */

cpts[ncpts][0] = wx;

cpts[ncpts][1] = wy;

cpts[ncpts][2] = 0.0;

ncpts++;

/* Draw the point */

glColor3f(0.0, 0.0, 0.0);

glPointSize(5.0);

glBegin(GL_POINTS);

glVertex3f(wx, wy, 0.0);

glEnd();

glFlush();

}

}

void keyboard(unsigned char key, int x, int y)

{

switch (key)

{

case 'q': case 'Q':

exit(0);

break;

case 'c': case 'C':

ncpts = 0;

glutPostRedisplay();

break;

case 'e': case 'E':

glutPostRedisplay();

break;

case 'b': case 'B':

附录A 实 例 程 序

drawCurves();

break;

}

}

void reshape(int w, int h)

{

width = w;

height = h;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW);

glViewport(0, 0, w, h);

}

void main(int argc, char **argv)

{

glutInit(&argc, argv);

glutInitDisplayMode(GLUT_RGB);

glutInitWindowSize(width, height); glutCreateWindow("curves");

glutDisplayFunc(display);

glutMouseFunc(mouse);

glutKeyboardFunc(keyboard);

glutReshapeFunc(reshape);

glClearColor(1.0, 1.0, 1.0, 1.0);

glColor3f(0.0,0.0,0.0);

glPointSize(5.0);

glEnable(GL_MAP1_VERTEX_3);

glutMainLoop();

}

643

更多相关推荐:
计算机图形学实验报告

福建农林大学计算机与信息学院课程名称姓名系专业年级学号指导教师职称实验报告计算机图形学洪世玉计算机计算机科学与技术10级102260010072李小林20xx年11月19日实验项目列表福建农林大学计算机与信息学...

计算机图形学实验报告及代码

第1章概述一教学目标通过本章的学习使学生能够了解计算机图形学的基本概念研究内容当前的发展概况本门课程的特点和应用二教学要求1了解计算机图形学的概念和研究内容2了解本门课程的发展概况三教学内容提要1计算机图形学的...

计算机图形学实验(全)

实验1直线的绘制实验目的1通过实验进一步理解和掌握DDA和Bresenham算法2掌握以上算法生成直线段的基本过程3通过编程会在TC环境下完成用DDA或中点算法实现直线段的绘制实验环境计算机TurboC或其他C...

计算机图形学实验报告

实验报告实验课程:计算机图形学学生姓名:XXXX学号:XXXX专业班级:软件20##年12月25日目录i.实验一矩阵变换ii.实验二图形绘制iii.实验三曲线的生成算法实现iv.实验四二维基本图形生成的算法v.…

计算机图形学实验报告

计算机图形学实验报告河南理工大学测绘学院计算机图形学实验报告学号姓名成绩评语交报告日期20xx年6月25日计算机图形学实验报告实验项目一图形学光栅化算法验证实验实验日期20xx年6月5日一实验目的1加强对直线圆...

计算机图形学实验报告

班级10计科姓名敖智挺学号20xx30457117实验一直线生成与二次曲线拟合实验内容应用Bresenham画线算法实现一程序完成直线生成实验目的了解掌握VC下D图元的扫描转换原理及VC实现掌握图元属性原理及V...

图形学实验报告

计算机图形学实验报告书姓名班级学号中南大学软件学院二0一一年六月一实验的任务性质与目的计算机图形学是软件工程专业的一门专业技术课程计算机图形学应用于生产工程文化和艺术等领域该课程对于培养和提高学生的算法设计和实...

华北电力大学 计算机图形学实验报告

科技学院课程设计综合实验报告20xx20xx年度第2学期实验名称课程名称计算机图形学专业班级计算机11K1学生姓名曲强学号1119xx010118成绩指导教师姜丽梅实验日期20xx65实验一OpenGL基本图元...

南邮计算机图形学实验报告(完整版)

实验报告12实验报告三实验过程描述与结果分析实验代码includeltGLgluthgt绘制立方体将立方体的八个顶点保存到一个数组里面staticconstfloatvertexlist305f05f05f05...

计算机图形学实验报告-实验1直线段扫描转换

计算机图形学实验报告班级计算机工硕班学号20xx220xx6姓名王泽晶1实验一直线段扫描转换实验目的通过本次试验学生可以掌握直线段的扫描转换算法及其程序设计方法实验内容1绘制2020的网格线格子X和Y方向间隔均...

计算机图形学 基本图形生成算法实验报告

实验题目实验一基本图形生成算法实验目的掌握中点Bresenham绘制直线的原理设计中点Bresenham算法编程实现中点Bresenham算法实验描述使用中点Bresenham算法绘制斜率为0k1的直线算法设计...

计算机图形学实验报告2 - DDA画线

班级R数学111大连交通大学姓名实验报告同组人无课程名称计算机图形学成绩实验名称DDA画线指导老师任洪海

图形学实验报告(49篇)