Как я могу переместить 3D-окно, чтобы остаться на вращающейся плоскости? - PullRequest
0 голосов
/ 13 января 2019

У меня есть вращающаяся плоскость и коробка на ней. Когда самолет вращается и наклоняется под углом, я хочу, чтобы коробка оставалась в том же положении на плоскости.

Здесь плоскость не наклонена,

пока здесь самолет наклонен,

но коробка не следует за плоскостью вниз.

При каждом обновлении я визуализирую коробку и перевожу ее по заданному vec3 в glm::translate:

{
    glm::mat4 modelMatrix = glm::mat4(1);
    modelMatrix = glm::translate(modelMatrix, glm::vec3(boxOX, boxOY, boxOZ));
    modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOX), glm::vec3(1, 0, 0));
    modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOY), glm::vec3(0, 1, 0));
    modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOZ), glm::vec3(0, 0, 1));
    modelMatrix = glm::scale(modelMatrix, glm::vec3(0.2f));
    RenderSimpleMesh(meshes["box"], shaders["ShaderLab8"], modelMatrix, glm::vec3(1, 0, 0));
}

Самолет движется, нажимая клавиши WASD:

    if (window->KeyHold(GLFW_KEY_W) && (anglePlaneOX > -90.0f)) {
        anglePlaneOX -= deltaTime * DELTA_SLOPE;
    }
    if (window->KeyHold(GLFW_KEY_S) && (anglePlaneOX < 90.0f)) {
        anglePlaneOX += deltaTime * DELTA_SLOPE;
    }
    if (window->KeyHold(GLFW_KEY_D) && (anglePlaneOZ > -90.0f)) {
        anglePlaneOZ -= deltaTime * DELTA_SLOPE;
    }
    if (window->KeyHold(GLFW_KEY_A) && (anglePlaneOZ < 90.0f)) {
        anglePlaneOZ += deltaTime * DELTA_SLOPE;
    }

Я попробовал следующее

при нажатии клавиши A:

boxOY += deltaTime * (1 - (float)cos((double)anglePlaneOZ * PI / 180));

при нажатии клавиши W:

boxOX -= deltaTime * sinf(anglePlaneOX * PI / 180);

Но, похоже, ни один из них не работает.

Каковы математические соотношения для перемещения прямоугольника соответственно плоскости?

1 Ответ

0 голосов
/ 13 января 2019

Вы должны сделать перевод «до» вращения:

glm::mat4 modelMatrix = glm::mat4(1);  

modelMatrix = glm::translate(modelMatrix, glm::vec3(boxOX, boxOY, boxOZ));

modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOX), glm::vec3(1, 0, 0));  
modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOY), glm::vec3(0, 1, 0));  
modelMatrix = glm::rotate(modelMatrix, RADIANS(anglePlaneOZ), glm::vec3(0, 0, 1));

modelMatrix = glm::translate(modelMatrix, glm::vec3(boxOX, boxOY, boxOZ)); //  translate here

modelMatrix = glm::scale(modelMatrix, glm::vec3(0.2f));
RenderSimpleMesh(meshes["box"], shaders["ShaderLab8"], modelMatrix, glm::vec3(1, 0, 0));  

Пояснение:

Матрица перевода выглядит следующим образом:

glm::mat4 translate;
translate[0] : ( 1,  0,  0,  0 )
translate[1] : ( 0,  1,  0,  0 )
translate[2] : ( 0,  0,  1,  0 )
translate[3] : ( tx, ty, tz, 1 )

И матрица вращения вокруг оси Y выглядит следующим образом:

mat4  rotate;
float angle;
rotate[0] : ( cos(angle),  0, sin(angle), 0 )
rotate[1] : ( 0,           1, 0,          0 )
rotate[2] : ( -sin(angle), 0, cos(angle), 0 )
rotate[3] : ( 0,           0, 0,          1 ) 

Результат translate * rotate таков:

model[0] : ( cos(angle),  0,  sin(angle), 0 )
model[1] : ( 0,           1,  0,          0 )
model[2] : ( -sin(angle), 0,  cos(angle), 0 )
model[3] : ( tx,          ty, tz,         1 )

Обратите внимание, что результат rotate * translate будет:

model[0] : ( cos(angle),                     0,   sin(angle),                     0 )
model[1] : ( 0,                              1,   0,                              0 )
model[2] : ( -sin(angle),                    0,   cos(angle),                     0 )
model[3] : ( cos(angle)*tx - sin(angle)*tx,  ty,  sin(angle)*tz + cos(angle)*tz,  1 )

...