Одним из самых простых методов предварительной проверки пересекаются ли два объекта в пространстве, является проверка по ограничивающим объектам, в частности по AABB (Axis Aligned Bounding Box).
Хотя проверка коллизий по AABB не очень очная, так как совершенно не учитывает форму объектов, она позволяет исключить из дальнейших, более точных и более затратных, проверок объекты, которые заведомо не пересекаются, что особенно полезно при проверке сложных сцен со множеством объектов.
Рассмотрим проверку пересечений для двух параллелограммов. AABB для параллелограмма совпадает с его фактической формой, что дает нам возможность наглядно отслеживать их пересечения.
Добавим в сцену два куба и немного изменим их размеры, чтобы они превратились в параллелограммы. Мы можем обращаться к ним через указатель в bpy.data:
1 2 |
obj1 = bpy.data.objects['Cube'] obj2 = bpy.data.objects['Cube.001'] |
Переведем координаты их точек в глобальную систему координат, чтобы учесть смещения и трансформации объектов:
1 2 |
obj1_w = [obj1.matrix_world @ vertex.co for vertex in obj1.data.vertices] obj2_w = [obj2.matrix_world @ vertex.co for vertex in obj2.data.vertices] |
И рассчитаем для каждого из них AABB при помощи функции _aabb().
1 2 3 4 5 |
aabb1 = _aabb(obj1_w) aabb2 = _aabb(obj2_w) # {'min_x': -1.272713541984558, 'min_y': -4.576056480407715, 'min_z': ...} # {'min_x': -3.163292646408081, 'min_y': -6.7881975173950195, 'min_z': ...} |
Определим функцию, которая будет проверять два AABB на пересечение.
Наша функция будет возвращать True, если есть пересечение между двумя переданными в параметрах AABB, или False, если пересечения между переданными в параметрах AABB нет.
1 2 3 4 5 6 7 8 9 10 |
def collision_aabb(aabb_1, aabb_2): if aabb_1['min_x'] < aabb_2['max_x'] \ and aabb_1['max_x'] > aabb_2['min_x'] \ and aabb_1['min_y'] < aabb_2['max_y'] \ and aabb_1['max_y'] > aabb_2['min_y'] \ and aabb_1['min_z'] < aabb_2['max_z'] \ and aabb_1['max_z'] > aabb_2['min_z']: return True else: return False |
Теперь мы можем проверить, пересекаются ли AABB для наших объектов в сцене:
1 2 3 4 |
col = collision_aabb(aabb1, aabb2) print('YES' if col else 'NO') # NO |
Если пересечений двух AABB нет, мы можем гарантированно считать, что объекты не пересекаются и не тратить время и мощности компьютера на более точные и затратные проверки.