- Home /
Imported mesh loses material information when assigning to triangles array
Hi all, after importing an FBX model it looks fine with six materials on the same mesh nicely positioned in the right places. But if I do anything with the triangles array the material properties change.
The statue on the left looks the same after running the following code on it:
Mesh mesh;
MeshFilter meshFilter;
meshFilter = obj.GetComponent(typeof(MeshFilter)) as MeshFilter;
mesh = meshFilter ? meshFilter.sharedMesh : null;
Mesh mesh2 = new Mesh();
mesh2 = mesh;
//mesh.triangles = mesh.triangles;
obj.GetComponent<MeshFilter>().sharedMesh = mesh2;
I can modify the vertices and uvs and any other property of the mesh and the materials stay the same but if I uncomment the seventh line then the model looks like the one on the right.
If I had to guess I think what is happening is that Unity is creating a copy of the triangles and then creating a new instance of the object. I've checked and new statue has all six materials applied all over the mesh in layers, which is normal and explained in the docs. The last material is the yellow one so that explains the final look of the model.
The questions then are, what is so different about the new mesh that Unity doesn't preserve the positions the materials? And if Unity can import a model and preserve the material placement where or in what class is this information stored? And can I play with these?
Many thanks!
Answer by MediaGiant · Feb 06, 2014 at 03:13 AM
Just in case anybody else is dealing with a similar misunderstanding to mine,
The imported model uses submeshes with a different set of triangles and a separate material for each submesh. To work with the triangles of each submesh we need to use an array of arrays. The following is an example of copying, manipulating and writing the submeshes of a model, which works even if there is only the single mesh.
// copy submeshes of selected game object
Mesh mesh = Selection.activeGameObject.GetComponent<MeshFilter>().sharedMesh;
int[][] copy_triangles = new int[mesh.subMeshCount][];
for (int i = 0; i < mesh.subMeshCount; i++)
{
copy_triangles[i] = new int[mesh.GetTriangles(i).Length];
copy_triangles[i] = mesh.GetTriangles(i);
}
// do something with the triangle array of each submesh
int tempInt = 0;
for (int i = 0; i < mesh.subMeshCount; i++)
{
for (int j = 0; j < copy_triangles[i].Length; j += 3)
{
// reverse triangle winding
tempInt = copy_triangles[i][j];
copy_triangles[i][j] = copy_triangles[i][j+1];
copy_triangles[i][j+1] = tempInt;
}
}
// create a new mesh and add submeshes
Mesh mesh2 = new Mesh();
mesh2.subMeshCount = mesh.subMeshCount; // important
mesh2.vertices = mesh.vertices;
mesh2.uv = mesh.uv;
mesh2.normals = mesh.normals;
for (int i = 0; i < mesh.subMeshCount; i++)
{
mesh2.SetTriangles(copy_triangles[i], i);
}
mesh2.RecalculateBounds();
Answer by Eric5h5 · Feb 06, 2014 at 02:32 AM
You need to set the submeshes properly using SetTriangles.