渲染场景图的转换顺序
Order of transformations for rendering a scenegraph
在我的 2D 游戏引擎中,如果 objects 处于 parent-child 关系中,我很难正确渲染精灵。图片说明了问题。
我使用场景图进行渲染并使用访问者模式进行遍历。
我希望 parent 的旋转仅将 child 旋转到位。
//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();
}
我通过以附加方式跟踪旋转找到了一个可行的解决方案。
所以,而不是
// in SpriteRenderer::Enter
m_modelMatrix = glm::rotate(m_modelMatrix, node.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
我使用 m_additiveRotation += node.GetLocalRotation();
并在 SpriteRenderer::Leave 中再次减去金额。
最后,在 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));
在我的 2D 游戏引擎中,如果 objects 处于 parent-child 关系中,我很难正确渲染精灵。图片说明了问题。 我使用场景图进行渲染并使用访问者模式进行遍历。 我希望 parent 的旋转仅将 child 旋转到位。
//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();
}
我通过以附加方式跟踪旋转找到了一个可行的解决方案。
所以,而不是
// in SpriteRenderer::Enter
m_modelMatrix = glm::rotate(m_modelMatrix, node.GetLocalRotation(), glm::vec3(0.0f, 0.0f, 1.0f));
我使用 m_additiveRotation += node.GetLocalRotation();
并在 SpriteRenderer::Leave 中再次减去金额。
最后,在 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));