Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 76

6.

    Chương trình earth01.cpp vẽ hình trái đất quay xung quanh mặt
trời
#include "Gl/glut.h"
 static int year = 0, day = 0; /* Thong so chi thoi gian trong nam va
thoi gian trong ngay de xac dinh vi tri cua trai dat tren quy dao va xac
dinh goc quay cua no quanh tam */
 
/* Khoi tao */
void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
// Chuc nang cho phep loai bo mot phan cua doi tuong bi che boi doi
tuong khac
   glEnable(GL_DEPTH_TEST);     
glShadeModel (GL_FLAT);
}
 
void display(void)
{
// xoa color buffer va depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix(); // luu lai ma tran hien hanh   
glColor3f (1.0, 0, 0); // thiet lap mau ve la mau do
// ve mat troi la mot luoi cau co tam tai goc toa do
glutWireSphere(1.0, 20, 16);  
 
/* di chuyen den vi tri moi de ve trai dat */
// quay mot goc tuong ung voi thoi gian trong nam
   glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
// tinh tien den vi tri hien tai cua trai dat tren quy dao quanh mat
troi
   glTranslatef (2.0, 0.0, 0.0);
// quay trai dat tuong ung voi thoi gian trong ngay
   glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
   glColor3f (0, 0, 1.0); // thiet lap mau ve la mau blue    
glutWireSphere(0.2, 10, 8);    // ve trai dat
// phuc hoi lai ma tran hien hanh cu: tuong ung voi quay lai vi tri
ban dau
   glPopMatrix(); 
    glutSwapBuffers();
}
 
/* xu ly khi cua so bi thay doi */
void reshape (int w, int h)
{
// Thay doi kich thuoc viewport 
glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
/* Thao tac tren chieu */    
glMatrixMode (GL_PROJECTION);   
glLoadIdentity ();
// Chieu phoi canh
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
 
/* Thao tac tren ModelView */    
glMatrixMode(GL_MODELVIEW);   
glLoadIdentity();
// Thiet lap view
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
 
/* xu ly su kien keyboard */
void keyboard (unsigned char key, int x, int y)
{   
switch (key) {      
case 'd':  day = (day + 10) % 360;         
glutPostRedisplay();         
break;      
case 'D': day = (day - 10) % 360;         
glutPostRedisplay();         
break;      
case 'y':  year = (year + 5) % 360;         
glutPostRedisplay();         
break;      
case 'Y':         
year = (year - 5) % 360;         
glutPostRedisplay();         
break;      
default:         
break;
   }

 
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);   
glutInitWindowSize (500, 500);    
glutInitWindowPosition (100, 100);   
glutCreateWindow (argv[0]);   
init ();
glutDisplayFunc(display);    
glutReshapeFunc(reshape);   
glutKeyboardFunc(keyboard);   
glutMainLoop();   
return 0;
}

·        Kết quả chạy chương trình


.    Bài tập
1        Lập trình OpenGL vẽ một đối tượng 3D đơn giản (như ngôi nhà, hình hộp chữ nhật,
…). Minh họa cách thức hoạt động của các phép biến đổi affine (tịnh tiến, quay, tỉ lệ,
biến dạng, tổng hợp các phép biến đổi).
 
------------------------------------------------
 
 

 
1.1         Chương trình linebres01
 
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
 
void init(void)
{
  glClearColor(1.0,1.0,1.0,0.0);
  glMatrixMode(GL_PROJECTION);
  gluOrtho2D(0.0,400.0,0.0,400.0);
}
 
void setPixel(GLint x,GLint y)
{
  glBegin(GL_POINTS);
     glVertex2i(x,y);
  glEnd();
}
 
void line()
{
  int x0 = 50, y0=50, xn = 300, yn = 150, x, y;
  int  dx, dy,             //deltas
       pk,           //decision parameter
       k;            //looping variable
 
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f( 1 ,0, 0); 
  setPixel(x0, y0); //plot first point
 
  // difference between starting and ending points
  dx = xn - x0;
  dy = yn - y0;
  pk = 2 * dy - dx;
  x = x0;    y = y0;
 
  for ( k = 0; k < dx-1; ++k ) {
    if ( pk < 0 ) {
      pk = pk + 2 * dy;                 //calculate next pk
                                  //next pixel: (x+1, y )
    } else {
                                  //next pixel: (x+1, y+1)
      pk = pk + 2*dy - 2*dx;            //calculate next pk
      ++y;
    }
    ++x;
    setPixel( x, y );
  }
 
  glFlush();
}
 
int main(int argc,char **argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(500,500);
    glutCreateWindow("Bresenham Line");
    init();
    glutDisplayFunc( line );
    glutMainLoop();
    return 0;
}

1.2         Chương trình linebres02


 
#include <gl/glut.h>
#include <stdio.h>
 
int x1, y1, x2, y2;
 
void myInit() {
       glClear(GL_COLOR_BUFFER_BIT);
       glClearColor(0.0, 0.0, 0.0, 1.0);
       glMatrixMode(GL_PROJECTION);
       gluOrtho2D(0, 500, 0, 500);
}
 
void draw_pixel(int x, int y) {
       glBegin(GL_POINTS);
       glVertex2i(x, y);
       glEnd();
}
 
void draw_line(int x1, int x2, int y1, 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);
              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);
              }
 
       } else {
              draw_pixel(x, y);
              e = 2*dx-dy;
              inc1 = 2*(dx-dy);
              inc2 = 2*dx;
              for (i=0; i<dy; i++) {
                     if (e >= 0) {
                           x += incx;
                           e += inc1;
                     }
                     else
                           e += inc2;
                     y += incy;
                     draw_pixel(x, y);
              }
       }
}
 
void myDisplay() {
       draw_line(x1, x2, y1, y2);
       glFlush();
}
 
int main(int argc, char **argv) {
 
       printf( "Enter (x1, y1, x2, y2)\n");
       scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
 
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
       glutInitWindowSize(500, 500);
       glutInitWindowPosition(0, 0);
       glutCreateWindow("Bresenham's Line Drawing");
       myInit();
       glutDisplayFunc(myDisplay);
       glutMainLoop();
}
 

2.    Thuật toán DDA


#include<gl/glut.h>
#include<math.h>
 
 
void LineDDA(int x1, int y1, int x2, int y2)
{
        // Find Δm = max(|Δx|, |Δy|)
       int dm = 0;
        if (abs(x2-x1) >= abs(y2-y1)) //abs is a function for absolute value
               dm = abs(x2-x1); //x is the length direction
       else
               dm = abs(y2-y1); //y is the length direction
 
        //Find ∆𝒙⁄∆𝒎, and (∆𝒚)⁄∆𝒎, the length direction will be equal to 1
       float dx = (float)(x2 - x1) / dm;
       float dy = (float)(y2 - y1) / dm;
 
        // Round the current coordinates
       float x = x1 + 0.5;
       float y = y1 + 0.5;
 
        // Draw points in a loop, the x direction is increased to ∆𝒙⁄∆𝒎 and the y
direction is increased to (∆𝒚)⁄∆𝒎
        glColor3f(0.0f, 0.0f, 1.0f);//blue
       glPointSize(5);
       for (int i = 0; i < dm; i++)
       {
              glBegin(GL_POINTS);
              glVertex2i((int)x, (int)y);
              glEnd();
              x += dx;
              y += dy;
       }
}
 
void myDisplay()
{
        glClearColor(1.0, 1.0, 1.0, 1.0);//Clear color, white
        glClear(GL_COLOR_BUFFER_BIT);//Eliminate the buffer, use the above clear color
to eliminate
 
        glColor3f(1.0f, 0.0f, 0.0f);//Set the color, red
       glLineWidth(5);
       glBegin(GL_LINES);
       glVertex3f(200.0f, 200.0f, 0.0f);
       glVertex3f(400.0f, 400.0f, 0.0f);
       glEnd();
 
       //LineDDA(0, 0, 200, 200);
       //LineDDA(200, 200, 0, 0);
       LineDDA(0, 200, 100, 100);
 
        glFlush();//Forced refresh
}
 
void Reshape(int w, int h)
{
        glViewport(0, 0, (GLsizei)w, (GLsizei)h); //Define the viewport size
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
       gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//Make the coordinates of the
lower left corner be (0, 0) and the coordinates of the upper right corner be (w, h)
}
 
void main(int argc, char* argv[])
{
        glutInit(&argc, argv);//Initialize GLUT
        glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//Display mode
        glutInitWindowPosition(100, 100);//Window position, the coordinates of the
upper left corner of the window on the screen
        glutInitWindowSize(400, 400);//Window size
        glutCreateWindow("LineDDA");//Create a window, the parameter is the title of
the window
        glutDisplayFunc(myDisplay);//Tell GLUT which function is responsible for
drawing, that is, register a drawing function myDisplay
        glutReshapeFunc(Reshape); //When the window changes, what function is used to
redraw
        glutMainLoop();//Handle the never-ending loop monitoring
}

3.    Thuật toán Mid-point vẽ đường thẳng


#include<gl/glut.h>
#include<math.h>
 
 
void MidPLine(int x0, int y0, int x1, int y1)
{
         glColor3f(0.0f, 0.0f, 1.0f);//Set the color, blue
         glPointSize(3);//Rasterized point with a diameter of 3
 
    int a, b, d, x, y, temp, tag = 0;
         if (abs(x1-x0) <abs(y1-y0)) //If the absolute value of the slope is greater
than 1, swap the coordinates x and y
    {
        temp = x0, x0 = y0, y0 = temp;
        temp = x1, x1 = y1, y1 = temp;
        tag = 1;
    }
         if (x0> x1)//guarantee x0<x1
    {
        temp = x0, x0 = x1, x1 = temp;
        temp = y0, y0 = y1, y1 = temp;
    }
         a = y0-y1;//The discriminant a
         b = x1-x0; // discriminant b
         d = a + b / 2;//The initial value of the discriminant
         if (y0 <y1)//The slope is positive
    {
        x = x0; y = y0;
                 glBegin(GL_POINTS);//Draw the starting point
        glVertex2i(x, y);
        glEnd();
        while (x < x1)
        {
                         if (d <0) // Discriminant <0, take point P2, the increment is
a+b
            {
                x++; y++; d = d + a + b;
            }
                         else// Discriminant >=0, take point P1, increment is a
            {
                x++; d += a;
            }
                         if (tag)//The slope is greater than 1
            {
                glBegin(GL_POINTS);
                glVertex2i(y, x);
                glEnd();
            }
            else
            {
                glBegin(GL_POINTS);
                glVertex2i(x, y);
                glEnd();
            }
        }  /* while */
    }
         else//The slope is negative (y0>=y1)
    {
        x = x1;
        y = y1;
                 glBegin(GL_POINTS);//Draw the starting point
        glVertex2i(x, y);
        glEnd();
        while (x > x0)
        {
                         if (d <0)// Discriminant <0, the increment is -a+b
            {
                x--; y++; d = d - a + b;
            }
                         else// Discriminant >=0, the increment is -a
            {
                x--; d -= a;
            }
                         if (tag)//The slope is greater than 1
            {
                glBegin(GL_POINTS);
                glVertex2i(y, x);
                glEnd();
            }
            else
            {
                glBegin(GL_POINTS);
                glVertex2i(x, y);
                glEnd();
            }
        }  /* while */
    }
}
void myDisplay()
{
         glClearColor(1.0, 1.0, 1.0, 1.0);//Clear color, white
         glClear(GL_COLOR_BUFFER_BIT);//Eliminate the buffer, use the above clear
color to eliminate
 
 
    //MidPLine(0, 0, 200, 200);
    //MidPLine(200, 200, 0, 0);
    //MidPLine(0, 200, 100, 100);
    MidPLine(200, 200, 400, 0);
 
         glFlush();//Forced refresh
}
 
void Reshape(int w, int h)
{
         glViewport(0, 0, (GLsizei)w, (GLsizei)h); //Define the viewport size
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
         gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//Make the coordinates of the
lower left corner be (0, 0) and the coordinates of the upper right corner be (w, h)
}
 
void main(int argc, char* argv[])
{
         glutInit(&argc, argv);//Initialize GLUT
         glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//Display mode
         glutInitWindowPosition(100, 100);//Window position, the coordinates of the
upper left corner of the window on the screen
         glutInitWindowSize(400, 400);//Window size
         glutCreateWindow("Midpoint drawing method");//Create window, the parameter is
the title of the window
         glutDisplayFunc(myDisplay);//Tell GLUT which function is responsible for
drawing, that is, register a drawing function myDisplay
         glutReshapeFunc(Reshape); //When the window changes, what function is used to
redraw
         glutMainLoop();//Handle the never-ending loop monitoring
}

4.    Thuật toán Bresenham vẽ đường tròn

4.1         Chương trình michener01


#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
 
void init(void)
{
  glClearColor(1.0,1.0,1.0,0.0);
  glMatrixMode(GL_PROJECTION);
  gluOrtho2D(0.0,200.0,0.0,200.0);
}
 
void setPixel(GLint x,GLint y)
{
  glBegin(GL_POINTS);
     glVertex2i(x,y);
  glEnd();
}
 
void Circle(){
      
  int xCenter=100,yCenter=100,r=50;
  int x=0,y=r;
  int d = 3/2 - r;                       // = 1 - r
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f( 1 ,0, 0); 
  while(x<=y){
    setPixel(xCenter+x,yCenter+y);
    setPixel(xCenter+y,yCenter+x);             //find other points by symmetry
    setPixel(xCenter-x,yCenter+y);
    setPixel(xCenter+y,yCenter-x);
    setPixel(xCenter-x,yCenter-y);
    setPixel(xCenter-y,yCenter-x);
    setPixel(xCenter+x,yCenter-y);
    setPixel(xCenter-y,yCenter+x);
 
    if (d<0)
       d += (2*x)+3;
    else {
       d += (2*(x-y))+5;
       y -= 1;
    }
    x++;
  }
 
  glFlush();
}
 
int main(int argc,char **argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowPosition(0,0);
    glutInitWindowSize(500,500);
    glutCreateWindow("Bresenham Circle");
    init();
    glutDisplayFunc(Circle);
    glutMainLoop();
    return 0;
}

4.2         Chương trình michener02


 
#include <GL/glut.h>
#include <math.h>
#define window_wide 1300
#define window_height 700
 
float ax,ay,bx,by,check=0;
void setPixel(int x, int y)
{
       glBegin(GL_POINTS);
       glVertex2i(x,y);
       glEnd();
       glFlush();
}
 
void breselham_func()
{
       int r = sqrt((bx-ax)*(bx-ax)+(by-ay)*(by-ay));
       int x = 0, y = r;
       int d = 3-2*r;
       while(x<=y)
       {
                     setPixel(ax+x,ay+y);
                     setPixel(ax+x,ay-y);
                     setPixel(ax-x,ay+y);
                     setPixel(ax-x,ay-y);
                     setPixel(ax+y,ay+x);
                     setPixel(ax+y,ay-x);
                     setPixel(ax-y,ay+x);
                     setPixel(ax-y,ay-x);
                     if(d<0)
                     {
                           d = d+4*x+6;
                     }
                     else
                     {
                           d = d+4*(x-y)+10;
                           y--;
                     }
                     x++;
       }
}
 
void myMouse(int button, int state, int x, int y)
{
       if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
       {
              if(check==0)
              {
                     ax = x;
                     ay = window_height-y;
                     check = 1;
                     setPixel(ax,ay);
              }
              else if(check==1)
              {
                     bx = x;
                     by = window_height-y;
                     check = 0;
                     breselham_func();
                     //glFlush();
              }
       }
}
 
void myDisplay(void)
{
       glClearColor(1.0,1.0,1.0,0.0);
       glColor3f(1.0,0.0,0.0);
       gluOrtho2D(0.0,window_wide,0.0,window_height);
       glClear(GL_COLOR_BUFFER_BIT);
       glutMouseFunc(myMouse);
}
 
int main(int argc, char** argv)
{
       glutInitWindowSize(window_wide,window_height);
       glutInitWindowPosition(0, 0);
       glutCreateWindow("Bresenham Center Algorithm");
       glutDisplayFunc(myDisplay);
       glutMainLoop();
       return 0;
}
 

§  Kết quả chạy chương trình:

5.    Thuật toán Midpoint vẽ đường tròn


#include<GL/glut.h>
#include<math.h>
#include<Windows.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
GLsizei winWidth = 500, winHeight = 500;
GLuint regHex;//Display table identification
GLint xc,yc;
GLint radius;
class screenPt
{
private:
       GLint x, y;
public:
       screenPt()
       {
              x = y = 0;
       }
       void setCoords(GLint xcord, GLint ycord)
       {
              x = xcord;
              y = ycord;
       }
       GLint getXcord()
       {
              return x;
       }
       GLint getYcord()
       {
              return y;
       }
       void incrementx()
       {
              x++;
       }
       void decrementy()
       {
              y--;
       }
};
void setPixel(GLint x, GLint y)
{
      
       glBegin(GL_POINTS);
       glVertex2i(x, y);
       glEnd();
}
void circlePoints(GLint xc, GLint yc, screenPt circPt)
{
      
       setPixel(xc + circPt.getXcord(), yc + circPt.getYcord());
       setPixel(xc - circPt.getXcord(), yc + circPt.getYcord());
       setPixel(xc + circPt.getXcord(), yc - circPt.getYcord());
       setPixel(xc - circPt.getXcord(), yc - circPt.getYcord());
       setPixel(xc + circPt.getYcord(), yc + circPt.getXcord());
       setPixel(xc - circPt.getYcord(), yc + circPt.getXcord());
       setPixel(xc + circPt.getYcord(), yc - circPt.getXcord());
       setPixel(xc - circPt.getYcord(), yc - circPt.getXcord());
}
void circMidPoint(GLint xc, GLint yc, GLint radius)
{
      
       screenPt cirPt;
       cout << "radius" << radius << endl;
       cirPt.setCoords(0, radius);//initial point
       GLint p = 1-radius;//initial p
       circlePoints(xc, yc, cirPt);
       cout << cirPt.getXcord() << "," << cirPt.getYcord() << endl;
       while (cirPt.getXcord() < cirPt.getYcord())
       {
               cout << "Enter while" << endl;
              cirPt.incrementx();
              if (p < 0)
              {
                     p += 2 * cirPt.getXcord() + 1;
              }
              else
              {
                     cirPt.decrementy();
                     p += 2 * (cirPt.getXcord() - cirPt.getYcord()) + 1;
              }
              circlePoints(xc, yc, cirPt);
               cout << "The current pixel point is" << cirPt.getXcord() << "," <<
cirPt.getYcord() << endl;
       }
 
}
 
static void init(void)
{
        //Initialize the function and join the table
 
        glClearColor(1.0, 1.0, 1.0, 0.0);//Set to white background
        regHex = glGenLists(1);//Get a logo
 
       glNewList(regHex, GL_COMPILE);
       glColor3f(1.0, 0.0,0.0);
       glPointSize(5);
       circMidPoint(xc, yc, radius);
       glEndList();
 
}
 
void circlePlot(void)
{
       //Draw a circle
       glClear(GL_COLOR_BUFFER_BIT);
       glCallList(regHex);//Display list
       glFlush();
}
 
void winReshapeFcn(int newWidth, int newHeight)
{
       //Window reshaping function
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();//Move the origin of the current user coordinate system to the
center of the screen: similar to a reset operation
       gluOrtho2D(0.0, (GLdouble)newWidth, 0.0, (GLdouble)newWidth);
       glClear(GL_COLOR_BUFFER_BIT);
 
 
} int main(int argc, char**argv)
{
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
       glutInitWindowPosition(100, 100);
       glutInitWindowSize(winWidth, winHeight);
       glutCreateWindow("Example");
       cout << "Enter the circle center coordinates (range 0-500, 0-500):" << endl;
       cin >> xc >> yc;
 
        cout << "Enter radius" << endl;
       cin >> radius;
       init();
       glutDisplayFunc(circlePlot);
       glutReshapeFunc(winReshapeFcn);
       glutMainLoop();
       return 0;
}
6.    Thuật toán vẽ đường ellipse

#include <gl/glut.h>
using namespace std;
 
void drawDot (GLint x, GLint y, GLfloat r, GLfloat g, GLfloat b)
{
  glColor3f(r,g,b);
  glBegin (GL_POINTS);
      glVertex2i (x,y);
  glEnd();
}
 
void symmetricPixels (int x, int y, int xc, int yc, float r, float g, float b)
{ drawDot (xc + x, yc + y, r,g,b);
  drawDot (xc - x, yc + y,r,g,b);
  drawDot (xc + x, yc - y,r,g,b);
  drawDot (xc - x, yc - y,r,g,b);
}
 
void Ellipse (int a, int b, int xc, int yc, float r, float g, float bl)
{ int aSq,bSq,twoASq,twoBSq,d,dx,dy,x,y;
 
  aSq = a*a;
  bSq = b*b;
  twoASq = 2*aSq;
  twoBSq = 2*bSq;
  d = bSq - b*aSq + aSq/4;
  dx = 0;
  dy = twoASq*b;
  x = 0;
  y = b;
  symmetricPixels(x,y,xc,yc,r,g,bl);
  while (dx < dy)
  { x++;
    dx += twoBSq;
    if (d >= 0)
    { y--;
      dy -= twoASq;
    }
    if (d < 0)
     d += bSq + dx;
    else
     d += bSq + dx - dy;
    symmetricPixels (x,y,xc,yc,r,g,bl);
  }
  d = (int)(bSq*(x+0.5)*(x+0.5) + aSq*(y-1)*(y-1) -
                 aSq*bSq);
  while (y > 0)
  { y--;
    dy -= twoASq;
    if (d <= 0)
    { x++;
      dx += twoBSq;
    }
    if (d > 0)
         d += aSq - dy;
    else
         d += aSq -dy +dx;
    symmetricPixels(x,y,xc,yc,r,g,bl);
  }
}  
void Set_Graphics( int width, int height )
{
    glClearColor( 1.0, 1.0, 1.0, 0.0 );
    glColor3f( 0.0f, 0.0f, 0.0f );
    glViewport( 0, 0, width, height );
    glMatrixMode( GL_PROJECTION );  
    glLoadIdentity( );
    glEnable( GL_DEPTH_TEST );
    gluPerspective( 45, ( float ) width / height, 1.0, 0 );
    glMatrixMode( GL_MODELVIEW );
    glTranslatef( 0, 0, 5 * ( -height) );
}
void Start_Line( )
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//    Line_Algo( 5, 8, 29,32 );
//    Circle (40,0,0,1);
    Ellipse (100,30,20,20,0,1,0);
  // glFlush();
    glutSwapBuffers( );
}
int main( int argc, char** argv  )
{
  
    glutInit( &argc, argv );
    glutInitWindowSize( 640,480);
    glutInitWindowPosition( 100, 150 );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
    glutCreateWindow( " Elipse Drawing" );
    glutDisplayFunc( Start_Line );
    Set_Graphics( 100, 100 /*window_width, window_height*/ );
    glutMainLoop( );
    return 0;
}
 
7.    Thuật toán xén hình
#include <glut.h>
#include <math.h>
 
#define  INC 10
#define M_PI 3.14159265358979323846
 
typedef struct {
       int x,y;
} Point;
 
Point A,B, wmax, wmin;;
float goc;
char chuot;
 
//-----------------------------------------
 
void KhoiTao(){
       glClearColor(0,0,0,0);
       glLineWidth(2);
 
       wmin.x=0;wmin.y=0;
       wmax.x=200;wmax.y=120;
       A.x=300;     A.y=200;
       B.x=50;             B.y=-100;
 
       goc=0;
       chuot=0;
}
int Ma(Point M){
       int m=0;
       if(M.x<wmin.x) m |=1;
       if(M.x>wmax.x) m |=2;
       if(M.y<wmin.y) m |=4;
       if(M.y>wmax.y) m |=8;
       return m;
}
void HoanVi(Point *A,Point *B){
       Point T;
       T=*A;  *A=*B; *B=T;
}
Point Xoay(Point A,int g)
{
       float goc_rad =g * M_PI/180;
       Point T;
       T.x=A.x*cos(goc_rad)-A.y*sin(goc_rad);
       T.y=A.x*sin(goc_rad)+A.y*cos(goc_rad);
       return T;
}
void VeDuongThang(Point A,Point B){
       glBegin(GL_LINES);
       glVertex2i(A.x,A.y);
       glVertex2i(B.x,B.y);
       glEnd();
}
void VeHCN(Point wmin,Point wmax,int g)
{
       Point A,B,C,D;     
       A=wmin;
       C=wmax;
       B.x=wmax.x; B.y=wmin.y;
       D.x=wmin.x; D.y=wmax.y;
      
       A=Xoay(A,g);
       B=Xoay(B,g);
       C=Xoay(C,g);
       D=Xoay(D,g);
      
       glBegin(GL_LINE_LOOP);
       glVertex2i(A.x,A.y);
       glVertex2i(B.x,B.y);
       glVertex2i(C.x,C.y);
       glVertex2i(D.x,D.y);
       glEnd();
      
}
 
void ClipCohen(Point A,Point B,Point wmin,Point wmax,int g){
       int thoat=0 , ve=1;
       double m;
      
       while(thoat==0){
              if((Ma(A)|Ma(B))==0)       thoat=1;     // A va B nam trong vung cn
ma(A)=ma(B)=0000
              else if((Ma(A) & Ma(B))!=0)                    // AB nam hoan toan ben
ngoai vung cn
              {
                     thoat =1;           ve=0;
              }else{
                     if(Ma(A)==0) HoanVi(&A,&B);      //A nam trong vung cn
                     if(A.x==B.x)                             // A va B cung nam doc
                     {
                           if(A.y>wmax.y)      A.y=wmax.y;  //
                           else A.y=wmin.y;
                     }
                     else
                     {
                           m=(double)(B.y-A.y)/(B.x-A.x);
                           if(A.x<wmin.x)
                           {
                                  A.y=A.y+(wmin.x-A.x)*m;
                                  A.x=wmin.x;
                           }else if(A.x>wmax.x)
                           {
                                  A.y=A.y+(wmax.x-A.x)*m;
                                  A.x=wmax.x;
                           }else if(A.y<wmin.y)
                           {
                                  A.x=A.x+(wmin.y-A.y)/m;
                                  A.y=wmin.y;
                           }else if(A.y>wmax.y)
                           {
                                  A.x=A.x+(wmax.y-A.y)/m;
                                  A.y=wmax.y;
                           }
                     }
 
              }
       }
       if(ve) VeDuongThang(Xoay(A,g),Xoay(B,g));
}
void XenHinhNhiPhan(Point A,Point B,Point wmin,Point wmax,int g){
       Point P,Q,M;
      
       if((Ma(A)|Ma(B))==0) VeDuongThang(Xoay(A,g),Xoay(B,g));
       if((Ma(A)&Ma(B))!=0) return ;
       if((Ma(A)!=0) &&(Ma(B)==0))       HoanVi(&A,&B);
       if((Ma(A)==0) &&(Ma(B)!=0))
       {
              P=A;Q=B;
              while((abs(P.x-Q.x)+abs(P.y-Q.y))>2)
              {
                     M.x=(P.x+Q.x)/2;
                     M.y=(P.y+Q.y)/2;
                     if(Ma(M)==0) P=M;
                     else                Q=M;                      
              }
              VeDuongThang(Xoay(A,g),Xoay(P,g));
       }
       if((Ma(A)!=0)&&(Ma(B)!=0)&&((Ma(A) & Ma(B))==0))
       {
              P=A;Q=B;
              M.x=(P.x+Q.x)/2;
              M.y=(P.y+Q.y)/2;
 
              while(( Ma(M)!=0) && ((abs(P.x-Q.x)+abs(P.y-Q.y))>2))
              {
                     if((Ma(P)& Ma(M)) !=0)     P=M;
                     else Q=M;
                     M.x=(P.x+Q.x)/2;
                     M.y=(P.y+Q.y)/2;                 
              }
              if(Ma(M)==0)
              {
                     XenHinhNhiPhan(P,M,wmin,wmax,g);
                     XenHinhNhiPhan(M,Q,wmin,wmax,g);
              }
       }
}
 
void Mydisplay(){
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
       glColor3f(0.0, 1.0, 0.0);
       VeHCN(wmin,wmax,goc);
      
       glColor3f(0.0, 0.0, 1.0);
       VeDuongThang(A,B);
      
       glColor3f(1.0, 0.0, 0.0);
       ClipCohen(Xoay(A,-goc),Xoay(B,-goc),wmin,wmax,goc);
       //XenHinhNhiPhan(Xoay(A,-goc),Xoay(B,-goc),wmin,wmax,goc);
      
       glFlush();
}
 
void KeyboardEventHandler(int key,int x,int y)
{
       switch(key)
       {
       case GLUT_KEY_UP:
              goc += INC;
              if(goc >360) goc=0;
              glutPostRedisplay();
              break;
       case GLUT_KEY_DOWN:
              goc -= INC;
              if(goc <0) goc=360;
              glutPostRedisplay();
              break;
       }
}
 
void MouseEventHandler(int button, int state, int x, int y)
{
      
       if(button == GLUT_LEFT_BUTTON && state ==  GLUT_UP)
              if(chuot==0)
              {
                     A.x=x-300;
                     A.y=300-y;         
                     chuot=1;
              }
       else
              {
                     B.x=x-300;
                     B.y=300-y;  
                     chuot=0;
                     glutPostRedisplay();
              }
      
}
//-----------------------------------------
int main(int argc,char* arg[]){
 
       glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
       glutInitWindowSize (600, 600);
       glutInitWindowPosition (10, 10);
       glutCreateWindow("Thuat Toan Xen Hinh");
       gluOrtho2D(-300, 300, -300, 300);
       KhoiTao();
       glutMouseFunc(MouseEventHandler);
       glutDisplayFunc(Mydisplay);
       glutSpecialFunc(KeyboardEventHandler);
       glutMainLoop();
}
 

8.    Cohen-Sutherland cropping algorithm


 
#include <GL/glut.h>
#include <cstdio>
 
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8
 
int x1=150,y1=50, x2=50, y2=250, XL=100, XR=300, YB=100, YT=200;  //(x1,y1), (x2,y2)
are the end points of the straight line segment, XL is the left boundary, XR is the
right boundary, YB is the lower boundary, and YT is the upper boundary
int x1_init = 150, y1_init = 50, x2_init = 50, y2_init = 250;  //Back up the end
points of the straight line segment so as to draw the straight line segment before
cutting
 
int encode(int x,int y)
{
    int c = 0;
    if (x < XL) c |= LEFT;
    if (x > XR) c |= RIGHT;
    if (y < YB) c |= BOTTOM;
    if (y > YT) c |= TOP;
    return c;
}
 
void CS_LineClip()  //Cohen-Sutherland cropping algorithm
{
    int x, y;
    int code1, code2, code;
    code1 = encode(x1, y1);
    code2 = encode(x2, y2);
 
    while (code1 != 0 || code2 != 0)
    {
        if (code1 & code2)
            return;
        if (code1 != 0)
            code = code1;
        else
            code = code2;
 
        if (LEFT & code)
        {
            x = XL;
            y = y1 + (y2 - y1)*(XL - x1) / (x2 - x1);
        }
        else if (RIGHT & code)
        {
            x = XR;
            y = y1 + (y2 - y1)*(XR - x1) / (x2 - x1);
        }
        else if (BOTTOM & code)
        {
            y = YB;
            x = x1 + (x2 - x1)*(YB - y1) / (y2 - y1);
        }
        else if (TOP & code)
        {
            y = YT;
            x = x1 + (x2 - x1)*(YT - y1) / (y2 - y1);
        }
        if (code == code1)
        {
            x1 = x; y1 = y; code1 = encode(x1, y1);
        }
        else
        {
            x2 = x; y2 = y; code2 = encode(x2, y2);
        }
    }
 
}
 
 
void init()  //Initialization function
{
    glClearColor(1.0, 1.0, 1.0, 0.0);  //Set the background color
    glMatrixMode(GL_PROJECTION);       // Set projection parameters
    gluOrtho2D(0.0, 600.0, 0.0, 400.0); // Set the size of the scene
    CS_LineClip();  //Execute a cropping algorithm
}
 
void mydisplay()  //Display function
{
    //Draw a square border
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);  
    glPointSize(2);
    glBegin(GL_LINE_LOOP);
        glVertex2i(XL, YT);
        glVertex2i(XL, YB);
        glVertex2i(XR, YB);
        glVertex2i(XR, YT);
    glEnd();
    glFlush();
    //Draw the line segment before cropping
    glBegin(GL_LINES);
        glVertex2i(x1_init, y1_init);
        glVertex2i(x2_init, y2_init);
    glEnd();
    glFlush();
    //Draw the trimmed line segment
    glColor3f(0.0, 0.0, 0.0);
    glBegin(GL_LINES);
        glVertex2i(x1, y1);
        glVertex2i(x2, y2);
    glEnd();
    glFlush();
}
 
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Cohen-Sutherland cropping algorithm");
    init();
    glutDisplayFunc(&mydisplay);
    glutMainLoop();
    return 0;
CHIẾU SÁNG, TÔ BÓNG VÀ KẾT XUẤT ĐỒ HỌA
 
1.     Chiếu sáng và tô bóng
2.     Tạo mặt trụ và tô bóng
3.     Chương trình light.c
4.     Chương trình lighted-cylinder01.c
5.     Chương trình lighted-cylinder02.c
6.     Chương trình lighted-cylinder03.c
7.     Tô bóng Gouraud
 

1.    Chiếu sáng và tô bóng


#include <gl/glut.h>
 
void DrawCoordinate()
{
  glDisable(GL_LIGHTING);
  glBegin(GL_LINES);
  glColor3f(1.0, 0.0, 0.0);
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(10.0, 0.0, 0.0);
  glEnd();
 
  glBegin(GL_LINES);
  glColor3f(0.0, 1.0, 0.0);
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(0.0, 10.0, 0.0);
  glEnd();
 
  glBegin(GL_LINES);
  glColor3f(0.0, 0.0, 1.0);
  glVertex3f(0.0, 0.0, 0.0);
  glVertex3f(0.0, 0.0, 10.0);
  glEnd();
 
  glEnable(GL_LIGHTING);
}
 
 
void RendenScene()
{
 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
 
  gluLookAt(5.0, 5.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 
  glPushMatrix();
  DrawCoordinate();
  glutSolidTeapot(3.0);
  glPopMatrix();
 
  glFlush();
}
 
void ReShape(int width, int height)
{
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  float ratio = (float)width/(float)height;
  gluPerspective(45.0, ratio, 1, 100.0);
  glMatrixMode(GL_MODELVIEW);
}
 
 
void Init()
{
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
 
    GLfloat light_pos [] = {0.0, 0.0, 1.0, 0.0};
    glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
 
    GLfloat ambient [] = {1.0, 0.0, 0.0, 1.0};
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
 
    GLfloat diff_use [] = {0.0, 0.5, 0.0, 1.0};
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff_use);
 
    GLfloat specular[] = {1.0, 1.0, 1.0, 1.0};
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
 
    GLfloat shininess = 50.0f;
    glMateriali(GL_FRONT, GL_SHININESS, shininess);
}
 
void main()
{
  glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB);
  glutInitWindowSize(500, 500);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("Opengl Study");
 
  Init();
  glutReshapeFunc(ReShape);
  glutDisplayFunc(RendenScene);
 
  glutMainLoop();
 
}
 

2.    Tạo mặt trụ và tô bóng


Bổ sung thêm các khai báo để chạy chương trình sau:
#include "GL/glut.h"
float MatCong[300][300][3];
int N = 10, M = 10;
float gocquayx = 0;
float gocquayy = 0;
void Init(void)
{
    // Thiet lap mau nen
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
 
    // Thiet lap phep chieu
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glOrtho(-width/2,width/2,-height/2,height/2,100,1000);
    glOrtho(-2.0, 2.0, -2.0, 2.0, -1.5, 1.5);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0,0,-400);
    glEnable(GL_DEPTH_TEST);
    KhoiTaoMatTru();
    KhoiTaoMoHinhChieuSang();
    return;
}
void KhoiTaoMatTru(void)
{
    int R = 70, A = 150;
    float PI = 4.0*atan(1.0);
    float u, du = 2*PI/M;
    float v, dv = 1.0/N;
    float x, y, z;
    int m, n;
    for (n=0; n<=N; n++) {
           v=n*dv;
           for (m=0; m<=M; m++) {
                  u=m*du;
                  x = R*cos(u);
                  y = A*v;
                  z = R*sin(u);
                  MatCong[n][m][0] = x;
                  MatCong[n][m][1] = y;
                  MatCong[n][m][2] = z;
           }
    }
    return;
}
void ChieuSangMatCong(void)
{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glPushMatrix();
glRotatef(gocquayx,1,0,0);
glRotatef(gocquayy,0,1,0);
float mauden[] = {0.0, 0.0, 0.0, 1.0};
float mauvang[] = {0.8, 0.8, 0.0, 1.0};
float V[3];
int n, m;
for (n=0; n<=N-1; n++) {
           if (n%2 == 0) {
                  glMaterialfv(GL_FRONT,GL_AMBIENT,mauden);
                  glMaterialfv(GL_FRONT,GL_DIFFUSE,mauden);
                  glMaterialfv(GL_FRONT,GL_SPECULAR,mauden);
           }
           else {
                  glMaterialfv(GL_FRONT,GL_AMBIENT,mauvang);
                  glMaterialfv(GL_FRONT,GL_DIFFUSE,mauvang);
                  glMaterialfv(GL_FRONT,GL_SPECULAR,mauvang);
           }
           for (m=0; m<=M-1; m++) {
           glBegin(GL_QUADS);
PhapVector(MatCong[n][m],MatCong[n+1][m],MatCong[n+1][m+1],V);
                  glNormal3fv(V);
                  glVertex3fv(MatCong[n][m]);
                  glVertex3fv(MatCong[n+1][m]);
                  glVertex3fv(MatCong[n+1][m+1]);
                  glVertex3fv(MatCong[n][m+1]);
           glEnd();
           }
}
glPopMatrix();
glDisable(GL_LIGHT0);
glDisable(GL_LIGHTING);
return;
}

3.    Chương trình light.c


/*
 *  light.c
 *  This program demonstrates the use of the OpenGL lighting
 *  model.  A sphere is drawn using a grey material characteristic.
 *  A single light source illuminates the object.
 */
#include <GL/glut.h>
#include <stdlib.h>
 
/*  Initialize material property, light source, lighting model,
 *  and depth buffer.
 */
void init(void)
{
   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat mat_shininess[] = { 50.0 };
   GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
 
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);
 
   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
 
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
}
 
void display(void)
{
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glutSolidSphere (1.0, 20, 16);
   glFlush ();
}
 
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity();
   if (w <= h)
      glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
         1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
   else
      glOrtho (-1.5*(GLfloat)w/(GLfloat)h,
         1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}
 
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}
 
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}

4.    Chương trình lighted-cylinder01.c


Chỉnh sửa và chạy chương trình sau. Xuất kết quả minh họa.
/*
 * lighted-cylinder01.c
 *
 * This program is cylinder.c enhanced with normal vectors
 * in a normal array and lighting.
 */
 
/* Use the x, X, y, Y, z, Z keys to turn the cylinder. */
 
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
 
#define PI 3.14159265358979324
 
#define M  25 
#define N  15
 
 
#define FNX(i,j) ( cos( ( (float) i/M ) * 2 * PI) )
#define FNY(i,j) ( sin( ( (float) i/M ) * 2 * PI) )
#define FNZ(i,j) ( 3.0 * (float) j/N )
 
//Define the i,j,k components of the normal vector at cylinder grid points.
#define NORMX(i,j) ( cos( ( (float) i/M ) * 2 * PI) )
#define NORMY(i,j) ( sin( ( (float) i/M ) * 2 * PI) )
#define NORMZ(i,j) ( 0 )
 
// Vertex array: the x,y,z co-ordinates of the points to which the grid points
// are mapped.
static GLfloat vdata[3*(M+1)*(N+1)];
 
// Normal array: the i,j,k components of the normals to the cylinder where
// grid points are mapped.
static GLfloat ndata[3*(M+1)*(N+1)];
 
// Angles used to rotate the cylinder with keyboard entry.
static int Xangle = 0, Yangle = 0, Zangle = 0;
 
void init (void)
{
   int i, j, k, l;
 
   GLfloat ambient[] = { 0.8, 0.8, 0.8, 1.0 };
   GLfloat diffuse[] = { 1.0, 1.0, 0.0, 1.0 };
   GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat position[] = { 0.0, 1.0, 3.0, 0.0 };   
   GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
 
   glClearColor (0.0, 0.0, 0.0, 0.0);
 
   // The vertex and normal arrays are filled.
   k = 0;
   l = 0;
   for (j = 0; j <= N; j++)
      for (i = 0; i <= M; i++)
      {
         vdata[k++] = FNX(i,j);
         vdata[k++] = FNY(i,j);
         vdata[k++] = FNZ(i,j);
 
         ndata[l++] = NORMX(i,j);
         ndata[l++] = NORMY(i,j);
         ndata[l++] = NORMZ(i,j);
      } 
 
   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_NORMAL_ARRAY);
 
   glVertexPointer(3, GL_FLOAT, 0, vdata);
   glNormalPointer(GL_FLOAT, 0, ndata);
 
   // Define properties of the light source.
   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
   glLightfv(GL_LIGHT0, GL_POSITION, position);
   
   // Define properties of the ambient light.
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
 
   // Enable two-sided lighting.
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
}
 
void display(void)
{
   int  i, j;
 
   GLfloat mat_specular1[] = { 1.0, 0.0, 0.0, 1.0 };
   GLfloat mat_shininess1[] = { 50.0 };
   GLfloat mat_diffuse1[] = {0.9, 0.0, 0.0};
 
   GLfloat mat_specular2[] = { 0.0, 1.0, 0.0, 1.0 };
   GLfloat mat_shininess2[] = { 50.0 };
   GLfloat mat_diffuse2[] = {0.0, 0.9, 0.0};
 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glColor3f (1.0, 1.0, 1.0);
 
   glRotatef ((GLfloat) Zangle, 0.0, 0.0, 1.0);
   glRotatef ((GLfloat) Yangle, 0.0, 1.0, 0.0);
   glRotatef ((GLfloat) Xangle, 1.0, 0.0, 0.0);
 
   // Material properties are specified for the cylinder.
   for(j = 0; j < N; j++)
   {
      if(j%2==0)
      {
         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular1);
         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess1);
         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse1);
      }
   else
   {
      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular2);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess2);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse2);
   }
 
      glBegin(GL_TRIANGLE_STRIP);
      for(i = 0; i <= M; i++)
      {
         glArrayElement( (j+1)*(M+1) + i );
         glArrayElement( j*(M+1) + i );
      }
      glEnd();
   }
 
   glFlush ();
}
 
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt (0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
 
void keyboard (unsigned char key, int x, int y)
{
   switch (key) {
      case 'x':
         Xangle = (Xangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'X':
         Xangle = (Xangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'y':
         Yangle = (Yangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Y':
         Yangle = (Yangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'z':
         Zangle = (Zangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Z':
         Zangle = (Zangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 27:
         exit(0);
         break;
      default:
         break;
   }
}
 
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow ("lighted-cylinder");
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0; 
}
 

§  Kết quả chạy chương trình:

5.    Chương trình lighted-cylinder02.c


Chỉnh sửa và chạy chương trình sau. Xuất kết quả minh họa.
/*
 * lighted-cylinder02.c
 * This program is cylinder2.c enhanced with normal vectors
 * in a normal array and lighting.
 * NOTE that we have to fix a problem with the orientation of
 * of front-facing triangles with a call to glFrontFace() .
 */
 
/* Use the x, X, y, Y, z, Z keys to turn the cylinder. */
 
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
 
#define PI 3.14159265358979324
 
/*
 * The parameter space is the unit plane square with corners at (0,0) and (1,1)
 * subdivided into an N horizontal triangle strips each with 2M triangles.
 */
#define M  25 
#define N  15
 
/* Define the parametrizing fuction that maps the parameter point (i/M, j/N)
 * on the plane square to the point (FNX(i,j), FNY(i,j), FNZ(i,j)) on the cylinder.
 */
 #define FNX(i,j) ( cos( ( (float) i/M ) * 2 * PI) )
 #define FNY(i,j) ( sin( ( (float) i/M ) * 2 * PI) )
 #define FNZ(i,j) ( 3.0 * (float) j/N )
 
/* Define the i,j,k components of the normal vector at cylinder grid points. */
 #define NORMX(i,j) ( cos( ( (float) i/M ) * 2 * PI) )
 #define NORMY(i,j) ( sin( ( (float) i/M ) * 2 * PI) )
 #define NORMZ(i,j) ( 0 )
 
// Vertex array: the x,y,z co-ordinates of the points to which the grid points
// are mapped.
static GLfloat vdata[3*(M+1)*(N+1)];
 
// Normal array: the i,j,k components of the normals to the cylinder where
// grid points are mapped.
static GLfloat ndata[3*(M+1)*(N+1)];
 
// Angles used to rotate the cylinder with keyboard entry.
static int Xangle = 0, Yangle = 0, Zangle = 0;
 
void init (void)
{
  int i, j, k, l;
 
  GLfloat ambient[] = { 0.8, 0.8, 0.8, 1.0 };
  GLfloat diffuse[] = { 1.0, 1.0, 0.0, 1.0 };
  GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat position[] = { 0.0, 1.0, 3.0, 0.0 };    
  GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
 
  glClearColor (0.0, 0.0, 0.0, 0.0);
 
  // The vertex and normal arrays are filled.
  k = 0;
  l = 0;
  for (j = 0; j <= N; j++)
    for (i = 0; i <= M; i++){
      vdata[k++] = FNX(i,j);
      vdata[k++] = FNY(i,j);
      vdata[k++] = FNZ(i,j);
 
      ndata[l++] = NORMX(i,j);
      ndata[l++] = NORMY(i,j);
      ndata[l++] = NORMZ(i,j);
    } 
 
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_NORMAL_ARRAY);
 
  glVertexPointer(3, GL_FLOAT, 0, vdata);
  glNormalPointer(GL_FLOAT, 0, ndata);
 
/* Define properties of the light source */
   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
   glLightfv(GL_LIGHT0, GL_POSITION, position);
   
/* Define properties of the ambient light */
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
 
/* Enable two-sided lighting */
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
}
 
void display(void)
{
   int  i, j;
 
   GLfloat mat_specular1[] = { 1.0, 0.0, 0.0, 1.0 };
   GLfloat mat_shininess1[] = { 50.0 };
   GLfloat mat_diffuse1[] = {0.9, 0.0, 0.0};
 
   GLfloat mat_specular2[] = { 0.0, 1.0, 0.0, 1.0 };
   GLfloat mat_shininess2[] = { 50.0 };
   GLfloat mat_diffuse2[] = {0.0, 0.9, 0.0};
 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
/* IMPORTANT: The order of the vertices in the triangle strips is
 * such that looking from the outside at the cylinder the triangles
 * are ordered clockwise. This is a problem because, by default,
 * OpenGL consider only counter-clockwise ordered faces to be on the
 * outside. We could rewrite the triangle strip statement to fix the
 * problem there (this is indicated below).
 * Another solution is the following statement which causes OpenGL
 * to consider clockwise oriented faces to be front-facing
 * (the default mode is GL_CCW).
 */
   glFrontFace(GL_CW);
 
   glColor3f (1.0, 1.0, 1.0);
 
   glRotatef ((GLfloat) Zangle, 0.0, 0.0, 1.0);
   glRotatef ((GLfloat) Yangle, 0.0, 1.0, 0.0);
   glRotatef ((GLfloat) Xangle, 1.0, 0.0, 0.0);
 
/* Material lighting properties are specified for the cylinder */
   for(j = 0; j < N; j++){
     if(j%2==0){
          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular1);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess1);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse1);
     }
     else {
          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular2);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess2);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse2);
     }
     glBegin(GL_TRIANGLE_STRIP);
     for(i = 0; i <= M; i++){
       // Comment out the glFrontFace(GL_CW) statement above and
       // interchange the following two glArrayElement() statements.
       glArrayElement( j*(M+1) + i );
       glArrayElement( (j+1)*(M+1) + i );
     }
   glEnd();
   }
 
  glFlush ();
}
 
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt (0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
 
void keyboard (unsigned char key, int x, int y)
{
   switch (key) {
      case 'x':
         Xangle = (Xangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'X':
         Xangle = (Xangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'y':
         Yangle = (Yangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Y':
         Yangle = (Yangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'z':
         Zangle = (Zangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Z':
         Zangle = (Zangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 27:
         exit(0);
         break;
      default:
         break;
   }
}
 
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow ("lighted-cylinder");
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0; 
}

6.    Chương trình lighted-cylinder03.c


Chỉnh sửa và chạy chương trình sau. Xuất kết quả minh họa.
/*
 * lighted-cylinder2.c
 * Here we compute the vertex normals by averaging the normals
 * to the triangles surrounding each vertex.
 *
 * From the output the program seems to have a bug.
 */
 
/* Use the x, X, y, Y, z, Z keys to turn the cylinder. */
 
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
 
#define PI 3.14159265358979324
 
#define M  25 
#define N  15
 
/* Define the parametrizing fuction that maps the parameter point (i/M, j/N)
 * on the plane square to the point (FNX(i,j), FNY(i,j), FNZ(i,j)) on the cylinder.
 */
 #define FNX(i,j) ( cos( ( (float) i/M ) * 2 * PI) )
 #define FNY(i,j) ( sin( ( (float) i/M ) * 2 * PI) )
 #define FNZ(i,j) ( 3.0 * (float) j/N )
 
// Vertex array: the x,y,z co-ordinates of the points to which the grid points
// are mapped.
static GLfloat vdata[3*(M+1)*(N+1)];
 
// Normal array.
static GLfloat ndata[3*(M+1)*(N+1)];
 
// Angles used to rotate the cylinder with keyboard entry.
static int Xangle = 0, Yangle = 0, Zangle = 0;
 
// The normal to a triangle whose vertices are v0, v1, v2 are added
// component-wise to the vector n.
normalToTriangle(float* v0, float* v1, float* v2, float* n)
{
  n[0] += (v1[1]-v0[1])*(v2[2]-v0[2]) - (v2[1]-v0[1])*(v1[2]-v0[2]);
  n[1] += (v2[0]-v0[0])*(v1[2]-v0[2]) - (v1[0]-v0[0])*(v2[2]-v0[2]);
  n[2] += (v1[0]-v0[0])*(v2[1]-v0[1]) - (v2[0]-v0[0])*(v1[1]-v0[1]);
}
 
// The normal to a vertex is obtained by adding successively the normals
// to each of the surrounding triangles. These normals are finally normalized
// to unit length.
normalToVertex(int i, int j, float* n)
{
  GLfloat length;
  n[0] = 0;
  n[1] = 0;
  n[2] = 0;
 
  if (j==0)
    {
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*(j*(M+1)+i+1)),
vdata+(3*((j+1)*(M+1)+i+1)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j+1)*(M+1)+i+1)),
vdata+(3*((j+1)*(M+1)+i)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j+1)*(M+1)+i)), vdata+(3*(j*(M+1)+i-
1)), n);
    }
  else if (j==N)
    {
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*(j*(M+1)+i-1)), vdata+(3*((j-
1)*(M+1)+i-1)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j-1)*(M+1)+i-1)), vdata+(3*((j-
1)*(M+1)+i)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j-1)*(M+1)+i)),
vdata+(3*(j*(M+1)+i+1)), n);
    }
  else
    {   
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*(j*(M+1)+i+1)),
vdata+(3*((j+1)*(M+1)+i+1)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j+1)*(M+1)+i+1)),
vdata+(3*((j+1)*(M+1)+i)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j+1)*(M+1)+i)), vdata+(3*(j*(M+1)+i-
1)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*(j*(M+1)+i-1)), vdata+(3*((j-
1)*(M+1)+i-1)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j-1)*(M+1)+i-1)), vdata+(3*((j-
1)*(M+1)+i)), n);
      normalToTriangle(vdata+(3*(j*(M+1)+i)), vdata+(3*((j-1)*(M+1)+i)),
vdata+(3*(j*(M+1)+i+1)), n);
    }
  length = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
  // Dangerous! No check for 0 length.
  n[0] /= length; n[1] /= length; n[2] /= length;
}
 
void init (void)
{
  int i, j, k;
 
  GLfloat ambient[] = { 0.8, 0.8, 0.8, 1.0 };
  GLfloat diffuse[] = { 1.0, 1.0, 0.0, 1.0 };
  GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat position[] = { 0.0, 1.0, 3.0, 0.0 };   
  GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
 
  glClearColor (0.0, 0.0, 0.0, 0.0);
 
  // The vertex array is filled.
  k = 0;
  for (j = 0; j <= N; j++)
    for (i = 0; i <= M; i++){
      vdata[k++] = FNX(i,j);
      vdata[k++] = FNY(i,j);
      vdata[k++] = FNZ(i,j);
    } 
 
  // The normal array is filled.
  for (j = 0; j <= N; j++)
    for (i = 0; i <= M; i++){
      normalToVertex(i, j, ndata+(3*(j*(M+1)+i)));
    } 
    
   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_NORMAL_ARRAY);
 
   glVertexPointer(3, GL_FLOAT, 0, vdata);
   glNormalPointer(GL_FLOAT, 0, vdata);
 
/* Define properties of the light source */
   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
   glLightfv(GL_LIGHT0, GL_POSITION, position);
   
/* Define properties of the ambient light */
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
 
/* Enable two-sided lighting */
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);
}
 
void display(void)
{
   int  i, j;
 
   GLfloat mat_specular1[] = { 1.0, 0.0, 0.0, 1.0 };
   GLfloat mat_shininess1[] = { 50.0 };
   GLfloat mat_diffuse1[] = {0.9, 0.0, 0.0}; 
  
   GLfloat mat_specular2[] = { 0.0, 1.0, 0.0, 1.0 };
   GLfloat mat_shininess2[] = { 50.0 };
   GLfloat mat_diffuse2[] = {0.0, 0.9, 0.0};
 
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glColor3f (1.0, 1.0, 1.0);
 
   glRotatef ((GLfloat) Zangle, 0.0, 0.0, 1.0);
   glRotatef ((GLfloat) Yangle, 0.0, 1.0, 0.0);
   glRotatef ((GLfloat) Xangle, 1.0, 0.0, 0.0);
 
/* Material lighting properties are specified for the cylinder */
   for(j = 0; j < N; j++){
     if (j%2 == 0)
       {
     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular1);
     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess1);
     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse1);
       }
     else
       {
     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular2);
     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess2);
     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse2);
       }
     glBegin(GL_TRIANGLE_STRIP);
     for(i = 0; i <= M; i++){
       // The order of the glArrayElement() statements have been
       // reversed from lighted-cylinder1.c
       glArrayElement( (j+1)*(M+1) + i );
       glArrayElement( j*(M+1) + i );
     }
   glEnd();
   }
 
  glFlush ();
}
 
void reshape (int w, int h)
{
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt (0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
 
void keyboard (unsigned char key, int x, int y)
{
   switch (key) {
      case 'x':
         Xangle = (Xangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'X':
         Xangle = (Xangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'y':
         Yangle = (Yangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Y':
         Yangle = (Yangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 'z':
         Zangle = (Zangle + 5) % 360;
         glutPostRedisplay();
         break;
      case 'Z':
         Zangle = (Zangle - 5) % 360;
         glutPostRedisplay();
         break;
      case 27:
         exit(0);
         break;
      default:
         break;
   }
}
 
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow ("cylinder2");
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0; 
}
 
 

7.    Tô bóng Gouraud


#include <GL/glut.h>
#include <math.h>
 
// for memcpy
#include <string.h>
 
#include <map>
#include <vector>
#include <iostream>
 
using namespace::std;
 
/* Verticies for simplified demo */
const int VERTICES_SIZE = 4;
float vertices[VERTICES_SIZE][3] = {
            {0.1, 0.1, 0.1},
            {0.2, 0.8, 0.3},
            {0.3, 0.5, 0.5},
            {0.8, 0.2, 0.1},
           };
 
// this is now a plain array
float vertex_normals[VERTICES_SIZE][3];
 
/* Polygons for simplified demo */
const int POLYGON_SIZE = 4;
int polygon[POLYGON_SIZE][3] = {
                {0, 1, 3},
                {0, 2, 1},
                {0, 3, 2},
                {1, 2, 3},
};
 
/* Average point for looking at */
float av_point[3];
   
/*
 * Calculates average point in list of vertices
 * Stores in result
 */
void averagePoint(float vertices[][3], int length, float result[3]) {
  for(int i = 0; i < length; i++) {
    result[0] += vertices[i][0];
    result[1] += vertices[i][1];
    result[2] += vertices[i][2];
  }
 
  result[0] /= length;
  result[1] /= length;
  result[2] /= length;
}
 
/*
 * Performs inplace normalisation of vector v
 */
void normalise(float v[3]) {
  GLfloat length = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  v[0] /= length;
  v[1] /= length;
  v[2] /= length;
}
 
/*
 * Performs cross product of vectors u and v and stores
 * result in result
 * Normalises result.
 */
void crossProduct(float u[], float v[], float result[]) {
  result[0] = u[1] * v[2] - u[2] * v[1];
  result[1] = u[2] * v[0] - u[0] * v[2];
  result[2] = u[0] * v[1] - u[1] * v[0];
}
 
/*
 * Calculates normal for plane
 */
void calculate_normal(int polygon[3], float vertices[][3], float normal[3]) {
  GLfloat u[3], v[3];
  for (int i = 0; i < 3; i++) {
    u[i] = vertices[polygon[0]][i] - vertices[polygon[1]][i];
    v[i] = vertices[polygon[2]][i] - vertices[polygon[1]][i];
  }
 
  crossProduct(u, v, normal);
  normalise(normal);
}
 
/*
 * Populates normals with it's averaged face normal
 *
 * Passing the normal output buffer as a parameter was a bit
 * pointless, as this procedure accesses global variables anyway.
 * Either pass everything as parameters or noting at all,
 * be consequent. And doing it mixed is pure evil.
 */
void calculate_vertex_normals()
{
  // We love RAII, no need for new and delete!
  vector< vector<int> > vertex_to_faces(POLYGON_SIZE);
  vector< vector<float> > faces_to_normal(POLYGON_SIZE);
 
  // Loop over faces
  for (int i = 0; i < POLYGON_SIZE; i++) {
    vector<float> normal(3);
    calculate_normal(polygon[i], vertices, &normal[0]);
    for (int j = 0; j < 3; j++) {
     vertex_to_faces[polygon[i][j]].push_back(i);
    }
    faces_to_normal[i] = normal;
  }
 
  // Loop over vertices
  for (int v = 0; v < VERTICES_SIZE; v++) {
    // avoid a copy here by using a reference
    vector<int> &faces = vertex_to_faces[v];
    int faces_count = 0;
    float normal[3];
    for (vector<int>::iterator it = faces.begin(); it != faces.end(); ++it){
      normal[0] += faces_to_normal[*it][0];
      normal[1] += faces_to_normal[*it][1];
      normal[2] += faces_to_normal[*it][2];
      faces_count++;
    }
    // dividing a vector obtained by a number of unit length vectors
    // summed by the number of unit vectors summed does not normalize
    // it. You need to normalize it properly!
    normalise(normal);
 
    // memcpy is really be best choice here
    memcpy(vertex_normals[v], normal, sizeof(normal));
  }
}
 
/*
 * Draws polygons in polygon array.
 */
 
void draw_polygon() {
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_NORMAL_ARRAY);
 
  glVertexPointer(3, GL_FLOAT, 0, &vertices[0][0]);
  glNormalPointer(GL_FLOAT, 0, &vertex_normals[0][0]);
 
  glDrawElements(GL_TRIANGLES, POLYGON_SIZE*3, GL_UNSIGNED_INT, polygon);
}
 
/*
 * Sets up lighting and material properties
 */
void init_geometry()
{
  // Calculate average point for looking at
  averagePoint(vertices, VERTICES_SIZE, av_point);
 
  // Calculate vertices average normals
  calculate_vertex_normals();
}
 
 
void setup_illumination()
{
  // Intialise and set lighting parameters
  GLfloat light_pos[] = {1.0, 1.0, 1.0, 0.0};
  GLfloat light_ka[] = {0.2, 0.2, 0.2, 1.0};
  GLfloat light_kd[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat light_ks[] = {1.0, 1.0, 1.0, 1.0};
 
  glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
  glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ka);
  glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_kd);
  glLightfv(GL_LIGHT0, GL_SPECULAR, light_ks);
 
  // Initialise and set material parameters
  GLfloat material_ka[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat material_kd[] = {0.43, 0.47, 0.54, 1.0};
  GLfloat material_ks[] = {0.33, 0.33, 0.52, 1.0};
  GLfloat material_ke[] = {0.0, 0.0, 0.0, 0.0};
  GLfloat material_se[] = {10.0};
 
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,  material_ka);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  material_kd);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  material_ks);
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,  material_ke);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_se);
 
  // Smooth shading
  glShadeModel(GL_SMOOTH);
 
  // Enable lighting
  glEnable (GL_LIGHTING);
  glEnable (GL_LIGHT0);
}
 
/*
 * Display simple polygon
 */
void display (void)
{
  // float window sizes are usefull for view volume calculations
  //
  // requesting the window dimensions for each drawing iteration
  // is just two function calls. Compare this to the number of function
  // calls a typical application will do for the actual rendering
  // Trying to optimize away those two calls is a fruitless microoptimization
  float const window_width  = glutGet(GLUT_WINDOW_WIDTH);
  float const window_height = glutGet(GLUT_WINDOW_HEIGHT);
  float const window_aspect = window_width / window_height;
 
  // glViewport operates independent of the projection --
  // another reason to put it into the drawing code
  glViewport(0, 0, window_width, window_height);
 
  glClearDepth(1.);
  glClearColor (0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
  // It's a often made mistake to setup projection in the window resize
  // handler. Projection is a drawing state, hence should be set in
  // the drawing code. Also in most programs you will have multiple
  // projections mixed throughout rendering a single frame so there you
  // actually **must** set projection in drawing code, otherwise it
  // wouldn't work.
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(70, window_aspect, 1, 100);
 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(0, 0, -3, av_point[0], av_point[1], av_point[2], 0, 1, 0);
 
  // Fixed function pipeline light position setup calls operate on the current
  // modelview matrix, so we must setup the illumination parameters with the
  // modelview matrix at least after the view transformation (look-at) applied.
  setup_illumination();
 
  // Enable depth testing (z buffering would be enabled/disabled with glDepthMask)
  glEnable(GL_DEPTH_TEST);
 
  draw_polygon();
 
  glutSwapBuffers();
}
  
int main (int argc, char **argv)
{   
  // Initialize graphics window
  glutInit(&argc, argv);
  glutInitWindowSize(256, 256);
  glutInitDisplayMode    (GLUT_DEPTH | GLUT_DOUBLE);
 
  // we actually have to create a window
  glutCreateWindow("illuination");
 
  // Initialize geometry
  init_geometry();
 
  glutDisplayFunc(display);
 
  glutMainLoop();
 
  return 0;
}
 

----------------------------------------------

 
 

 
 

1.    Đường cong Kock


#include <cmath>
#include <vector>
#include <windows.h>
#include <gl/glut.h>
 
using namespace std;
 
#define eps 0.00001
#define WINDOW_WIDTH 500.0
#define WINDOW_HEIGHT 500.0
#define pi (2*acos(0.0))
 
#define MAX_VAL 9999999
#define MIN_VAL -9999999
 
class Point
{
public:
     double x,y,z;
 
     Point(){
     }
     Point(double a, double b, double c){
        x = a;
        y = b;
        z = c;
     }
     ~Point(){}
     double dot(Point v){
        return x*v.x + y*v.y + z*v.z;
     }
     Point operator+(Point pt) {
        return Point(x + pt.x, y + pt.y, z + pt.z);
    }
    Point operator-(Point pt) {
        return Point(x - pt.x, y - pt.y, z - pt.z);
    }
    Point operator*(double v) {
        return Point(x*v, y*v, z*v);
    }
    Point operator*(Point v){
        return Point(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x);
    }
    Point operator/(double pt) {
        return Point(x/pt, y/pt, z/pt);
    }
    Point normalize() {
        return *this / sqrt(x*x + y*y + z*z);
    }
 
};
 
Point pos(0, 0, -150);
Point u(0,1,0);
Point r(1, 0, 0);
Point l(0, 0, 1);
 
void drawKoch(double x1, double y1, double x2, double y2, int it){
    float angle = 60 * (pi/180);
    double x3 = (2*x1+x2)/3;
    double y3 = (2*y1+y2)/3;
 
    double x4 = (x1+2*x2)/3;
    double y4 = (y1+2*y2)/3;
 
    double x = x3 + (x4 - x3)* cos(angle) + (y4 -y3)* sin(angle);
    double y = y3 - (x4 - x3)* sin(angle) + (y4 -y3)* cos(angle);
 
    if(it>0){
        drawKoch(x1,y1,x3,y3,it-1);
        drawKoch(x3,y3,x,y,it-1);
        drawKoch(x,y,x4,y4,it-1);
        drawKoch(x4,y4,x2,y2,it-1);
    }
    else{
        glColor3f(1.0, 0, 0);
            glBegin(GL_LINES);{
                   glVertex3f( x1,y1,0);
                   glVertex3f(x3,y3,0);
 
                   glVertex3f(x3,y3,0);
                   glVertex3f(x,y,0);
 
                   glVertex3f(x,y,0);
                   glVertex3f(x4,y4,0);
 
                   glVertex3f(x4,y4,0);
                   glVertex3f(x2,y2,0);
            }glEnd();
    }
}
 
void display(){
 
     //clear the display
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glClearColor(0,0,0,0); //color black
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
     /********************
     / set-up camera here
     ********************/
     //load the correct matrix -- MODEL-VIEW matrix
     glMatrixMode(GL_MODELVIEW);
 
     //initialize the matrix
     glLoadIdentity();
 
     //now give three info
     //1. where is the camera (viewer)?
     //2. where is the camera looking?
     //3. Which direction is the camera's UP direction?
 
     //gluLookAt(100,100,100,     0,0,0, 0,0,1);
     //gluLookAt(200*cos(cameraAngle), 200*sin(cameraAngle),
cameraHeight,            0,0,0, 0,0,1);
     gluLookAt(pos.x, pos.y, pos.z, pos.x + l.x, pos.y + l.y, pos.z + l.z, u.x, u.y,
u.z);
 
     //again select MODEL-VIEW
     glMatrixMode(GL_MODELVIEW);
 
    drawKoch(50,0,0,100,2);
    drawKoch(0,100,-50,0,2);
    drawKoch(-50,0,50,0,2);
 
     //ADD this line in the end --- if you use double buffer (i.e. GL_DOUBLE)
     glutSwapBuffers();
}
 
void init(){
     //codes for initialization
     //clear the screen
     glClearColor(0,0,0,0);
 
     /************************
     / set-up projection here
     ************************/
     //load the PROJECTION matrix
     glMatrixMode(GL_PROJECTION);
 
     //initialize the matrix
     glLoadIdentity();
 
     //give PERSPECTIVE parameters
     //gluPerspective(fovY, aspect_ratio,  Near, Far);
     gluPerspective(80,    1,     1,     1000.0);
     //field of view in the Y (vertically)
     //aspect ratio that determines the field of view in the X direction (horizontally)
     //near distance
     //far distance
}
 
int main(int argc, char **argv){
 
     glutInit(&argc,argv);
     glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
     glutInitWindowPosition(0, 0);
     glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);   //Depth, Double
buffer, RGB color
 
     glutCreateWindow("My OpenGL Program");
     init();
 
     glEnable(GL_DEPTH_TEST);     //enable Depth Testing
     glutDisplayFunc(display);     //display callback function
     glutMainLoop();              //The main loop of OpenGL
 
     return 0;
}

----------------------------------------------------------
 

You might also like