實驗2 直線生成算法實現


1.實驗目的:

理解基本圖形元素光柵化的基本原理,掌握一種基本圖形元素光柵化算法,利用OpenGL實現直線光柵化的DDA算法。

2.實驗內容:

(1) 根據所給的直線光柵化的示范源程序,在計算機上編譯運行,輸出正確結果;

(2) 指出示范程序采用的算法,以此為基礎將其改造為中點線算法或Bresenham算法,寫入實驗報告;

(3) 根據示范代碼,將其改造為圓的光柵化算法,寫入實驗報告;

(4) 了解和使用OpenGL的生成直線的命令,來驗證程序運行結果。

3.實驗原理:

示范代碼原理參見教材直線光柵化一節中的DDA算法。下面介紹下OpenGL畫線的一些基礎知識和glutReshapeFunc()函數。

(1)數學上的直線沒有寬度,但OpenGL的直線則是有寬度的。同時,OpenGL的直線必須是有限長度,而不是像數學概念那樣是無限的。可以認為,OpenGL的“直線”概念與數學上的“線段”接近,它可以由兩個端點來確定。這里的線由一系列頂點順次連結而成,有閉合和不閉合兩種。

前面的實驗已經知道如何繪“點”,那么OpenGL是如何知道拿這些頂點來做什么呢?是一個一個的畫出來,還是連成線?或者構成一個多邊形?或是做其它事情呢?為了解決這一問題,OpenGL要求:指定頂點的命令必須包含在glBegin函數之后,glEnd函數之前(否則指定的頂點將被忽略),並由glBegin來指明如何使用這些點。

例如:

glBegin(GL_POINTS);

    glVertex2f(0.0f, 0.0f);

    glVertex2f(0.5f, 0.0f);

glEnd();

則這兩個點將分別被畫出來。如果將GL_POINTS替換成GL_LINES,則兩個點將被認為是直線的兩個端點,OpenGL將會畫出一條直線。還可以指定更多的頂點,然后畫出更復雜的圖形。另一方面,glBegin支持的方式除了GL_POINTS和GL_LINES,還有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN等,每種方式的大致效果如圖A.2所示:

clip_image002

圖A.2 OpenGL幾何圖元類型

(2)首次打開窗口、移動窗口和改變窗口大小時,窗口系統都將發送一個事件,以通知程序員。如果使用的是GLUT,通知將自動完成,並調用向glutReshapeFunc()注冊的函數。該函數必須完成下列工作:

Ÿ 重新建立用作新渲染畫布的矩形區域;

Ÿ 定義繪制物體時使用的坐標系。

如:

void Reshape(int w, int h)

{

glViewport(0, 0, (GLsizei) w, (GLsizei) h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);

}

在GLUT內部,將給該函數傳遞兩個參數:窗口被移動或修改大小后的寬度和高度,單位為像素。glViewport()調整像素矩形,用於繪制整個窗口。接下來三個函數調整繪圖坐標系,使左下角位置為(0, 0),右上角為(w, h)。

4.實驗代碼:

  1 #include <GL/glut.h>
  2 
  3 void LineDDA(int x0,int y0,int x1,int y1/*,int color*/)
  4 
  5 {
  6 
  7     int x, dy, dx, y;
  8 
  9     float m;
 10 
 11     dx=x1-x0;
 12 
 13     dy=y1-y0;
 14 
 15     m=dy/dx;
 16 
 17     y=y0;
 18 
 19     glColor3f (1.0f, 1.0f, 0.0f);
 20 
 21     glPointSize(1);
 22 
 23     for(x=x0;x<=x1; x++)
 24 
 25     {
 26 
 27         glBegin (GL_POINTS);
 28 
 29         glVertex2i (x, (int)(y+0.5));
 30 
 31         glEnd ();
 32 
 33         y+=m;
 34 
 35     }
 36 
 37 }
 38 
 39 void myDisplay(void)
 40 
 41 {
 42 
 43     glClear(GL_COLOR_BUFFER_BIT);
 44 
 45     glColor3f (1.0f, 0.0f, 0.0f);
 46 
 47     glRectf(25.0, 25.0, 75.0, 75.0);
 48 
 49     glPointSize(5);
 50 
 51     glBegin (GL_POINTS);
 52 
 53     glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (0.0f, 0.0f);
 54 
 55     glEnd ();
 56 
 57     LineDDA(0, 0, 200, 300);
 58 
 59     glBegin (GL_LINES);
 60 
 61     glColor3f (1.0f, 0.0f, 0.0f); glVertex2f (100.0f, 0.0f);
 62 
 63     glColor3f (0.0f, 1.0f, 0.0f); glVertex2f (180.0f, 240.0f);
 64 
 65     glEnd ();
 66 
 67     glFlush();
 68 
 69 }
 70 
 71 void Init()
 72 
 73 {
 74 
 75     glClearColor(0.0, 0.0, 0.0, 0.0);
 76 
 77     glShadeModel(GL_FLAT);
 78 
 79 }
 80 
 81 void Reshape(int w, int h)
 82 
 83 {
 84 
 85     glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 86 
 87     glMatrixMode(GL_PROJECTION);
 88 
 89     glLoadIdentity();
 90 
 91     gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);
 92 
 93 }
 94 
 95 int main(int argc, char *argv[])
 96 
 97 {
 98 
 99     glutInit(&argc, argv);
100 
101     glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
102 
103     glutInitWindowPosition(100, 100);
104 
105     glutInitWindowSize(400, 400);
106 
107     glutCreateWindow("Hello World!");
108 
109     Init();
110 
111     glutDisplayFunc(myDisplay);
112 
113     glutReshapeFunc(Reshape);
114 
115     glutMainLoop();
116 
117     return 0;
118 
119 }

注: glShadeModel選擇平坦或光滑漸變模式。GL_SMOOTH為缺省值,為光滑漸變模式,GL_FLAT為平坦漸變模式。

5.實驗提高

示范代碼有個小錯誤,能否指出並改正?請將結果寫入實驗報告。

附: 本實驗的VC++工程代碼(VC++2008)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM