Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 镜像网格和错误的UV贴图运行时导出_C#_Unity3d_Assimp - Fatal编程技术网

C# 镜像网格和错误的UV贴图运行时导出

C# 镜像网格和错误的UV贴图运行时导出,c#,unity3d,assimp,C#,Unity3d,Assimp,编辑:所以在与Assimp开发人员进行了简短的接触之后,我被指向了导入过程。当我从其他人手中接过代码时,我并不认为这一部分: using (var importer = new AssimpContext()) { scene = importer.ImportFile(file, PostProcessSteps.Triangulate | PostProcessSteps.FlipUVs | PostProcessSteps.JoinIdenticalVertices); } Fli

编辑:所以在与Assimp开发人员进行了简短的接触之后,我被指向了导入过程。当我从其他人手中接过代码时,我并不认为这一部分:

using (var importer = new AssimpContext())
{
   scene = importer.ImportFile(file, PostProcessSteps.Triangulate | PostProcessSteps.FlipUVs | PostProcessSteps.JoinIdenticalVertices);
}
FlipUV完全按照它所说的做,它在y轴上翻转,因此原点现在位于左上角。因此,现在我可以得到适当的UV模型,但仍然是镜像网格。将父对象的比例设置为x=-1会将其翻转回正常状态并使其看起来很好,但我猜这并不是故意的。所以我一直在找


如图所示,有两种起重机型号。左侧的一个在运行时通过序列化和重建加载,而右侧的一个是原始的一个,只是简单地拖动到场景中。 序列化使用Assimp库进行

地板恰好是首先创建的,似乎得到了正确的uv贴图。而其他项目得到错误的uv贴图。虽然我正在打印uv贴图的值,但它们似乎与原始贴图匹配

这是如何序列化的,这是Assimp的Mesh类,而不是Unity Mesh类,应用序列化是UWP中内置的Windows应用程序:

    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); }
    }
我在代码中没有看到任何导致这种行为的原因,我想说,如果值错误,它将完全破坏网格

我可以看到,我的fbx文件使用的是四边形而不是三角形作为索引


可能是因为Assimp与此不匹配吗?

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

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

一个更合适的解决方案是将所有顶点馈送到Unity侧的一个矩阵,以便它正确解析顶点的位置

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

我能想到的唯一原因是使用foreach循环。有时foreach并没有按预期进行迭代。尝试在-serialization和反序列化中使用classic for()循环。希望这有助于从3d建模软件中导出具有不同设置的这些?在调试过程中,在哪一点上会出现异常?没有异常。它实际上一直在工作,但不是以预期的方式。听起来你的创作工具使用右手坐标系,而Unity使用左手坐标系。如果是这样的话,如果你导出带有旋转的游戏对象层次,你还需要做更多的事情。
    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;
    }
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;
}