上一篇glm来实现的mvp矩阵变换实现opengl渲染模型,讲到了如何利用glm库实现mvp矩阵,这篇主要讲解下,我们如何利用glm库的平移、旋转矩阵实现一个简单的3d漫游的效果。
原理
移动
camera位置 和 视点 按照一个方向移动。这里主要是要修改视觉矩阵 viewMatrix
// 相当于人移动,那就是 视点 和 相机位置,按照 一定方向 移动
void translateCamera(glm::vec3 translateVector, float ra){
translateVector = glm::normalize(translateVector)*ra;
glm::mat4 translateMatrix;
translateMatrix= glm::translate(translateMatrix,translateVector);
glm::vec4 newCameraPos = translateMatrix*(glm::vec4(cameraPos[0] , cameraPos[1] , cameraPos[2], 1.0f));
glm::vec4 newVPos = translateMatrix*(glm::vec4(vPos[0] , vPos[1] , vPos[2], 1.0f));
cameraPos[0] = newCameraPos[0];
cameraPos[1] = newCameraPos[1];
cameraPos[2] = newCameraPos[2];
vPos[0] = newVPos[0];
vPos[1] = newVPos[1];
vPos[2] = newVPos[2];
}
改变视角
camera位置不变, 视点位置 改变,相当于人看不同的目标。当旋转的时候,旋转矩阵乘以 视点,得到 目标视点,修改视觉矩阵 viewMatrix
// 改变视野方向,就是改变视点的方向
void changeDirection(glm::vec3 rotateVector, float ra) {
rotateVector = glm::normalize(rotateVector)*ra;
glm::mat4 translateMatrix;
translateMatrix= glm::translate(translateMatrix,rotateVector);
glm::vec4 newVPos = translateMatrix*(glm::vec4(vPos[0] , vPos[1] , vPos[2], 1.0f));
vPos[0] = newVPos[0];
vPos[1] = newVPos[1];
vPos[2] = newVPos[2];
}
移动和改变方向,都是需要修改投影矩阵的,因此,在draw的时候需要传入viewMatrix 。如下:
void Draw(){
// translateCamera(glm::vec3(-1.0f , -1.0f ,-1.0f), 0.01f);
changeDirection(glm::vec3(0.0f , 1.0f ,0.0f),0.010f);
viewMatrix=glm::lookAt(cameraPos,vPos,glm::vec3(0.0f,1.0f,0.0f));
model.rotateMode(glm::vec3(0.0f , 1.0f ,0.0f) ,0.10f );
threeDCoordinates.Draw(viewMatrix,projectMatrix);
model.Draw(viewMatrix,projectMatrix);
}
物体的移动旋转
物体的移动旋转主要是 modelMatrix来实现,主要是物体在世界坐标系的移动,旋转。只有在屏幕上渲染的时候才需要 projectMatrix和 viewMatrix,这2个矩阵就是把世界坐标系里的内容投放当屏幕坐标中。
void model::translateMode(glm::vec3 vec, float v) {
vec = glm::normalize(vec);
// modelMatrix = glm::translate(modelMatrix, vec*v);
position[0] = position[0] + vec[0]*v;
position[1] = position[1] + vec[1]*v;
position[2] = position[2] + vec[2]*v;
setPosition( position[0] , position[1] ,position[2] );
}
int i = 0;
void model::rotateMode(glm::vec3 v, float angel) {
glm::mat4 mat ={
1.0f , 0.0f, 0.0f, 0.0f
, 0.0f, 1.0f, 0.0f, 0.0f
, 0.0f, 0.0f, 1.0f, 0.0f
, 0.0f, 0.0f, 0.0f, 1.0f
};
LOGE("i = %d" , i);
modelMatrix = glm::rotate(mat, angel*i ,v);
modelMatrix = glm::translate(modelMatrix, position);
i++;
// setPosition(position[0] ,position[1],position[2]);
}
void model::setPosition(float x , float y , float z) {
glm::mat4 mat;
modelMatrix = glm::translate(mat, glm::vec3(x, y , z));
position[0] = x;
position[1] = y;
position[2] = z;
}
node: 绘制模型的时候一定要启动,否则实现背面不会绘制。
glEnable(GL_DEPTH_TEST);
这里提供demo,实现了视线的改变,相机的平移,物体的平移,旋转。
物体边自转边移动
如何让物体一边自转,一边移动?上面实现的,具有累加效果,会绕y轴不挺的旋转,但也会偏离原来的轨道。
如下:视点(10,10,10), 视点(0,0,0),红线为z轴,向上的为y轴,蓝线为x轴,如何让地球沿着z轴移动,并且自转
思路:我们上面已经实现了绕y轴旋转,则是自转,我们先绕y轴自转,然后按照z轴移动。
1、我们将地球的圆心translate的位置记住,
2、然后在着色器中,先旋转计算出每个点的坐标 :rotateMatrix*points 计算出旋转后的 points坐标,然后利用 translate vector矩阵计算平移后的世界坐标。
3、 和 vp 矩阵来计算最终屏幕绘制的点。