Мы создаем FPS в XNA, и мы находимся в процессе реализации обнаружения столкновений. Наши стены имеют прямоугольную форму, поэтому класс BoundingBox кажется хорошим вариантом, но он выровнен по оси. Нам бы очень хотелось иметь неосевые стены. Большая часть обсуждений, которые мы видели, говорит об использовании BoundingSpheres, но это не кажется лучшим вариантом, потому что стены на самом деле представляют собой просто повернутые прямоугольники.
Нам удалось смоделировать движение персонажа в виде лучей, и мы знаем, что мы должны быть в состоянии перевести эти лучи из мирового пространства в выровненное по оси поле, используя матрицу вращения. К сожалению, мы думаем, что с этим преобразованием что-то не так, потому что мы, кажется, сталкиваемся с невидимыми (или как-то более большими) стенами, и наша генерация лучей работает для пересечений пола (которые еще не вращаются [в любом случае]). Единственная причина, по которой мы используем лучи, заключается в том, что они легко генерируются, должны легко преобразовываться в пространство блока, и мы можем использовать классы XNA, такие как BoundingBox для выравнивания оси, для фактического обнаружения столкновений.
Мы реализовали это так:
internal float? collide(Ray ray) {
Matrix transform = Matrix.Invert(Transform);
ray.Direction = Vector3.Transform(ray.Direction, transform);
ray.Position = Vector3.Transform(ray.Position, transform);
return new BoundingBox(new Vector3(-.5f, -.5f, -.5f), new Vector3(.5f, .5f, .5f)).Intersects(ray);
}
public Matrix Transform { get { return Matrix.CreateScale(size) * rotate * Matrix.CreateTranslation(pos); } }
Rotate передается в конструкторе и формируется с помощью вызова Matrix.CreateRotationY (theta). Луч, прошедший в столкновение, находится в мировом пространстве. Transform - это также матрица, применяемая к нашей модели для рендеринга. Эта модель представляет собой куб, который изменяется от (-.5, -.5, -.5) до (.5, .5, .5).
В любом случае наш вопрос сводится к нескольким вещам: есть ли лучший способ обнаружения столкновений для неосевых выравнивающих прямоугольников по лучам? Есть ли лучший способ сделать это, чем с помощью лучей? Мы просто идиоты с чем-то явно не в нашем коде? Если возможно, мы бы хотели как можно больше полагаться на классы XNA (или, по крайней мере, на уже написанный код) и не должны писать намного больше, чем класс-оболочка.