Chỉ với tối đa 30 đối tượng, bạn không cần tối ưu hóa nhiều thứ khác ngoài việc không kiểm tra hai cặp giống nhau hơn một lần trên mỗi khung. Mà mẫu mã dưới đây sẽ bao gồm. Nhưng nếu bạn thấy thú vị trong các tối ưu hóa khác nhau mà một công cụ vật lý sẽ sử dụng thì hãy tiếp tục đọc qua phần còn lại của bài đăng này.
Những gì bạn sẽ cần là một triển khai phân vùng không gian , chẳng hạn như Octree (cho trò chơi 3D) hoặc Quadtree (cho trò chơi 2D). Các phân vùng này thế giới thành các phần phụ, và sau đó mỗi phần phụ được phân vùng hơn nữa trong cùng một trang viên, cho đến khi chúng được chia thành một kích thước tối thiểu. Điều này cho phép bạn kiểm tra rất nhanh những vật thể khác trong cùng khu vực với thế giới khác, điều này hạn chế số lượng va chạm mà bạn phải kiểm tra.
Ngoài phân vùng không gian, tôi khuyên bạn nên tạo AABB ( hộp giới hạn căn chỉnh trục ) cho mỗi đối tượng vật lý của bạn. Điều này cho phép bạn kiểm tra AABB của một đối tượng so với đối tượng khác, nhanh hơn nhiều so với kiểm tra per-poly chi tiết giữa các đối tượng.
Điều này có thể tiến thêm một bước nữa đối với các đối tượng vật lý phức tạp hoặc lớn, trong đó bạn có thể tự phân chia lưới vật lý, tạo cho mỗi hình dạng AABB của chính nó mà bạn chỉ có thể kiểm tra nếu hai AABB của đối tượng bị chồng chéo.
Hầu hết các động cơ vật lý sẽ hủy kích hoạt mô phỏng vật lý hoạt động trên cơ thể vật lý một khi chúng nghỉ ngơi. Khi một cơ thể vật lý bị vô hiệu hóa, nó chỉ cần kiểm tra va chạm với AABB của nó từng khung và nếu có bất cứ điều gì va chạm với AABB thì nó sẽ kích hoạt lại và thực hiện kiểm tra va chạm chi tiết hơn. Điều này giữ cho thời gian mô phỏng xuống.
Ngoài ra, nhiều động cơ vật lý sử dụng 'đảo mô phỏng', đó là nơi một nhóm các cơ thể vật lý gần nhau được nhóm lại với nhau. Nếu tất cả mọi thứ trong đảo mô phỏng đều dừng lại thì đảo mô phỏng tự hủy. Lợi ích của đảo mô phỏng là tất cả các cơ thể bên trong nó có thể ngừng kiểm tra va chạm một khi hòn đảo không hoạt động, và việc kiểm tra duy nhất mỗi khung là xem có thứ gì vào AABB của đảo không. Chỉ khi một cái gì đó đi vào AABB của hòn đảo, mỗi cơ quan trong đảo sẽ cần kiểm tra va chạm. Đảo mô phỏng cũng kích hoạt lại nếu bất kỳ cơ thể nào bên trong nó bắt đầu tự di chuyển trở lại. Nếu một cơ thể di chuyển đủ xa từ trung tâm của nhóm, nó sẽ bị xóa khỏi đảo.
Cuối cùng, bạn còn lại một cái gì đó như thế này (bằng mã giả):
// Go through each leaf node in the octree. This could be more efficient
// by keeping a list of leaf nodes with objects in it.
for ( node in octreeLeafNodes )
{
// We only need to check for collision if more than one object
// or island is in the bounds of this octree node.
if ( node.numAABBsInBounds > 1)
{
for ( int i = 0; i < AABBNodes.size(); ++i )
{
// Using i+1 here allows us to skip duplicate checks between AABBS
// e.g (If there are 5 bodies, and i = 0, we only check i against
// indexes 1,2,3,4. Once i = 1, we only check i against indexes
// 2,3,4)
for ( int j = i + 1; j < AABBNodes.size(); ++j )
{
if ( AABBOverlaps( AABBNodes[i], AABBNodes[j] ) )
{
// If the AABB we checked against was a simulation island
// then we now check against the nodes in the simulation island
// Once you find overlaps between two actual object AABBs
// you can now check sub-nodes with each object, if you went
// that far in optimizing physics meshes.
{
}
}
}
}
Tôi cũng khuyên bạn không nên có quá nhiều vòng lặp trong các vòng lặp như thế này, mẫu ở trên chỉ để bạn có ý tưởng, tôi sẽ chia nó thành nhiều chức năng cung cấp cho bạn chức năng giống như những gì được hiển thị ở trên.
Ngoài ra, đảm bảo không thay đổi bộ chứa AABBNodes trong khi lặp qua nó, vì điều đó có thể có nghĩa là kiểm tra va chạm bị bỏ lỡ. Điều này nghe có vẻ như lẽ thường, nhưng bạn sẽ ngạc nhiên khi mọi thứ phản ứng với va chạm dễ dàng gây ra những thay đổi mà bạn không lường trước được. Ví dụ: nếu một vụ va chạm khiến một trong các đối tượng va chạm thay đổi vị trí đủ để loại bỏ chúng khỏi AABB của nút Octree mà bạn đang kiểm tra thì nó có thể thay đổi vùng chứa đó. Để giải quyết vấn đề này, tôi khuyên bạn nên giữ một danh sách tất cả các sự kiện va chạm xảy ra trong quá trình kiểm tra, và sau đó sau khi tất cả các kiểm tra hoàn tất, hãy chạy qua danh sách và gửi bất kỳ sự kiện va chạm nào.