我已經堅持了兩天了,我不確定在哪裏看。我使用OpenGL呈現兩個3D立方體,並嘗試將這些場景中的每個立方體應用局部旋轉以響應我按下按鈕。我的3D OpenGL對象圍繞世界原點旋轉,而不是本地空間原點。我在做什麼錯誤或誤解?
我已經到了我的立方體在三維空間旋轉的地步,但它們都圍繞着世界空間的起源旋轉,而不是它們自己的本地起源。
(夫婦第二視頻) https://www.youtube.com/watch?v=3mrK4_cCvUw
在網上淘後,計算MVP合適的公式爲:
auto const model = TranslationMatrix * RotationMatrix * ScaleMatrix;
auto const modelview = projection * view * model;
我的每個立方體都有它自己的「模型」,這定義如下:
struct model
{
glm::vec3 translation;
glm::quat rotation;
glm::vec3 scale = glm::vec3{1.0f};
};
當我按下鍵盤上的按鈕時,我創建了一個代表n的四元數並將其與先前的旋轉四元數相乘,並將其更新到位。
功能如下:
template<typename TData>
void rotate_entity(TData &data, ecst::entity_id const eid, float const angle,
glm::vec3 const& axis) const
{
auto &m = data.get(ct::model, eid);
auto const q = glm::angleAxis(glm::degrees(angle), axis);
m.rotation = q * m.rotation;
// I'm a bit unsure on this last line above, I've also tried the following without fully understanding the difference
// m.rotation = m.rotation * q;
}
軸由用戶提供的,像這樣:
// inside user-input handling function
float constexpr ANGLE = 0.2f;
...
// y-rotation
case SDLK_u: {
auto constexpr ROTATION_VECTOR = glm::vec3{0.0f, 1.0f, 0.0f};
rotate_entities(data, ANGLE, ROTATION_VECTOR);
break;
}
case SDLK_i: {
auto constexpr ROTATION_VECTOR = glm::vec3{0.0f, -1.0f, 0.0f};
rotate_entities(data, ANGLE, ROTATION_VECTOR);
break;
}
我的GLSL頂點着色器是非常簡單的從我的發現示例代碼在那裏:
// attributes input to the vertex shader
in vec4 a_position; // position value
// output of the vertex shader - input to fragment
// shader
out vec3 v_uv;
uniform mat4 u_mvmatrix;
void main()
{
gl_Position = u_mvmatrix * a_position;
v_uv = vec3(a_position.x, a_position.y, a_position.z);
}
在我的繪圖代碼中,我使用的確切代碼來計算ea的MVP CH立方體是:
...
auto const& model = shape.model();
auto const tmatrix = glm::translate(glm::mat4{}, model.translation);
auto const rmatrix = glm::toMat4(model.rotation);
auto const smatrix = glm::scale(glm::mat4{}, model.scale);
auto const mmatrix = tmatrix * rmatrix * smatrix;
auto const mvmatrix = projection * view * mmatrix;
// simple wrapper that does logging and forwards to glUniformMatrix4fv()
p.set_uniform_matrix_4fv(logger, "u_mvmatrix", mvmatrix);
我的程序早些時候,我計算我的看法/投影矩陣,像這樣:
auto const windowheight = static_cast<GLfloat>(hw.h);
auto const windowwidth = static_cast<GLfloat>(hw.w);
auto projection = glm::perspective(60.0f, (windowwidth/windowheight), 0.1f, 100.0f);
auto view = glm::lookAt(
glm::vec3(0.0f, 0.0f, 1.0f), // camera position
glm::vec3(0.0f, 0.0f, -1.0f), // look at origin
glm::vec3(0.0f, 1.0f, 0.0f)); // "up" vector
將在世界空間我的立方體的位置是在Z軸上,所以他們應該是可見的:
cube0.set_world_position(0.0f, 0.0f, 0.0f, 1.0f);
cube1.set_world_position(-0.7f, 0.7f, 0.0f, 1.0f);
// I call set_world_position() exactly once before my game enter's it's main loop.
// I never call this again, it just modifies the vertex used as the center of the shape.
// It doesn't modify the model matrix at all.
// I call it once before my game enter's it's game loop, and I never modify it after that.
所以,我的問題是,是更新對象的旋轉的適當方式?
我應該直接在對象的「模型」中存儲四元數嗎?
我應該存儲我的翻譯和縮放作爲單獨的vec3?
有沒有更簡單的方法來做到這一點?我一直在閱讀和重讀任何我能找到的東西,但我沒有看到任何人以同樣的方式做這件事。
本教程對細節略有不足,具體如何將旋轉應用於現有旋轉(我相信這只是將四元數乘以一起,這正是我在rotate_entity(...)中所做的) 。 http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ https://github.com/opengl-tutorials/ogl/blob/master/tutorial17_rotations/tutorial17.cpp#L306-L311
是否更有意義,存儲所產生的「MVP」矩陣幻想自己爲「模型」和應用GLM ::變換/ GLM ::規模/ GLM ::在MVP矩陣旋轉操作直? (我早些時候嘗試了最後一個選項,但我無法弄清楚如何讓它工作)。
謝謝!
編輯:更好的鏈路
我不知道如何產生一個自包含的例子,因爲這使用OpenGL。 – Short
'cube * .set_world_position()'做了什麼?在將它們發送到GPU之前,它是否修改了立方體的頂點座標?它是否修改對象的模型矩陣? – user1118321
我編了功能,你的確切正確。它在發送給GPU之前修改立方體的頂點座標。它根本不修改模型矩陣。在我的遊戲進入它的遊戲循環之前,我會調用它一次,之後我再也不會修改它。對不起,我不得不重讀你的評論,我第一次沒有正確理解它。 – Short