我最近在我的一个项目中实现了Arcball指南:https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball,但是在缩放和平移对象时遇到了一些问题。
问题:涉及缩放和平移时,旋转会产生错误的输出,例如向内弯曲或以特定角度放大对象的某些部分。 但是,当我将缩放和平移直接应用于对象的顶点时,旋转就起作用了。也就是说,在工作状态下,我针对该对象的模型矩阵是一个单位矩阵。除此之外,这都失败了。因此,我知道这是应用这些命令的顺序。我只是不确定要点什么。在TRS顺序中应用平移和缩放以及旋转也没有帮助,并且产生了错误的结果。
编辑:修复了平移和缩放问题,但是对象相对于更改的中心不会旋转。它相对于旧中心旋转。
相关代码:
对象渲染代码的一部分:
if (R.mouseMoved) {
glm::vec3 va = get_arcball_vector(R.click_mx, R.click_my);
glm::vec3 vb = get_arcball_vector(R.cur_mx, R.cur_my);
float ang = glm::degrees(acos(min(1.0f, glm::dot(va, vb)))) * MMOVE_FACTOR * R.deltaTime;
glm::vec3 axis_in_camera_coord = glm::cross(va, vb);
glm::mat3 camera2object = glm::inverse(glm::mat3(R.view) * glm::mat3(model));
glm::vec3 rotaxis = camera2object * axis_in_camera_coord;
model = glm::rotate(model, ang, rotaxis);
}
// assuming this is what I needed to do here for view matrix, TRT, this doesn't work
glm::mat4 mv = /*glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -WINDOW_X * .5)) * */R.view * model/* * glm::translate(glm::mat4(1.0f), -center)*/;
glm::mat4 pvm = Renderer::proj * mv;
pvm = glm::translate(pvm, translation);
pvm = glm::scale(pvm, scale);
紧接着将pvm矩阵发送到着色器,并渲染对象。
向量计算功能:
glm::vec3 get_arcball_vector(int x, int y) {
glm::vec3 P = glm::vec3(1.0*x / WINDOW_X * 2 - 1.0,
1.0*y / WINDOW_Y * 2 - 1.0,
0);
P.y = -P.y;
float OP_squared = P.x * P.x + P.y * P.y;
if (OP_squared <= 1 * 1)
P.z = sqrt(1 * 1 - OP_squared); // Pythagoras
else
P = glm::normalize(P); // nearest point
return P;
}
MMOVE_FACTOR为0.05,R.deltaTime调节渲染时间和鼠标移动,使其感觉更平滑。所讨论的对象可以进行任意缩放和平移,以使其出现在场景的不同位置。无论我尝试了什么,都不会产生我想要的结果。例如,我尝试了以下方法:
model = glm::translate(model, -center);
model = glm::rotate(model, glm::degrees(ang), rotaxis);
model = glm::translate(model, center);
但这也不能提供良好的结果,并且旋转仍然不正确。
编辑2:根据httpdigest的建议,这是最新的代码:
glm::mat4 tr = glm::translate(glm::mat4(1.0f), -R.camera.getPos());
glm::mat4 trc = glm::translate(glm::mat4(1.0f), -center);
glm::mat4 tmc = glm::translate(glm::mat4(1.0f), center);
glm::mat4 rx = glm::rotate(glm::mat4(1.0f), -(float)R.camera.getPitch(), glm::vec3(1.0, 0, 0));
glm::mat4 ry = glm::rotate(glm::mat4(1.0f), (float)R.camera.getYaw(), glm::vec3(0, 1.0, 0));
glm::mat4 pvm = Renderer::proj * tr * rx * ry * trc * tmc;
pvm = glm::translate(pvm, translation);
pvm = glm::scale(pvm, scale);
中心是glm :: vec3,其顶点总和除以顶点数。
上述问题:不适用于绕X轴的平移。当我旋转到足以使其与平移值位于相同距离时,它会在Y轴上正确旋转。另一个问题是,它的行为不像弓箭,但我猜想这是如何处理旋转的。我可能是错的。