Giải quyết một vụ va chạm với các lực lượng


14

Trong công cụ vật lý 2D của tôi, tôi có thể phát hiện các va chạm AABB và AABB và giải quyết chúng bằng cách tìm vectơ thâm nhập ngắn nhất và thêm nó vào vị trí của AABB.

Làm điều này "đẩy" AABB đầu tiên bên ngoài AABB thứ hai, nhưng hoàn toàn không đối phó với thay đổi vận tốc / gia tốc.

Nếu tôi thêm gia tốc trọng lực vào mô phỏng của mình, vận tốc của AABB động đầu tiên sẽ tiếp tục tăng ngay cả khi nó nằm trên đỉnh AABB tĩnh thứ hai. Cuối cùng, vận tốc sẽ trở nên quá lớn và va chạm sẽ không được phát hiện (AABB động sẽ rơi qua trạng thái tĩnh).

Tôi đã thử đặt vận tốc về 0 sau khi phân giải, nhưng rõ ràng nó không hoạt động tốt và tạo ra các mô phỏng không thực tế.

Tôi đọc trực tuyến rằng giải quyết va chạm bằng cách làm việc thủ công trên vị trí hoặc vận tốc là không chính xác. Tôi đã thử thực hiện các lực lượng (khối lượng là "mã hóa cứng" 1 bây giờ):

void Body::applyForce(sf::Vector2f mForce) { acceleration += mForce; }

void Body::integrate(float mFrameTime)
{
    velocity += acceleration * mFrameTime;
    position += velocity * mFrameTime;

    acceleration = {0, 0};
}

Nếu tôi áp dụng vectơ xuyên thấu ngắn nhất như một lực trong quá trình phân giải va chạm, AABB động sẽ bị "đẩy ra" khỏi tĩnh, nhưng vận tốc của nó sẽ không bao giờ giảm trong một mô phỏng mà không có trọng lực và nó sẽ tiếp tục di chuyển mãi mãi.

Có cách nào để áp dụng một lực lượng "tạm thời" không? Một lực liên quan đến việc đẩy AABB đầu tiên ra khỏi AABB thứ hai, sau đó dừng lại khi AABB không va chạm nữa?

Toàn bộ mã nguồn có sẵn tại đây: https://github.com/SuperV1234/SSVSCollision


1
Tôi quan tâm đến điều này. Bạn đã đưa ra một giải pháp chưa?
TravisG

@TravisG: chưa, thật không may. Tôi sẽ thêm tiền thưởng vào ngày mai nếu tôi không nhận được bất kỳ câu trả lời nào.
Vittorio Romeo

Lực lượng không bằng gia tốc, trước hết. Bạn cần khối lượng để tính gia tốc. Nếu bạn đang sửa đổi vị trí để ngăn hai cơ thể xâm nhập, bạn cũng nên sử dụng khối lượng và di chuyển cả hai cơ thể dựa trên nó. Áp dụng một lực bằng với vectơ thâm nhập không có công. Box2D dựa trên xung lực, nó hoạt động trực tiếp với vận tốc, nó có thể không "chính xác", nhưng nó đủ tốt. Xử lý các thay đổi vận tốc trong động cơ dựa trên xung rất đơn giản, vì vậy bạn có thể chỉ định nếu bạn chắc chắn muốn một giải pháp dựa trên lực, hoặc là giải pháp dựa trên xung đơn giản hơn nhiều đủ tốt.
dreta

Cá nhân, tôi khuyên bạn nên chọn một cuốn sách về động cơ vật lý, ít nhất là đọc một vài chương đầu tiên về vật lý Newton. Giả định của bạn là không chính xác và cố gắng trả lời câu hỏi này có nghĩa là phải dạy cho bạn những điều cơ bản về vật lý trong khi cố gắng giải thích các thuật toán cấp cao để giải quyết va chạm.
dreta

@dreta giả định của anh ấy là tốt. Anh ấy đã chỉ ra rằng khối lượng của anh ấy cho tất cả các đối tượng chỉ đơn giản là "1", điều này làm cho các phần mã của anh ấy hợp lệ. Nhân tiện, mặc dù Box2D có thể trực tiếp xử lý vận tốc, nhưng bằng cách nào đó nó phải giải quyết cùng một vấn đề. Nếu thay vì áp dụng một lực, Box2D áp dụng một xung, bằng cách nào đó, nó vẫn phải đối phó với thực tế là xung không biến mất một khi các vật thể được tách ra. Mặc dù, có thể thực tế là nó hoàn toàn không đối phó với điều này và chỉ để cho các vật thể giữ năng lượng của chúng (
rốt cuộc

Câu trả lời:


13

Đầu tiên, tôi khuyên bạn nên sử dụng thư viện vật lý nguồn mở miễn phí như Box2D và chỉ tập trung vào các khía cạnh của trò chơi khiến nó trở nên độc đáo! Nếu bạn khăng khăng phát minh lại bánh xe, hãy đọc tiếp ... lưu ý tất cả các động cơ vật lý là gần đúng và trong khi phương pháp tôi phác thảo dưới đây sẽ chính xác hơn mô hình hiện tại của bạn, kết quả của Box2D sẽ thực tế hơn nhiều.


Để biết cách nhanh chóng để mô hình hóa độ phân giải va chạm chính xác hơn của hai đối tượng A và B:

  1. Tìm các vị trí ngay trước khi va chạm. Bạn đã xấp xỉ điều này bằng cách: "tìm vectơ thâm nhập ngắn nhất và thêm nó vào vị trí của AABB."
  2. Tìm vận tốc ngay sau va chạm bằng vật lý Newton :
    • Đối với trường hợp khối lượng được mã hóa cứng là 1, chỉ cần trao đổi vận tốc (điều này không áp dụng cho các đối tượng tĩnh phải có khối lượng vô hạn):
      • Av = Bu
      • Bv = Âu
    • Nếu vật A và B có khối lượng khác nhau:
      • Av = (Au * (Am - Bm) + (2 * Bm * Bu)) / (Am + Bm)
      • Bv = (Bu * (Bm - Am) + (2 * Am * Au)) / (Am + Bm)
    • Ở đâu:
      • v: vận tốc sau va chạm
      • u: vận tốc trước khi va chạm
      • m: khối lượng (sử dụng số lớn nhất có thể cho khối lượng của một vật thể cố định, tĩnh)
  3. Đặt gia tốc về 0: Gia tốc từ va chạm được tính ở trên bằng các tính toán vận tốc ở bước số 2.

Xin hãy xem chương trình tiểu hành tinh mẫu của tôi thể hiện những khái niệm này.


Tiếp theo, tài khoản cho các đối tượng xếp chồng:

Như bạn đã lưu ý, sử dụng vận tốc để mô phỏng các vật thể xếp chồng / nghỉ ngơi không hoạt động tốt: vận tốc là tốc độ mà một vật thể đang di chuyển, vì vậy nếu nó nằm trên một vật thể tĩnh, vận tốc phải ở gần 0. Sẽ không có ý nghĩa gì khi tăng vận tốc của một vật thể làm cho nó xuất hiện ở trạng thái nghỉ:

Nếu tôi thêm gia tốc trọng lực vào mô phỏng của mình, vận tốc của AABB động đầu tiên sẽ tiếp tục tăng ngay cả khi nó nằm trên đỉnh AABB tĩnh thứ hai. Cuối cùng, vận tốc sẽ trở nên quá lớn và va chạm sẽ không được phát hiện (AABB động sẽ rơi qua trạng thái tĩnh).

Điều thực sự nên xảy ra là một lực tăng tốc đang đi theo hướng ngược lại vì trọng lực sẽ triệt tiêu trọng lực ra ngoài. (Đây được gọi là lực tiếp xúc bình thường). Một lối tắt đơn giản là không áp dụng trọng lực cho các cơ thể không có trong không khí:

  • Một phương pháp để làm điều này bằng cách giữ trạng thái "có căn cứ":
    • Không áp dụng trọng lực cho các đối tượng ở trạng thái có căn cứ.
    • Nếu một vật va chạm với một vật từ bên dưới và vận tốc của nó rất nhỏ thì nó sẽ chuyển sang trạng thái tiếp đất.
    • Một vật thể thoát khỏi trạng thái nối đất khi vận tốc dọc của nó vượt quá một giá trị dương nhất định.

Cập nhật:

  • Theo thuật ngữ của giáo dân, vật lý Newton cho biết tổng năng lượng trước và sau khi va chạm phải khớp. Khi hai vật thể đâm vào nhau, năng lượng của chúng được phân phối lại. Năng lượng là sự kết hợp giữa tốc độ và trọng lượng: những thứ nặng hơn, nhanh hơn có nhiều năng lượng hơn. Đó là trực giác. Tuy nhiên, những gì không trực quan là cách chính xác trọng lượng ảnh hưởng đến phân phối lại năng lượng.
  • Vận tốc hoán đổi là một phím tắt chỉ dành cho hai vật thể động, không trộn lẫn có cùng khối lượng (vật thể tĩnh, cố định có khối lượng rất lớn, vô hạn).
  • Phím tắt khi một cơ thể tĩnh được cố định là: cơ thể động, không trộn khác giữ tốc độ như nhau; chỉ có góc được thay đổi (hãy tưởng tượng một bàn bi-a khi một quả bóng chạm vào đường ray. Về cơ bản đường ray có khối lượng rất lớn, vô hạn).
  • Đối với các trường hợp khác, như ba hoặc nhiều đối tượng, các phương trình chuyển động Newton đầy đủ phải được giải (bảo toàn động lượng và bảo toàn động năng).
  • Tôi không chắc các phương trình chuyển động của Newton có thể được giải quyết cho nhiều hơn hai cơ thể hay không. Tuy nhiên, may mắn thay, ba vật thể gần như không bao giờ va chạm cùng một lúc. Nó là đủ để xử lý hai cơ thể đầu tiên va chạm, sau đó xử lý bất kỳ va chạm nào sau đây bằng vận tốc mới từ các độ phân giải va chạm trước đó. Đây là một lý do tốt để giữ cho các bước thời gian vật lý của bạn nhỏ nhất có thể và xử lý các va chạm trước khi bất kỳ sự xâm nhập nào xảy ra.
  • Bạn sẽ nhận thấy trong bản demo tiểu hành tinh của tôi, nhiều cơ thể được tạo ra khi những tảng đá lớn hơn được chia thành những phần nhỏ hơn. Tuy nhiên, tôi luôn xử lý va chạm giữa các cặp cơ thể; không bao giờ xử lý rõ ràng một vụ va chạm với hơn hai cơ thể.

Cảm ơn bạn đã trả lời chi tiết. Có một điều tôi không hiểu mặc dù: vận tốc hoán đổi hoạt động tốt khi va chạm với 2 cơ thể - tuy nhiên, tôi không thấy nó có thể hoạt động như thế nào khi nhiều cơ thể (và cả cơ thể tĩnh) va chạm cùng một lúc. Ngay cả khi không có trọng lực, việc có một cơ thể năng động va chạm cùng một lúc với một cơ thể tĩnh và một cơ thể năng động khác gây ra vấn đề. Vì vận tốc được hoán đổi, tất cả phụ thuộc vào thứ tự va chạm. Nếu cơ thể tĩnh bị va chạm lần cuối, cơ thể sẽ ngừng di chuyển. Nếu một người năng động, cơ thể sẽ di chuyển một lần nữa. Cái này cố định thế nào?
Vittorio Romeo

@Vee: Câu hỏi hay! Ba cơ thể + và cơ thể tĩnh là hai vấn đề riêng biệt. Tôi đã giải quyết cả hai trong một bản cập nhật. Tóm tắt: xử lý va chạm hai đối tượng cùng một lúc; cơ thể tĩnh có khối lượng rất lớn, vô hạn.
Leftium

Mô hình của bạn để nghỉ liên lạc là kỳ lạ. Liên lạc nghỉ ngơi không chỉ vì trọng lực, họ nên làm việc cho bất kỳ lực nào. Cách dễ nhất để làm việc là chỉ cần loại bỏ vận tốc đạt được do tăng tốc trong khung trước khi tiếp xúc. Ngoài ra, với vận tốc nhỏ, bạn có thể loại bỏ hoàn toàn sự bồi thường, mặc dù các tính toán của bạn không tính đến sự phục hồi. Cách tiếp cận này hiệu quả với tất cả các lực lượng, nó dễ thực hiện và có vẻ đủ tốt.
dreta

16

Giải quyết vấn đề này đòi hỏi phải điều chỉnh vị trí và có thể là vận tốc. Các động cơ vật lý cơ thể cứng nhắc có một bộ giải di chuyển các vật thể về phía trước theo thời gian bằng cách sử dụng các định luật chuyển động của Newton đồng thời giải quyết các hạn chế và ma sát không thâm nhập. Những động cơ này có thể tính toán sự kết hợp đúng của chuyển động tuyến tính và góc để tạo ra quỹ đạo hợp lý.

Nếu bạn chỉ muốn giải quyết sự chồng chéo, bạn có thể sử dụng vận tốc giả tạo ra các quỹ đạo tách biệt mà không cần thêm động lượng. Điều này được thực hiện trong bộ giải vị trí của Box2D.

Tôi khuyên bạn nên nhận các bài thuyết trình GDC của mình từ năm 2006 và 2007 tại đây:

http://code.google.com.vn/p/box2d/doads/list

Ngoài ra, bạn có thể xem Box2D Lite để thực hiện đơn giản hóa.


+1 cho nhận xét là cần thiết để điều chỉnh vị trí là tốt. Rất ít người thưởng thức điều này, nhưng để thêm vào sự ổn định mô phỏng, hầu hết các động cơ gian lận bằng cách điều chỉnh các vị trí trực tiếp. Nói chung, nếu nó hợp lý, nó hoạt động cho các trò chơi.
teodron

Cảm ơn câu trả lời. Tôi muốn biết một điều mà có lẽ tôi đã bỏ lỡ trong bài thuyết trình: các cơ quan tĩnh được xử lý theo cách đặc biệt trong Box2D? Ý tôi là - điều gì xảy ra khi một cơ thể năng động chạm vào một cơ thể tĩnh?
Vittorio Romeo

2

nhập mô tả hình ảnh ở đây

Trong thế giới thực, không có lực lượng nào "đẩy" một cơ thể ra bên ngoài một cơ thể khác bởi vì các vật thể không bao giờ xâm nhập lẫn nhau. Điều gần nhất là lực bình thường : được tạo ra tại thời điểm tiếp xúc trong các vụ va chạm trong thế giới thực, nó ngăn chặn sự xâm nhập ở nơi đầu tiên.

Góc của lực bình thường này vuông góc với bề mặt tiếp xúc của hai vật va chạm. Độ lớn phụ thuộc vào mức độ cần thiết để ngăn chặn sự xâm nhập. (Lưu ý chỉ nên sử dụng thành phần y của lực thông thường trừ khi các lực khác như lực ma sát cũng được mô hình hóa).

Mặc dù có thể mô hình hóa lực bình thường một cách rõ ràng, nhưng đơn giản hơn là chỉ mô hình hóa các hiệu ứng của nó:

  1. Ngăn chặn giao lộ đối tượng bằng một trong hai cách:
    • Điều chỉnh vận tốc bằng cách giải quyết va chạm tại thời điểm va chạm. (tốt)
    • Tự điều chỉnh vị trí của các cơ thể để chúng không giao nhau. (dễ dàng hơn) Bạn đã thực hiện việc này "bằng cách tìm vectơ thâm nhập ngắn nhất và thêm nó vào vị trí của AABB."
  2. Không áp dụng trọng lực khi có lực bình thường triệt tiêu lực hấp dẫn.
    • Một vật tiếp xúc với một vật khác bên dưới nó chịu tác dụng của lực bình thường. Do đó, đây là vấn đề theo dõi các đối tượng đó. (Trên thực tế, bất kỳ vật thể nào tiếp xúc nên được áp dụng một lực bình thường, nhưng không phải tất cả những vật thể này sẽ có tác động ròng đối với trọng lực.)
    • Nếu bạn muốn thêm các vật thể có thể trượt xuống các vật thể khác ở một góc, bạn sẽ phải thêm lực ma sát và thành phần x của lực thông thường.

Tôi đã mô tả điều này hơi khác trong câu trả lời khác của tôi, nói thêm về va chạm nói chung .

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.