- Home /
Isolating and separating geometry of a mesh
We have a project where we have been given a .fbx of a door, the main mesh is comprised of separate objects "Frame" and "Door" but has been combined into one mesh object. We cannot edit the mesh with an external modelling software as the whole project has to be contained within Unity.
I was wondering if anyone knew a solution for programmatically identifying and separating parts of the mesh that are not physically joined by faces or verts?
Any suggested ways would be great I'm willing to program the logic myself but maybe a nice algorithm to start me off would be great.
EDIT:
Have got a idea but I don't really know how to implement it... Would looping through each vert and seeing if it has any linked verts until we reach a vert which has no more new linked verts, thus meaning this part of the geometry is isolated work?
That sounds like a feasible way of doing it. The only problems I can see after that is assigning all of the associated vertices information e.g. triangles, normals, uvs, colors, tangents, etc.
I have never attempted this, just curious on what answers other members supply, so this comment is also serving as a bump =]
Thanks for the comment. I'm glad it actually makes sense, was hard to explain in writing!
What I was thinking was maybe if we could identify the vertices of the geometry which is isolated, split that part of the array then use that data to get the correct set of UVs and Triangles data.
Would be nice to hear the thoughts of others! :D
Had another thought, $$anonymous$$y objects have separate UV groups with define the separate elements on the mesh, could using this UV information help in splitting the mesh into separate bits?
Could be easily separated into submeshes if used different materials.
Answer by Caiuse · Oct 05, 2012 at 09:13 AM
Elements of this solution are not perfect but at least I've given it a crack!...
@tomekkie2 in the comments suggested that the mesh could be separated via the submesh data which was absolutely correct :
Basic principle of this script to grab the triangle set which makes up the subMesh and use that data to construct a new mesh, by providing the new mesh with all the data from the original mesh we get a "chunk" of the original.
MeshFilter mf = selectedObject.GetComponent<MeshFilter>();
mesh = mf.sharedMesh;
for(int i = 0; i < mesh.subMeshCount; i++){
subMeshTris = mesh.GetTriangles(i);
CreateMesh(subMeshTris,i);
}
Mesh CreateMesh(int[] triangles,int index){
Mesh newMesh = new Mesh();
newMesh.Clear();
newMesh.vertices = mesh.vertices;
newMesh.triangles = triangles;
newMesh.uv = mesh.uv;
newMesh.uv1 = mesh.uv1;
newMesh.uv2 = mesh.uv2;
newMesh.colors = mesh.colors;
newMesh.subMeshCount = mesh.subMeshCount;
newMesh.normals = mesh.normals;
AssetDatabase.CreateAsset(newMesh, "Assets/"+mesh.name+"_submesh["+index+"].asset");
}
From what I am seeing from your script, it would work, but each vertex array of your newly created meshes will still contain ALL the vertex data from the main mesh? Seems like you still need a step where you trim the vertex data and reset your triangle indices?
Answer by icepick912 · May 08, 2016 at 01:04 PM
//Takes all submeshes and creates new child game objects with the extracted meshes.
//Assign to gameobject with mesh rendered or mesh collider that has desired meshes to extract,
//Click activateRender or ActivateCollider depending on the need.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class ExtractSubMeshes : MonoBehaviour
{
public Mesh mesh;
private int[] subMeshTris;
public bool activateRenderMesh;
public bool activateColliderMesh;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void OnDrawGizmos()
{
if (activateRenderMesh)
{
activateRenderMesh = false;
MeshFilter mf = this.GetComponent<MeshFilter>();
mesh = mf.sharedMesh;
for (int i = 0; i < mesh.subMeshCount; i++)
{
GameObject go = new GameObject(mesh.name + "_SubMesh_" + i, typeof(MeshFilter), typeof(MeshRenderer));
go.transform.parent = transform;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
subMeshTris = mesh.GetTriangles(i);
go.GetComponent<MeshFilter>().sharedMesh = CreateMesh(subMeshTris, i);
}
}
if (activateColliderMesh)
{
activateColliderMesh = false;
MeshCollider mc = this.GetComponent<MeshCollider>();
mesh = mc.sharedMesh;
for (int i = 0; i < mesh.subMeshCount; i++)
{
GameObject go = new GameObject(mesh.name + "_Collider_" + i, typeof(MeshFilter), typeof(MeshRenderer));
go.transform.parent = transform;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
subMeshTris = mesh.GetTriangles(i);
go.GetComponent<MeshFilter>().sharedMesh = CreateMesh(subMeshTris, i);
}
}
}
Mesh CreateMesh(int[] triangles, int index)
{
Mesh newMesh = new Mesh();
List<int> vertexIndices = new List<int>();
List<Vector3> verts = new List<Vector3>();
List<Color> colors = new List<Color>();
List<Vector3> normals = new List<Vector3>();
List<Vector2> uvs, uvs2, uvs3, uvs4;
uvs = new List<Vector2>(); uvs2 = new List<Vector2>(); uvs3 = new List<Vector2>(); uvs4 = new List<Vector2>();
List<int> tris = new List<int>();
newMesh.Clear();
int curVertIndex = 0;
int newVertIndex;
int curSubVertIndex = 0;
for (int i = 0; i < triangles.Length; i++)
{
curVertIndex = triangles[i];
if (!vertexIndices.Contains(curVertIndex))
{
newVertIndex = curSubVertIndex;
vertexIndices.Add(curVertIndex);
verts.Add(mesh.vertices[curVertIndex]);
if (mesh.colors != null && mesh.colors.Length > curVertIndex)
colors.Add(mesh.colors[curVertIndex]);
normals.Add(mesh.normals[curVertIndex]);
if (mesh.uv != null && mesh.uv.Length > curVertIndex)
uvs.Add(mesh.uv[curVertIndex]);
if (mesh.uv2 != null && mesh.uv2.Length > curVertIndex)
uvs2.Add(mesh.uv2[curVertIndex]);
if (mesh.uv3 != null && mesh.uv3.Length > curVertIndex)
uvs3.Add(mesh.uv3[curVertIndex]);
if (mesh.uv4 != null && mesh.uv4.Length > curVertIndex)
uvs4.Add(mesh.uv4[curVertIndex]);
curSubVertIndex++;
}
else
{
newVertIndex = vertexIndices.IndexOf(curVertIndex);
}
tris.Add(newVertIndex);
}
newMesh.vertices = verts.ToArray();
newMesh.triangles = tris.ToArray();
if (uvs.Count > 0)
newMesh.uv = uvs.ToArray();
if (uvs2.Count > 0)
newMesh.uv2 = uvs2.ToArray();
if (uvs3.Count > 0)
newMesh.uv3 = uvs3.ToArray();
if (uvs4.Count > 0)
newMesh.uv4 = uvs4.ToArray();
if (colors.Count > 0)
newMesh.colors = colors.ToArray();
newMesh.Optimize();
newMesh.RecalculateBounds();
newMesh.RecalculateNormals();
return newMesh;
//AssetDatabase.CreateAsset(newMesh, "Assets/"+mesh.name+"_submesh["+index+"].asset");
}
}
Your answer
Follow this Question
Related Questions
Fix split shared UVs on mesh 0 Answers
sparklies on mesh 1 Answer
Rigged model facing the wrong way 1 Answer
create a collider onto an fbx 1 Answer