Как следует обновлять Axis-Aligned Bounding Box (AABB) при выполнении поворота объекта?

Как вычислить AABB бокс после выполнения поворота объекта, если у меня уже есть инициированные AABB и OBB боксы, и я не хочу пересчитывать точки? У объекта имеется матрица трансформации, а также минимальный охватывающий прямоугольник со своей матрицей. Я пробовал реализовать функцию, но она не работает должным образом — прямоугольник всегда оказывается большим, и при первом повороте он ломается. Есть ли другой способ расчета, помимо полного пересчета?
  • 2 апреля 2025 г. 4:05
Ответы на вопрос 2
Для обновления Axis-Aligned Bounding Box (AABB) объекта после его поворота, если у вас уже есть OBB (Oriented Bounding Box) и матрица трансформации, вы можете воспользоваться следующими шагами.

1. **Вычисление OBB после поворота**: Для начала вам нужно рассчитать новый OBB для объекта. Вам необходимо умножить векторы, описывающие OBB, на матрицу трансформации (она должна содержать информацию о повороте, а также, возможно, о масштабировании и сдвиге). Если у вас есть углы OBB, вы можете получить новые координаты точек, применив трансформацию.

   Для вращения OBB вам нужно будет просто использовать его текущие углы и применить вращение.

2. **Получение AABB из OBB**: Теперь у вас есть OBB, и вы можете получить AABB, просто найдя его минимальные и максимальные координаты. Для этого вам нужно будет вычислить минимальное (min) и максимальное (max) значение для каждой оси (X, Y, Z) в OBB.

3. **Выявление новых границ AABB**:
   - Сначала определите 8 вершин OBB.
   - Для каждой вершины OBB выясните, в каких пределах она попадает по каждой из осей (X, Y, Z).
   - Используйте эти значения, чтобы обновить минимальные и максимальные границы для AABB.

### Примерный алгоритм:

```python
def update_aabb(aabb, obb):
    # предполагается, что OBB представлен как матрица 4x4, где первые три строки и 
    # столбцы соответствуют осям OBB и последняя строка отвечает за перенос
    points = []
    
    # Сбор вершин OBB
    for i in [-1, 1]:
        for j in [-1, 1]:
            for k in [-1, 1]:
                point = np.array([obb.center[0] + i * obb.extents[0],
                                  obb.center[1] + j * obb.extents[1],
                                  obb.center[2] + k * obb.extents[2],
                                  1])
                transformed_point = obb.transform_matrix @ point
                points.append(transformed_point[:3])  # сохраняем только X, Y, Z

    # Актуализируем AABB
    min_x = min(point[0] for point in points)
    max_x = max(point[0] for point in points)
    min_y = min(point[1] for point in points)
    max_y = max(point[1] for point in points)
    min_z = min(point[2] for point in points)
    max_z = max(point[2] for point in points)

    return np.array([min_x, min_y, min_z]), np.array([max_x, max_y, max_z])
```

### Условия для корректного обновления:

1. **Тщательная работа с матрицей трансформации**: Убедитесь, что ваша матрица трансформации действительно учитывает только поворот (и, если необходимо, масштабирование). Если вы добавляете сдвиг, то он также повлияет на ваше AABB.

2. **Точное преобразование векторов**: Проверяйте, как вы рассчитываете новые координаты. Ошибочные преобразования к координатам 3D могут увеличить размеры AABB.

Если у вас есть еще какие-то конкретные примеры или данные, в которых происходит сбой, я могу помочь более детально.
С OBB проще, поскольку он находится в системе координат объекта и трансформируется вместе с объектом. 
AABB находится в базовой системе координат и при повороте объекта его надо полностью пересчитывать, определяя новые минимальные и максимальные координаты точек объекта после поворота.
Похожие вопросы