Nano Hash - криптовалюты, майнинг, программирование

3D-графика - Матричная математика не работает

Я новичок в 3D-графике, поэтому полагаю, что сделал что-то в корне неправильно. Я построил 4 матрицы для обработки моих объектов в трехмерном пространстве: матрицу масштабирования, матрицу перевода, матрицу перспективы и матрицу вращения.

Матрица вращения и масштабирования работают нормально, однако мои матрицы перспективы и перевода ведут себя не так, как ожидалось, из того, что я понимаю, матрицы перевода и перспективы выглядят так:

Translation      Perspective 
[1, 0, 0, x]    [1, 0,  0 , 0]
[0, 1, 0, y]    [0, 1,  0 , 1]
[0, 0, 1, z]    [0, 0,  1 , 0]
[0, 0, 0, 1]    [0, 0, 1/D, 1]

Чтобы понять, как все работает за кулисами, я пишу свою собственную библиотеку Math - для создания определенных выше матриц у меня есть следующие методы:

public static ASMATRIX4 CreatePerspectiveMatrix(double focalLength)
{
    // Create matrix as an identity matrix
    var m = new ASMATRIX4();

    // Set the perspective matrix 
    m.Matrix[3].Points[2] = 1 / focalLength;
    m.Matrix[1].Points[3] = 1;

    return m;
}

public static ASMATRIX4 CreateTranslationMatrix(double x, double y, double z)
{
    // reset to identity matrix
    var m = new ASMATRIX4();

    // Set the translation matrix
    m.Matrix[0].Points[3] = x;
    m.Matrix[1].Points[3] = y;
    m.Matrix[2].Points[3] = z;

   return m;
}

Ничего особенного, но когда я умножаю свои матрицы вместе, ничего не происходит - я могу вращаться вокруг любой оси, но не могу переводить. Также обратите внимание, что new ASMATRIX4() инициализирует новую матрицу 4x4 как единичную матрицу.

Чтобы перемножить свои матрицы, я делаю следующее:

m_scaling = ASMATRIX4.CreateScalingMatrix(s, s, s);
m_translation = ASMATRIX4.CreateTranslationMatrix(tX, tY, tZ);
m_perspective = ASMATRIX4.CreatePerspectiveMatrix(f);
m_rotation = ASMATRIX4.RotateByDegrees(rX, rY, rZ);

var transformationMatrix = m_scaling*m_translation*m_perspective*m_rotation;

Я также написал перегрузку оператора для совместной обработки умножаемых матриц:

public static ASMATRIX4 operator *(ASMATRIX4 mA, ASMATRIX4 mB)
{
    //  Creates a new identity matrix
    var m = new ASMATRIX4();

    // Multiply the two matrixes together and return the output matrix
    for (var i = 0; i < 4; i++)
    {
        for (var j = 0; j < 4; j++)
        {
            m.Matrix[i].Points[j] =
                (mB.Matrix[i].Points[0]*mA.Matrix[0].Points[j]) +
                (mB.Matrix[i].Points[1]*mA.Matrix[1].Points[j]) +
                (mB.Matrix[i].Points[2]*mA.Matrix[2].Points[j]) +
                (mB.Matrix[i].Points[3]*mA.Matrix[3].Points[j])
        }
    }
    return m;
 }

Наконец, чтобы действительно преобразовать мою сетку, у меня есть массив Faces, которые я рисую в контексте 2D-рендеринга, метод ниже преобразует каждое лицо с помощью матрицы преобразования, определенной выше.

private void TransformMesh()
{
    var transformationMatrix = m_scaling*m_translation*m_perspective*m_rotation;
    for (var i = 0; i < m_numFaces; i++)
    {     
        m_meshData[i] = m_meshData[i].TransformFace(transformationMatrix);
    }
}

Метод TransformFace выглядит так, как описано ниже:

public ASFace TransformFace(ASMATRIX4 matrix)
{
    var transformedFace = new ASFace();

    for (var i = 0; i < 3; i++)
    {
        transformedFace.m_points[i] = m_points[i].TransformVector(matrix);
        transformedFace.m_points[i] = transformedFace.m_points[i].Rescale();
    }

    return transformedFace;
 }

Этот первый метод в цикле преобразует однородную точку с помощью входной матрицы, а затем вызывается метод масштабирования для нормализации вектора.

Я не понимаю, что я сделал не так? Я думаю, что порядок операций по умножению матриц может быть неправильным, но я не слишком уверен, любые предложения будут приняты с благодарностью.

22.04.2015

  • Порядок умножения важен, умножение это добавление или добавление? Вы можете перетасовать матрицы в m_scaling*m_translation*m_perspective*m_rotation 22.04.2015
  • Я считаю, что это добавление 22.04.2015
  • @Alex Также убедитесь, что ваш конструктор для ASMATRIX4 создает единичную матрицу, а не нулевую или (что менее вероятно) случайную матрицу. Я знаю, что это сказано в комментариях, но вы должны убедиться, что это так. 22.04.2015
  • Спасибо за внимание, и я уже подтвердил это - каждый раз создается единичная матрица. Чувствую себя довольно сбитым с толку 22.04.2015
  • @Alex Было бы полезно, если бы вы могли опубликовать образцы входных и выходных данных (то есть матричные операнды и результаты) вместе с кратким, самодостаточным, правильным (компилируемым), примером (sscce.org). То, как ваш код указан здесь, и, учитывая, что приведенные ниже ответы не решают вашу проблему, вероятная причина проблемы может быть не в чем-то, что вы до сих пор указали выше. 23.04.2015

Ответы:


1

Я вижу две проблемы в опубликованном вами коде. Во-первых, ваш метод CreatePerspectiveMatrix не устанавливает элемент (1, 3) в 1; либо метод, либо первоначальное определение матрицы перспективы неверны. (Или оба!) Во-вторых, в вашем коде умножения кажется, что вы просто умножаете подматрицу первых трех строк и столбцов. Поскольку эти субматрицы изначально являются единичными матрицами, неудивительно, что ничего не происходит.

22.04.2015
  • Привет, Рольф, спасибо за ответ - следуя вашим предложениям, я обновил свой код, но ничего не происходит. Верен ли мой порядок операций для умножения матрицы трансформации? 22.04.2015
  • Собственно, я не могу сказать о порядке операций, потому что я не знаю, является ли ASMATRIX4 главным по строкам или по столбцам. Общие предложения по отладке: 1. Изолировать перевод - не пытайтесь отлаживать его вместе с масштабированием, поворотом и перспективой. 2. Напишите модульный тест; умножьте известный вектор на известный перевод и посмотрите, что вы получите, сначала сделав вычисления вручную. Легче отлаживать, когда вы точно знаете, что вам нужно. 3. Распечатайте выписки! В модульном тесте распечатайте Умножение x на y по индексам i и j на каждом шаге каждого цикла; затем следуйте инструкциям вручную. 23.04.2015
  • Спасибо Рольф - помогло тонну, оказалось проблема с моим матричным мульт. :) 23.04.2015

  • 2

    Я не эксперт в этом вопросе, но разве вам здесь не хватает строки / столбца?

    - РЕДАКТИРОВАТЬ (tnx andand)

    public static ASMATRIX4 operator *(ASMATRIX4 mA, ASMATRIX4 mB)
    {
        //  Creates a new identity matrix
        var m = new ASMATRIX4();
    
        // Multiply the two matrixes together and return the output matrix
        for (var i = 0; i < 4; i++)
        {
            for (var j = 0; j < 4; j++)
            {
                m.Matrix[i].Points[j] =
                    (mB.Matrix[i].Points[0]*mA.Matrix[0].Points[j]) +
                    (mB.Matrix[i].Points[1]*mA.Matrix[1].Points[j]) +
                    (mB.Matrix[i].Points[2]*mA.Matrix[2].Points[j]) +
                    (mB.Matrix[i].Points[3]*mA.Matrix[3].Points[j]);   //  <----
            }
        }
        return m;
    }
    
    22.04.2015
  • Я думаю, что циклы должны быть for (var i=0; i<4; i++) ... аналогично внутреннему циклу. Это матрицы 4х4, а не 3х3. 22.04.2015
  • плохая ошибка от моего имени, там вы правы, однако это все еще не решает мою проблему с переводом :( Спасибо, что указали на это :) 22.04.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..