镜像网格和错误的UV贴图运行时导出 [英] Mirrored mesh and wrong UV map runtime export

查看:116
本文介绍了镜像网格和错误的UV贴图运行时导出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在与Assimp开发人员短暂联系后,我被指出了导入过程.当我从别人那里接管代码时,我不认为要看那部分:

So after a brief contact with the Assimp dev, I was pointed towards the import process. As I took over the code from someone else, I did not think looking that part:

using (var importer = new AssimpContext())
{
   scene = importer.ImportFile(file, PostProcessSteps.Triangulate | PostProcessSteps.FlipUVs | PostProcessSteps.JoinIdenticalVertices);
}

FlipUVs完全按照其说的进行操作,它在y轴上翻转,因此原点现在位于左上角.因此,现在我可以使用适当的UV来获得模型,但仍然可以镜像网格.将父对象设置为比例x = -1会将其翻转回正常状态,并使它看起来不错,但是我想这并不是本意.所以我一直在寻找.

FlipUVs does exactly what it says, it flips on the y axis so the origin is now top left corner. So now I am able to get the model with proper UV but still mirrored mesh. Setting the parent object with scale x = -1 flips it back to normal and makes it look fine but I guess this is not meant to be. So I keep looking.

看图片,有两种起重机型号.左侧的一个是在运行时通过序列化和重构加载的,而右侧的是一个简单地拖到场景中的原始的. 序列化通过Assimp库进行.

See the picture, there are two crane models. The one on the left is loaded at runtime via serialization and reconstruction while the right one is the original one simply dragged to the scene. Serialization happens with Assimp library.

地板恰好是首先创建的,并且似乎获得了正确的uv贴图.而其他项目得到错误的uv贴图.尽管我正在打印uv贴图的值,但它们似乎与原始图应该匹配.

The floor happens to be created first and seems to get the right uv map. While the other items get wrong uv map. Though I am printing the values of the uv maps and they seem to match the original one as they should.

这是序列化的方法,这是Assimp的Mesh类,而不是Unity Mesh类,应用序列化是在UWP中构建的Windows应用程序:

This is how to serialize, this is Mesh class from Assimp, not the Unity Mesh class, the app serializing is Windows application built in UWP:

    private static void SerializeMeshes(BinaryWriter writer, IEnumerable<Mesh> meshes)
    {
        foreach (Mesh mesh in meshes)
        {
            ICollection<int> triangles = MeshLoadTriangles(mesh);
            MeshSerializeHeader(writer, mesh.Name, mesh.VertexCount, triangles.Count, mesh.MaterialIndex);
            MeshSerializeVertices(writer, mesh.Vertices);
            MeshSerializeUVCoordinate(writer, mesh.TextureCoordinateChannels);
            MeshSerializeTriangleIndices(writer, triangles);                       
        }
    }

    private static void MeshSerializeUVCoordinate(BinaryWriter writer, List<Vector3D>[] textureCoordinateChannels)
    {
        // get first channel and serialize to writer. Discard z channel
        // This is Vector3D since happening outside Unity
        List<Vector3D> list = textureCoordinateChannels[0];
        foreach (Vector3D v in list)
        {
            float x = v.X;
            float y = v.Y;
            writer.Write(x);
            writer.Write(y);
        }
    }
    private static void MeshSerializeVertices(BinaryWriter writer, IEnumerable<Vector3D> vertices)
    {
        foreach (Vector3D vertex in vertices)
        {
            Vector3D temp = vertex;
            writer.Write(temp.X);
            writer.Write(temp.Y);
            writer.Write(temp.Z);
        }
    }
    private static void MeshSerializeTriangleIndices(BinaryWriter writer, IEnumerable<int> triangleIndices)
    {
          foreach (int index in triangleIndices)  { writer.Write(index); }
    }

这是反转过程:

    private static void DeserializeMeshes(BinaryReader reader, SceneGraph scene)
    {           
        MeshData[] meshes = new MeshData[scene.meshCount];
        for (int i = 0; i < scene.meshCount; i++)
        {
             meshes[i] = new MeshData();
             MeshReadHeader(reader, meshes[i]);
             MeshReadVertices(reader, meshes[i]);
             MeshReadUVCoordinate(reader, meshes[i]);
             MeshReadTriangleIndices(reader, meshes[i]);
        }
        scene.meshes = meshes as IEnumerable<MeshData>;
    }
private static void MeshReadUVCoordinate(BinaryReader reader, MeshData meshData)
    {
        bool hasUv = reader.ReadBoolean();
        if(hasUv == false) { return; }
        Vector2[] uvs = new Vector2[meshData.vertexCount];
        for (int i = 0; i < uvs.Length; i++)
        {
            uvs[i] = new Vector2();
            uvs[i].x = reader.ReadSingle();
            uvs[i].y = reader.ReadSingle();
        }
        meshData.uvs = uvs;
    }
    private static void MeshReadHeader(BinaryReader reader, MeshData meshData)
    {
        meshData.name = reader.ReadString();
        meshData.vertexCount = reader.ReadInt32();
        meshData.triangleCount = reader.ReadInt32();
        meshData.materialIndex = reader.ReadInt32();
    }
    private static void MeshReadVertices(BinaryReader reader, MeshData meshData)
    {
        Vector3[] vertices = new Vector3[meshData.vertexCount];

        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = new Vector3();
            vertices[i].x = reader.ReadSingle();
            vertices[i].y = reader.ReadSingle();
            vertices[i].z = reader.ReadSingle();
        }
        meshData.vertices = vertices;
    }
    private static void MeshReadTriangleIndices(BinaryReader reader, MeshData meshData)
    {
        int[] triangleIndices = new int[meshData.triangleCount];

        for (int i = 0; i < triangleIndices.Length; i++)
        {
            triangleIndices[i] = reader.ReadInt32();
        }
        meshData.triangles = triangleIndices;
    }

MeshData只是一个临时容器,带有来自fbx的反序列化值. 然后,创建网格:

MeshData is just a temporary container with the deserialized values from the fbx. Then, meshes are created:

private static Mesh[] CreateMeshes(SceneGraph scene)
{
    Mesh[] meshes = new Mesh[scene.meshCount];
    int index = 0;
    foreach (MeshData meshData in scene.meshes)
    {
        meshes[index] = new Mesh();           
        Vector3[] vec = meshData.vertices;
        meshes[index].vertices = vec;
        meshes[index].triangles = meshData.triangles;
        meshes[index].uv = meshData.uvs;   
        meshes[index].normals = meshData.normals;  
        meshes[index].RecalculateNormals();
        index++;
    }
    return meshes;
}

我看不到代码中会导致这种行为的任何原因,我想说的是,如果值错误,它将完全拧紧网格.

I don't see any reason in the code that should result in this kind of behaviour, I'd say it would totally screw the mesh if the values were wrong.

我可以看到我拥有的fbx文件正在使用四边形而不是三角形进行索引.

I can see that the fbx files I have are using quad instead of triangle for the indexing.

可能是Assimp对此做得不好吗?

Could it be that Assimp does not go to well with this?

推荐答案

我没有以正确的方式从Assimp解决此问题.

I did not solve the issue in a proper way from Assimp.

我们使用的基本解决方案是对对象变换中翻转的轴进行负缩放.

The basic solution we used was to scale negatively the axis that was flipped in the object transform.

一种更合适的解决方案是将所有顶点馈入Unity侧的矩阵,以便其正确解析顶点的位置.

A more appropriate solution would have been to feed all the vertices to a matrix in the Unity side so it resolves the position of the vertices properly.

  • 获取顶点列表
  • foreach顶点与旋转矩阵相乘
  • 将数组分配给网格
  • 使用网格渲染

这篇关于镜像网格和错误的UV贴图运行时导出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆