openGL缩放/旋转(首先是......)

时间:2015-01-17 13:06:56

标签: ios c opengl 2d

最近,我跳进了openGL。大多数事情都做得很好,但我一直用这个把头撞在墙上。

我正在尝试旋转/缩放2D图像。我正在努力解决这个问题,我应先旋转,然后进行缩放,或者相反。这两种方式都没有达到我想要的效果。

我制作了两个简短的视频,展示了它出了什么问题:

首先旋转,然后缩放 https://dl.dropboxusercontent.com/u/992980/rotate_then_scale.MOV

先缩放,然后旋转 https://dl.dropboxusercontent.com/u/992980/scale_then_rotate.MOV

左图像是方形,右图像是矩形。正如您所看到的,使用这两种方法,有些事情并不完全正确:)

黑色区域是openGL视口。当视口是方形时,一切都很好,当它是一个矩形时,事情开始出错:)对于我绘制的每个图像,我计算一个不同的X和Y标度,参考视口,我想我在做某事错了...... 请注意,我对openGL很新,我可能做了一些愚蠢的事情(我希望我是)。希望我能以这种方式清楚地解决我的问题。

提前感谢您提供任何帮助!

Corjan

绘制一张图片的代码:

void instrument_renderer_image_draw_raw(struct InstrumentRenderImage* image, struct InstrumentRendererCache* cache, GLuint program) {

// Load texture if not yet done
if (image->loaded == INSTRUMENT_RENDER_TEXTURE_UNLOADED) {
    image->texture = instrument_renderer_texture_cache_get(image->imagePath);

    if (image->texture == 0) {
        image->loaded = INSTRUMENT_RENDER_TEXTURE_ERROR;
    }
    else {
        image->loaded = INSTRUMENT_RENDER_TEXTURE_LOADED;
    }
}

// Show image when texture has been correctly loaded into GPU memory
if (image->loaded == INSTRUMENT_RENDER_TEXTURE_LOADED) {

    float instScaleX = (float)cache->instBounds.w / cache->instOrgBounds.w;
    float instScaleY = (float)cache->instBounds.h / cache->instOrgBounds.h;

    float scaleX = (float)image->w / (float)cache->instOrgBounds.w;
    float scaleY = (float)image->h / (float)cache->instOrgBounds.h;

    // Do internal calculations when dirty
    if (image->base.dirty) {

        mat4 matScale;
        mat4 matRotate;
        mat4 matModelView;
        mat4 matProjection;

        matrixRotateZ(image->angle, matRotate);

        matrixScale(scaleX , scaleY  * -1, 0, matScale);

        matrixMultiply(matRotate, matScale, matModelView);

        // Determine X and Y within this instrument's viewport
        float offsetX = ((float)cache->instOrgBounds.w - (float)image->w) / 2 / (float)cache->instOrgBounds.w;
        float offsetY = ((float)cache->instOrgBounds.h - (float)image->h) / 2 / (float)cache->instOrgBounds.h;

        float translateX = ( ((float)image->x / (float)cache->instOrgBounds.w) - offsetX) * 2;
        float translateY = ( ( ( (float)cache->instOrgBounds.h - (float)image->y - (float)image->h ) / (float)cache->instOrgBounds.h) - offsetY) * -2;

        matrixTranslate(translateX, translateY*-1, -2.4,matModelView);

        //matrixPerspective(45.0, 0.1, 100.0, (double)cache->instOrgBounds.w/(double)cache->instOrgBounds.h, matProjection);
        matrixOrthographic(-1, 1, -1, 1, matProjection);

        matrixMultiply(matProjection, matModelView, image->glMatrix);

        image->base.dirty = 0;
    }

    glUseProgram(program);

    glViewport(cache->instBounds.x * cache->masterScaleX,
               cache->instBounds.y * cache->masterScaleY,
               cache->instBounds.w * cache->masterScaleX,
               cache->instBounds.w * cache->masterScaleX);

    glUniformMatrix4fv(matrixUniform, 1, GL_FALSE, image->glMatrix);

    // Load texture
    glBindTexture(GL_TEXTURE_2D, image->texture);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

1 个答案:

答案 0 :(得分:0)

您使用什么框架/库进行矩阵乘法?

首先需要的东西取决于你的矩阵表示(例如行与列主要和后期与预乘之比)。你使用的图书馆决定了这一点;固定功能OpenGL(glMultMatrix (...) 等。)是列主要和后乘法。大多数基于OpenGL的框架都遵循传统,尽管有一些例外,如OpenTK。传统的矩阵乘法按以下顺序进行:

1. Translation
2. Scaling
3. Rotation

但由于后乘乘列主要矩阵的性质(矩阵乘法是非交换的),操作有效地从底部到顶部发生。即使您在旋转之前进行平移乘法,旋转实际上也会应用于预平移坐标。

实际上,假设您的矩阵库遵循OpenGL约定,那么您正在反向执行矩阵乘法序列。