Правильная настройка преобразования для масштаба и затем вращения - PullRequest
2 голосов
/ 03 апреля 2011

Моя матричная математика немного заржавела, поэтому у меня возникли проблемы с определением правильного процесса преобразования, который мне нужно применить здесь.

У меня полноэкранный квад с координатами от [-1, 1] в обоих направлениях. Я накладываю текстуру на этот квадрат не квадратной текстурой, а затем масштабирую матрицу вида модели, чтобы изменить размер и сохранить соотношение сторон. Я также хочу повернуть измененный квадрат, но я получаю растянутые / искаженные результаты.

Вот процесс, который я прохожу:

_gl.viewport(0, 0, _gl.viewportWidth, _gl.viewportHeight); // full-screen viewport
mat4.rotate(_modelview_matrix, degToRad(-1.0 * _desired_rotation), [0, 0, 1]); // rotate around z
mat4.scale(_modelview_matrix, [_shape.width / _gl.viewportWidth, _shape.height / _gl.viewportHeight, 1]); // scale down

Обратите внимание, что это реализовано в WebGL, но процесс должен быть универсальным.

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

Rotation distortion

Если я хочу, чтобы размер четырехугольника был _shape.width, _shape.height и иметь поворот на произвольный угол, чего мне не хватать?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 03 апреля 2011

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

Это на C, но концепция должна быть достаточно легко переносимой.

typedef struct Projection {
    enum{perspective, ortho} type;
    union {
        GLfloat fov;
        GLfloat size;
    };
    GLfloat near;
    GLfloat far;
} Projection;

Projection projection;

GLuint tex_width;
GLuint tex_height;

GLuint viewport_width;
GLuint viewport_height;

/*...*/

void display()
{
    GLfloat viewport_aspect;

    if(!viewport_width || !viewport_height)
        return;

    viewport_aspect = (float)viewport_width/(float)viewport_height;

    glViewport(0, 0, viewport_width, viewport_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    switch(projection.type) {
    case ortho: {
            glOrtho(-0.5 * viewport_aspect * projection.size, 
                     0.5 * viewport_aspect * projection.size, 
                    -0.5 * projection.size,
                     0.5 * projection.size,
                    -projection.near,
                     projection.far );
        }
    case perspective: {
            glFrustum( -0.5 * viewport_aspect * projection.near * projection.fov, 
                        0.5 * viewport_aspect * projection.near * projection.fov, 
                       -0.5 * projection.near * projection.fov,
                        0.5 * projection.near * projection.fov,
                       -projection.near,
                        projection.far );
        }
    default:
        return;
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    {
        GLfloat const T = 0.5*(float)texture_width/(float)texture_height;

        GLfloat quad[4][4] = {
           /* X     Y,   U,     V */
            {-T, -0.5,  0.0,  0.0},
            { T, -0.5,  1.0,  0.0},
            { T,  0.5,  1.0,  1.0},
            {-T,  0.5,  0.0,  1.0},
        }

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]);
        glTexCoordPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]);

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, texture_ID);

        glDrawArrays(GL_QUADS, 0, 4);
    }
}
2 голосов
/ 03 апреля 2011

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

Пример того, как это сделать, можно найти здесь .

...