OpenGL 构建层次变换系统

OpenGL building hierarchy transform system

我正在尝试构建转换系统,模仿 Unity 的。看我的代码:

void BaseObject::RecalculateTransform()
{
    // For top object
    if (parent.expired())
    {
        worldTransform = localTransform = glm::mat4(1);
        return;
    }

    // bunch of shit
    localTransform = glm::translate(glm::mat4(1), localPosition) * glm::scale(glm::mat4(1), localScale) * glm::mat4(localRotation);

    worldTransform = parent.lock()->GetWorldTransform() * localTransform;
}

这就是我计算局部变换和世界变换的方式。我已经尝试了很多变换矩阵顺序的组合,但其中 none 可以正常工作。我试图引用 Unity3d,但找不到有用的东西。

localPositionlocalScaleglm::vec3类型,localRotationglm::quat类型。

可能有帮助,我从上面的代码中截取了一个屏幕截图:

auto top = app->GetHierarchy()->GetTopObject();

auto childDepth1 = top->Instantiate().lock();
childDepth1->SetLocalPosition(glm::vec3(0, 1, 0));

// spiral one
auto mesh1 = childDepth1->AddComponent<RandomMesh>().lock();
mesh1->SetVerticeData("l 30");

auto childDepth2 = childDepth1->Instantiate().lock();
childDepth2->SetLocalPosition(glm::vec3(0, 1, 0));

// spherical one
auto mesh2 = childDepth2->AddComponent<RandomMesh>().lock();
mesh2->SetVerticeData("s 100 t");

截图:

如您所见,螺旋形的子元素是球体。螺旋形的 localPosition(0, 1, 0)worldPosition 也是如此。但它呈现在 -y 位置。 (我已经通过其他方式确认+y位置在中线以上。)

此外,球体的 localPosition 也是 (0, 1, 0),因此它是 worldPosition (0, 2, 0)。保持 +y 位置在中线下方的方向,它必须渲染在螺旋线下方,但它渲染 球体上方。通过打印调试,它说球体的 worldPosition(0, 0, 0),而不是 (0, 2, 0).

经过一些实验,我发现变换矩阵应用正负,取决于子深度的奇偶性。

我要的就是类Unity的变换系统。 我该如何解决这个问题?

这是由于我的愚蠢错误。当我初始化localRotation四元数值时,我在做

localRotation = glm::quat(0, 0, 0, 1);

我不知道为什么,但是使用调试器,每次旋转矩阵相乘时它都会否定位置值。

正确的初始化是

localRotation = glm::identity<glm::quat>();

根本不会应用旋转,顾名思义

这是我的解决方案:

void BaseObject::RecalculateTransform()
{
    isTransformChanged = false;

    // For top object
    if (parent.expired())
    {
        worldTransform = localTransform = glm::mat4(1);
        return;
    }

    const auto& scaled = glm::scale(glm::mat4(1), localScale);
    const auto& rotated = glm::mat4(localRotation) * scaled;
    const auto& translated = glm::translate(glm::mat4(1), localPosition) * rotated;

    localTransform = translated;

    worldTransform = parent.lock()->GetWorldTransform() * localTransform;
}

一切都很好。在韩国已经是午夜了。我终于可以去睡觉了。 和我遇到同样问题的人,请不要犯傻:(