从 C++ 创建和显示 DynamicMesh - 弄乱了一半面的法线

问题描述 投票:0回答:1

我很难在 UE 中从 C++ 级别做相当简单的事情。 目标很简单。我希望能够显示一个立方体。我想手动指定顶点、面和法线。用 C++ 对其进行硬编码,创建网格并显示。但我还是做不到。

此存储库中提供了该项目的完整代码。请查看 AMyActor::RegenerateMeshByHand 方法。 https://github.com/stryku/BareBonesDynamicMesh/blob/forum-question/Source/BareBonesDynamicMesh/MyActor.cpp#L154

我有一个简单的项目,只有一个从 AActor 派生的 MyActor。我创建了一个 UDynamicMeshComponent 并将其设置为我的根组件。 在 PostLoad() 中,我尝试创建 UE::Geometry::FDynamicMesh3 网格并将其设置在我的根组件中。

一切正常,网格已设置,但看起来不太好。其他每个面的法线都混乱了,因此立方体的一半面是不可见的。它们只能“从内部”看到,因为只有在这个视图中,法线才面向相机(我认为)。

当我调用 mesh.CheckValidity() 时,我得到 false,所以我一定做错了什么。

我尝试了另一件事:在 Blender 中创建一个立方体,导出到 OBJ 文件,看看里面有什么,然后从代码中执行相同的操作。并且它有效(在 ReverseOrientation 和 InitializeOverlayToPerTriangleNormals 之后)!显示完整的立方体,所有法线都很好。 所以,我很困惑。

当然我错过了引擎明显需要的东西。有人知道出了什么问题吗?

该方法的完整代码(如果有人喜欢的话):

UE::Geometry::FDynamicMesh3 AMyActor::RegenerateMeshByHand() {

  UE::Geometry::FDynamicMesh3 mesh;
  mesh.EnableAttributes();

  UE::Geometry::FDynamicMeshNormalOverlay *normalsOverlay =
      mesh.Attributes()->PrimaryNormals();

  const std::array vertices{FVector3d(-1, -1, -1), FVector3d(1, -1, -1),
                            FVector3d(-1, -1, 1),  FVector3d(1, -1, 1),
                            FVector3d(-1, 1, -1),  FVector3d(1, 1, -1),
                            FVector3d(-1, 1, 1),   FVector3d(1, 1, 1)};

  const std::array normals{FVector3f(0, -1, 0), FVector3f(0, 1, 0),
                           FVector3f(-1, 0, 0), FVector3f(1, 0, 0),
                           FVector3f(0, 0, -1), FVector3f(0, 0, 1)};

  int32 id;
  UE::Geometry::EMeshResult result;

  for (auto vertex : vertices) {
    mesh.AppendVertex(vertex * 100);
  }

  for (auto normal : normals) {
    normalsOverlay->AppendElement(normal);
    normalsOverlay->AppendElement(normal);
    normalsOverlay->AppendElement(normal);
  }

  // Face 0, 1. Normal 0
  id = mesh.AppendTriangle(0, 1, 2);
  result = normalsOverlay->SetTriangle(id, {0, 1, 2});

  id = mesh.AppendTriangle(3, 1, 2);
  result = normalsOverlay->SetTriangle(id, {0, 1, 2});

  // Face 2, 3. Normal 1
  id = mesh.AppendTriangle(4, 5, 6);
  result = normalsOverlay->SetTriangle(id, {1 * 3, 1 * 3 + 1, 1 * 3 + 2});

  id = mesh.AppendTriangle(7, 5, 6);
  result = normalsOverlay->SetTriangle(id, {1 * 3, 1 * 3 + 1, 1 * 3 + 2});

  // Face 4, 5. Normal 2
  id = mesh.AppendTriangle(4, 6, 0);
  result = normalsOverlay->SetTriangle(id, {2 * 3, 2 * 3 + 1, 2 * 3 + 2});

  id = mesh.AppendTriangle(2, 6, 0);
  result = normalsOverlay->SetTriangle(id, {2 * 3, 2 * 3 + 1, 2 * 3 + 2});

  // Face 6, 7. Normal 3
  id = mesh.AppendTriangle(1, 5, 3);
  result = normalsOverlay->SetTriangle(id, {3 * 3, 3 * 3 + 1, 3 * 3 + 2});

  id = mesh.AppendTriangle(7, 5, 3);
  result = normalsOverlay->SetTriangle(id, {3 * 3, 3 * 3 + 1, 3 * 3 + 2});

  // Face 8, 9. Normal 4
  id = mesh.AppendTriangle(0, 1, 4);
  result = normalsOverlay->SetTriangle(id, {4 * 3, 4 * 3 + 1, 4 * 3 + 2});

  id = mesh.AppendTriangle(5, 1, 4);
  result = normalsOverlay->SetTriangle(id, {4 * 3, 4 * 3 + 1, 4 * 3 + 2});

  // Face 10, 11. Normal 5
  id = mesh.AppendTriangle(2, 3, 6);
  result = normalsOverlay->SetTriangle(id, {5 * 3, 5 * 3 + 1, 5 * 3 + 2});

  id = mesh.AppendTriangle(7, 3, 6);
  result = normalsOverlay->SetTriangle(id, {5 * 3, 5 * 3 + 1, 5 * 3 + 2});

  // Why is this false?
  const auto validityResult =
      mesh.CheckValidity({}, UE::Geometry::EValidityCheckFailMode::ReturnOnly);

  return mesh;
}
c++ mesh unreal-engine5
1个回答
0
投票

必须调用ReverseOrientation。会有帮助

© www.soinside.com 2019 - 2024. All rights reserved.