Hi,
i looked deeper into Blender:
Here is a python script that makes Blender crash (on both Linux and Windows systems):
based on Blender 2.31a sources
------------------------------------------------------- --
import Blender from Blender import *
scene = Scene.GetCurrent()
mat = Material.New("mat") # this line is important
mesh = NMesh.New("mesh") mesh.verts = [ NMesh.Vert(0,0,0), NMesh.Vert(1,0,0), NMesh.Vert(1,0,1) ] mesh.faces = [ NMesh.Face(mesh.verts) ] mesh.addMaterial(mat)
obj1 = Object.New("Mesh", "obj1") obj1.link(mesh) scene.link(obj1) mesh.update(1)
mesh2 = NMesh.GetRaw(mesh.name) # or simply mesh2 = mesh obj2 = Object.New("Mesh", "obj2") obj2.link(mesh2) # <--- THIS link() corrupts the mesh!!! scene.link(obj2)
------------------------------------------------------- --
The problem is the obj2.link(mesh2). If the mesh is already linked to another object, the link will corrupt the mesh's material setting.
First another question: what is obj2.link(mesh) supposed to do excatly? It seems it does the same as obj1.shareFrom(obj2). BTW: it would be helpful if there is a way to get the linked object(s) from a mesh (or other data a object can link to).
Ok, back to the crash. I assume the above script is valid code, means it should do what it is supposed to do. And that is to link to objects to the same mesh.
The problem here is the material setting. At the second link() Blender runs into following code in NMesh.c
Mesh *Mesh_FromPyObject (PyObject *pyobj, Object *ob) { if (pyobj->ob_type == &NMesh_Type) { Mesh *mesh; BPy_NMesh *nmesh = (BPy_NMesh *)pyobj;
if (nmesh->mesh) { mesh = nmesh->mesh;
*** unlinks the materials from <mesh> (in EXPP_unlink_mesh()) *** and frees the mesh->mat array (in unlink_existingMeshData()) *** but does NOT set mesh->totcol to 0! unlink_existingMeshData(mesh); *** sets mesh->mat = NULL, but mesh->totcol is still <> 0 convert_NMeshToMesh(mesh, nmesh); } else { nmesh->mesh = Mesh_fromNMesh(nmesh); mesh = nmesh->mesh; }
.... }
and this code means: static int convert_NMeshToMesh (Mesh *mesh, BPy_NMesh *nmesh) { ...
/*@ material assignment moved to PutRaw */
... }
Have i do a PutRaw() after a obj.link(mesh)??? I assume not
After Blender has run through this code, Blender does not crash immediately but e.g. if you open the OOPS Schematic View. In this case, Blender wants to draw the link from the mesh to the material and iterates over the mesh->mat array, *but* it is not checked if mesh->mat is <> 0:
in oops.c: void add_mesh_oopslinks(Mesh *me, Oops *oops, short flag) { int a;
if(flag & OOPS_MA) { for(a=0; a<me->totcol; a++) { ******************* **** crash because me->mat == 0 but me->totcol > 0 ******************* if(me->mat[a]) { add_oopslink("ma", oops, ID_MA, me->mat+a, 0.0, (float) (0.5*OOPSY)); } } } .... }
Sorry, i'm not familiar enough with the blender python code to supply a patch immediatelly, but it should help the blender python devs to fix the problem
I add this post to the bug tracker too.
-Bala Gi
##########################################
ascotan supplied following fix:
The problem is that when the NMesh is converted to a mesh datablock for linking to the object the mesh->mat pointer is left NULL and materials are not added. To fix the problem add the lines:
f(nmesh->materials){ mesh->mat = EXPP_newMaterialList_fromPyList (nmesh- >materials); }
at the end of the function: convert_NMeshToMesh() in NMesh.c
|