我正在尝试制作一个简单的动画,其中的对象使用glm lib在OpenGL中围绕世界原点旋转。我的想法是:
将对象发送到原点
旋转
发送回原始位置
看看我想要的东西
这是我的实现方式
{
"ShoppingCart": {
"Products": [
{
"Sku": "123",
"Size": "S",
"Quantity": "1"
},
{
"Sku": "456",
"Size": "M",
"Quantity": "2"
},
{
"Sku": "789",
"Size": "L",
"Quantity": "3"
}
],
"ShipToZip": "54452",
"ShipMethod": "Ground"
}
}
getMatrix()仅返回一个4x4矩阵,如下所示:
// 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];
}
}
我正在使用这张图片作为参考:
因为这是我的模型在开始动画时就消失了。如果删除下面的行| 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(在本例中为原点)时产生的效果。当我尝试时,我的模型消失了。如何使其旋转到我想要的位置,以及在旋转完后如何为模型添加新的“前/右/上”矢量?
This是我在上面的gif中运行的代码
答案 0 :(得分:1)
glm::translate()
或glm::roate()
之类的操作通过其参数构建矩阵,并将输入矩阵乘以新矩阵
这意味着
rotation = glm::translate(rotation, Position - p );
可以表示为(伪代码):
rotation = rotation * translation(Position - p);
请注意,矩阵乘法必须从左到右“读取”。 (请参见GLSL Programming/Vector and Matrix Operations)
操作translate * rotate
引起围绕对象原点的旋转:
操作rotate * translate
引起围绕世界原点的旋转:
矩阵glm::mat4 rotation
(在您的问题代码中)是对象的当前模型矩阵。
它包含对象的位置(平移)和方向。
您想围绕世界的起源旋转对象。
为此,您必须创建一个包含新旋转的矩阵
glm::mat4 new_rot = glm::rotate(glm::mat4(1.0f), ROTATION_SPEED * deltaTime, axis);
然后您可以计算出最终矩阵,如下所示:
Matrix = new_rot * rotation * scale_m;
如果要围绕点p
旋转对象,并且该对象应始终面对点p
,则所需要做的就是对象(start_position
)的位置和旋转轴。
在您的情况下,旋转轴是世界的向上向量。
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]);
}
答案 1 :(得分:0)
解决方案:
问题出在这部分:
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 - Position
的结果,即轨道半径。发生这种情况时,模型会“抽搐”,因为它丢失了旋转信息。
我通过为轨道半径使用其他变量并将平移应用于模型的z-axis
来解决了这一问题。当在x轴上应用平移时,最初面向相机的模型将侧向终止于原点。但是,根据信号的不同,在z轴上应用平移将最终使模型面向原点或面向原点。