将局部空间法线转换为世界空间

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

我需要将局部空间网格转换为全局空间。 得到的法线向量似乎不正确。

我得到了顶点的世界变换矩阵(这有效,因为顶点的位置是正确的)。然后,我通过获取世界变换矩阵的逆矩阵的转置矩阵来获得法线的变换矩阵。我用它来变换局部空间法向量。

结果是: Calculation Result

但是结果应该更像这样: Expected Result

当前结果使用的代码(查看“// TODO:修复法线(Buggy)”在哪里)

        FMeshData &MeshData = ModelData.Meshes[MeshIndex];
        aiMesh *Mesh = Scene->mMeshes[MeshIndex];
        aiNode *Node = GetParentNode(Scene->mRootNode, MeshIndex);

        // Get world transform
        FMatrix PositionMatrix = GetWorldTransformOfNode(Node);
        FMatrix NormalMatrix =   UKismetMathLibrary::Matrix_GetTransposed(PositionMatrix.Inverse());

        // Material id
        MeshData.MaterialId = Mesh->mMaterialIndex;

        // Lod Data
        GetLodData(LodFilePath, FString(Mesh->mName.C_Str()), MeshData.LodData);

        // Vertices
        for (uint32 VertexIndex = 0; VertexIndex < Mesh->mNumVertices; VertexIndex++)
        {
            // Position
            aiVector3D &aiVertex = Mesh->mVertices[VertexIndex];
            FVector PositionVertex = PositionMatrix.TransformFVector4(FVector(
                aiVertex.x,
                aiVertex.y,
                aiVertex.z));

            FVector3f Position(
                PositionVertex.X,
                PositionVertex.Y,
                PositionVertex.Z);

            // Normal
            FVector3f Normal = FVector3f::ZeroVector;
            if (Mesh->HasNormals())
            {
                //TODO: Fix normals (Buggy)
                aiVector3D &aiNormal = Mesh->mNormals[VertexIndex];
                FVector NormalVector = NormalMatrix.TransformFVector4(FVector(
                    aiNormal.x,
                    aiNormal.y,
                    aiNormal.z));

                Normal = FVector3f(
                    NormalVector.X,
                    NormalVector.Y,
                    NormalVector.Z);
            }

            // Tangent
            FVector3f Tangent = FVector3f::ZeroVector;
            if (Mesh->HasTangentsAndBitangents())
            {
                aiVector3D &aiTangent = Mesh->mTangents[VertexIndex];
                Tangent = FVector3f(
                    aiTangent.x,
                    aiTangent.y,
                    aiTangent.z);
            }

            // Linear Color
            FLinearColor LinearColor = FLinearColor::White;
            if (Mesh->HasVertexColors(0))
            {
                aiColor4D &aiColor = Mesh->mColors[0][VertexIndex];
                LinearColor = FLinearColor(
                    aiColor.r,
                    aiColor.g,
                    aiColor.b,
                    aiColor.a);
            }

            // UVs
            FVector2f UV0 = FVector2f::ZeroVector;
            FVector2f UV1 = FVector2f::ZeroVector;
            FVector2f UV2 = FVector2f::ZeroVector;
            FVector2f UV3 = FVector2f::ZeroVector;
            for (uint32 ChannelIndex = 0; ChannelIndex <= 3; ChannelIndex++)
            {
                if (Mesh->HasTextureCoords(ChannelIndex))
                {
                    aiVector3D &aiCoordinate = Mesh->mTextureCoords[ChannelIndex][VertexIndex];
                    FVector2f Coordinate(aiCoordinate.x, -aiCoordinate.y);

                    switch (ChannelIndex)
                    {
                    case 0:
                        UV0 = Coordinate;
                        break;
                    case 1:
                        UV1 = Coordinate;
                        break;
                    case 2:
                        UV2 = Coordinate;
                        break;
                    case 3:
                        UV3 = Coordinate;
                        break;
                    }
                }
            }

            // Create vertex
            FVertexData Vertex;
            Vertex.Position = Position;
            Vertex.Normal = Normal;
            Vertex.Tangent = Tangent;
            Vertex.Color = LinearColor;
            Vertex.UV0 = UV0;
            Vertex.UV1 = UV1;
            Vertex.UV2 = UV2;
            Vertex.UV3 = UV3;

            // Save vertex
            MeshData.Verticies.Push(Vertex);
        }
    }
mesh unreal-engine5 assimp
1个回答
0
投票

普通矩阵是变换矩阵旋转部分的逆矩阵的转置。看起来你是在也有位置的变换矩阵上做的。

从技术上讲,您只需要反转旋转矩阵,因为法向量都是有方向的,因此已归一化。我们使用旋转部分的逆转置的原因只是为了消除任何比例。请参阅此链接以回顾其背后的数学:http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/

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