Вращение камеры деформирует объекты

Я работаю над лучом-индикатором на C ++ с регулируемой камерой для университетского задания. Я совершенно новый с графикой, и я борюсь с чем-то.

У меня есть матрица как объект mat4 (матрица 4x4 с каждой ячейкой, сохраненной в 1D-массиве), которую я сохраняю в объекте Camera, который обрабатывает преобразования каждой точки сцены (которая в настоящее время представляет собой только две сферы). Переводы, кажется, работают нормально , но когда я пытаюсь совершить поворот, вещи ломаются . Облака деформируются, и это только ухудшается, тем больше я пытаюсь повернуть камеру.

Здесь я устанавливаю матрицу камеры:

mat4 Renderer::setCameraMatrix(const Camera &camera)
{
    mat4 cameraToWorld = mat4(); // Initialise 4x4 matrix.

    // Translation.
    cameraToWorld.cell[3] = camera.pos.x;
    cameraToWorld.cell[7] = camera.pos.y;
    cameraToWorld.cell[11] = camera.pos.z;

    // Rotation.
    cameraToWorld.cell[0] = camera.orientmat.cell[0], cameraToWorld.cell[1] = camera.orientmat.cell[1], cameraToWorld.cell[2] = camera.orientmat.cell[2];
    cameraToWorld.cell[4] = camera.orientmat.cell[4], cameraToWorld.cell[5] = camera.orientmat.cell[5], cameraToWorld.cell[6] = camera.orientmat.cell[6];
    cameraToWorld.cell[8] = camera.orientmat.cell[8], cameraToWorld.cell[9] = camera.orientmat.cell[9], cameraToWorld.cell[10] = camera.orientmat.cell[10];

    return cameraToWorld;
}

Эта матрица затем используется для установки начала и направления камеры в мировом пространстве позже в коде:

vec3 orig = transformpoint(vec3(0), cameraToWorld);
/*...*/
vec3 dir = transformvector(vec3(x, y, -1), cameraToWorld) - orig;
dir.normalize();

Функции преобразования и преобразования вектора в основном умножают вектор v на матрицу M (M.v), за исключением того, что первое принимает во внимание сдвиги, а последнее - нет. Их код можно найти здесь .

Матрица ориентирования вычисляется по трем отдельным углам ориентации (orient.x, orient.y, orient.z) в этой строке кода:

cam->orientmat = mat4().rotatexyz(cam->orient.x, cam->orient.y, cam->orient.z);

С помощью этой функции:

mat4 mat4::rotatexyz(const float a, const float b, const float c)
{
    mat4 M;
    const float ca = cosf(a), sa = sinf(a);
    const float cb = cosf(b), sb = sinf(b);
    const float cc = cosf(c), sc = sinf(c);

    M.cell[0] = cb * cc, M.cell[1] = -1 * cb * sc, M.cell[2] = sb;
    M.cell[4] = sa * sb * cc + ca * sc, M.cell[5] = -1 * sa * sb * sc + ca * cc, M.cell[6] = -1 * sa * cb;
    M.cell[8] = -1 * ca * sb * cc + sa * sc, M.cell[9] = ca * sb * sc + sa * cc, M.cell[10] = ca * cb;

    return M;
}

(Эта функция в основном создает эту матрицу преобразования из трех ориентации камеры углы.)

Я старался максимально упростить этот вопрос, но при необходимости я могу предоставить больше кода. Я полностью озадачен тем, почему я получаю такую ​​деформацию на своих сферах, и некоторое понимание будет бесценным! Спасибо.

4 голоса | спросил Step 2 SatEurope/Moscow2017-12-02T21:29:58+03:00Europe/Moscow12bEurope/MoscowSat, 02 Dec 2017 21:29:58 +0300 2017, 21:29:58

1 ответ


1

Ну, во-первых, в отличие от трансформации и масштаба, вы не можете просто комбинировать матрицы ориентации, чтобы получить реальную матрицу ориентации. Вы должны применить матрицы ориентации по отношению к одной оси , применить их отдельно или использовать одиночную комплекснозначную матрицу кватернионов . Возможно, вы попадаете во что-то, называемое gimbal lock или какой-то другой странный позиционный артефакт в сочетании с другими ошибок в вашем коде.

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

Самый простой способ избежать блокировки карданного вала - просто повернуть по отношению к каждой оси отдельно, что-то вроде этого:

// because I don't want to use silly linear indexing
class mat3 : ...{
    ...
    // incase of inheritance
    int width(){
        return 3;
    }
    int height(){
        return 3;
    }
    // can put this in parent class if inherits width and height functions
    float& operator () (int row, int col){
        // if m_array is row ordered
        int linear_index = row * width() + col;
        // if m_array is column ordered
        int linear_index = col * height() + row;

        assert(linear_index < (width()*height()));

        return m_array[linear_index];
    }

    // duplicated for const usage
    const float& operator () (int row, int col) const{
        // if m_array is row ordered
        int linear_index = row * width() + col;
        // if m_array is column ordered
        int linear_index = col * height() + row;

        assert(linear_index < (width()*height()));

        return m_array[linear_index];
    }
    ...    
};

...

mat3 mat3::xAxisRotMat(const float radians){
    //from https://stackoverflow.com/questions/14607640/rotating-a-vector-in-3d-space
    mat3 m;

    float cos_rad = cosf(radians);
    float sin_rad = sinf(radians);

    m(0,0) = 1;
    m(0,1) = 0;
    m(0,2) = 0;

    m(1,0) = 0;
    m(1,1) = cos_rad;
    m(1,2) = -sin_rad;

    m(2,0) = 0;
    m(2,1) = sin_rad;
    m(2,2) = cos_rad;
}

mat3 mat3::yAxisRotMat(const float radians){
    //from https://stackoverflow.com/questions/14607640/rotating-a-vector-in-3d-space
    mat3 m;

    float cos_rad = cosf(radians);
    float sin_rad = sinf(radians);

    m(0,0) = cos_rad;
    m(0,1) = 0;
    m(0,2) = sin_rad;

    m(1,0) = 0;
    m(1,1) = 1;
    m(1,2) = 0;

    m(2,0) = -sin_rad;
    m(2,1) = 0;
    m(2,2) = cos_rad;
}

mat3 mat3::zAxisRotMat(const float radians){
    //from https://stackoverflow.com/questions/14607640/rotating-a-vector-in-3d-space
    mat3 m;

    float cos_rad = cosf(radians);
    float sin_rad = sinf(radians);

    m(0,0) = cos_rad;
    m(0,1) = -sin_rad;
    m(0,2) = 0;

    m(1,0) = sin_rad;
    m(1,1) = cos_rad;
    m(1,2) = 0;

    m(2,0) = 0;
    m(2,1) = 0;
    m(2,2) = 1;
}

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

Я также должен указать, что перевод вектора [0,0,0] другим вектором [x,y,z] просто возвращает [x,y,z], потому что весь перевод будет добавлять x, y и z в исходные элементы xyz.

ответил opa 8 FriEurope/Moscow2017-12-08T21:29:16+03:00Europe/Moscow12bEurope/MoscowFri, 08 Dec 2017 21:29:16 +0300 2017, 21:29:16

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132