【发布时间】:2021-06-21 13:12:00
【问题描述】:
我正在尝试构建转换系统,模仿 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;
}
这就是我计算局部变换和世界变换的方式。我已经尝试了很多转换矩阵顺序的组合,但没有一个能正常工作。我尝试引用 Unity3d,但找不到有用的东西。
localPosition 和 localScale 是 glm::vec3 类型,localRotation 是 glm::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 的变换系统。 我该如何解决这个问题?
【问题讨论】:
-
如果
worldTransform = localTransform * parent.lock()->GetWorldTransform();istead 会怎样? -
@AlexeyLarionov 我试过了,没有任何改变:(