Nhờ vào đồ họa máy tính mà một hoạt động các ứng dụng máy tính ra đời, đồ họa giúp cho việc giao tiếp với máy tính trở nên dễ dàng hơn, nó được ứng dụng trong nhiều lĩnh vực như khoa học
Trang 1TRƯỜNG ĐẠI HỌC ĐIỆN LỰC
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO CHUYÊN ĐỀ HỌC PHẦN
ĐỒ HỌA MÁY TÍNH
ĐỀ TÀI: MÔ PHỎNG CHUYỂN ĐỘNG TÀU VŨ TRỤ
Sinh viên thực hiện : LÊ VIỆT LÂM
HOÀNG MINH DUY NGUYỄN MẠNH DŨNG Giảng viên hướng dẫn : NGÔ TRƯỜNG GIANG
Hà Nội, tháng 6 năm 2020.
Trang 2PHIẾU CHẤM ĐIỂM STT Họ và tên sinh viên Nội dung thực hiện Điểm Chữ
ký
1 LÊ VIỆT LÂM
2 HOÀNG MINH DUY
Trang 3Chương 1: Các Thuật Toán Cơ Bản 4
1 Thuật toán Bressenham 4
1.1 Ý tưởng thuật toán Bressenham 4
1.2 Áp dụng thuật toán Bressenham để vẽ đường thẳng 4
1.3 Áp dụng thuật toán Bressenham để vẽ đường tròn 8
1.4 Áp dụng thuật toán Bressenham để vẽ hình elip 13
2 Thuật toán Midpoint 16
2.1 Thuật toán Midpoint vẽ đường thẳng 16
2.2 Thuật toán Midpoint vẽ đường tròn 19
2.3 Thuật toán midpoint vẽ hình elip 23
3 Thuật toán tô màu loang 28
3.1 Khái niệm 28
3.2 Giải thuật 29
4 Thuật toán tô màu quét 32
4.1 Khái niệm 32
4.2 Thuật giải 32
Chương 2: Phát triển ứng dụng 33
1 Phân tích bài toán 33
1.1 Yêu cầu bài toán 33
1.2 Các bước thực hiện 33
2 Giải quyết bài toán 33
2.1 Khởi tạo môi trường 3D và thiết lập hiệu ứng 33
2.2 Vẽ các đối tượng đồ họa 34
3 Kết quả thực nghiệm 48
Trang 4LỜI NÓI ĐẦU
Đồ họa máy tính là một trong những lĩnh vực hấp dẫn và phát triển rất mau lẹ,
nó làm thay đổi hoàn toàn việc tương tác giữa người và máy Nhờ vào đồ họa máy tính mà một hoạt động các ứng dụng máy tính ra đời, đồ họa giúp cho việc giao tiếp với máy tính trở nên dễ dàng hơn, nó được ứng dụng trong nhiều lĩnh vực như khoa học công nghệ, y học, kiến trúc, giải trí…
Trên cơ sở đó, môn đồ họa máy tính đã được đưa vào giảng dạy ở chuyên
ngành công nghệ thông tin và các lĩnh vực liên quan khác trong các trường đại học.Môn này là tiền đề cung cấp cho sinh viên các lý thuyết cơ sở nhằm kiến tạo và xử
lý thông tin dưới dạng hình ảnh giúp cho việc giao tiếp với máy tính dễ dàng hơn trong các môn ngành khác như: xử lý ảnh, kỹ thuật CAD
Chương II: Phát tiển ứng dụng sử dụng các hàm trong OpenGL để phát triển ứng dụng 3D phản ánh các kỹ thuật trong đồ họa 3D: Tô màu, chiếu sáng, textmaping, phản chiếu, chuyển động
Trang 5Chương 1: Các Thuật Toán Cơ Bản
1.
Thuật toán Bressenham1.1.
Ý tưởng thuật toán Bressenham- Thay thế các phép toán các phép toán trên số thực bằng các phép toán trên số nguyên
- Giảm thời gian của thuật toán hơn so với DDA
- Hạn chế phép toán được thực hiện để giảm tải thời gian
1.2.
Áp dụng thuật toán Bressenham để vẽ đường thẳng2 điểm gần kề nó nhất Nếu điểm nào nằm gần điểm thực hơn thì
sẽ được chọn làm điểm vẽ tiếp theo.
Trang 6Hình 1.1: Mô tả thuật toán Bressenham
Ta có phương trình đường thẳng có dạng:
y = mx +b, m = ∆y / ∆x
Gọi d1 là khoảng cách từ điểm M đến điểm Q
Gọi d2 là khoảng cách từ điểm M đến điểm P
Trang 7Đặt pi = dx(d1 -d2)
Pi = dx[2m(xi +1) + 2b – 2yi -1]
Thay m = dy/dx vào phương trình trên ta được:
Pi = 2dyxi - 2dxyi + c ( với c = 2dy + (2b – 1)dx )Mặt khác dx ≥ 0 với mọi trường hợp
Dấu của pi cùng dấu với (d1-d2)
pi > 0 => yi+1 = yi +1
pi ≤ 0 => yi+1 = yi
ta có Pi+1 = 2dyxi+1 – 2dxyi+1 + c
Pi = 2dyxi - 2dxyi + c
Pi+1 - Pi = 2dy(xi+1 - xi) – 2dx(yi+1- yi)
= 2dy – 2dx(yi+1 – yi ) với (xi+1 – xi) = 1
Pi+1 = Pi + 2dy – 2dx(yi+1 – yi )
Nếu Pi < 0 => yi+1 = yi => Pi+1 = Pi + 2dy
Ngược lại Pi < 0 => yi+1 = yi +1 => Pi+1 = Pi + 2(dy – dx)
Ta có P1 = 2x1dy – 2y1dx + c
= 2x1dy -2((dy/dx)x1 + b)dx + 2dy + (2b -1)dx = 2dy -dx
Lưu đồ thuật toán:
Trang 8Hình 1.2: Lưu đồ thuật toán Bressenham vẽ đường thẳng
Code minh họa:
void BrePoint(int x1, int y1, int x2, int y2)
Trang 9if (p < 0){
p = p + c1;
}else{
p = p + c2;
y++;
}x++;
Trang 10Hình 1.3: Hình tròn với các điểm đối xứng
Ta có xi+1 = xi +1 và yi+1 = yi hay yi+1 = yi -1
Phương trình đường tròn tâm (xc,yc) bán kính R : (x-xc)2 + (y-yc)2 = R2
Đặt d1 = yi 2 – y2 và d2 = y2 – (yi -1)2
Đặt pi = d1-d2 do đó việc chọn tọa độ của yi+1 phụ thuộc và dấu của pi:
Hình 1.4: Xác định và vẽ các tọa độ
Trang 11d1 = yi 2 – y2 = yi 2 – (R2 – (xi +1)2)
d2 = y2 – (yi -1)2 = (R2 – (xi +1)2) - (yi -1)2
Xét pi = d1-d2 = (yi)2+(yi-1)2-2(R2 – (xi+1)2)
Tính pi+1 - pi = 4xi + 6 + 2((yi-1)2 – (yi)2) – 2(yi+1 – yi))
pi+1 = pi + 4xi + 6 + 2((yi-1)2 – (yi)2) – 2(yi+1 – yi))
Xác định dấu của pi thì ta sẽ xác định được yi+1
Nếu pi < 0 thì yi+1 = yi khi đó pi+1 = pi + 4xi + 6
Nếu pi >= 0 thì yi+1 = yi-1 nên pi+1 = pi + 4(xi – yi) + 10
Gía tri p đầu tiên được tính tại điểm (x1,y1) = (0,R) là p1 = 3-2R
Trang 12Hình 1.5: Lưu đồ thuật toán Bressenham vẽ hình tròn
Trang 13Code minh họa :
void BresCircle(int xc ,int yc, int r)
p1 += 4 * x + 6;
}else{
p1 += 4 * (x - y) + 10;
y ;
}x++;
Trang 141.4.
Áp dụng thuật toán Bressenham để vẽ hình elip1.4.1 Thuật giải:
Tính khoảng cách từ điểm thực đến 2 điểm vẽ được, xem
khoảng cách nào ngắn hơn
Vẽ 1 nửa elip, sau đó lấy đối xứng qua các đường phân giác.Phương trình đường elip có dang:
hệ số góc của tiếp tuyến với Elip bằng -1.Chúng ta dễ dàng thấy đượcnhánh vẽ từ trên xuống : khi x tăng lên 1 đơn vị thì y chỉ tăng lên rất ít
; và ngược lại với nhánh vẽ từ dưới lên: khi y tăng lên 1 đơn vị thì x chỉ tăng lên rất ít Nếu như chúng ta chọn cách vẽ liền một mạch thì việc tăng lên không đồng đều của tọa độ x và y sẽ khiến đường elip không mịn, đứt gãy, rất xấu Do đó, muốn vẽ được đường elip mịn nét, chúng ta sẽ phải chia elip thành 2 nhánh để vẽ.
Hình 1.6: Vẽ elip theo 2 hướng
Trang 15Giả sử giao điểm (xi,yi) đã được vẽ điểm tiếp theo cần được vẽ
từ (*) => pi+1 = pi + 2.(a2/b2).(2y+3) – 4xi
với điểm đầu tiên (a,0) ta có:
pi = 2(a2 / b2) – 2a + 1code minh họa:
void BreElip(int xc, int yc, int a, int b)// ve elipse
Trang 16//ve nhanh thu 1(tu tren xuong )
while (((float)b2 / a2) * x <= y)
p = p + 2 * ((float)b2 / a2) * (2 * x + 3);
}else {
p = p - 4 * y + 2 * ((float)b2 / a2) * (2 * x + 3);y ;
}x++;
Trang 17p = p + 2 * ((float)a2 / b2) * (2 * y + 3);
}else{
return;
}
2.
Thuật toán Midpoint2.1.
Thuật toán Midpoint vẽ đường thẳngThuật giải:
Cho 2 điểm A(x1,y1) và B(x2,y2) Vẽ đường thẳng đi qua 2 điểm A,B
Hình 1.7 : Vẽ đường thẳng bằng thuật toán midpoint
Trang 18Thuật toán Midpoint đưa ra cách chọn điểm yi+1 là yi hay yi+1 bằng cách so sánh điểm thực Q(xi+1 , y) với điểm Midpoint là trung điểm của S và P.
Nếu điểm Q nằm dưới điểm Midpoint thì ta chọn điểm S là điểm vẽ tiếp theo Ngược lại , nếu điểm Q nằm trên điểm Midpoint thì ta chọn P
Ta có dạng tổng quát của PT đường thẳng :
Vị trí tương đối của điểm Midpoint (x,y) với đường thẳng:
F(x,y) < 0 nếu (x,y) nằm phía trên đường thẳng
F(x,y) = 0 nếu (x,y) thuộc về đường thẳng
F(x,y) > 0 nếu (x,y) nằm phía dưới đường thẳng
Lúc này việc chọn các điểm S, P ở trên được đưa về việc xét dấu của
pi = 2F(Midpoint) = 2F(xi +1 , yi +1/2)
Nếu pi < 0 ⇒ Midpoint nằm phía trên đường thẳng ⇒Lúc này điểm thực Q nằm phía dưới điểm Midpoint ⇒ Chọn S(xi+1,yi)
Nếu pi >= 0 ⇒ Midpoint nằm phía dưới đường thẳng ⇒ Lúc này điểm thực
Q nằm trên điểm Midpoint ⇒ Chọn P(xi+1,yi+1)
Mặt khác:
pi+1 –pi = 2F(xi+1 +1 , yi+1 +1/2) – 2F(xi +1 , yi +1/2)
⇒ pi+1 –pi =2[A(xi+1 +1) + B(yi+1 +1/2) +C] – 2[A(xi +1) + B(yi+1/2) +C]
⇒ pi+1 –pi = 2A + 2B(yi+1 – yi)
⇒ pi+1 –pi = 2Dy – 2Dx(yi+1 – yi)
Vậy
Trang 19pi+1 =pi + 2Dy nếu pi <0 do ta chọn yi+1 =yi
pi+1 =pi + 2Dy – 2Dx nếu pi >=0 do ta chọn yi+1 =yi +1
Ta tính giá trị p1 ứng với điểm ban đầu (x1, y1) với nhận xét rằng điểm (x1, y1) là điểm thuộc đường thẳng, tức là có Ax1 + By1 + C =0
Trang 20Code minh họa :
void Midpoint(int x1, int y1, int x2, int y2) {
//Truong hop 0<m<1 && x1<x2 && y1<y2
glVertex2i(x, y); //Ve diem pixel dau tien
p = 2 * a + b; //tinh vi tri tuong doi cua diem Midpoint so voi duong thang
Trang 21Với mọi điểm P(x, y) nằm trong hệ tọa độ Oxy, ta có:
P(x, y) nằm trên đường tròn O nếu f(x, y) = 0
P(x, y) nằm ngoài đường tròn O nếu f(x, y) > 0
P(x, y) nằm trong đường tròn O nếu f(x, y)< 0
Do đường tròn có tính đối xứng qua các cũng 1/8, nghĩa là ứng với một điểm có tọa độ (x, y) thuộc 1 cung nào đó, ta có thể hoàn toàn xácđịnh được tọa độ 7 điểm còn lại bằng cách lấy đối xứng qua các cung
Từ tính chất đó nên chúng ta chỉnh cần vẽ 1/8 đường tròn là đủ, sau
đó sẽ lấy đối xứng để được đường tròn hoàn chỉnh
Điểm đầu tiên ta vẽ là điểm (x = 0, y = R)
Trong cung 1/8 thứ nhất do khoảng biến thiên của x lớn hơn khoảng biến thiên của y, nên xi+1 = xi + 1
Giả sử ta đã vẽ được (Xi, Yi) ở bước thứ i, ta cần xác định (Xi+1, Yi+1)
ở bước thứ i + 1
Như vậy ta có:
xi+1 = xi + 1
yi+1 ∈ {yi,yi-1}
Trang 22Hình 1.9: Cách lựa chọn điểm trong midpoint
Đặt fi = f(x,y-1/2) ta hình thành công thức:
f(xi+1,yi-1/2) = (xi + 1)2 + (yi-1/2)2 – R2
fì = xi2 + 2xi + yi2 – yi + 5/4 – R2
Nếu fi <0 ( xi+1,yi) gần với yi => yi+1 = yi
Nếu fi ≥ 0 ( xi+1,yi) gần với yi -1 => yi+1 = yi -1
Tính fi+1 theo fi
fi + 1 - fi = 2xi + 3 + (yi+12 - yi2) + (yi+1 - yi) (*)
Nếu fi < 0 thì fi + 1 = fi + 2xi + 3, do ta thay thế yi+1 = yi vào (*)
Nếu fi ≥ 0 thì fi + 1 = fi + 2(xi - yi) + 5, do thay thế yi+1 = yi -1 vào (*)
Tìm điểm f với giá trị đầu tiên:
f(xi+1,yi-1/2) = (xi + 1)2 + (yi-1/2)2 – R2
fì = xi2 + 2xi + yi2 – yi + 5/4 – R2
Trang 23thay điểm xi = 0 và yi =R vào ta được f = 5/4 -R
Lưu đồ thuật toán:
Hình 1.10: Lưu đồ thuật toán Midpoint vẽ đường trònCode minh họa:
void DrawCircle(int xc, int yc, int r)
{
glColor3b(1, 0, 0);
Trang 24f += 2 * x + 3;
}else{
f += 2 * (x - y) + 5;
y ;
}x++;
Trang 25Hình 1.11: các lựa chọn điểm trong thuật toán midpoint
Phương trình của đường Elip:
f(x,y) = b2x2 + a2y2 – a2b2
f(x,y) < 0 nếu (x,y) nằm bên trong elip
f(x,y) = 0 nếu (x,y) nằm trên elip
f(x,y) > 0 nếu (x,y) nằm bên ngoài elip
Chia Elip làm 2 phần tại điểm Q nơi có hệ số góc của tiếp tuyến với Elip bằng -1 (véc tơ gradient bằng 1) ( lý do tại sao lại phải chia làm 2 phần thì bài 6 mình đã giải thích rồi nhé) Tại vùng thứ nhất, x biến thiên nhanh hơn
y và tại vùng thứ hai , y biến thiên nhanh hơn x Nhớ lại công thức hệ số góccủa đường cong :
dx/dy = fx/fy = (2b2x) /( 2a2y)trong đó: fx và fy là đạo hàm riêng phần của f(x,y) theo x, theo y
Trong phần thứ nhất:
Giả sử đã vẽ được điểm (xi,yi) , điểm tiếp theo trên elip được chọn trong bước nhảyi+1 là T hoặc S Trung điểm I của TS sẽ quyết định điểm nào được chọn Giá trị của f(x,y) tại điểm I:
di = f(xi + 1, yi – ½) = b2(xi + 1)2 + a2(yi – ½)2 – a2b2
Trang 26+Nếu di ≥ 0 thì trung điểm I nằm ngoài đường elip => điểm được chọn là S.
+Nếu di < 0 thì trung điểm I nằm trong đường elip => điểm được chọn là T
Ta có:
di+1 = di + 2b2xi+1 + b2 – 2a2yi+1 (= di + fx + b2 – fy)
= di + 2b2 (xi + 1) + b2 – 2a2 (yi – 1)
= di + b2 (2xi + 3) + a2 (-2yi + 2)Với điểm đầu tiên (0,b) ta có:
d1 = f(0,b) = b2 + a2(b – ½)2 – a2b2 = b2 ─ a2b + a2/4
Trong phần thứ hai:
Chúng ta tính toán như phần 1 Giả sử ta phải xác định điểm (xj+1, yj+1) tiếp theo trên elip trong bước j+1 Điểm được chọn là U hoặc V Trung điểm K của UV sẽ quyết định việc chọn điểm U hay điểm V Giá trị của f(x,y) tại điểm K:
ej = f(xj + ½, yj – 1) = b2(xj + ½)2 + a2(yj – 1)2 – a2b2
+ Nếu ej ≥ 0 điểm được chọn là U
+ Nếu ej < 0 điểm được chọn là V
Trang 27Ta có:
ej+1 = ej + 2b2xj+1 – 2a2yj+1 + a2 (= ej + fx – fy + a2)
= ej + 2b2(xj + 1)– 2a2(yj -1) + a2
= ej + b2(2xj + 2)+ a2(3 -2yj )Giá trị khởi tạo ban đầu trong phần 2 phụ thuộc vào vị trí cuối cùng của phần 1 , giả sử là (xk,yk) Khi đó:
e1 = f(xk + ½, yk – 1) = b2(xk + ½) + a2(yk – 1)2 – a2b2
Lưu đồ thuật toán :
Trang 28Hình 1.12: lưu đồ thuật toán midpoint
Code minh họa:
void DrawElip(int xc, int yc, int a, int b)
Trang 29fx += 2 * b2;
if (p < 0){
p += b2 * (2 * x + 3);//p=p + b2*(2x +3)}
else{
y ;
p += b2 * (2 * x + 3) + a2 * (2 - 2 * y);//p=p +b2(2x +3) 2y)
+a2(2-fy -= 2 * a2;
}glVertex2i(xc + x, yc + y);
p += a2 * (3 - 2 * y); //p=p +a2(3-2y)}
else{
x++;
fx += 2 * b2;
p += b2 * (2 * x + 2) + a2 * (3 - 2 * y);//p=p+ b2(2x +2) + a2(3-2y)
}glVertex2i(xc + x, yc + y);
Trang 30tô màu nó Lặp lại cho tới khi nào không còn tô được điểm nào nữa thìdừng.
3.2.
Giải thuậtThuật toán đệ quy:
-Bước 1: Kẻ vùng biên cần tô
-Bước 2: Xác định một điểm (x,y) bên trong vùng cần tô
-Bước 3: Tô điểm (x,y) sau đó tô loang những điểm lân cận
Trang 31+Việc gọi đệ quy, thuật toán cho 4 điểm lân cận của điểm hiện hành không quan tâm tới một trong bốn điểm đó đã được xét ở bước trước hay chưa (tức là sẽ có những điểm bị xét đi xét lại nhiều lần) Điều này khiến tốc độ chậm, không hiệu quả.
Áp dụng hàng đợi Queue, BFS
-Bước 1: Cất điểm hạt giống đầu tiên vào kho
-Bước 2: Lặp nếu kho không rỗng
+Lấy điểm hạt giống
+Tô điểm hạt giống, sau đó tô loang sang 2 bên
+Bổ sung những điểm hạt giống mới vào kho từ dòng trên và dòng dưới
Tiêu chuẩn để làm điểm hạt giống: điểm này chưa được tô màu và không phải điểm biên
Code minh họa:
Trang 32color = getPixelColor(x, y);
if (color.r == oldColor.r && color.g == oldColor.g && color.b
== oldColor.b)
{
setPixelColor(x, y, newColor);
floodFill(x + 1, y, oldColor, newColor);
floodFill(x, y + 1, oldColor, newColor);
floodFill(x - 1, y, oldColor, newColor);
floodFill(x, y - 1, oldColor, newColor);
Trang 33Color newColor = { 1.0f, 0.0f, 0.0f };
Color oldColor = { 1.0f, 1.0f, 1.0f };
floodFill(320, 240, oldColor, newColor);
}
void draw_circle(Point pC, GLfloat radius) {
GLfloat step = 20 / radius;
Trang 344.2.
Thuật giảiHình 1.13: Sơ đồ thuật toán tô màu quét
Tìm ymin, ymax lần lượt là giá trị nhỏ nhất, lớn nhất của tập các tung độ của các đỉnh của đa giác đã cho
-Ứng với mỗi dòng quét y=k, k thay đổi từ ymin đến ymax, lặp :
Tìm tất cả các hoành độ giao điểm của dòng quét y=k với các cạnh của đa giác
Sắp xếp các hoành độ giao điểm theo thứ tự tăng dần : x0, x1, …
Tô màu các đoạn thẳng y=k trên đường thẳng lần lượt được giới hạn bởi các cặp ( x0, x1), ( x2, x3), ….(x2k, x2k+1)
Trang 35Chương 2: Phát triển ứng dụng
1.
Phân tích bài toán1.1
Yêu cầu bài toán-Mô phỏng chương trình dưới dạng 3D
-Sử dụng các hàm trong OpenGL để phát triển ứng dụng 3D phản ánh
các kỹ thuật trong đồ họa 3D: Tô màu, chiếu sáng, textmaping, phản
-Cho các vật thể chuyển động, thay đổi hướng, vị trí theo thời gian
2
Giải quyết bài toán2.1 Khởi tạo môi trường 3D và thiết lập hiệu ứng
Trang 362.2.
Vẽ các đối tượng đồ họa Dùng hàm glutDisplayFunc() để gọi đến hàm vẽ các đối tượng:
Trang 37unsigned char r, g, b, a;
};
std::vector< Point > points;
GLUquadricObj* obj = gluNewQuadric();
Vòng lặp for để lấy giá trị cho Point:
for (size_t i = 0; i < 150; ++i)
Trang 43glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point),
glVertexPointer(3, GL_FLOAT, sizeof(Point), &points[0].x);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Point),
Trang 47glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, maycolor); glTranslatef(-35, 30, movemay+100);
Trang 51Hình 2.2 Tàu vũ trụ khi ở ngoài không gian