Порядок преобразований для рендеринга сценографа - PullRequest
0 голосов
/ 10 июня 2019

В моем 2D Game Engine я борюсь с правильным рендерингом спрайтов, если эти объекты находятся в родительско-дочерних отношениях.Картина объясняет проблему.Я использую сценограф для рендеринга и использую шаблон посетителя для обхода.Я хочу, чтобы вращение родителя вращало только ребенка на месте.

Image showing problem

//spriterenderer.cpp

// sprites are positioned & rotated around the center
    GLfloat vertices[] = {
        // Pos      // Tex
        -0.5f, 0.5f, 0.0f, 1.0f,
        0.5f, -0.5f, 1.0f, 0.0f,
        -0.5f, -0.5f, 0.0f, 0.0f,

        -0.5f, 0.5f, 0.0f, 1.0f,
        0.5f, 0.5f, 1.0f, 1.0f,
        0.5f, -0.5f, 1.0f, 0.0f
    };

// this gets called if a GameObject has children
bool SpriteRenderer::Enter(GameObject & node)
{
...
RenderSprite(...);

// save the current modelMatrix on the stack
m_matrixStack.push_back(m_modelMatrix);

// apply transformation. I assume this is where the mistake is made
m_modelMatrix = glm::translate(m_modelMatrix, glm::vec3(node.GetLocalPosition(), 0.0f));
m_modelMatrix = glm::rotate(m_modelMatrix, node.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
m_modelMatrix = glm::scale(m_modelMatrix, glm::vec3(node.GetLocalScale(), 1.0f));
return true;

}

// after drawing all children of a node restore the previous model matrix
bool SpriteRenderer::Leave(GameObject & node)
{
    m_modelMatrix = m_matrixStack.back();
    m_matrixStack.pop_back();
    return true;
}

// if a node doesn't have children
bool SpriteRenderer::Visit(GameObject & node)
{
    RenderSprite(...);
}

void SpriteRenderer::RenderSprite(...)
{
// save the current transformation
    m_matrixStack.push_back(m_modelMatrix);

    // apply model transform
    m_modelMatrix = glm::translate(m_modelMatrix, glm::vec3(gameObject.GetLocalPosition(), 0.0f));
    m_modelMatrix = glm::rotate(m_modelMatrix, gameObject.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
    m_modelMatrix = glm::scale(m_modelMatrix, glm::vec3(textureSize, 1.0f));

....
//restore previous transform
    m_modelMatrix = m_matrixStack.back();
    m_matrixStack.pop_back();
}

1 Ответ

0 голосов
/ 10 июня 2019

Я нашел рабочее решение, отслеживая вращение аддитивным способом.

Итак, вместо

// in SpriteRenderer::Enter
m_modelMatrix = glm::rotate(m_modelMatrix, node.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));

я использую m_additiveRotation += node.GetLocalRotation(); и в SpriteRenderer ::Оставьте я вычесть сумму снова.

Наконец, в SpriteRenderer :: RenderSprite он меняется на

m_modelMatrix = glm::translate(m_modelMatrix, glm::vec3(gameObject.GetLocalPosition(), 0.0f));
m_modelMatrix = glm::rotate(m_modelMatrix, m_additiveRotation, glm::vec3(0.0f, 0.0f, 1.0f));
m_modelMatrix = glm::rotate(m_modelMatrix, gameObject.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
m_modelMatrix = glm::scale(m_modelMatrix, glm::vec3(textureSize, 1.0f));
...