Phát hiện va chạm lục giác cho các đối tượng chuyển động nhanh?


39

Một vật có vị trí và vectơ tốc độ. Thông thường chỉ có vị trí được sử dụng để kiểm tra xem hai vật có va chạm hay không, đây là vấn đề đối với các vật thể chuyển động rất nhanh vì có thể xảy ra rằng vật thể di chuyển nhanh đến mức nó ở phía trước vật thể đầu tiên trong lần kiểm tra va chạm đầu tiên và phía sau nó kiểm tra va chạm thứ hai.

BoundingBox Va chạm thất bại

Bây giờ cũng có kiểm tra va chạm dựa trên dòng, trong đó bạn chỉ kiểm tra xem vectơ chuyển động của từng đối tượng có giao nhau với hộp giới hạn của đối tượng khác không. Điều này có thể được coi là một sự mở rộng của một điểm. Điều này chỉ hoạt động mặc dù nếu đối tượng di chuyển nhanh là thực sự nhỏ.

Hình lục giác Va chạm Win

Vì vậy, ý tưởng của tôi là, thay vì mở rộng một điểm, tại sao không mở rộng một hình chữ nhật? Điều này dẫn đến một hình lục giác.

Bây giờ, cho đến nay rất tốt. Nhưng làm thế nào để tôi thực sự kiểm tra nếu hai hình lục giác loại này giao nhau? Lưu ý rằng đây là những hình lục giác rất cụ thể.

Thông số kỹ thuật hình lục giác

Câu hỏi thưởng : Có thể tính toán chính xác nơi (hoặc đúng hơn sau bao nhiêu thời gian) vụ va chạm xảy ra không? Điều này có thể rất hữu ích để phát hiện những gì thực sự đã xảy ra, như ở đâu và với bao nhiêu năng lượng và mô phỏng cách chúng di chuyển trong khoảng thời gian giữa va chạm và kết thúc khung hình.


cho (các dòng trong A) cho (các dòng trong B) nếu (các đường chéo) va chạm - ngoại trừ việc không bao gồm A trong B hoặc B trong các trường hợp A. Hừm. =)
Jari Komppa

4
Bạn có cam kết với các hộp? Các hộp bạn vẽ có thể được biểu thị bằng các vòng tròn với độ chính xác tối thiểu nhưng độ va chạm tương đối dễ dàng. Tìm kiếm phát hiện va chạm vòng tròn quét. Nếu tỷ lệ chiều dài / chiều rộng của bạn di chuyển từ 1, thì điều này sẽ kém hấp dẫn hơn.
Steve H

@SteveH Tôi đang tìm giải pháp linh hoạt nhất, vì vậy tỷ lệ chiều dài / chiều rộng là một vấn đề lớn.
API-Beast

1
Bạn phải nhận ra rằng chỉ vì các hình lục giác giao nhau không có nghĩa là sự va chạm xảy ra. Ngay cả khi bạn có thể nói mà không nhầm lẫn liệu chúng có giao nhau hay không, bạn vẫn sẽ phải làm để xác định xem có va chạm hay không, và rõ ràng, nó xảy ra ở đâu và khi nào. Vì vậy, bạn không thể chuyển đến câu hỏi tiền thưởng của bạn chưa.
jrsala

2
Tôi chưa từng thử điều này trước đây nhưng dường như thay vì các hình lục giác trong không gian 2d, bạn có thể nghĩ chuyển động trong 2d là các khối trong không gian 3d trong đó một trục là thời gian. Sau đó, bạn giao hai khối đa diện 3d với tọa độ (x, y, t). Nếu hai vật thể rắn cắt nhau thì bạn muốn tìm giá trị t tối thiểu. Bạn có thể đơn giản hóa một chút bằng cách chuyển đổi tất cả các tọa độ của B thành khung tham chiếu của A. Tôi đã không thực hiện điều này nhưng đó là nơi tôi bắt đầu.
amitp

Câu trả lời:


34

Giải pháp thực sự đơn giản hơn mong đợi. Bí quyết là sử dụng phép trừ Minkowski trước kỹ thuật lục giác của bạn.

Dưới đây là hình chữ nhật A và B của bạn, với vận tốc vAvB. Lưu ý rằng vAvBkhông thực sự là vận tốc, chúng là khoảng cách di chuyển trong một khung hình.

bước 1

Bây giờ thay thế hình chữ nhật B bằng một điểm P và hình chữ nhật A bằng hình chữ nhật C = A + (- B), có kích thước tổng các kích thước của A và B. Các thuộc tính bổ sung Minkowski xảy ra va chạm giữa điểm và hình chữ nhật mới nếu và chỉ khi va chạm giữa hai hình chữ nhật ban đầu xảy ra:

bước 2

Nhưng nếu hình chữ nhật C di chuyển dọc theo vectơ vAvà điểm P di chuyển dọc theo vectơ vB, một thay đổi đơn giản của khung tham chiếu cho chúng ta biết nó giống như khi hình chữ nhật C vẫn còn và điểm P di chuyển dọc theo vectơ vB-vA:

bước 3

Sau đó, bạn có thể sử dụng công thức giao cắt phân đoạn hộp đơn giản để cho biết nơi xảy ra xung đột trong khung tham chiếu mới.

Bước cuối cùng là quay trở lại khung tham chiếu thích hợp. Chỉ cần chia khoảng cách di chuyển của điểm cho đến khi giao điểm được khoanh tròn theo chiều dài của vectơ vB-vAvà bạn sẽ nhận được một giá trị snhư vậy 0 < s < 1. Sự va chạm xảy ra vào thời điểm s * Tđó Tlà khoảng thời gian của khung hình của bạn.

Nhận xét của madshogo :
Một lợi thế lớn của kỹ thuật này so với câu trả lời của chính ông Beast là nếu không có phép quay, thì phép trừ "Minkowski" A + (- B) có thể được tính một lần cho tất cả các dấu thời gian tiếp theo !

Vì vậy, thuật toán duy nhất cần có thời gian trong tất cả điều này (tổng số Minkowski, độ phức tạp O (mn) trong đó m là số đỉnh trong An số lượng đỉnh trong B ) chỉ có thể được sử dụng một lần, giúp phát hiện va chạm không đổi vấn đề thời gian!

Sau đó, bạn có thể vứt tổng tiền đi một khi bạn biết chắc rằng AB ở các phần khác nhau trong cảnh của bạn (của phần tư của bạn?) Và sẽ không va chạm nữa.

Ngược lại, phương pháp của Mr Beast đòi hỏi khá nhiều tính toán ở mỗi bước.

Ngoài ra, đối với các hình chữ nhật được căn chỉnh theo trục, A + (- B) có thể được tính toán đơn giản hơn nhiều so với việc thực sự tính toán tất cả các tổng, đỉnh theo đỉnh. Chỉ cần mở rộng A bằng cách thêm chiều cao của B vào chiều cao của nó và chiều rộng của B thành chiều rộng của nó (một nửa ở mỗi bên).

Nhưng tất cả điều này chỉ hoạt động nếu cả AB đều không quay và nếu cả hai đều lồi. Nếu xoay có hoặc nếu bạn sử dụng hình dạng lõm thì bạn phải sử dụng khối lượng / vùng quét.
kết thúc bình luận


4
Trông giống như một cách tiếp cận khá thú vị, tuy nhiên, tôi chưa nắm bắt được 100%, điều gì xảy ra khi đối tượng thực sự nhỏ và đang di chuyển giữa hai dòng? i.imgur.com/hRolvAF.png
API-Beast

-1: Phương pháp này không theo bất kỳ cách nào cho phép bạn chắc chắn xảy ra va chạm. Nó chỉ cho phép bạn chắc chắn điều đó không xảy ra, trong trường hợp phân đoạn và khối lượng đùn không giao nhau. Nhưng điều đó hoàn toàn có thể là họ giao nhau và không có va chạm. Điều sai là phần "Bây giờ bạn có thể sử dụng [...] giao lộ phân đoạn đơn giản để quyết định nơi xảy ra va chạm".
jrsala

2
@madshogo Bạn nói đúng. Tôi giả định rằng dấu thời gian là đủ nhỏ so với kích thước đối tượng mà điều này sẽ không thành vấn đề, nhưng chắc chắn nó không mạnh lắm trong trường hợp chung. Tôi sẽ xem xét việc sửa nó.
sam hocevar

@SamHocevar Nếu bạn có thể sửa lại câu trả lời sẽ rất tuyệt.
API-Beast

1
@LuisAlves có và không ... tất cả các công trình logic, nhưng bạn sẽ phải thay thế vB-vAvới g(t)-f(t)nơi fglà A và B của các vị trí theo thời gian. Vì đây không còn là một đường thẳng, bạn sẽ phải giải một bài toán về giao điểm đường cong tham số.
sam hocevar

17

Trước hết, trong trường hợp hình chữ nhật được căn chỉnh theo trục, câu trả lời của Kevin Reid là tốt nhất và thuật toán là nhanh nhất.

Thứ hai, đối với các hình dạng đơn giản, sử dụng vận tốc tương đối (như được thấy dưới đây) và định lý trục tách để phát hiện va chạm. Nó sẽ cho bạn biết liệu một vụ va chạm xảy ra trong trường hợp chuyển động tuyến tính (không quay). Và nếu có vòng quay, bạn cần một dấu thời gian nhỏ để nó chính xác. Bây giờ, để trả lời câu hỏi:


Làm thế nào để biết trong trường hợp chung liệu hai hình lồi có giao nhau không?

Tôi sẽ cung cấp cho bạn một thuật toán hoạt động cho tất cả các hình lồi chứ không chỉ hình lục giác.

Giả sử XY là hai hình lồi. Chúng cắt nhau khi và chỉ khi chúng có một điểm chung, tức là có một điểm x X và một điểm y ∈ Y sao cho x = y . Nếu bạn coi không gian là không gian vectơ, thì điều này có nghĩa là nói x - y = 0 . Và bây giờ chúng ta có được doanh nghiệp Minkowski này:

Các Minkowski tổng của XY là tập hợp của tất cả các x + y cho x ∈ Xy ∈ Y .


Một ví dụ cho X và Y


X, Y và tổng số Minkowski của họ, X + Y

Giả sử (-Y) là tập hợp tất cả -y cho y ∈ Y , sau đó đưa ra đoạn trước, XY cắt nhau khi và chỉ khi X + (-Y) chứa 0 , nghĩa là gốc .

Nhận xét bên lề: tại sao tôi viết X + (-Y) thay vì X - Y ? Chà, bởi vì trong toán học, có một phép toán gọi là sự khác biệt giữa Minkowski của AB , đôi khi được viết X - Y nhưng không liên quan gì đến tập hợp tất cả x - y cho x ∈ Xy ∈ Y (thực sự là Minkowski sự khác biệt là một chút phức tạp hơn).

Vì vậy, chúng tôi muốn tính tổng của Minkowski là X-Y và để xem liệu nó có chứa nguồn gốc hay không. Nguồn gốc không đặc biệt so với bất kỳ điểm nào khác, để tìm xem nguồn gốc có nằm trong một miền nhất định hay không, chúng tôi sử dụng thuật toán có thể cho chúng tôi biết liệu có điểm nào thuộc về miền đó hay không.

Tổng số Minkowski của XY có một thuộc tính tuyệt vời, đó là nếu XY là lồi thì X + Y cũng vậy. Và việc tìm kiếm cho dù một điểm thuộc về một tập lồi là nhiều dễ dàng hơn nếu thiết lập được không (được gọi là) lồi.

Chúng ta không thể tính tất cả x - y cho x ∈ Xy ∈ Y vì có vô số điểm xy như vậy, vì vậy, hy vọng, vì X , YX + Y là lồi, chúng ta chỉ có thể sử dụng các điểm "ngoài cùng" xác định các hình dạng XY , là các đỉnh của chúng và chúng ta sẽ nhận được các điểm ngoài cùng của X + Y , và một số điểm khác.

Các điểm bổ sung này được "bao quanh" bởi các điểm ngoài cùng của X + Y để chúng không góp phần xác định hình dạng lồi mới thu được. Chúng tôi nói rằng họ không định nghĩa " thân lồi " của tập hợp các điểm. Vì vậy, những gì chúng tôi làm là chúng tôi loại bỏ chúng để chuẩn bị cho thuật toán cuối cùng cho chúng tôi biết nguồn gốc có nằm trong thân tàu lồi hay không.


Vỏ lồi của X + Y. Chúng tôi đã loại bỏ các đỉnh "bên trong".

Do đó, chúng tôi nhận được

Một thuật toán đầu tiên, ngây thơ

boolean intersect(Shape X, Shape Y) {

  SetOfVertices minkowski = new SetOfVertices();
  for (Vertice x in X) {
    for (Vertice y in Y) {
      minkowski.addVertice(x-y);
    }
  }
  return contains(convexHull(minkowski), Vector2D(0,0));

}

Các vòng lặp rõ ràng có độ phức tạp O (mn) trong đó mn là số đỉnh của mỗi hình. Bộ minkoswkichứa nhiều phần tử mn nhất. Các convexHullthuật toán có độ phức tạp mà phụ thuộc vào các thuật toán bạn sử dụng , và bạn có thể nhằm mục đích cho O (k log (k)) nơi k là kích thước của tập hợp các điểm, vì vậy trong trường hợp của chúng tôi, chúng tôi có được O (mn log (mn) ) . Các containsthuật toán có độ phức tạp đó là tuyến tính với số cạnh (2D) hoặc khuôn mặt (trong không gian 3D) của thân lồi, vì vậy nó thực sự phụ thuộc vào hình dạng bắt đầu của bạn, nhưng nó sẽ không được lớn hơn O (mn) .

Tôi sẽ cho bạn google containsthuật toán cho các hình lồi, đây là một thuật toán khá phổ biến. Tôi có thể đặt nó ở đây nếu tôi có thời gian.


Nhưng đó là phát hiện va chạm chúng tôi đang làm, vì vậy chúng tôi có thể tối ưu hóa điều đó rất nhiều

Chúng tôi ban đầu có hai cơ thể AB di chuyển mà không quay trong thời gian dt (từ những gì tôi có thể nói bằng cách nhìn vào hình ảnh của bạn). Chúng ta hãy gọi v Av B là tốc độ tương ứng của AB , không đổi trong khoảng thời gian của chúng tôi là dt . Chúng tôi nhận được như sau:

và, như bạn chỉ ra trong ảnh của mình, các cơ quan này sẽ quét qua các khu vực (hoặc tập, ở chế độ 3D) khi chúng di chuyển:

và chúng kết thúc là A 'B' sau dấu thời gian.

Để áp dụng thuật toán ngây thơ của chúng tôi ở đây, chúng tôi sẽ chỉ phải tính toán các khối lượng quét. Nhưng chúng tôi không làm điều này.

Trong khung tham chiếu của B , B không di chuyển (duh!). Và Avận tốc nhất định đối với B mà bạn có được bằng cách tính v A - v B (bạn có thể thực hiện ngược lại, tính vận tốc tương đối của B trong khung tham chiếu của A ).

Chuyển động tương đối

Từ trái sang phải: vận tốc trong khung tham chiếu cơ sở; vận tốc tương đối; tính toán vận tốc tương đối.

Bằng cách liên quan đến B như bất động trong hệ quy chiếu riêng của mình, bạn chỉ cần tính toán khối lượng Một quét qua khi nó di chuyển trong dt với thân nhân của nó vận tốc v Một - v B .

Điều này làm giảm số lượng đỉnh được sử dụng trong tính toán tổng số Minkowski (đôi khi rất nhiều).

Một tối ưu hóa khác có thể là tại điểm bạn tính toán âm lượng được quét bởi một trong các cơ thể, giả sử A. Bạn không phải dịch tất cả các đỉnh tạo thành A. Chỉ những phần thuộc về các cạnh (khuôn mặt trong 3D) có bên ngoài "mặt" bình thường theo hướng quét. Chắc chắn bạn đã nhận thấy rằng khi bạn tính toán các khu vực quét của mình cho các hình vuông. Bạn có thể biết liệu một bình thường có hướng về hướng quét hay không bằng cách sử dụng sản phẩm chấm của nó với hướng quét, điều này phải là dương.

Tối ưu hóa cuối cùng, không liên quan gì đến câu hỏi của bạn về các giao lộ, thực sự hữu ích trong trường hợp của chúng tôi. Nó sử dụng các vận tốc tương đối mà chúng ta đã đề cập và phương pháp trục tách. Chắc chắn bạn đã biết về nó rồi.

Giả sử bạn biết bán kính của AB đối với tâm khối lượng của chúng (nghĩa là khoảng cách giữa tâm khối lượng và đỉnh xa nhất so với nó), như thế này:

Một vụ va chạm có thể xảy ra chỉ khi nó có thể là hình tròn giới hạn của một đáp ứng của B . Chúng ta thấy ở đây là nó sẽ không, và cách nào để biết máy tính đó là để tính toán khoảng cách từ C B để tôi như trong hình dưới đây và chắc chắn rằng nó lớn hơn tổng của các bán kính của AB . Nếu nó lớn hơn, không có va chạm. Nếu nó nhỏ hơn, sau đó va chạm.

Điều này không hoạt động rất tốt với các hình dạng khá dài, nhưng trong trường hợp hình vuông hoặc hình dạng khác, đó là một cách giải quyết rất tốt để loại trừ va chạm .

Tuy nhiên, định lý trục phân tách áp dụng cho B và âm lượng quét bởi A , tuy nhiên, sẽ cho bạn biết liệu va chạm có xảy ra hay không. Độ phức tạp của thuật toán liên quan là tuyến tính với tổng số lượng đỉnh của mỗi hình lồi, nhưng sẽ ít kỳ diệu hơn khi đến lúc thực sự xử lý va chạm.

Thuật toán mới, tốt hơn của chúng tôi sử dụng các giao điểm để giúp phát hiện va chạm, nhưng vẫn không tốt bằng định lý trục tách để thực sự cho biết liệu có xảy ra va chạm hay không

boolean mayCollide(Body A, Body B) {

  Vector2D relativeVelocity = A.velocity - B.velocity;
  if (radiiHeuristic(A, B, relativeVelocity)) {
    return false; // there is a separating axis between them
  }

  Volume sweptA = sweptVolume(A, relativeVelocity);
  return contains(convexHull(minkowskiMinus(sweptA, B)), Vector2D(0,0));

}

boolean radiiHeuristic(A, B, relativeVelocity)) {
  // the code here
}

Volume convexHull(SetOfVertices s) {
  // the code here
}

boolean contains(Volume v, Vector2D p) {
  // the code here
}

SetOfVertices minkowskiMinus(Body X, Body Y) {

  SetOfVertices result = new SetOfVertices();
  for (Vertice x in X) {
    for (Vertice y in Y) {
      result.addVertice(x-y);
    }
  }
  return result;

}

2

Tôi không nghĩ sử dụng 'hình lục giác' là hữu ích. Đây là bản phác thảo một cách để có được các va chạm chính xác cho các hình chữ nhật được căn chỉnh theo trục:

Hai hình chữ nhật thẳng hàng trùng nhau trùng nhau khi và chỉ khi phạm vi tọa độ X của chúng trùng nhau và phạm vi tọa độ Y của chúng trùng nhau. (Đây có thể được xem là trường hợp đặc biệt của định lý trục phân tách.) Nghĩa là, nếu bạn chiếu các hình chữ nhật lên trục X và Y, bạn đã giảm vấn đề xuống hai giao điểm đường thẳng.

Tính khoảng thời gian mà hai đường thẳng trên một trục giao nhau (ví dụ: nó bắt đầu tại thời điểm (sự phân tách hiện tại của vật / tốc độ tiếp cận tương đối của vật thể)) và làm tương tự cho trục kia. Nếu các khoảng thời gian đó trùng nhau, thì thời gian sớm nhất trong phạm vi chồng chéo là thời gian va chạm.


3
Bạn đã quên bản phác thảo của bạn.
MichaelHouse

2
@ Byte56 Không, ý tôi là đó là bản phác thảo của một thuật toán, thậm chí không phải là mã giả.
Kevin Reid

Ồ ... tôi hiểu rồi. Lỗi của tôi.
MichaelHouse

Đây thực sự là phương pháp dễ nhất. Tôi đã thêm mã tương ứng để thực hiện nó.
Pasha

1

Tôi không nghĩ có một cách dễ dàng để tính toán sự va chạm của đa giác với nhiều cạnh hơn một hình chữ nhật. Tôi sẽ chia nó thành các hình dạng nguyên thủy như đường và hình vuông:

function objectsWillCollide(object1,object2) {
    var lineA, lineB, lineC, lineD;
    //get projected paths of objects and store them in the 'line' variables

    var AC = lineCollision(lineA,lineC);
    var AD = lineCollision(lineA,lineD);
    var BC = lineCollision(lineB,lineC);
    var BD = lineCollision(lineB,lineD);
    var objectToObjectCollision = rectangleCollision(object1.getRectangle(), object2.getRectangle());

    return (AC || AD || BC || BD || objectToObjectCollision);
}

minh họa các đường dẫn và trạng thái kết thúc của đối tượng

Lưu ý cách tôi bỏ qua trạng thái bắt đầu của từng đối tượng vì điều đó cần được kiểm tra trong quá trình tính toán trước đó.


3
Vấn đề với điều này là nếu kích thước của các đối tượng khác nhau rất nhiều, vật thể nhỏ hơn có thể di chuyển bên trong đường dẫn của vật thể lớn mà không gây ra va chạm.
API-Beast

0

Định lý trục chín

Định lý trục Sepate nói "Nếu chúng ta có thể tìm thấy một trục mà hai hình lồi không giao nhau thì hai hình không giao nhau" hoặc thực tế hơn cho CNTT:

"Hai hình lồi chỉ giao nhau nếu chúng giao nhau trên tất cả các trục có thể."

Đối với hình chữ nhật thẳng hàng trục có chính xác 2 trục có thể: x và y. Nhưng định lý không giới hạn ở hình chữ nhật, nó có thể áp dụng cho bất kỳ hình dạng lồi nào bằng cách thêm các trục khác mà hình dạng có thể giao nhau. Để biết thêm chi tiết về chủ đề, hãy xem hướng dẫn này của nhà phát triển N: http://www.metanetsoftware.com/technique/tutorialA.html#section1

Thực hiện nó trông như thế này:

axes = [... possible axes ...];
collision = true;
for every index i of axes
{
  range1[i] = shape1.getRangeOnAxis(axes[i]);
  range2[i] = shape2.getRangeOnAxis(axes[i]);
  rangeIntersection[i] = range1[i].intersectionWith(range2[i]);
  if(rangeIntersection[i].length() <= 0)
  {
    collision = false;
    break;
  }
}

Các trục có thể được biểu diễn dưới dạng các vectơ chuẩn hóa.

Một phạm vi là một dòng 1 chiều. Điểm bắt đầu nên được đặt thành điểm chiếu nhỏ nhất, điểm cuối đến điểm chiếu lớn nhất.

Áp dụng nó vào hình chữ nhật "quét"

Hình lục giác trong câu hỏi được tạo ra bằng cách "quét" AABB của đối tượng. Quét thêm chính xác một trục va chạm có thể vào bất kỳ hình dạng nào: vectơ chuyển động.

shape1 = sweep(originalShape1, movementVectorOfShape1);
shape2 = sweep(originalShape2, movementVectorOfShape2);

axes[0] = vector2f(1.0, 0.0); // X-Axis
axes[1] = vector2f(0.0, 1.0); // Y-Axis
axes[2] = movementVectorOfShape1.normalized();
axes[3] = movementVectorOfShape2.normalized();

Cho đến nay rất tốt, bây giờ chúng ta đã có thể kiểm tra xem hai hình lục giác có giao nhau không. Nhưng nó thậm chí còn tốt hơn.

Giải pháp này sẽ hoạt động cho mọi hình dạng lồi (ví dụ hình tam giác) và bất kỳ hình dạng lồi quét nào (ví dụ như hình bát giác được quét). Tuy nhiên, hình dạng càng phức tạp thì nó sẽ càng kém hiệu quả.


Tiền thưởng: Trường hợp phép thuật xảy ra.

Như tôi đã nói các trục bổ sung duy nhất là các vectơ chuyển động. Chuyển động là thời gian nhân với tốc độ, vì vậy theo một nghĩa nào đó, chúng không chỉ là trục không gian, chúng là trục không gian thời gian.

Điều này có nghĩa là chúng ta có thể rút ra thời gian va chạm có thể xảy ra từ hai trục này. Đối với điều này, chúng ta cần tìm giao điểm giữa hai giao điểm trên trục chuyển động. Trước khi chúng ta có thể làm điều này, chúng ta cần bình thường hóa cả hai phạm vi, vì vậy chúng ta thực sự có thể so sánh chúng.

shapeRange1 = originalShape1.getRangeOnAxis(axes[2]);
shapeRange2 = originalShape2.getRangeOnAxis(axes[3]);
// Project them on a scale from 0-1 so we can compare the time ranges
timeFrame1 = (rangeIntersection[2] - shapeRange1.center())/movementVectorOfShape1.project(axes[2]);
timeFrame2 = (rangeIntersection[3] - shapeRange2.center())/movementVectorOfShape2.project(axes[3]);
timeIntersection = timeFrame1.intersectionWith(timeFrame2);

Khi tôi hỏi câu hỏi này, tôi đã chấp nhận thỏa hiệp rằng sẽ có một vài kết quả dương tính giả hiếm gặp với phương pháp này. Nhưng tôi đã nhầm, bằng cách kiểm tra giao lộ thời gian này, chúng ta có thể kiểm tra xem vụ va chạm "thực sự" có xảy ra hay không và chúng ta có thể sắp xếp những thông tin sai lệch đó với nó:

if(collision)
{
  [... timeIntersection = see above ...]
  if(timeIntersection.length() <= 0)
    collision = false;
  else
    collisionTime = timeIntersection.start; // 0: Start of the frame, 1: End of the frame
}

Nếu bạn nhận thấy bất kỳ lỗi nào trong các ví dụ mã cho tôi biết, tôi chưa thực hiện nó và do đó không thể kiểm tra nó.


1
Chúc mừng bạn đã tìm ra giải pháp! Nhưng như tôi đã nói trước đây: chỉ vì các hình lục giác giao nhau không có nghĩa là sẽ có một vụ va chạm. Bạn có thể sử dụng phương pháp của mình để tính thời gian va chạm tất cả những gì bạn muốn, nếu không có va chạm, nó không hữu ích lắm. Thứ hai, bạn có thể sử dụng tốc độ tương đối để chỉ phải tính 1 khối lượng quét và để đơn giản hóa các tính toán khi sử dụng SAT. Cuối cùng, tôi chỉ có một ý tưởng sơ bộ về thủ thuật "thời gian giao nhau" của bạn hoạt động như thế nào, bởi vì có thể bạn đã nhầm lẫn các chỉ số của mình, xem như shapeRange1 == shapeRange2với mã của bạn, phải không?
jrsala

@madshogo Nên có ý nghĩa hơn bây giờ.
API-Beast

Tôi vẫn không hiểu làm thế nào điều bình thường hóa phạm vi hoạt động, nhưng tôi đoán đó là vì tôi cần một hình ảnh. Tôi hy vọng nó làm việc cho bạn.
jrsala

-2

Miễn là các khu vực quét đều được đóng kín (không có khoảng trống trong ranh giới được hình thành bởi các đường biên), điều sau đây sẽ hoạt động (chỉ cần giảm các thử nghiệm va chạm của bạn thành đường thẳng và điểm trực tiếp / điểm-tri):

  1. Các cạnh của chúng có chạm nhau không? (va chạm đường thẳng) Kiểm tra xem có bất kỳ đường biên nào của khu vực quét có giao nhau với bất kỳ đường biên nào của khu vực quét khác không. Mỗi khu vực quét có 6 mặt.

  2. Là cái nhỏ bên trong cái lớn? (Sử dụng các hình dạng căn chỉnh trục (điểm-trực tràng & điểm-tri)) Định hướng lại (xoay) các khu vực quét để cái lớn hơn được căn chỉnh theo trục và kiểm tra xem cái nhỏ hơn có nằm trong không (bằng cách kiểm tra xem có bất kỳ điểm góc nào không (bằng cách kiểm tra xem có điểm góc nào không ( nên là tất cả hoặc không) trong khu vực quét được căn chỉnh theo trục). Điều này được thực hiện bằng cách phân tách hex của bạn thành tris và rects.

Thử nghiệm nào bạn thực hiện trước tiên tùy thuộc vào khả năng của từng thử nghiệm (thực hiện thử nghiệm thường xảy ra trước tiên).

Bạn có thể thấy dễ dàng hơn khi sử dụng vòng tròn giới hạn quét (viên nang thay vì hex) bởi vì việc chia nó thành hai nửa vòng tròn và chỉnh lưu khi nó được căn chỉnh theo trục dễ dàng hơn. .. Tôi sẽ cho phép bạn rút ra giải pháp


Không hoạt động nếu một trong các hình chữ nhật thực sự nhỏ và di chuyển trong không gian giữa hai đường biên.
jrsala

@madshogo Tôi vừa thêm vào phản hồi của mình. Nên là một giải pháp hoàn chỉnh ngay bây giờ.
sợi trục

1
"Sử dụng các hình dạng thẳng hàng trục (điểm-trực tràng & điểm-tri)": Làm thế nào để bạn thậm chí căn chỉnh một hình tam giác hoặc "tam giác điểm" (bất cứ điều gì có nghĩa) với các trục? "sao cho cái lớn hơn được căn chỉnh theo trục": làm thế nào bạn có thể biết cái nào lớn hơn cái kia? Bạn có tính toán các khu vực của họ? "Điều này được thực hiện bằng cách phân tách hex của bạn thành tris và rects.": Hex nào? Có hai. "(hoặc upvote phản hồi này nếu bạn muốn tôi minh họa nó cho bạn)": Bạn có nghiêm túc không ??
jrsala

"Làm thế nào để bạn thậm chí sắp xếp một hình tam giác với các trục?" A: Căn chỉnh đường đi của obj làm cho vùng quét. Chọn một cạnh và sử dụng trig. "làm thế nào bạn có thể biết cái nào lớn hơn cái kia?" A: Ví dụ: sử dụng khoảng cách giữa hai điểm chéo đối diện của trực tràng (giữa hình lục giác). "hex nào?" A: Cái lớn
sợi trục
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.