Вычислить верхний левый и нижний правый угол прямоугольника с заданным началом координат, направлением и размером

#c# #xna #3d #vector-graphics

#c# #xna #3D #векторная графика

Вопрос:

Я выполнил поиск по этому вопросу, но не нашел вопроса, который вполне соответствовал тому, что мне было нужно. Я хочу, чтобы пользователь мог определять текстурированную плоскость. У меня есть следующие параметры:

  • Размер (вектор2)
  • Направление (вектор3)
  • Начало координат (вектор3)

Итак, я хочу иметь возможность вычислить 4 вершины прямоугольника с учетом приведенной выше информации. Итак, если бы я хотел, чтобы плоскость была обращена вверх, с шириной и высотой 1000:

  • Размер = (1000, 1000)
  • Направление = 0, 1, 0 (вверх)
  • Начало координат = 0, 0, 0

Таким образом, это определило бы плоскость на оси X и Z, обращенную вверх. Чего я не понимаю, так это как рассчитать 4 угла в трехмерном пространстве с учетом этой информации. Нужна ли мне дополнительная информация или есть лучший способ произвольно указать плоскость?

Редактировать: текущий код

В следующем коде:

  • Размер = 10000, 10000
  • Центр = 0, 0, 0
  • Нормальный = 0, 1, 0

             Vector3 arb = new Vector3(1, 1, 1);
            Vector3 planeY = Vector3.Normalize(Vector3.Cross(Normal, arb));
            Vector3 planeX = Vector3.Normalize(Vector3.Cross(Normal, planeY));
    
            planeX *= Size.X / 2;
            planeY *= Size.Y / 2;
    
            Vector3[] ret =  new Vector3[4] 
            {
                (Center - planeX - planeY),
                (Center - planeX   planeY),
                (Center   planeX - planeY),
                (Center   planeX   planeY)
            };
      

Ответ №1:

Ваша плоскость еще не полностью определена. Вам нужен другой вектор, идущий вдоль плоскости, так называемый «касательный» вектор. В приведенном выше примере, куда должна указывать ось Y текстуры? Вдоль оси X, вдоль оси Z? Или, может быть, совершенно другая пользовательская ось? Ваш касательный вектор — это вектор, который должен указывать в общем направлении, куда должна проходить ось X плоскости.

Допустим, у нас также есть касательный вектор, он не обязательно должен указывать вдоль плоскости. Вы можете построить плоскость следующим образом:

         Vector3[] vertices(Vector2 size, Vector3 center, Vector3 normal, Vector3 tangent)
    {
        Vector3 planeY = Vector3.Normalize(Vector3.Cross(normal, tangent));
        Vector3 planeX = Vector3.Normalize(Vector3.Cross(normal, planeY));

        planeX *= size.X / 2;
        planeY *= size.Y / 2;

        vertices = new Vector3[]
        {
            (center - planeX - planeY),
            (center - planeX   planeY),
            (center   planeX - planeY),
            (center   planeX   planeY),
        };
        return vertices;
    }
  

planeX и planeY являются нормализованными векторами, которые указывают вдоль осей X и Y самой плоскости. Умножая их на size / 2, мы получаем 2 вектора, которые простираются от центра до края плоскости в обоих направлениях X и Y. Складывая эти два вместе разными способами, мы получаем четыре угла.

Вот диаграмма, чтобы вы могли лучше представить себе картину в своей голове. Касательный вектор T «сплющивается» по оси X. Диаграмма

Комментарии:

1. Привет, Ханнаш, спасибо за ваш комментарий и пример кода. Предполагая tangent , что в вашем примере вектор ВВЕРХ, я реконструировал то, что вы передали Vector3.Up вместо касательной, но значения planeY — это все NaN , поэтому не уверен, что здесь происходит. Возможно, причина в том, что моя нормальная 0,1,0 , потому что я хочу, чтобы эта конкретная плоскость была обращена вверх. И поэтому он вызывается как `Vector3.Cross(«0, 1, 0», «0, 1, 0»)’ что, я уверен, неправильно.

2. Именно по этой причине :), выберите любое другое значение для up, и оно будет работать нормально. Вы не можете определить плоскость с той же осью X, что и направление, в котором она обращена к себе.

3. Я подумал, поэтому я предоставил вектор вверх (1,1,1). Учитывая начало координат 0, 0, 0 , нормаль 0, 1, 0 и размер 10000, 10000 , я получаю очень странные результаты. [0] = {X:0.0002441406 Y:0 Z:7071.068} . [1] = {X:7071.068 Y:0 Z:0.0002441406} , [2] = {X:-7071.068 Y:0 Z:-0.0002441406} и [3] = {X:-0.0002441406 Y:0 Z:-7071.068} . Пытаюсь выяснить, что не так. Я действительно ценю вашу помощь в этом.

4. Я только что обновил свой пост текущим кодом, который у меня есть. Когда дело доходит до математики и меня, колесо вращается, но хомяк мертв.

5. Это выглядит правильно. Чего вы ожидали? Плоскость лежит на оси X и Z (компоненты X и Z равны ~ 0). Вы касаете точки по диагонали, поэтому ваша плоскость поворачивается на 45 градусов. Попробуйте Vector3.Left для «нормальной» плоскости.

Ответ №2:

Это прекрасно подходит для определения плоскости: у вас есть точка и вектор нормали. Вам нужно получить два вектора (A amp; B) на плоскости и добавить один (A * одно из значений размера) к началу координат, чтобы получить второй угол. Добавьте второй вектор (B * другое значение размера), чтобы получить третий угол, и добавьте оба вектора * их соответствующие значения размера к началу координат, чтобы получить четвертый угол.

Чтобы получить первый вектор, вычислите перекрестное произведение вектора нормали (направления) с произвольным вектором (не равным направлению). Это даст вам вектор A. Чтобы получить вектор B, вычислите перекрестное произведение A и направления.

Комментарии:

1. Спасибо вам за это. Я не совсем уверен, что вы подразумеваете под «произвольным вектором (не равным направлению)». Я пытаюсь представить, как это будет выглядеть, но не очень далеко. Спасибо за ваш быстрый ответ.

2. Ну, направление — это трехмерный вектор, поэтому создайте новый вектор с любыми 3 значениями, которые не равны значениям вектора направления. Перекрестное произведение этого даст вам нормализованный вектор, ортогональный направлению. Вы можете умножить этот новый вектор на одно из свойств размера, чтобы получить второй угол.