使用 Blender、Assimp.NET 和 FBX 文件时,包含“*0”或“*1”的奇怪相对路径会截断路径的前 3 个字符

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

我正在尝试制作一个程序来合并 fbx 模型。每个模型都有多个节点。一些节点有一个特定的名称,这意味着它们充当其他模型的连接点。

我已经解决了几乎所有有关合并的问题,除了纹理问题。网格和材质索引已更新,但当涉及到材质作为文件路径引用的纹理时,我遇到了一个奇怪的问题。 为了解决合并具有不同完整路径的模型的问题,纹理会导致问题,因为它们是通过模型文件的相对路径引用的。

加载以下基本代码时:

// Initialize the Assimp context
AssimpContext importer = new AssimpContext();

// Load the model with desired post-processing flags
Scene model = importer.ImportFile(filePath, PostProcessPreset.TargetRealTimeMaximumQuality | 
                                            PostProcessSteps.Triangulate |
                                            PostProcessSteps.FlipUVs |
                                            PostProcessSteps.EmbedTextures |
                                            PostProcessSteps.GlobalScale |
                                            PostProcessSteps.ValidateDataStructure);

材质存储的路径看起来很奇怪。 例如,与 fbx 文件本身位于同一文件夹中的文件“Normal.jpg”的相对路径存储为“*1 mal.jpg”,另一个存储在名为“GPV-2.fbm\BaseColor”的 .fbm 子文件夹中。 jpg”为“*0 -2 BG.fbm\BaseColor.jpg”。 对我来说,前 3 个字符似乎在导入过程中的某个时刻被覆盖。

我使用 Assimp.NET 5.0.0-beta1 包。

以前有人见过这样的事情吗?路径看起来像这样的原因是什么?我该如何解决它?

由于 Assimp.NET 加载纹理没有问题,我猜导入期间路径是好的。也许我可以以某种方式从 assimp 中获取完整路径?


Path.Combine 不起作用。我尝试手动剪切碎片,但丢失的字符仍然会导致问题,如果没有其他方法,我会尝试文件搜索。

我尝试查看 Assimp 代码,但找不到它到底是如何导入的。

我也尝试与ChatGPT讨论它,但也无法解决它,也无法给我指示去哪里寻找。

c# .net relative-path fbx assimp
1个回答
0
投票

同时我找到了解决方案。

如果引用了纹理,那么 GLB 文件实际上引用了某种图像,例如旁边的 JPEG,那么模型中的材质将引用作为文件路径。 然而,在嵌入纹理的情况下,它们会转换为压缩的二进制形式并添加到场景的“纹理”属性中。然后材质使用“*index”作为文件路径来知道它不是外部引用,而是嵌入的引用。由于字符串处理方面的差异,“ ”可能来自 C++/C# 兼容性错误。

相对于我想要做的实际任务(合并模型),现在的解决方案相当简单。我刚刚将嵌入纹理添加到根模型纹理中,然后调整子模型材质中的索引,然后再将它们添加到根中。

private static void MergeModelData(string path, Scene model, Scene subModel)
{
    UpdateMeshIndices(model, subModel.RootNode);
    foreach (Mesh mesh in subModel.Meshes)
    {
        mesh.MaterialIndex += model.MaterialCount;
    }

    int idx = model.Textures.Count;

    model.Textures.AddRange(subModel.Textures);

    foreach (Material mat in subModel.Materials)
    {
        AppendMaterial(model, mat, mat.TextureAmbient, path, idx);
        AppendMaterial(model, mat, mat.TextureAmbientOcclusion, path, idx);
        AppendMaterial(model, mat, mat.TextureDiffuse, path, idx);
        AppendMaterial(model, mat, mat.TextureDisplacement, path, idx);
        AppendMaterial(model, mat, mat.TextureEmissive, path, idx);
        AppendMaterial(model, mat, mat.TextureHeight, path, idx);
        AppendMaterial(model, mat, mat.TextureLightMap, path, idx);
        AppendMaterial(model, mat, mat.TextureNormal, path, idx);
        AppendMaterial(model, mat, mat.TextureOpacity, path, idx);
        AppendMaterial(model, mat, mat.TextureReflection, path, idx);
        AppendMaterial(model, mat, mat.TextureSpecular, path, idx);
    }

    model.Meshes.AddRange(subModel.Meshes);
}

private static void UpdateMeshIndices(Scene model, Node currentNode)
{
    if (currentNode.HasMeshes)
    {
        for (int i = 0; i < currentNode.MeshIndices.Count; i++)
        {
            currentNode.MeshIndices[i] += model.MeshCount;
        }
    }

    foreach (Node child in currentNode.Children)
    {
        UpdateMeshIndices(model, child);
    }
}

private static void AppendMaterial(Scene model, Material mat, TextureSlot slot, string path, int idx)
{
    if (slot.FilePath == null)
    {
        return;
    }

    string texPath;

    SwitchTextureInMaterial(mat, slot, $"*{idx++}\0");

    model.Materials.Add(mat);
}

private static void SwitchTextureInMaterial(Material mat, TextureSlot slot, string texPath)
{
    TextureSlot ts = new TextureSlot();
    ts.FilePath = texPath;
    ts.TextureType = slot.TextureType;
    ts.TextureIndex = slot.TextureIndex;
    ts.Mapping = slot.Mapping;
    ts.UVIndex = slot.UVIndex;
    ts.BlendFactor = slot.BlendFactor;
    ts.Operation = slot.Operation;
    ts.WrapModeU = slot.WrapModeU;
    ts.WrapModeV = slot.WrapModeV;
    ts.Flags = slot.Flags;

    mat.RemoveMaterialTexture(slot);
    mat.AddMaterialTexture(in ts);
}

我希望我能帮助下一个尝试同样做法的人。 =)

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