建议在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。
模型平移后,模型还是以原点进行旋转。而模型中心已经不在原点上,导致旋转异常。
这时因为:
在物体刚刚放入世界坐标系的时候使用的是本地坐标,也就是本地和世界坐标系的原点和坐标轴都是重合的,此时所有物体都“把世界坐标系当做自己的本地坐标系”。
而经过了坐标变换之后:
缩放变换不改变坐标轴的走向,也不改变原点的位置,所以两个坐标系仍然重合。
旋转变换改变坐标轴的走向,但不改变原点的位置,所以两个坐标系坐标轴不再处于相同走向。
平移变换不改变坐标轴走向,但改变原点位置,两个坐标系原点不再重合。
一、在顶点着色器中声明一个uniform 变量
uniform mat4 transform; glPosition = transform*vec4(aPos,1.0f);
二、创建变换矩阵
1 glm::mat4 trans; 2 trans = glm::rotate(trans,glm:radians(90.0f),glm::vec3(0.0,0.0,1.0)); 3 trans = glm::scale(trans,glm::vec3(0.5,0.5,0.5));
首先,我们把箱子在每个轴上都缩小0.5倍,然后沿z轴旋转90度。GLM希望它的角度是弧度制的(Radian),所以我们使用glm::radians
将角度转化为弧度。
三、把矩阵发送给着色器,着色器会变换传入的顶点坐标
1 unsigned int transformLoc = glGetUniformLocation(ourShader.ID,"transform");//查询uniform变量的地址 2 glUniformMatrix4f(transformLoc,1,GL_FALSE,glm::value_ptr(trans));
然后用有Matrix4fv后缀的glUniform函数把矩阵数据trans发送给着色器.
第一个参数:uniform变量(transform)的位置值
第二个参数:告诉openGL我们将要发送多少个矩阵
第三个参数:询问我们是否需要对矩阵进行转置
最后一个参数:真正的矩阵数据,GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。
若让物体随着时间推移旋转:
1 glm::mat4 trans; 2 trans = glm::translate(trans,glm::vec3(0.5f,-0.5f,0.5f)); 3 trans = glm::rotate(trans,(float)glfwGetTime(),glm::vec3(0.0f,0.0f,1.0f));
在这里我们先把箱子围绕原点(0, 0, 1)旋转,之后,我们把旋转过后的箱子位移到屏幕的右下角。记住,实际的变换顺序应该与阅读顺序相反:尽管在代码中我们先位移再旋转,实际的变换却是先应用旋转再是位移的。