Splitting a mesh to get one material/mesh

Hi all,

I’m busy rewriting the .osg exporter plugin to handle materials/textures in a better way. AFAIK openscenegraph doesn’t support multiple materials per mesh so I’ve decided to cut a mesh into seperate meshes with only one material.
But I’m not entirely sure how to do that. I thought the best approach is to make a for ‘face in mesh.faces’ loop and for each face determine which material is used and either create a new mesh or append to the already created mesh for that material.
The questions I have:
does this sound like a workable method?
can I use newmesh = mesh.new(name) and append a face?
If I append a face will it also take material with it?

Thanks,
steven

Stumbling onwards I came up with:

objectList = []
        meshList = []
        matIdx = []
        i=0
        meshName = self.cleanStr(mesh.name)
        for face in mesh.faces:
            if face.materialIndex in matIdx:
                meshList[<don't know>].faces.append(face)
            else:
                matIdx.append(face.materialIndex)
                newmesh=NMesh.GetRaw() 
                newmesh.faces.append(face)
                meshList[<don't know>] = newmesh
        for newMesh in meshList:
            newName = ("%s%s" % meshName, i)
            objectList[i] = PutRaw(newMesh,newName,recalculate_normals=0)
            i = i+1
        return objectList;

But I’m not sure what materialIndex really is, I hoped it was an integer giving the number of the material in the material-index, but that appear not to be the case. :frowning:
The idea was to check each face if it’s material was already in the matIdx, if so append the face to the corresponding mesh, if not create a new mesh in meshList and append the face. Once all faces where parsed the meshList would be transformed into an objectList, since I need objects for the next step.

The problem is that I don’t know how to get the position of the face.materialIndex in matIdx[], is there a way to get that position?
Or is there a better way to get a list of objects with one material per object ?

Lists have a method called “index” to return the index of an element in the list.

In any case, if you are doing a lot of lookup, you should use a dictionnary.


        objectList = []
        meshes = {}
        i=0
        meshName = self.cleanStr(mesh.name)
        for face in mesh.faces:
            try:
                meshes[face.materialIndex].faces.append(face)
            except KeyError:
                newmesh=NMesh.GetRaw()
                newmesh.faces.append(face)
                meshes[face.materialIndex] = newmesh
        for newMesh in meshes.values():
            newName = ("%s%s" % meshName, i)
            objectList[i] = PutRaw(newMesh,newName,recalculate_normals=0)
            i = i+1
        return objectList

Martin

Thanks, it looks better, but it still doesn’t work, I’ve slightly addepted the code to fix some bugs so now I have:

objectList = []
        meshes = {}
        i=0
        meshName = self.cleanStr(mesh.name)
        for face in mesh.faces:
            try:
                meshes[face.materialIndex].faces.append(face)
            except KeyError:
                newmesh=NMesh.GetRaw()
                newmesh.faces.append(face)
                meshes[face.materialIndex] = newmesh
        for newMesh in meshes.values():
            newName = ("ME_%s_%s" % (meshName,i))
            print("%s" % newName)
            objectList[i] = NMesh.PutRaw(newMesh,name=newName,recalculate_normals=0)
            i = i+1
        return objectList

But I get the error: TypeError: PutRaw() takes no keyword arguments

NMesh.PutRaw(newMesh, newName, 0)

Use PutRaw like this, it uses positional arguments, not keyword arguments.

Martin