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

编辑:所以在与Assimp dev进行短暂接触之后,我被指向了导入过程。 当我从其他人手中接过代码时,我认为没有看到那部分:

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

FlipUV完全按照它所说的做,它在y轴上翻转,因此原点现在是左上角。 所以现在我能够获得具有适当UV但仍然是镜像网格的模型。 设置具有缩放x = -1的父对象将其翻转回正常并使其看起来很好,但我想这并不意味着。 所以我一直在寻找。


看图,有两种起重机型号。 左边的那个通过序列化和重建在运行时加载,而右边的那个是原始的只是拖动到场景。 序列化发生在Assimp库中。

在此处输入图像描述

地板碰巧首先被创建,似乎得到了正确的紫外线地图。 而其他项目出错了uv map。 虽然我正在打印uv地图的值,但它们似乎与原始地图相匹配。

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

  private static void SerializeMeshes(BinaryWriter writer, IEnumerable meshes) { foreach (Mesh mesh in meshes) { ICollection 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[] textureCoordinateChannels) { // get first channel and serialize to writer. Discard z channel // This is Vector3D since happening outside Unity List list = textureCoordinateChannels[0]; foreach (Vector3D v in list) { float x = vX; float y = vY; writer.Write(x); writer.Write(y); } } private static void MeshSerializeVertices(BinaryWriter writer, IEnumerable 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 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; } 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的反序列化值。 然后,创建网格:

 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; } 

我没有在代码中看到任何导致这种行为的原因,我会说如果值是错误的话,它会完全搞砸网格。

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

可能是Assimp不顺利吗?

我没有从Assimp以适当的方式解决问题。

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

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

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