2016-12-14 30 views
2

我已經堅持了兩天了,我不確定在哪裏看。我使用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矩陣旋轉操作直? (我早些時候嘗試了最後一個選項,但我無法弄清楚如何讓它工作)。

謝謝!

編輯:更好的鏈路

+0

我不知道如何產生一個自包含的例子,因爲這使用OpenGL。 – Short

+1

'cube * .set_world_position()'做了什麼?在將它們發送到GPU之前,它是否修改了立方體的頂點座標?它是否修改對象的模型矩陣? – user1118321

+0

我編了功能,你的確切正確。它在發送給GPU之前修改立方體的頂點座標。它根本不修改模型矩陣。在我的遊戲進入它的遊戲循環之前,我會調用它一次,之後我再也不會修改它。對不起,我不得不重讀你的評論,我第一次沒有正確理解它。 – Short

回答

4

一般情況下,你不想修改CPU上你的模型的各個頂點的位置。這是頂點程序的全部目的。模型矩陣的目的是將模型定位在頂點程序中的世界中。要使模型圍繞其中心旋轉,需要先將中心移動到原點,然後旋轉它,然後將中心移動到其最終位置。假設你有一個從(0,0,0)延伸到(1,1,1)的立方體。您需要:

  1. 由角由(-0.5,-0.5,-0.5)
  2. 旋轉轉換立方體
  3. 由(0.5,0.5,0.5)
  4. 轉換立方體的翻譯立方體無論它屬於場景

您可以在最後2名翻譯合併成一個單一的一個,當然,你可以摺疊所有這些轉換爲一個矩陣那是你的模型矩陣。

+0

謝謝,我沒有意識到,當我從使用全球「世界座標」來使用這些矩陣乘法時,我已經開始這樣做了。完全切換到使用glm :: translate來初始化我的立方體的位置,修復會造成問題,這是有道理的。感謝您花時間寫這篇文章,但由於我每幀計算完整的MVP,這並不是答案。謝謝你 – Short

+0

所以我花了幾天時間,幫助我解決這個問題的大提示(對於將來通過谷歌發現這一點的其他人)是因爲我沒有考慮到對象的高度/寬度/長度如本答案所示)當我旋轉物體時。我只需要根據翻譯來計算我的頂點。 – Short