C++ 在使用GLM的OpenGL中,当对象面对原点时围绕原点旋转对象?
我正在尝试制作一个简单的动画,其中一个对象在OpenGL中使用glm lib围绕世界原点旋转。我的想法是: 将对象发送到源 旋转它 发回原位 让它看看我想要什么 以下是我的实现:C++ 在使用GLM的OpenGL中,当对象面对原点时围绕原点旋转对象?,c++,opengl,matrix,rotation,glm-math,C++,Opengl,Matrix,Rotation,Glm Math,我正在尝试制作一个简单的动画,其中一个对象在OpenGL中使用glm lib围绕世界原点旋转。我的想法是: 将对象发送到源 旋转它 发回原位 让它看看我想要什么 以下是我的实现: // Rotates object around point p void rotate_about(float deltaTime, glm::vec3 p, bool ended) { glm::vec3 axis = glm::vec3(0,1,0); //rotation axis glm::
// Rotates object around point p
void rotate_about(float deltaTime, glm::vec3 p, bool ended) {
glm::vec3 axis = glm::vec3(0,1,0); //rotation axis
glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale, scale, scale)); //scale matrix
glm::mat4 rotation = getMatrix(Right, Up, Front, Position); //builds rotation matrix
rotation = glm::translate(rotation, p - Position );
rotation = glm::rotate(rotation, ROTATION_SPEED * deltaTime, axis);
rotation = glm::translate(rotation, Position - p );
Matrix = rotation * scale_m;
//look at point P
Front = glm::normalize(p - start_Position);
Right = glm::normalize(glm::cross(WorldUp, Front));
Up = glm::normalize(glm::cross(Right, Front));
if (ended == true) { //if last iteration of my animation: saves position
Position.x = Matrix[3][0];
Position.y = Matrix[3][1];
Position.z = Matrix[3][2];
}
}
getMatrix只返回4x4矩阵,如下所示:
| Right.x Right.y Right.z |
| Up.x Up.y Up.z |
| Front.x Front.y Front.z |
| Pos.x Pos.y Pos.z |
我使用此图像作为参考:
因为它是我的模型只是消失时,我开始动画。如果我删除下面的线//看点P,它会围绕原点旋转,但每次动画重新启动时都会抽动。我猜我正在丢失或混合我不应该在某处的信息。
如何存储模型的前/右/上信息,以便从头开始重建其矩阵
首先编辑,这是当我不试图让我的模型看到点p时产生的效果,在本例中是原点。当我尝试时,我的模型消失了。我怎样才能让它看起来像我想要的,在我完成旋转后,我怎样才能得到我的模型新的前/右/上向量
我在上面的gif中运行的代码是否类似于或通过其参数构建矩阵,并将输入矩阵乘以新矩阵
这意味着
rotation = glm::translate(rotation, Position - p );
可以表示为伪代码:
rotation = rotation * translation(Position - p);
注意,矩阵乘法必须从左到右读取。看
“平移*旋转”操作导致围绕对象原点旋转:
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
“旋转*平移”操作导致围绕世界原点旋转:
问题代码中的矩阵glm::mat4旋转是对象的当前模型矩阵。
它包含对象的位置平移和方向。
要围绕世界原点旋转对象
glm::vec3 WorldUp( 0.0f, 1.0f, 0.0f );
glm::vec3 start_position = ...;
float scale = ...;
glm::vec3 p = ...;
为此,必须创建一个包含新旋转的矩阵
glm::mat4 new_rot = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, axis);
然后,您可以按如下方式计算最终矩阵:
Matrix = new_rot * rotation * scale_m;
如果要围绕点p旋转对象,且对象应始终面向点p,则只需对象开始位置和旋转轴的位置即可。
在您的例子中,旋转轴是世界的上方向向量
glm::vec3 WorldUp( 0.0f, 1.0f, 0.0f );
glm::vec3 start_position = ...;
float scale = ...;
glm::vec3 p = ...;
计算旋转矩阵和新的旋转位置
glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
glm::vec3 pos_rot = glm::vec3( pos_rot_h ) + p;
计算对象应该看的方向
glm::vec3 Front = glm::normalize(p - pos_rot);
可以使用函数getMatrix设置对象的当前方向矩阵:
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
计算模型矩阵:
glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
Matrix = pos_look * scale_m;
最终代码可能如下所示:
glm::mat4 getMatrix(const glm::vec3 &X, const glm::vec3 &Y, const glm::vec3 &Z, const glm::vec3 &T)
{
return glm::mat4(
glm::vec4( X, 0.0f ),
glm::vec4( Y, 0.0f ),
glm::vec4( Z, 0.0f ),
glm::vec4( T, 1.0f ) );
}
void rotate_about(float deltaTime, glm::vec3 p, bool ended) {
glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
glm::vec3 pos_rot = glm::vec3( pos_rot_h ) + p;
glm::vec3 Front = glm::normalize(p - pos_rot);
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
Matrix = pos_look * scale_m;
if ( ended == true )
Position = glm::vec3(Matrix[3]);
}
类似于或的操作通过其参数构建矩阵,并将输入矩阵乘以新矩阵
这意味着
rotation = glm::translate(rotation, Position - p );
可以表示为伪代码:
rotation = rotation * translation(Position - p);
注意,矩阵乘法必须从左到右读取。看
“平移*旋转”操作导致围绕对象原点旋转:
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
“旋转*平移”操作导致围绕世界原点旋转:
问题代码中的矩阵glm::mat4旋转是对象的当前模型矩阵。
它包含对象的位置平移和方向。
要围绕世界原点旋转对象
glm::vec3 WorldUp( 0.0f, 1.0f, 0.0f );
glm::vec3 start_position = ...;
float scale = ...;
glm::vec3 p = ...;
为此,必须创建一个包含新旋转的矩阵
glm::mat4 new_rot = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, axis);
然后,您可以按如下方式计算最终矩阵:
Matrix = new_rot * rotation * scale_m;
如果要围绕点p旋转对象,且对象应始终面向点p,则只需对象开始位置和旋转轴的位置即可。
在您的例子中,旋转轴是世界的上方向向量
glm::vec3 WorldUp( 0.0f, 1.0f, 0.0f );
glm::vec3 start_position = ...;
float scale = ...;
glm::vec3 p = ...;
计算旋转矩阵和新的旋转位置
glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
glm::vec3 pos_rot = glm::vec3( pos_rot_h ) + p;
计算对象应该看的方向
glm::vec3 Front = glm::normalize(p - pos_rot);
可以使用函数getMatrix设置对象的当前方向矩阵:
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
计算模型矩阵:
glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
Matrix = pos_look * scale_m;
最终代码可能如下所示:
glm::mat4 getMatrix(const glm::vec3 &X, const glm::vec3 &Y, const glm::vec3 &Z, const glm::vec3 &T)
{
return glm::mat4(
glm::vec4( X, 0.0f ),
glm::vec4( Y, 0.0f ),
glm::vec4( Z, 0.0f ),
glm::vec4( T, 1.0f ) );
}
void rotate_about(float deltaTime, glm::vec3 p, bool ended) {
glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, WorldUp);
glm::vec4 pos_rot_h = rotate * glm::vec4( start_position - p, 1.0f );
glm::vec3 pos_rot = glm::vec3( pos_rot_h ) + p;
glm::vec3 Front = glm::normalize(p - pos_rot);
glm::vec3 Right = glm::normalize(glm::cross(WorldUp, Front));
glm::mat4 pos_look = getMatrix(Right, WorldUp, Front, pos_rot);
glm::mat4 scale_m = glm::scale(glm::mat4(1.0f), glm::vec3(scale));
Matrix = pos_look * scale_m;
if ( ended == true )
Position = glm::vec3(Matrix[3]);
}
解决方案:
问题在于这一部分:
rotation = glm::translate(rotation, p - Position );
rotation = glm::rotate(rotation, ROTATION_SPEED * deltaTime, axis);
rotation = glm::translate(rotation, Position - p );
if (ended == true) { //if last iteration of my animation: saves position
Position.x = Matrix[3][0];
Position.y = Matrix[3][1];
Position.z = Matrix[3][2];
}
请注意,我使用世界原点和模型之间的距离作为平移的半径。但是,动画结束后,我会更新模型位置,这会更改p位置的结果,即轨道半径。发生这种情况时,模型会抖动,因为它丢失了旋转信息
我通过对轨道半径使用不同的变量,并在模型的z轴上应用平移来解决这个问题。当平移应用于x轴时,最初面向摄影机的模型将侧向终止于原点。但是,根据信号,在z轴上应用平移将导致模型朝向或向后到原点。解决方案:
问题在于这一部分:
rotation = glm::translate(rotation, p - Position );
rotation = glm::rotate(rotation, ROTATION_SPEED * deltaTime, axis);
rotation = glm::translate(rotation, Position - p );
if (ended == true) { //if last iteration of my animation: saves position
Position.x = Matrix[3][0];
Position.y = Matrix[3][1];
Position.z = Matrix[3][2];
}
请注意,我使用世界原点和模型之间的距离作为平移的半径。但是,动画结束后,我会更新模型位置,这会更改p位置的结果,即轨道半径。当这种情况发生时,模型会抽搐,因为它丢失了
轮换信息
我通过对轨道半径使用不同的变量,并在模型的z轴上应用平移来解决这个问题。当平移应用于x轴时,最初面向摄影机的模型将侧向终止于原点。但是,根据信号,在z轴上应用平移将导致模型朝向或向后朝向原点。谢谢您的回答,拉比76。但我对你的建议也有同样的看法。我这里的主要问题是,当模型围绕一个点旋转时,让它看到我想要的位置。我编辑了我的问题,以便让它更清楚,如果你能看一看,我会很高兴的。@MatheusIanzer我扩展了答案谢谢你的回答,拉比76。但我对你的建议也有同样的看法。我这里的主要问题是,当模型围绕一个点旋转时,让它看到我想要的位置。我编辑了我的问题,以便让它更清楚,如果你能看一下,我会很高兴的。@MatheusIanzer我扩展了答案,首先围绕外轴MR1矩阵旋转。然后平移模型MT,然后围绕其自身垂直轴MR2旋转。合成运动通过MFInal=MR2 x MT x MR1实现。矩阵的顺序是多方面的,这会让我的模型面对问题吗?如果是这样,在动画之后我应该保留什么信息,以便我可以将其放置在位置,以便从停止的位置继续进行另一次旋转?使用angleE进行外部旋转后,您可以知道模型的中心位置,一个简单的位置New=矩阵x位置Old乘法。使用此新位置和角度,可以计算应用于自旋转的角度。只要为下一个运动存储位置和当前自转角。使用这种方法,我必须为每个轴x、y、z存储自转角,然后创建3个旋转矩阵?@MatheusIanzer在系统中,它必须是[Right=glm::normalizeglm::crossFront,WorldUp;]`。但目前还不清楚您想要实现什么。首先围绕外轴MR1矩阵旋转。然后平移模型MT,然后围绕其自身垂直轴MR2旋转。合成运动通过MFInal=MR2 x MT x MR1实现。矩阵的顺序是多方面的,这会让我的模型面对问题吗?如果是这样,在动画之后我应该保留什么信息,以便我可以将其放置在位置,以便从停止的位置继续进行另一次旋转?使用angleE进行外部旋转后,您可以知道模型的中心位置,一个简单的位置New=矩阵x位置Old乘法。使用此新位置和角度,可以计算应用于自旋转的角度。只要为下一个运动存储位置和当前自转角。使用这种方法,我必须为每个轴x、y、z存储自转角,然后创建3个旋转矩阵?@MatheusIanzer在系统中,它必须是[Right=glm::normalizeglm::crossFront,WorldUp;]`。但目前还不清楚你想要实现什么。