Một vật thể 3D có thể biểu diễn trong máy tính bằng nhiều mô hình khác nhau, song hai mô hình phổ biến nhất đó là mô hình khung dây (WireFrame) và mô hình các mặt đa giác ( Polygon mesh model) • Mô hình WireFrame: Đã trình bày ở chương 5, nó cho ta hình dáng của vật thể dưới dạng một bộ khung • Mô hình các mặt đa giác: ở đây một vật thể 3D được xác định thông qua các mặt (thay vì các cạnh như trong mô hình WireFrame),...
CHƯƠNG VII KHỬ ĐƯỜNG VÀ MẶT KHUẤT 7.1 CÁC KHÁI NIỆM Một vật thể 3D biểu diễn máy tính nhiều mơ hình khác nhau, song hai mơ hình phổ biến mơ hình khung dây (WireFrame) mơ hình mặt đa giác ( Polygon mesh model) • Mơ hình WireFrame: Đã trình bày chương 5, cho ta hình dáng vật thể dạng khung • Mơ hình mặt đa giác: vật thể 3D xác định thơng qua mặt (thay cạnh mơ hình WireFrame), mặt lại xác định thông qua điểm mà điểm xem đỉnh mặt đa giác, với mơ hình mặt đa giác khơng tạo hình dáng vật thể mơ hình Wireframe mà cịn thể đặc tính màu sắc nhiều tính chất khác vật thể Song để mơ tả vật thể 3D cách trung thực (như giới Mặt thực) địi hỏi người lập trình phải tính tốn giả lập nhiều thơng tin, mà mấu chốt Mặt vấn đề khử mặt khuất chiếu sáng.Trong Mặt chương tập trung Mặt nghiên cứu vấn đề khử mặt khuất Ví dụ: Mơ tả vật thể Mặt hình 7.1 - Danh sách đỉnh: 1,2,3,4,5,6 Hình 7.1 - Danh sách mặt xác định theo bảng sau: Mặt Đỉnh Chương VII Khử đường mặt khuất 1,2,3 4,5,6 1,3,6,4 3,2,5,6 1,2,5,4 Chúng ta đưa nhiều cấu trúc liệu khác để lưu trữ cho đa giác Dưới phát thảo kiểu cấu trúc: Type Point3D = Record {Điểm chiều} x,y,z:real; end; Vector3D = Record {Vector chiều Mặc dù giống với x,y,z:real; Point3D song ta khai để thuật toán tường minh} end; RGBColor = Record {Cấu trúc màu sắc mặt} B,G,R:Byte; end; KieuMat = Record PhapVT:Vector3D; {Pháp vector mặt} Sodinh:cardinal; {Số đỉnh mặt} List:array of integer;{Danh sách thứ tự đỉnh tạo nên mặt Ở ta dùng mảng động} {màu sắc mặt} Color:RGBColor; end; Obj3D = record {Đối tượng chiều} ObjName:string; {Tên đối tượng} Sodinh:cardinal; {Số đỉnh} Dinh: array of point3d; {Danh sách đỉnh Ở ta dùng kiểu mảng động} SoMat:cardinal; {Số mặt} Mat:array of KieuMat; {Danh sách mặt} 84 Chương VII Khử đường mặt khuất Xworld,Yworld,Zworld,Zoom:Real; {Toạ độ kích thước thật vật hệ toạ độ giới} end; Khi cài đặt cho ứng dụng cụ việc sử dụng mảng cố định gây trở ngại kích thước tối đa hay tối thiểu, việc sử dụng nhớ khơng tối ưu Vì ngồi cách dùng mảng cố định, ta dùng mảng động số ngôn ngữ Visual Basic, Delphi hay Visual C++,… dùng cấu trúc danh sách móc nối Song song với điều việc bớt hay đưa thêm thuộc tính cần thiết để biểu diễn đặc tính khác mặt hay đối tượng * Vấn đề khử mặt khuất Khi thể vật thể 3D, vấn đề nảy sinh thể mặt nhìn thấy mà khơng thể mặt khuất phía sau Việc mặt bị khuất hay khơng bị khuất tuỳ thuộc vào cấu trúc mặt vật thể vị trí điểm nhìn bối cảnh mà vật thể đặt vào 7.2 CÁC PHƯƠNG PHÁP KHỬ MẶT KHUẤT 7.2.1 Giải thuật người thợ sơn xếp theo chiều sâu (Depth-Sorting) Người thợ sơn (hay Depth-sorting) tên thuật giải đơn giản số thuật toán vẽ ảnh thực chiều Nếu để ý người thợ sơn làm việc, thấy sơn tranh từ ngoài, với cảnh vật từ xa đến gần Chúng ta áp dụng cách tương tự để vẽ đa giác danh sách đa giác Song có vấn đề cần phải chọn lựa, đa giác tồn khơng gian 3D có tới ba bốn đỉnh, đỉnh có giá trị z ( giá trị độ sâu ) khác Chúng ta chọn giá trị số chúng Từ kinh nghiệm thực tế, người ta cho nên sử dụng giá trị z trung bình cho kết tốt hầu hết trường hợp Như vậy, cần phải xếp mặt theo thứ tự từ xa đến gần, sau vẽ mặt từ xa trước, vẽ mặt gần sau, mặt gần không bị che khuất mặt xa, mà có mặt xa bị mặt gần che khuất, mặt gần vẽ sau nên vẽ chồng lên hình ảnh mặt xa 85 Chương VII Khử đường mặt khuất Như vậy, thuật giải Depth-Sorting thực cách dễ dàng xác định giá trị độ sâu (là giá trị z hệ toạ độ quan sát) đại diện cho mặt Các mặt dựa vào độ sâu đại diện để so sánh xếp theo danh sách giảm dần (theo độ sâu đại diện) Bước vẽ mặt lên mặt phẳng theo thứ tự danh sách Giải thuật số vướng mắc sau (hình 7.2): Khi hai mặt cắt thuật giải thể chúng chồng lên Hình ảnh thật Khi vẽ giải thuật Hình 7.2 Khi hai mặt khoảng khơng gian độ sâu hình chiếu chúng lên mặt phẳng chiếu chồng lên (hay chồng phần lên nhau) Chẳng hạn như: Maët A Maët B Mắt nhìn Hình 7.3 Từ ví dụ thấy rằng, có trường hợp đa giác xếp sai dẫn đến kết hiển thị khơng Liệu khắc phục vấn đề không? Câu trả lời dĩ nhiên có đồng nghĩa phải xử lý thêm nhiều trường hợp làm tăng độ phức tạp tính tốn • Phép kiểm tra phần kéo dài Z 86 Chương VII Khử đường mặt khuất Phép kiểm tra nhằm xác định phần kéo dài z hai đa giác có gối lên hay không? Nếu phần kéo dài Z gối lên đa giác cần hốn đổi Vì phép kiểm tra phải thực • Phép kiểm tra phần kéo dài X Phép kiểm tra tương tự phép kiểm tra trước, kiểm tra phần kéo dài X hai đa giác có gối lên hay khơng? Nếu có, đa giác cần hốn đổi Vì phép kiểm tra phải thực • Phép kiểm tra phần kéo dài Y Phép kiểm tra kiểm tra phần kéo dài Y hai đa giác có gối lên hay khơng? Nếu có, đa giác cần hốn đổi Vì phép kiểm tra phải thực • Phép kiểm tra cạnh xa Giả sử A B hai đa giác mà sau xếp theo độ sâu trung bình A đứng trước B Song qua phép kiểm tra mà không xác định liệu trật tự hay chưa Lúc chúng phải tiến hành phép kiểm tra cạnh xa Phép kiểm tra cạnh xa nhằm xác định xem đa giác B có nằm phía sau cạnh xa đa giác A hay không? Nếu có trật tự đúng, ngược lại phải qua bước kiểm tra Để kiểm tra đa giác B có nằm sau cạnh xa đa giác A hay không, thực việc kiểm tra đỉnh đa giác B Các đỉnh nằm phía đa giác A theo chiều trục Z khơng? Nếu kết trật tự Ngược lại, xảy hai tình hình (7.2) hình (7.3), để xác định ta phải tiếp tục sang bước kiểm tra • Phép kiểm tra cạnh gần Phép kiểm tra cạnh gần nhằm xác định xem đa giác A có nằm phía sau cạnh gần đa giác B hay khơng? Nếu có trật tự xác định trước không 87 Chương VII Khử đường mặt khuất đúng, cần phải hoán đổi lại trật tự Ngược lại rõ ràng hai đa giác cắt (như hình 7.2) chéo vào (hình 7.4), lúc phải tiến hành chia nhỏ hai đa giác A B thành (hoặc 4) đa giác con, đường chia cắt đường giao cắt đa giác Sau phép chia tiến hành xếp lại đa giác Hình 7.4 7.2.2 Giải thuật BackFace Sẽ đơn giản ta dùng Vector pháp tuyến để khử mặt khuất đối tượng 3D đặc lồi Ta tính góc véc tơ hướng nhìn V pháp vector N mặt, góc lớn 90o mặt khơng nhìn thấy (bị khuất), ngược lại mặt khả kiến Dấu tích vơ hướng vector dương góc chúng nhỏ hay 90o Vậy thuật tốn để xét mặt bị khuất hay khơng đơn giản là: If V.N >= then Mặt thấy Else Mặt khơng thấy (mặt khuất); Mắt nhìn θ Vector hướng nhìn Vì θ= then {Mặt khả kiến} begin setlength(Poly,Obj.Mat[K].Sodinh); {Thiết lập độ dài mảng Poly số đỉnh đa giác} For i:=0 to Obj.Mat[K].Sodinh -1 {Đưa toạ độ đỉnh đa giác vào Poly} begin P:=Obj.Mat[K].list[i]; Poly[i].X:=round(Obj.dinh[P].x*zoom)+cx; Poly[i].Y:=-round(Obj.dinh[P].y*zoom)+cy; end; {Thiết lập màu cho bút tô trước tô} canvas.Brush.Color:=rgb(Obj.Mat[K].Color.R, Obj.Mat[K].Color.G,Obj.Mat[K].Color.G); Canvas.Polygon(poly); {Tô đa giác với màu thiết lập} end; setlength(poly,0); end; Rõ ràng, thuật toán đơn giản độ phức tạp tính tốn khơng cao Song sử dụng phải đảm bảo đối tượng có đặt tính “đặc lồi”, đối tượng khơng thoả mãn điệu kiện phải áp dụng thoật tốn khác hay có sửa đổi cần thiết để tránh thể sai lạc 7.2.3 Giải thuật vùng đệm độ sâu (Z-Buffer) Bằng cách tính giá trị độ sâu (là giá trị Z hệ toạ độ quan sát) điểm tất mặt đa giác, điểm mặt phẳng chiếu có ảnh nhiều điểm nhiều mặt đa giác khác nhau, song hình vẽ thể hình ảnh điểm có độ sâu thấp ( tức điểm gần nhất) Với cách thực giải thuật khử tất trường hợp mà giải thuật khác mắc phải 90 Chương VII Khử đường mặt khuất Giới hạn phương pháp đòi hỏi nhiều nhớ thực nhiều tính tốn Z-Buffer đệm dùng để lưu độ sâu cho pixel hình ảnh vật thể, thơng thường ta tổ chức ma trận hình chữ nhật Nếu dùng byte để biểu diễn độ sâu pixel, vật thể có hình ảnh mặt phẳng chiếu 100x100 cần 10000 byte dùng để làm Depth Buffer, vùng đệm độ sâu cho phép ta phân biệt 256 mức sâu khác nhau, điều có nghĩa có 257 pixel 257 độ sâu khác buột ta phải quy pixel độ sâu Nếu ta dùng byte để biểu diễn độ sâu pixel, vùng đệm độ sâu cho phép ta phân biệt 4294967296 (232) mức sâu khác nhau, song lúc phải cần 40000 byte cho đệm kích thước 100x100 Do tính chất mặt nên tuỳ vào tình yêu cầu mà ta tăng hay giảm số byte để lưu giữ độ sâu pixel Và thông thường người ta dùng byte để lưu giữ độ sâu điểm, độ xác cao Một câu hỏi đặt tính độ sâu điểm đa giác Ở có phương pháp: phương pháp trực tiếp phương pháp gián tiếp • Phương pháp trực tiếp tính độ sâu điểm dựa vào phương trình mặt phẳng chứa đa giác Với phương pháp cần duyệt qua tất điểm đa giác (tất nhiên hữu hạn điểm), cách cho thành phần x y, cặp giá trị (x,y) thoả miền giới hạn đa giác tìm thành phần thứ z cách thay x y vào phương trình mặt phẳng để tính thành phần z Về mặt tốn học phương pháp trực tiếp rõ ràng khoa học, song áp dụng ta gặp phải vướng mắc: Cần phải tính điểm để hình ảnh thể đa giác lên mặt phẳng chiếu đủ mịn khơng bị tình trạng q mịn (tức vẽ nhiều điểm chồng chất lên khơng cần thiết mà lại gây tình trạng chậm chạp tăng độ phức tạp tính tốn Cũng nên nhớ thể đa giác lên mặt phẳng chiếu ảnh phóng to hay thu nhỏ) • Phương pháp gián tiếp: Chúng ta tính độ sâu điểm gián tiếp thông qua độ sâu điểm lân cận Để thực tiến hành theo bước sau: 91 Chương VII Khử đường mặt khuất Gọi G mặt đa giác biểu diễn tập điểm P1, P2, … Pn G’ hình chiếu G xuống mặt phẳng chiếu với tập đỉnh P1’,P2’,… Pn’ Để thể hình ảnh G lên mặt phẳng chiếu rõ ràng phải tiến hành tô đa giác G’ Song thuật toán phát biểu, cần xác định xem điểm M’ thuộc G’ ảnh điểm M G dựa vào độ sâu M để so sánh với độ sâu có zbuffer để định có vẽ điểm M’ hay không Nếu ta gán thêm cho điểm ảnh thành phần nữa, giá trị độ sâu điểm tạo ảnh (tức điểm tạo điểm ảnh sau phép chiếu) lúc ta khơng cần thiết phải xác định M để tính độ sâu, mà ta tính giá trị độ sâu qua công thức sau: Nếu M’ nằm đoạn thẳng P’Q’ với tỷ lệ là: P’M’/P’Q’=t biết độ sâu P’ Q’ z(P’) z(Q’) độ sâu mà điểm ảnh M’ nhận z(M’)=z(P’)+(z(Q’)-z(P’))t (2.3.1) Ta sử dụng công thức với tất phép chiếu có bảo tồn đường thẳng Từ ta xác định quy trình vẽ đa giác G’ ảnh G sau: + Gán thêm cho điểm đỉnh đa giác G’ thành phần z có giá trị độ sâu điểm tạo ảnh Có nghĩa P’1 chứa thêm giá trị z(P1), P’2 chứa thêm giá trị z(P2), hay cách tổng quát P’i chứa thêm giá trị z(Pi) với i=1 n Tiến hành tô đa giác G’ theo quy trình tương tự thuật tốn tơ đa giác theo dịng qt Có nghĩa cho dịng qt chạy ngang qua đa giác, vị trí dịng qt, tiến hành tìm tập giao điểm dòng quét với đa giác Gọi {xm} tập giao điểm, điều cần ý ta cần tính độ sâu cho giao điểm Giả sử xi giao điểm đường qt với cạnh Pi’Pj’ ta tính độ sâu xi thông qua công thức (2.3.1) sau: 92 Chương VII Khử đường mặt khuất Nếu gọi yscan giá trị tung độ dòng quét thì: z(xi) = z(Pi’)+z(Pj’)*[(yscan – y(Pi’))/(y(Pj’)-y(Pi’))] (2.3.2) {trong y(P) thành phần toạ độ y điểm P} Rõ ràng qua công thức ta thấy, xi trung điểm Pi’Pj’ z(xi) = z(Pi’)+z(Pj’)*1/2 Cài đặt minh hoạ cho giải thuật “vùng đệm độ sâu” Từ phân tính tiến hành khai báo cấu trúc liệu cần thiết cài đặt cho thuật tốn • Khai báo cấu trúc liệu cần thiết: Sau khai báo cần thiết phép lưu trữ đối tượng 3D theo mơ hình mặt đa giác, khai báo cần thiết để tiến hành khử mặt khuất theo thuật tốn z-Buffer theo ngơn ngữ Pascal mơi trường trình biên dịch Delphi {Bắt đầu phần khai báo phục vụ cho giải thuật Z-buffer} Type Z_BufferType=Array of Array of cardinal; {Kiểu đệm Z, mảng động chiều mà phần tử có kiểu cardinal, điều có nghĩa vùng đệm độ sâu cho phép ta phân biệt 4294967296 (232) mức sâu khác nhau} NutPoly_Z=record {Cấu trúc đỉnh đa giác chiếu G’ } x,y:Integer; {Toạ độ ảnh mặt phẳng chiếu} z:real; {Thành phần độ sâu kèm (là độ sâu tạo ảnh)} end; Polygon_Z =array of NutPoly_Z; {Đa giác chiếu mảng động Như đa giác chiều, song đỉnh có chứa thêm thành phần độ sâu đỉnh} CanhCat_Z=record {Cấu trúc cạnh đa giác xây dựng nhằm phục vụ cho q trình tính giao điểm} y1,y2:Integer; {Tung độ bắt đầu kết thúc cạnh (y1