Làm thế nào để tôi tính toán phản ứng va chạm giữa một quả cầu và một mặt phẳng?


9

Tôi đang cố gắng tạo một trò chơi 3D đơn giản và cần giới hạn người chơi trong giới hạn của thế giới trò chơi. Khi người chơi đến hai bên thế giới, tôi muốn con tàu của người chơi bật lên một chút.

Thực tế, tôi đang cố nhốt người chơi trong một cái hộp và ngăn họ trốn thoát qua các bên ...

Tôi đã quản lý để xác định các giới hạn của thế giới trò chơi là một tập hợp các mặt phẳng, với các quy tắc và khoảng cách từ gốc. Người chơi có một hình cầu giới hạn hình cầu và từ trang web này http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php Tôi đã quản lý để phát hiện va chạm.

Bây giờ tôi không thể biết mình phải làm gì khi phát hiện va chạm. Điều tốt nhất tôi có thể quản lý là người chơi bị mắc kẹt trong máy bay, đi thẳng qua nó hoặc nảy liên tục ra khỏi nó với tốc độ rất nhanh.

Thông thường cho tôi biết tôi cần tính toán góc phản xạ khỏi mặt phẳng, sử dụng bình thường của nó và áp dụng điều đó cho vận tốc của người chơi, tuy nhiên tôi nghĩ rằng trước tiên tôi cần phải xem người chơi có đi qua máy bay không, đó là bit tôi không thể tập thể dục.

Câu trả lời:


4

Bạn sẽ phải áp dụng một xung cho đối tượng của bạn, đó là một sự thay đổi ngay lập tức trong vận tốc của nó. Trong thế giới thực, một lực mạnh sẽ được tác dụng lên vật thể trong một dấu thời gian rất ngắn, đảo ngược gia tốc của nó và khiến vận tốc của nó thay đổi. Tuy nhiên, vì chúng ta đang làm việc trong một thế giới riêng biệt, chúng ta phải gian lận một chút để mô phỏng sự thay đổi đột ngột này theo hướng. Đối với một hình cầu và một mặt phẳng, nó khá đơn giản. Phản ứng va chạm cơ bản nhất là phản ánh vận tốc của quả cầu xung quanh bình thường của mặt phẳng, và sau đó kết quả là vận tốc mới của quả cầu. Mã giả sẽ trông giống như thế này:

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected

Từ đó, bạn có thể thêm một số giảm xóc (nhân với một số hệ số, như 0,9) để tính năng lượng bị mất do nhiệt hoặc ma sát. Nếu bạn muốn có được vận tốc góc liên quan (có lẽ quả cầu của bạn đang quay), thì các phương trình trở nên phức tạp hơn một chút.

Để biết thêm thông tin, tôi sẽ giới thiệu cho bạn các bài viết của Chris Hecker về Cơ thể cứng nhắc . Nếu bạn chưa từng nghe về Chris Hecker trước đây, thì anh ta nổi tiếng về vật lý trò chơi cũng như công việc của anh ta về thế hệ nhân vật và hoạt hình thủ tục trong Spore.


4
Đây thực chất là cách đúng đắn để đi, tuy nhiên việc tính toán thời gian tác động (TOI) có thể khiến mọi thứ chính xác hơn khi các khung hình dao động hoặc giảm xuống. Biết được, dựa trên vận tốc hiện tại, tác động xảy ra cách đây bao lâu có thể giúp bạn tính toán thời gian va chạm và sử dụng để bạn có thể di chuyển quả cầu trở lại vị trí của nó tại thời điểm va chạm và điều chỉnh vận tốc từ đó. Sau khi điều chỉnh vị trí và vận tốc từ điểm va chạm, tại thời điểm va chạm, sau đó bạn di chuyển dọc theo vận tốc mới theo lượng thời gian bạn đã trừ để đến TOI.
Nic Foster

OK điều này có vẻ chủ yếu hoạt động, nhưng nó hơi ... lạ. Tôi nghĩ rằng tôi có thể đang làm điều này ở điểm sai trong mã của tôi. Tôi có nên lặp qua tất cả các đối tượng của mình và kiểm tra xem chúng có va chạm trước khi tôi di chuyển chúng không (dựa vào vị trí chúng sẽ ở khung tiếp theo) hoặc di chuyển chúng và sau đó kiểm tra va chạm sau đó?
Piku

@Piku, không phát hiện nếu họ sẽ va chạm. Nếu một vụ va chạm xảy ra hãy nhớ rằng rất có thể hai vật thể hiện đang chồng chéo nhau vượt xa nơi xảy ra va chạm thực tế. Về cơ bản, bạn cần phải tìm ra nơi xảy ra vụ va chạm như thể bạn có tốc độ khung hình vô hạn (mà bạn không) và di chuyển đối tượng trở lại vị trí xảy ra va chạm ban đầu. Nếu bạn không tách các đối tượng như thế này, bạn sẽ liên tục phản ứng với cùng một vụ va chạm và đối tượng sẽ bị kẹt.
Jonathan Dickinson

@Piku và để làm điều đó, chúng tôi tìm ra thời gian trong quá khứ xảy ra va chạm (gọi là TOI / thời gian tác động). Khi chúng ta có được điều đó, chúng ta có thể sử dụng vận tốc của vật thể để di chuyển nó trở lại ( distance = speed * time, thường là với một khoảng cách cực nhỏ để tránh lỗi) và sau đó cập nhật vận tốc của nó thành kết quả va chạm.
Jonathan Dickinson

@Piku chúng tôi cũng không tìm ra nơi chúng tôi sẽ ở trong khung tiếp theo (tôi chưa bao giờ thấy điều đó được thực hiện cá nhân), nhưng, nói chung, chúng tôi phát hiện và phản ứng va chạm: SAU chúng tôi tính toán vị trí mới cho khung NÀY, nhưng TRƯỚC chúng tôi áp dụng vị trí mới cho khung NÀY.
Jonathan Dickinson

1

F = ma, hoặc a = F / m. Tính điểm va chạm giữa quả cầu và mặt phẳng. Đây thường là tâm Sphere - bán kính * bình thường. Nếu bạn muốn độ chính xác cao hơn, hãy tính khoảng cách quả cầu đã xuyên qua mặt phẳng và điều chỉnh tính toán của bạn. Điều này phần lớn là tùy chọn tất nhiên, trừ khi bạn muốn vật lý thực sự chính xác. Bây giờ hãy tính vận tốc tương đối dọc theo bình thường. Đối với mặt phẳng tĩnh, đây là: Vball Dot N. Sau đó nhân VballDotN với -1 và nhân với khối lượng. Trong vật lý ở giai đoạn này, bạn cũng sẽ nhân hệ số này với hệ số phục hồi (hệ số nảy). Nhân số vô hướng này với N và bạn có lực của bạn.

Khi điều chỉnh Vball, chia lực theo khối lượng một lần nữa và bạn có gia tốc cuối cùng, vì vậy chỉ cần thêm điều này vào vận tốc và bạn có vận tốc va chạm bài cuối cùng.

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());

Phương pháp này là chính xác cho các công thức của phản ứng va chạm. Nếu bạn muốn độ chính xác cao hơn nữa, bạn sẽ muốn tính đến ma sát, điều này sẽ khiến quả bóng quay, nhưng tôi không biết nếu bạn muốn điều đó trong trò chơi của mình. Trong trường hợp bạn làm, đây là cách bạn tính toán lực tiếp tuyến:

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));

Đảm bảo tính toán Ft trước khi áp dụng bất kỳ hiệu ứng tuyến tính nào, hoặc ma sát sẽ không chính xác.


Không nên dòng 3 là : vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;?
Shital Shah

Quả thực là có, tôi đã bỏ lỡ phần đó. Cảm ơn đã chỉ ra điều đó.
Ian Young

0

Tôi sẽ đề nghị tính toán khoảng cách từ máy bay trước; và sau đó khi khoảng cách <= đến bán kính thực hiện phản ứng va chạm.

Sau đó, bạn có thể thay đổi điều này để tính khoảng cách và nếu khoảng cách nhỏ hơn bán kính đó (có nghĩa là vật thể chồng lên nhau) dịch chuyển vị trí quả bóng và sau đó thực hiện phản ứng va chạm.

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.