我将 OpenGL 与 GLFW 一起使用,我正在尝试旋转多个对象,每个对象都在同一轴心点上具有各自的模型矩阵。我为我的兔子准备了三种不同的模型,一种是身体,一种是前腿,另一种是后腿,我试图将它们都旋转到 Y 轴的最后面朝一个方向。然而,当我试图将它们旋转到位时,腿看起来像是在“移动”。如果我不沿 Y 轴旋转它们,那么它们就可以了。我想找到一种在一个轴心点上旋转所有三个模型矩阵的方法,这样当它们最终旋转时,它们就不会在自己的原点上旋转。这是我的主要代码:
class rabbit {
public:
std::vector<colored_model_object*> rabbit_renderers;
std::vector<glm::mat4> rabbit_models;
glm::vec3 position = glm::vec3(0.0f);
float fore_leg_rotation = 0;
float hind_leg_rotation = 0;
float whole_rotation = 0;
int jump_phase = 0;
float jump_lerp = 0.0f;
float jump_speed = 0.003f;
glm::vec3 jump_start, jump_end;
float y_velocity = 0;
rabbit() {
rabbit_renderers.push_back(new colored_model_object("res/objects/rabbit/rabbit_body.obj"));
rabbit_renderers.push_back(new colored_model_object("res/objects/rabbit/rabbit_front_legs.obj"));
rabbit_renderers.push_back(new colored_model_object("res/objects/rabbit/rabbit_hind_legs.obj"));
}
void jump(glm::vec3 direction, float magnitude) {
if (jump_phase >= 1) return;
glm::vec3 jump_power = glm::normalize(direction) * magnitude;
jump_start = position;
jump_end = position + jump_power;
jump_phase = 1;
jump_lerp = 0;
fore_leg_rotation = 0.0f;
hind_leg_rotation = 0.0f;
y_velocity = 1;
glm::vec2 dir_2d = glm::normalize(glm::vec2(direction.x, direction.z));
glm::vec2 up = glm::vec2(0, 1);
float dot = dir_2d.x * up.x + dir_2d.y * up.y;
float det = dir_2d.x * up.y - dir_2d.y * up.x;
float body_angle = atan2(det, dot);
whole_rotation = body_angle;
}
void update() {
position.y += y_velocity;
y_velocity -= 0.008f;
if (position.y < 0) position.y = 0;
if (jump_phase> 0) {
glm::vec2 jump_start_xz = glm::vec2(jump_start.x, jump_start.z);
glm::vec2 jump_end_xz = glm::vec2(jump_end.x, jump_end.z);
glm::vec2 position_xz = glm::mix(jump_start_xz, jump_end_xz, jump_lerp);
position.x = position_xz.x;
position.z = position_xz.y;
jump_lerp += jump_speed;
}
if (jump_phase == 1) {
fore_leg_rotation += 1;
hind_leg_rotation += 1;
if (fore_leg_rotation > 45.0f) {
jump_phase = 2;
}
}
if (jump_phase == 2) {
fore_leg_rotation -= 0.2f;
hind_leg_rotation -= 0.2f;
if (fore_leg_rotation < 0.0f) {
jump_phase = 3;
}
}
if (jump_lerp > 1) {
jump_phase = 0;
jump_lerp = 0;
fore_leg_rotation = 0.0f;
hind_leg_rotation = 0.0f;
}
}
void update_models() {
update();
rabbit_models.clear();
rabbit_models.push_back(system3d::get_model());
rabbit_models.push_back(system3d::get_model());
rabbit_models.push_back(system3d::get_model());
rabbit_models.at(0) = (system3d::create_model(rabbit_models.at(0),glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(-100 + position.x, 310.5f + position.y, 0 + position.z), 0.0f, glm::vec3(1, 1, 1)));
rabbit_models.at(1) = (system3d::create_model(rabbit_models.at(1), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(-100 + position.x, 310.5f + position.y, 0 + position.z), fore_leg_rotation, glm::vec3(1, 0, 0), glm::vec3(0, -42.0f, 0)));
rabbit_models.at(2) = (system3d::create_model(rabbit_models.at(2), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(-100 + position.x, 310.5f + position.y, 0 + position.z), hind_leg_rotation, glm::vec3(1, 0, 0), glm::vec3(0, -42.0f, 17.0f)));
for (int i = 0; i < rabbit_models.size(); i++) {
rabbit_models.at(i) = glm::rotate(rabbit_models.at(i), glm::radians(whole_rotation), glm::vec3(0, 1, 0));
}
}
};
这里是引用的 system3d 类:
class system3d {
public:
static glm::mat4 get_model(glm::vec3 scale_vec, glm::vec3 translate_vec, float rotation, glm::vec3 rotation_vec) {
glm::mat4 model = glm::mat4(1.0f);
model = glm::scale(model, scale_vec);
model = glm::rotate(model, glm::radians(rotation), rotation_vec);
model = glm::translate(model, translate_vec);
return model;
}
static glm::mat4 get_model(glm::vec3 scale_vec, glm::vec3 translate_vec, float rotation, glm::vec3 rotation_vec, glm::vec3 rotation_pivot) {
glm::mat4 model = glm::mat4(1.0f);
model = glm::scale(model, scale_vec);
model = glm::translate(model, translate_vec);
model = glm::translate(model, -rotation_pivot);
model = glm::rotate(model, glm::radians(rotation), rotation_vec);
model = glm::translate(model, rotation_pivot);
return model;
}
static glm::mat4 create_model(glm::mat4 existing, glm::vec3 scale_vec, glm::vec3 translate_vec, float rotation, glm::vec3 rotation_vec) {
glm::mat4 model = existing;
model = glm::scale(model, scale_vec);
model = glm::rotate(model, glm::radians(rotation), rotation_vec);
model = glm::translate(model, translate_vec);
return model;
}
static glm::mat4 create_model(glm::mat4 existing, glm::vec3 scale_vec, glm::vec3 translate_vec, float rotation, glm::vec3 rotation_vec, glm::vec3 rotation_pivot) {
glm::mat4 model = existing;
model = glm::scale(model, scale_vec);
model = glm::translate(model, translate_vec);
model = glm::translate(model, -rotation_pivot);
model = glm::rotate(model, glm::radians(rotation), rotation_vec);
model = glm::translate(model, rotation_pivot);
return model;
}
static glm::mat4 get_model() {
glm::mat4 model = glm::mat4(1.0f);
return model;
}
};
几个小时以来,我一直在努力寻找解决方案,但我还没有找到不涉及四元数的解决方案。 (我发现四元数真的很令人困惑,我个人无法编写有效的四元数代码。)
这是一个视频,首先是当他们 Y 轴旋转为 0 时,然后当 y 轴旋转不为 0 时:
有人知道我能做什么吗?