Làm cách nào để triển khai CollisionObject Bullet Vật lý đại diện cho khối lập phương của tôi như địa hình?


8

Tôi đã tích hợp thành công thư viện Bullet Vật lý vào hệ thống thực thể / thành phần của mình. Các thực thể có thể va chạm với nhau. Bây giờ tôi cần cho phép chúng va chạm với địa hình vốn là hữu hạn và giống như khối lập phương (nghĩ InfiniMiner hoặc nó là bản sao Minecraft ). Tôi chỉ bắt đầu sử dụng thư viện Bullet Vật lý ngày hôm qua, vì vậy có lẽ tôi đang thiếu một cái gì đó rõ ràng.

Cho đến nay tôi đã mở rộng RigidBodylớp để ghi đè checkCollisionWith(CollisionObject co)hàm. Hiện tại, nó chỉ là một kiểm tra đơn giản về nguồn gốc, không sử dụng hình dạng khác. Tôi sẽ lặp lại về điều đó sau. Bây giờ nó trông như thế này:

@Override
public boolean checkCollideWith(CollisionObject co) {
    Transform t = new Transform();
    co.getWorldTransform(t);
    if(COLONY.SolidAtPoint(t.origin.x, t.origin.y,t.origin.z)){
        return true;
    }
    return false;
}

Điều này hoạt động rất tốt, theo như phát hiện khi va chạm xảy ra. Tuy nhiên, điều này không xử lý các phản ứng va chạm. Có vẻ như phản ứng va chạm mặc định là để di chuyển các vật thể va chạm bên ngoài các hình dạng khác, có thể là AABB của chúng.

Hiện tại hình dạng của địa hình chỉ là một cái hộp có kích thước của thế giới. Điều này có nghĩa là các thực thể va chạm với địa hình chỉ bắn ra bên ngoài hộp kích thước thế giới đó. Vì vậy, rõ ràng là tôi cần phải sửa đổi phản ứng va chạm hoặc tôi cần tạo một hình dạng phù hợp trực tiếp với hình dạng của địa hình. Vì vậy, lựa chọn nào là tốt nhất và làm thế nào để tôi thực hiện nó? Có lẽ có một lựa chọn tôi không nghĩ đến?

Cần lưu ý rằng địa hình là động và thường xuyên được người chơi sửa đổi.

Câu trả lời:


8

Mặc dù tôi đánh giá cao câu trả lời của Kevin Reid, nhưng nó ở mức cao hơn câu hỏi của tôi. Có thể hiểu được với kiến ​​thức về Bullet Vật lý, thật khó để trả lời câu hỏi này. Tôi đã làm việc này và có một câu trả lời dành riêng cho Bullet Vật lý.

Cùng với việc mở rộng RigidBodylớp học như tôi đã đề cập trong câu hỏi của tôi. Tôi cũng cần phải mở rộng CollisionAlgorithmlớp học. Điều này chủ yếu là để ghi đè processCollision()chức năng. Bên trong processCollision()hàm (lấy hai cơ thể va chạm làm đối số), tôi có thể tạo một hình khối và phù hợp Transformvới khối mà thực thể của tôi hiện đang va chạm. Sau đó, chỉ cần để xung đột mặc định xảy ra dựa trên thực thể và khối / khối cụ thể mà nó va chạm. Để sử dụng phần mở rộng mới CollisionAlgorithm, tôi cần phải đăng ký thuật toán để xử lý các hình dạng mà tôi muốn nó xử lý. Trong trường hợp này, đó là loại địa hình khá nhiều so với mọi thứ khác. Cho rằng tôi đã sử dụng registerCollisionCreateFunc()với của tôi CollisionDispatcher.

Vì vậy, đối với những người theo sau trong tương lai:

  1. Mở rộng RigidBodyđể kiểm tra va chạm cơ bản với địa hình của bạn.
  2. Tạo một thể hiện của RigidBodylớp của bạn và thêm nó vào DynamicsWorldhoặc bất cứ thứ gì PhysicsProccesorbạn đang sử dụng.
  3. Mở rộng CollisionAlgorithm, đặc biệt processCollision()để tạo các hình dạng Vật lý Bullet và Biến đổi phù hợp với vị trí va chạm của bạn.
  4. Đăng ký phiên bản của CollisionAlgorithmbạn với việc CollisionDispatchersử dụng của bạn registerCollisionCreateFunc(). (Việc đăng ký này được thực hiện nhiều lần, một lần cho mỗi cặp hình bạn muốn va chạm.)

BIÊN TẬP

Đây là một video của nó trong hành động nếu bất cứ ai quan tâm.

Phát hiện va chạm ban đầu

Đối với kiểm tra va chạm ban đầu của tôi, phần mở rộng của tôi rigidBodyghi đè checkCollideWithchức năng được mô tả trong câu hỏi của tôi. Tôi có một chức năng cho địa hình của mình có thể kiểm tra xem thế giới có vững chắc tại một điểm cụ thể không. Về cơ bản, tôi kiểm tra địa hình của mình chống lại vật thể được truyền vào bởi checkCollideWithchức năng, xem liệu địa hình của tôi có vững chắc ở bất kỳ đâu trong giới hạn của vật thể đó không.

Bây giờ, cũng có bước tiếp theo trong Bullet, tìm kiếm các điểm liên lạc. Điều này diễn ra trong processCollision()chức năng tôi đã đề cập ở trên. Ở đây, tôi đã tạo một hình hộp Kích thước của một khối địa hình, sau đó khi tôi phát hiện ra một vụ va chạm trong checkCollideWithchức năng, tôi đặt hộp hình khối có kích thước khối địa hình đó vào vị trí va chạm và để Bullet sử dụng tất cả các thuật toán mặc định của nó để phát hiện các điểm va chạm ở đó .

Vì vậy, về cơ bản, nếu một đối tượng vật lý giới hạn chạm vào vật liệu rắn. Tôi sẽ đặt cơ thể vật lý tạm thời của mình đến vị trí đó và bảo Bullet kiểm tra va chạm với khối lập phương tạm thời đó, như thể nó luôn ở đó. Điều này giống như siêu tối ưu hóa việc đặt một BoxShape cho mọi khối trong địa hình của tôi. Thay vì hàng triệu BoxShapes, tôi chỉ cần có một cái dịch chuyển tức thời xung quanh khi phát hiện va chạm.


Bạn có thể mở rộng thêm về cách bạn phát hiện va chạm ở nơi đầu tiên không?
timoxley

1
@timoxley Tôi đã cập nhật câu trả lời một chút.
MichaelHouse

Làm thế nào bạn sẽ xử lý một vật phẩm va chạm tại nhiều điểm, ví dụ như một cái thang dựa trên mặt đất và trên tường?
timoxley

Khối lập phương tạm thời được di chuyển xung quanh cho tất cả những nơi mà một vật thể tiếp xúc với địa hình. Nó chỉ được sử dụng để phát hiện tốt để có được điểm liên lạc và phản hồi thích hợp.
MichaelHouse

3

Tôi đã gặp một số rắc rối với chiến lược được thực hiện trong câu trả lời khác của tôi. Các điểm tiếp xúc đôi khi sẽ dính xung quanh, thật khó để tạo ra các hình dạng khác với hình khối và đôi khi nó sẽ cho phép các vật thể trượt qua địa hình.

Vì vậy, thay vì sửa đổi hoặc ghi đè bất kỳ lớp Bullet nào, có một tùy chọn khác là sử dụng một đối tượng va chạm Bullet tích hợp sẽ đại diện cho địa hình. Các BvhTriangleMeshShape( doc ) là một xây dựng trong tình trạng được đại diện bởi một lưới tam giác.

Lưới này có thể được tạo ra cùng lúc với lưới để trực quan hóa thế giới. Điều này có nghĩa là đối tượng vật lý có thể khớp chính xác với đối tượng được kết xuất.

Tôi tạo một RigidBodycho mỗi đoạn trong địa hình của tôi. Cơ thể đó có hình dạng của nó được đặt thành a BvhTriangleMeshShape. Khi địa hình được sửa đổi, đồng thời tôi đang xây dựng lại hình ảnh đại diện của khối, tôi cũng đang xây dựng lại hình dạng vật lý. Sau đó, khi đến lúc để đệm hình dạng trực quan, tôi cũng trao đổi các hình dạng vật lý như vậy:

dynamicsWorld.removeRigidBody(chunk.getRigidBody());
chunk.getRigidBody().setCollisionShape(newShape);
dynamicsWorld.addRigidBody(chunk.getRigidBody());

Điều này đảm bảo rằng cơ thể được loại bỏ đúng cách, làm sạch các điểm tiếp xúc. Sau đó, hình dạng của nó được thay đổi và nó được thêm lại.

Để tạo ra BvhTriangleMeshShapemỗi đoạn phải duy trì một TriangleIndexVertexArray( doc ). Đây thực chất là hai bộ đệm byte. Một với các vị trí của các đỉnh tam giác và một với các chỉ số để xây dựng các tam giác đó. Mảng đỉnh này phải được duy trì vì BvhTriangleMeshShapekhông tạo ra một bản sao của dữ liệu.

Sử dụng tất cả các lớp vật lý được xây dựng trong Bullet có khả năng nhanh hơn bất cứ thứ gì tôi có thể viết, và nó thực sự chạy rất nhanh. Tôi chưa thấy sự chậm lại nào sau khi thực hiện chiến lược mới này.

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


Tôi sẽ lưu ý với bất kỳ ai đọc điều này, ít nhất là trong thử nghiệm của tôi, JBONS RẤT chậm trong việc nấu lưới (tức là tiền xử lý chúng trước khi chúng có thể được sử dụng cho vật lý), ít nhất là so với thời gian tôi cần để chuyển đổi một miếng thành một lưới thông qua các hình khối diễu hành. Chúng ta đang nói những đơn đặt hàng có cường độ chậm hơn. Vì vậy, tôi sẽ xem xét PhysX và xem tôi có thể thực hiện nó tốt hơn như thế nào. Nếu bất cứ ai có thông tin về điều này, tôi rất muốn nghe nó.
Philip Guin

2

Tôi không quen thuộc với Bullet Vật lý, nhưng tôi đã sử dụng ODE. Ở đó, sau thử nghiệm va chạm có hoặc không, có một thử nghiệm va chạm hình dạng hình dạng chi tiết hơn tạo ra một tập hợp các điểm tiếp xúc.

Trong trường hợp của bạn, thế giới của bạn là một tập hợp các hộp, vì vậy bạn có thể làm điều này:

  1. Lấy AABB của thực thể di chuyển.
  2. Lặp đi lặp lại trên các voxels địa hình trong khối lượng giao nhau với nó.
  3. Đối với mỗi voxel của địa hình rắn, xây dựng một hộp phù hợp và tính toán (tốt nhất là sử dụng các thói quen được cung cấp của động cơ vật lý) sự va chạm của hộp đó với thực thể di chuyển.
  4. Trả về bộ sưu tập của tất cả các điểm liên lạc kết quả.

Đây không phải là xác định lại phản ứng va chạm ; đây là một lớp trước đó Phản ứng va chạm được xác định đầy đủ bởi các điểm tiếp xúc được tính từ vụ va chạm.

Như tôi đã nói, tôi không quen thuộc với Bullet Vật lý, vì vậy tôi không biết liệu kiến ​​trúc của nó có phù hợp với điều này không.


Cảm ơn. Tôi nghĩ rằng phản ứng va chạm cũng được gắn vào thử nghiệm va chạm hình dạng. Nó phải sử dụng thông tin đó để quyết định cách nào để di chuyển chúng ra xa nhau và cách chúng cách xa nhau đúng không? Tôi sẽ ổn với phản ứng va chạm hiện tại nếu nó phản ứng với hình dạng địa hình của tôi.
MichaelHouse

Đúng; Tôi có nghĩa là bạn không xác định lại thuật toán phản ứng va chạm mà chỉ xác định lại việc tạo các điểm tiếp xúc là đầu vào của thuật toán đó.
Kevin Reid
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.