Không gian vector và sự tịnh tiến các vật thể trong không gian

Một phần của tài liệu Nghiên cứu tìm hiểu va chạm chung giữa các đối tượng trong thực tế được mô phỏng vào máy tính (Trang 27 - 41)

Thuật toán sử dụng phương pháp Elipsoid sau đây thiên về việc sử dụng không gian vector không phải thuộc dạng chuẩn để làm đơn giản hoá việc tính toán. Chúng ta sẽ đi tìm hiểu sơ qua cách chuyển từ một không gian vector này sang không gian vector khác.

Phần lớn chúng ta chưa từng bắt gặp bấ kì không gian vector nào khác 2 loại không gian mà chúng ta đã học ở trường và sử dụng rất nhiều đó là không gian 2 và 3 chiều hay R2

và R3. Những không gian này được dùng trong hệ toạ độ chuẩn. Chúng ta cũng dễ dàng định nghĩa các không gian có số chiều lớn hơn (4 , 5 hoặc vô hạn) bằng cách đưa ra các luật mà tất cả các vector trong không gian đó phải tuân theo. Tất nhiên R2 và R3 cũng phải tuân theo.

Tất nhiên chúng ta cũng khó có thể tưởng tượng loại không gian có số chiếu lớn hơn 3 và rõ ràng đây là một thách thức rất lớn khi chúng ta phải làm việc với các loại không gian vector như vậy. Tuy nhiên trong phần này chúng ta cũng chỉ sử dụng không gian 3 chiều mà thôi.

Sau đây sẽ đưa ra các luật mà một không gian vector đều phải theo:

 Thỏa mãn luật cộng và nhân. Có nghĩa là cho 2 vector X, Y thuộc không gian vector đang xét thì Z = X + Y cũng thuộc không gian đó. Cho một số thực r, nếu X nằm trong không gian thì r*X cũng thuộc không gian đó.

 Tồn tại vector không V0 sao cho với mọi vector X trong không gian đó thì V0+X=X. Với mọi vector X thì X*0 = V0.

Khái niệm về tổ hợp tuyến tính của các vector trong một không gian vector: đó là một vector nhận được khi ta tổ hợp các vector trong không gian vector bởi các phép cộng và phép nhân với một số vô hướng. Ví dụ, nếu bạn có các Vector X, Y ,Z và phép tổ hợp được thực hiện như sau:

V = 2*X + (-3)*Y + 4*Z

Rõ ràng theo luật 1 ở trên ta thấy rằng vector V nằm trong cùng không gian với các vector X, Y, Z.

Tiếp theo ta đi định nghĩa một cơ sở cho một không gian vector. Cơ sở cho một không gian Vector là các Vector nằm trong không gian đó và được theo các luật sau đây:

 Tất cả các Vector trong không gian vector là tổ hợp tuyến tính của các vector cơ sở.  Mỗi vector cơ sở không thể được tạo thành bằng cách tổ hợp các vector còn lại trong

cơ sở đó.

Số lượng các vector cần thiết để tạo nên cơ sở cho không gian vector đó bằng với số chiều của không gian đó.

R3 là một không gian Vector và cơ sở của nó là: e1 = (1,0,0)

e2 = (0,1,0) e3 = (0,0,1)

Toạ độ của một điểm trong không gian vector chính là các thành phần vô hướng trong phép nhân với các vector cơ sở trong phép tổ hợp tuyến tính. Ví dụ, ta có điểm v =(5,2,4), ta có thể phân tích thành như sau:

v = 5*e1 + 2*e2 + 4*e3 (OK)

Đi thẳng vào vấn đề chính của chúng ta đó là làm thể nào để tạo ra được một không gian vector (ta sẽ tạo không gian Elipsoid). Chúng ta sẽ bắt đầu đi từ cơ sở của không gian đó (và đó cũng là đủ để định nghĩa không gian vector). Nếu như một ellipsoid được định nghĩa bởi vector các bán kính là (x,y,z) thì chúng ta sẽ chọn cơ sở của không gian đó là:

v1 = (x,0,0) v2 = (0,y,0) v3 = (0,0,y)

Trong không gian ellipsoid này thì bán kính của ellipsoid sẽ là (1,1,1). Vấn đề cuối cùng của chúng ta là làm thế nào để chuyển được một điểm từ không gian R3 vào không gian mới (không gian Ellipsoid). Chúng ta sẽ sử dụng cơ sở ở trên để thực hiện việc này (thông qua phép tổ hợp tuyến tính): 3 2 1 1 1*v 0*v 0*v x e = + + 3 2 1 2 0* 1*v 0*v y v e = + + 3 2 1 3 0* 0* 1*v z v v e = + + Từ đó ta có được ma trận chuyển là :

2.3.2. Phát hiện va chạm

Ý tưởng của thuật toán là mô phỏng đối tượng trong thế giới thực bởi Ellipsoid (hình bao Ellipsoid). Ellipsoid này được định nghĩa bởi tâm và bán kính của nó theo 3 trục tọa độ. Ví dụ như hình sau:

Vị trí của tâm Ellipsoid được ta coi như là vị trí của đối tượng… Ta di chuyển đối tượng bằng cách tác dụng lực lên đối tượng theo một hướng nào

đó. Hướng này được biểu diễn bởi vector vận tốc. Vị trí mới của Ellipsoid sau khi di chuyên được tính bằng cách cộng vị trí hiện tại với vector vận tốc.

Giả sử thế giới ta giả lập được tạo bởi các tam giác (phân chia bề mặt vật thể hay mặt nền bởi các tam giác). Chúng ta

không thể biết được chính xác là Ellipsoid trong lúc di chuyển sẽ va chạm chính xác vào tam giác nào. Chính vì vậy ta sẽ phải kiểm tra tất cả các tam giác đó (ta cũng có thể chia các vật thể thành các đơn vị nhỏ hơn). Kiểm tra tất cả các khả năng va chạm nếu có. Nếu phát hiện có một va chạm xảy ra (với một tam giác nào đó) thì ta không được dừng lại mà phải kiểm tra với các tam giác khác để tìm ra va chạm xảy ra gần nhất.

Hình vẽ sau mô tả hiện tượng xảy ra khi ta tìm thấy một va chạm với tam giác A và không kiểm tra các tam giác còn lại (bao gồm tam giác B – cũng va chạm với Ellipsoid):

Để làm giảm độ phức tạp của vấn đề ta sẽ chuyển tất cả các đối tượng vào trong không gian mới của chúng ta – không gian Ellipsoid. Trong không gian này thì Ellipsoid thực sự là hình cầu đơn vị. Thao ta và tính toán trên hình cầu tất nhiên là dễ dàng hơn rất nhiều (chỉ có bán kính và không bị ảnh hưởng bởi phép quay quanh trục đi qua tâm).

Tiếp theo chúng ta sẽ kiểm tra tất cả các mặt (tam giác). Thủ tục kiểm tra mỗi mặt có thể được chia làm 5 bước nhỏ như sau:

1. Tính mặt phẳng chứa tam giác.

2. Tính điểm giao trên hình cầu khi chúng sẽ va chạm với mặt phẳng. 3. Tính điểm giao trên mặt phẳng khi hình cầu va chạm với mặt phẳng.

4. Tính toán nếu điểm va chạm trên mặt phẳng nằm trong tam giác. Nếu không ta phải tính lại điểm va chạm thực sự.

5. Nếu xảy ra khả năng điểm giao không thực sự và khoảng cách tới điểm giao nhỏ hơn hoặc bằng độ lớn của khoảng cách mà chúng ta muốn di chuyển đối tượng, chúng ta sẽ kiểm tra điểm va chạm gần nhất có thể. Lưu thông tin va chạm.

Khi thuật toán kết thúc, chúng ta sẽ lưu thông tin về điểm va chạm gần nhất (nếu có), những thông tin này là cần thiết để xử lý phản hồi sau va chạm (response).

Khi toàn bộ quá trình phát hiện và xử lý va chạm kết thúc chúng ta sẽ chuyển toàn bộ kết quả vào không gian R3 chuẩn để được kết quả cuối cùng, cập nhật vị trí mới của đối tượng.

Ta sẽ lần lượt thực hiện 5 bước trên:

a. Tính mặt phẳng chứa tam giác.

Ta cần nhớ mặt phẳng là vô hạn còn tam giác là một tập con của mặt phẳng đó (tập đóng). Chúng ta định nghĩa một mặt phẳng bởi một điểm gốc và một vector pháp tuyến

vuông góc với mọi vector nằm trong mặt phẳng đó. Để xác định vector pháp tuyến ta dựa vào 2 vector không song song nằm trong mặt phẳng.

Giả sử ta có mặt phẳng chưa tam giác ABC. Chọn A làm gốc và ta có 2 vector không song song được tính bởi công thức:

v1 = B – A v2 = C – A

Vector pháp tuyến được tính thông qua tích có hướng của 2

vector v1,v2 . H ình 2.3.2a: Tính mặt

phẳng chứa tam giác

inline D3DVECTOR wedge(D3DVECTOR v1, D3DVECTOR v2) { D3DVECTOR result;

// Tính tích có hướng của 2 vector v1 và v2 result.x = (v1.y * v2.z) - (v2.y * v1.z); result.y = (v1.z * v2.x) - (v2.z * v1.x); result.z = (v1.x * v2.y) - (v2.x * v1.y);

return (result); }

D3DVECTOR pOrigin = A;

D3DVECTOR pNormal = wedge(v1,v2);

Chú ý rằng thứ tự của các Vector v1,v2 là rất quan trọng, nó xác định chiều của vector pháp tuyến. Chuẩn hóa vector pháp tuyến (độ dài bằng 1):

inline void normalizeVector(D3DVECTOR& v) { double len = sqrt(v.x*v.x + v.y*v.y + v.z*v.z); v.x /= len;

v.y /= len; v.z /= len; }

normalizeVector(pNormal);

Như vậy ta đã có được mặt phẳng chứa tam giác đang xét. Ta cũng cần phải chuyển tam giác vào không gian Ellipsoid trước khi thao tác với chúng bởi vì chúng ta đang làm việc trong không gian Ellipsoid.

b. Tính điểm va chạm giả định trên hình cầu (cầu đơn vị)

Trong bước này chúng ta sẽ tính trước điểm giao (nằm trên mặt cầu) khi mặt cầu va chạm với tam giác. Chúng ta chỉ dựa vào hình cầu và mặt phẳng chứa tam giác. Nếu ta sử dụng Ellipsoid thì bước này cũng hơi khó, tuy nhiên ta phải tận dụng không gian Ellipsoid để làm giảm độ phức tạp của vấn đề. Vấn đề hiện tại được mô tả bởi hình sau:

Hình 2.3.2b: Tìm điểm va chạm giả định

Hình vẽ trên có vẻ hơi phức tạp ! Tuy nhiên ý tưởng của nó được thể hiện rất rõ: ta sẽ tính điểm giao trên hình cầu trước khi di chuyển hình cầu bằng cách tịnh tính (giả định) mặt phẳng tới làm mặt phẳng tiếp diện với mặt cầu và ta được tiếp điểm chính là giao điểm sẽ xảy ra va chạm. Đường chấm chấm ở trên biểu diễn mặt phẳng tiếp diện khi ta tịnh tiến mặt phẳng. Thuật toán thực hiện việc này rất đơn giản chỉ là:

eIPoint = source – pNormal;

c. Tính điểm va chạm giả định nằm trên mặt phẳng

Bước tiếp theo chúng ta sẽ tính điểm giao trên mặt phẳng khi hình cầu di chuyển dọc theo vector vận tốc sẽ va chạm với mặt phẳng tại điểm này. Để tìm điểm này thì rất đơn giản, ta chỉ cần kéo một tia từ điểm nằm trên mặt cầu dọc theo vector vận tốc, tia này cắt mặt phẳng tại đầu thì nó chính là điểm giao. Còn điểm nằm trên mặt cầu đó là điểm khi ta vẽ bán kính của mặt cầu song song và ngược chiều với vector pháp tuyến của mặt phẳng. Hình vẽ sau sẽ minh hoạ rõ điều này:

Hình 2.3.2c: Tính điểm va chạm giả định nằm trên mặt phẳng

Cài đặt như sau:

inline float dot(D3DVECTOR& v1, D3DVECTOR& v2) { return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); }

double intersectRayPlane(D3DVECTOR rOrigin, D3DVECTOR rVector, D3DVECTOR pOrigin, D3DVECTOR pNormal) {

double d = - (dot(pNormal,pOrigin)); double numer = dot(pNormal,rOrigin) + d; double denom = dot(pNormal,rVector);

if (denom == 0) // không xảy ra va chạm

return (-1.0f); return -(numer / denom); }

Trong thủ tục trên thì rVector là hướng của tia và vector này phải được chuẩn hoá. Hàm trả về độ dài của tia, tức là khoảng cách từ điểm sẽ va chạm trên hình cầu tới điểm sẽ va chạm trên mặt phẳng.

// kéo tia theo vector vận tốc

distToPlaneIntersection = intersectRayPlane(eIPoint, normalizedVelocity, pOrigin, pNormal);

// tính điểm va chạm trên mặt phẳng

pIPoint.x = eIPoint.x + distToPlaneIntersection * normalizedVelocity.x; pIPoint.y = eIPoint.y + distToPlaneIntersection * normalizedVelocity.y; pIPoint.z = eIPoint.z + distToPlaneIntersection * normalizedVelocity.z;

eIPoint: điểm va chạm nằm trên Ellipsoid pIPoint: điểm va chạm nằm trên mặt phẳng

Tuy nhiên, thủ tục nêu trên chưa xét hết tất cả các trường hợp. Ta hãy xét trường hợp mặt phẳng cắt mặt cầu như hình dưới, như vậy sẽ có chuyện gì xảy ra. Ta thấy rằng điểm va chạm bây giờ không phải là một điểm mà là một tập các điểm dẫn đến thủ trên sẽ gặp vấn đề.

Hình 2.3.2c1: điểm va chạm sẽ là một tập các điểm

Ta phải chọn điểm nằm trên mặt phẳng chính là điểm khi ta vẽ bán kính theo hướng của vector pháp tuyến của mặt phẳng, bán kính này giao với mặt phẳng tại điểm nào thì điểm đó là điểm cần tìm.

Ta chỉ phải làm việc này khi mặt phẳng cắt mặt cầu. Thủ tục để kiểm tra trường hợp này là:

DWORD classifyPoint(D3DVECTOR point, D3DVECTOR pO, D3DVECTOR pN) {

D3DVECTOR dir = pO - point; double d = dot(dir, pN); if (d<-0.001f) return PLANE_FRONT; else if (d>0.001f) return PLANE_BACKSIDE; return ON_PLANE; }

Thủ tục ở trên kiểm tra xem có hay không một điểm nằm ở trước, sau hoặc nằm trên mặt phẳng. Nếu điểm va chạm nằm sau mặt phẳng thì mặt phẳng sẽ cắt mặt cầu.

Thủ tục quản lý trường hợp này như sau:

DWORD pClass = classifyPoint(eIPoint, pOrigin, pNormal); // tìm điểm va chạm trên mặt phẳng

if (pClass == PLANE_BACKSIDE) { // Mặt phẳng cắt mặt cầu

// Tìm điểm va chạm bằng cách keo một tia dọc theo pháp tuyến của mặt phẳng distToPlaneIntersection = intersectRayPlane(eIPoint, pNormal, pOrigin, pNormal);

// Tính điểm va chạm trên mặt phẳng

pIPoint.x = eIPoint.x + distToPlaneIntersection * pNormal.x; pIPoint.y = eIPoint.y + distToPlaneIntersection * pNormal.y; pIPoint.z = eIPoint.z + distToPlaneIntersection * pNormal.z; }

Từ lúc này ta không cần quan tâm đến vấn đề là mặt phẳng có cắt mặt cầu hay không.

d. Tính toán điểm giao thực (nếu có)

Đây là bước mà ta tính được điểm xảy ra va chạm thực sự (nếu có) - điểm mà hình cầu sẽ va chạm với tam giác. Có 2 trường hợp xảy ra: hoặc là điểm va chạm nằm trong tam giác chúng ta đang xét hoặc là nằm ngoài tam giác (thuộc mặt phẳng) - tất nhiên là không tính trường hợp mặt cầu không va chạm với mặt phẳng.

Nếu điểm giao trên mặt phẳng nằm trong tam giác thì ta được điểm giao thực sự. Nếu không ta rơi vào tình huống là cả điểm giao trên mặt cầu và mặt phẳng đều không đúng và tất nhiên ta phải tính toán lại.

Trong trường hợp điểm va chạm với mặt phẳng nằm ngoài tam giác. Ta sẽ lấy điểm nằm trên cạnh của tam giác sao cho điểm này nằm gần với điểm va chạm với mặt phẳng nhất. Từ điểm này ta sẽ kéo một tia song song với vector vận tốc và cắt mặt cầu tại điểm nào thì điểm đó chính là điểm va chạm thực sự. Trong trường hợp tia không cắt hình cầu thì sẽ không có va chạm xảy ra. Hình vẽ sau đây sẽ cho thấy rõ ý tưởng của bước này.

Hình 2.3.2d: Tính điểm giao thực

Nói tóm lại là chúng ta chỉ cần tính toán xem điểm va chạm có nằm trong tam giác hay không. Chắc chắn rằng điểm này nằm trong cùng một mặt phẳng với tam giác. Ta sẽ làm giảm độ phức tạp của vấn đề khi đưa chúng xét trong không gian 2 chiều. Sử dụng thuật toán nhỏ sau đây để giải quyết vấn để trên.

Hình 2.3.2d1: Kiểm tra một điểm nằm trong tam giác

Giả sử ta có điểm P bất kì. Ta nối điểm P với các đỉnh của tam giác ABC. Khi đó: Nếu P nằm trong tam giác ABC thì : góc(APB) + góc(BPC) + góc(CPA) = 360o

Nếu P nằm ngoài tam giác ABC thì : góc(APB) + góc(BPC) + góc(CPA) < 360o

Ta có thể cài đặt thuật toán như sau (chú ý rằng tích vô hướng của 2 vector đơn vị bằng cosin của góc giữa chúng):

BOOL CheckPointInTriangle(D3DVECTOR point ,D3DVECTOR a, D3DVECTOR b, D3DVECTOR c) { double total_angles = 0.0f; // Tạo ra 3 vector D3DVECTOR v1 = point-a; D3DVECTOR v2 = point-b; D3DVECTOR v3 = point-c; normalizeVector(v1); normalizeVector(v2); normalizeVector(v3); total_angles += acos(dot(v1,v2)); total_angles += acos(dot(v2,v3)); total_angles += acos(dot(v3,v1));

// cho phép sai số trong khoảng xác định – vì thao tác với số dấu phảy động if (fabs(total_angles-2*PI) <= 0.005)

return (TRUE);

return(FALSE); }

Thủ tục trên đây chỉ giải quyết được 1 trường hợp. Trường hợp còn lại ta phải giải quyết là khi điểm va chạm nằm ngoài tam giác. Như vậy theo lý thuyết trên ta phải tính toán điểm nằm trên cạnh của tam giác và gần với điểm va chạm giả định nhất. Điều này thực hiện quá đơn giản. Ta chỉ việc hạ 3 đường vuông góc từ điểm va chạm giả định xuống 3 cạnh của tam giác. Lấy đường vuông góc có độ dài nhỏ nhất. Nếu chân đường vuông góc nằm trên cạnh của tam giác thì chân đường vuông góc đó chính là điểm cần tìm. Ngược lại ta sẽ lấy một trong 2 đỉnh gần nhất của cạnh ứng với đường vuông góc đó:

Hình 2.3.2d2: Kiểm tra điểm va chạm xác nhận điểm va chạm

e. Va chạm xảy ra ?

Qua 4 bước ở trên chúng ta đã tính được : - Khoảng cách tới điểm va chạm (nếu có) - Điểm va chạm trên mặt cầu

- Điểm va chạm trên tam giác

Trước hết ta thấy rằng va chạm xảy ra thì khoảng cách tới điểm va chạm phải nhỏ hơn hoặc bằng quãng đường di chuyển của hình cầu (độ lớn của vector vận tốc). Tất nhiên ta vẫn

Một phần của tài liệu Nghiên cứu tìm hiểu va chạm chung giữa các đối tượng trong thực tế được mô phỏng vào máy tính (Trang 27 - 41)

Tải bản đầy đủ (DOC)

(68 trang)
w