翻译时2D几何扭曲

时间:2014-06-27 16:23:33

标签: macos opengl

我正在使用一个项目来学习OSX上的OpenGL,我发现它here。我已将其修改为可以在简单的2D几何体上开始使用我自己的纹理。

我遇到了一个我经常被问到的问题,但我找不到适合我的解决方案。

我只想翻译几何体,使其向左,向右,向上,向下移动,但当我这样做时,它的形状会变形。

像这样:

enter image description here

它应该如下所示,但只是在X轴上移动:

enter image description here

我正在使用的代码是:

static GLfloat modelView[16];
static GLfloat projection[16];
static GLfloat objectMvp[16];
static GLfloat model[16];
static GLfloat view[16];

mtxLoadIdentity(model);
mtxLoadIdentity(view);
mtxLoadIdentity(modelView);
mtxLoadIdentity(projection);

//load the desired projection matrix into projection var
mtxLoadPerspective(projection, 90, m_viewAspect, 0.1, 100);
//m_viewAspect is updated every time the window changes shape
//and is window.width/window.height

mtxTranslateApply(model, 0.3, 0, -500);
mtxScaleApply(model, m_viewAspect, 1, 1); //[*]
mtxRotateXApply(model, 0);
mtxRotateYApply(model, 0);
mtxRotateZApply(model, 0);
mtxScaleApply(model, 1/m_viewAspect, 1, 1); //[*]

mtxMultiply(modelView, view, model);
mtxMultiply(objectMvp, projection, modelView);

//and send objectMvp to the shader for rendering…
glUniformMatrix4fv(m_UniformIdx, 1, GL_FALSE, objectMvp);

所有mtx*函数都执行指示的矩阵数学运算,并将结果放入传递的第一个参数中。我必须假设它们都正常工作,因为它们与最初的Apple示例项目保持不变。

mtxLoadPerspective()函数的签名是:

void mtxLoadPerspective(float* mtx, float fov, float aspect, float nearZ, float farZ)

两行[*]代码基于其他网站上类似问题的答案,其中指令根据纵横比在X轴上缩放,旋转然后缩小。

我是否正确地认为宽高比是问题的核心?是否有人知道的示例代码可以指导我?

编辑:着色器使用列主要数学作为位置

gl_Position = modelViewProjectionMatrix * inPosition;

如此answer所示。

编辑:澄清mtx*函数。

mtxLoadPerspective()将FOV转换为:

float f = 1.0f / tanf( (fov * (M_PI/180)) / 2.0f);

翻译功能是:

void mtxTranslateApply(float* mtx, float xTrans, float yTrans, float zTrans)
{

    mtx[12] += mtx[0]*xTrans + mtx[4]*yTrans + mtx[ 8]*zTrans;
    mtx[13] += mtx[1]*xTrans + mtx[5]*yTrans + mtx[ 9]*zTrans;
    mtx[14] += mtx[2]*xTrans + mtx[6]*yTrans + mtx[10]*zTrans;  
}

其他功能是:

void mtxMultiply(float* ret, const float* lhs, const float* rhs)
{
    ret[ 0] = lhs[ 0]*rhs[ 0] + lhs[ 4]*rhs[ 1] + lhs[ 8]*rhs[ 2] + lhs[12]*rhs[ 3];
    ret[ 1] = lhs[ 1]*rhs[ 0] + lhs[ 5]*rhs[ 1] + lhs[ 9]*rhs[ 2] + lhs[13]*rhs[ 3];
    ret[ 2] = lhs[ 2]*rhs[ 0] + lhs[ 6]*rhs[ 1] + lhs[10]*rhs[ 2] + lhs[14]*rhs[ 3];
    ret[ 3] = lhs[ 3]*rhs[ 0] + lhs[ 7]*rhs[ 1] + lhs[11]*rhs[ 2] + lhs[15]*rhs[ 3];

    ret[ 4] = lhs[ 0]*rhs[ 4] + lhs[ 4]*rhs[ 5] + lhs[ 8]*rhs[ 6] + lhs[12]*rhs[ 7];
    ret[ 5] = lhs[ 1]*rhs[ 4] + lhs[ 5]*rhs[ 5] + lhs[ 9]*rhs[ 6] + lhs[13]*rhs[ 7];
    ret[ 6] = lhs[ 2]*rhs[ 4] + lhs[ 6]*rhs[ 5] + lhs[10]*rhs[ 6] + lhs[14]*rhs[ 7];
    ret[ 7] = lhs[ 3]*rhs[ 4] + lhs[ 7]*rhs[ 5] + lhs[11]*rhs[ 6] + lhs[15]*rhs[ 7];

    ret[ 8] = lhs[ 0]*rhs[ 8] + lhs[ 4]*rhs[ 9] + lhs[ 8]*rhs[10] + lhs[12]*rhs[11];
    ret[ 9] = lhs[ 1]*rhs[ 8] + lhs[ 5]*rhs[ 9] + lhs[ 9]*rhs[10] + lhs[13]*rhs[11];
    ret[10] = lhs[ 2]*rhs[ 8] + lhs[ 6]*rhs[ 9] + lhs[10]*rhs[10] + lhs[14]*rhs[11];
    ret[11] = lhs[ 3]*rhs[ 8] + lhs[ 7]*rhs[ 9] + lhs[11]*rhs[10] + lhs[15]*rhs[11];

    ret[12] = lhs[ 0]*rhs[12] + lhs[ 4]*rhs[13] + lhs[ 8]*rhs[14] + lhs[12]*rhs[15];
    ret[13] = lhs[ 1]*rhs[12] + lhs[ 5]*rhs[13] + lhs[ 9]*rhs[14] + lhs[13]*rhs[15];
    ret[14] = lhs[ 2]*rhs[12] + lhs[ 6]*rhs[13] + lhs[10]*rhs[14] + lhs[14]*rhs[15];
    ret[15] = lhs[ 3]*rhs[12] + lhs[ 7]*rhs[13] + lhs[11]*rhs[14] + lhs[15]*rhs[15];
}

void mtxScaleApply(float* mtx, float xScale, float yScale, float zScale)
{
    mtx[ 0] *= xScale;
    mtx[ 4] *= yScale;
    mtx[ 8] *= zScale;

    mtx[ 1] *= xScale;
    mtx[ 5] *= yScale;
    mtx[ 9] *= zScale;

    mtx[ 2] *= xScale;
    mtx[ 6] *= yScale;
    mtx[10] *= zScale;

    mtx[ 3] *= xScale;
    mtx[ 7] *= yScale;
    mtx[11] *= xScale;
}

void mtxRotateXMatrix(float* mtx, float rad)
{
    float cosrad = cosf(rad);
    float sinrad = sinf(rad);

    float mtx01 = mtx[ 1];
    float mtx05 = mtx[ 5];
    float mtx09 = mtx[ 9];
    float mtx13 = mtx[13];

    mtx[ 1] = cosrad*mtx01 - sinrad*mtx[ 2];
    mtx[ 2] = sinrad*mtx01 + cosrad*mtx[ 2];

    mtx[ 5] = cosrad*mtx05 - sinrad*mtx[ 6];
    mtx[ 6] = sinrad*mtx05 + cosrad*mtx[ 6];

    mtx[ 9] = cosrad*mtx09 - sinrad*mtx[10];
    mtx[10] = sinrad*mtx09 + cosrad*mtx[10];

    mtx[13] = cosrad*mtx13 - sinrad*mtx[14];
    mtx[14] = sinrad*mtx13 + cosrad*mtx[14];
}


void mtxRotateYMatrix(float* mtx, float rad)
{
    float cosrad = cosf(rad);
    float sinrad = sinf(rad);

    float mtx00 = mtx[ 0];
    float mtx04 = mtx[ 4];
    float mtx08 = mtx[ 8];
    float mtx12 = mtx[12];

    mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 2];
    mtx[ 2] = sinrad*mtx00 + cosrad*mtx[ 2];

    mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 6];
    mtx[ 6] = sinrad*mtx04 + cosrad*mtx[ 6];

    mtx[ 8] = cosrad*mtx08 - sinrad*mtx[10];
    mtx[10] = sinrad*mtx08 + cosrad*mtx[10];

    mtx[12] = cosrad*mtx12 - sinrad*mtx[14];
    mtx[14] = sinrad*mtx12 + cosrad*mtx[14];
}


void mtxRotateZMatrix(float* mtx, float rad)
{
    float cosrad = cosf(rad);
    float sinrad = sinf(rad);

    float mtx00 = mtx[ 0];
    float mtx04 = mtx[ 4];
    float mtx08 = mtx[ 8];
    float mtx12 = mtx[12];

    mtx[ 0] = cosrad*mtx00 - sinrad*mtx[ 1];
    mtx[ 1] = sinrad*mtx00 + cosrad*mtx[ 1];

    mtx[ 4] = cosrad*mtx04 - sinrad*mtx[ 5];
    mtx[ 5] = sinrad*mtx04 + cosrad*mtx[ 5];

    mtx[ 8] = cosrad*mtx08 - sinrad*mtx[ 9];
    mtx[ 9] = sinrad*mtx08 + cosrad*mtx[ 9];

    mtx[12] = cosrad*mtx12 - sinrad*mtx[13];
    mtx[13] = sinrad*mtx12 + cosrad*mtx[13];
}

1 个答案:

答案 0 :(得分:0)

那么,

我终于让代码工作了,但我不清楚为什么。

总的来说,我将身份矩阵加载到viewmodelprojection

x,y,z缩放应用于model矩阵。

然后将x,y,z旋转应用于model矩阵。

x和y翻译也适用于model

然而,z转换应用于view矩阵(虽然我理解将相机移回去看几何的概念,但我不明白为什么要将x和y转换应用到view矩阵什么都不做。)

然后我进行乘法model * view,这会进入modelView矩阵。

然后执行modelView * projection并将此产品发送到着色器。

如果有人可以发表评论并阐明这一点我会感激不尽,但与此同时我会犯错误。