我正在使用一个项目来学习OSX上的OpenGL,我发现它here。我已将其修改为可以在简单的2D几何体上开始使用我自己的纹理。
我遇到了一个我经常被问到的问题,但我找不到适合我的解决方案。
我只想翻译几何体,使其向左,向右,向上,向下移动,但当我这样做时,它的形状会变形。
像这样:
它应该如下所示,但只是在X轴上移动:
我正在使用的代码是:
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];
}
答案 0 :(得分:0)
那么,
我终于让代码工作了,但我不清楚为什么。
总的来说,我将身份矩阵加载到view
,model
和projection
。
x,y,z缩放应用于model
矩阵。
然后将x,y,z旋转应用于model
矩阵。
x和y翻译也适用于model
。
然而,z转换应用于view
矩阵(虽然我理解将相机移回去看几何的概念,但我不明白为什么要将x和y转换应用到view
矩阵什么都不做。)
然后我进行乘法model * view
,这会进入modelView
矩阵。
然后执行modelView * projection
并将此产品发送到着色器。
如果有人可以发表评论并阐明这一点我会感激不尽,但与此同时我会犯错误。