Crash switching to Edit Mode when "edges" is used in from_pydata

Hello Developpers,

Blender 2.58.1 (r38019) on XP.

I am using from_pydata to fill my mesh with the list of coordinates and the edges:
my_mesh.from_pydata ( coords, edges, [] )
As soon as edges is used, I get a violent crash when switching to Edit Mode.
my_mesh.update (calc_edges…) does not help any.

Does somebody know this ? What is wrong in the code ?

Thanks much for any info.
Santaflam


import bpy
 
def creation_mesh () :
 
    me_da = bpy.data.meshes.new ( 'mesh_data' )
 
    me_ob = bpy.data.objects.new ( 'MESH', me_da )
    me_ob.data = me_da
 
    scene = bpy.context.scene
    scene.objects.link ( me_ob )
 
    edgeIdx = 0
    edges = []
    coords = []
    vertex = []
 
    for z in range (0,500,10) :
 
        vertex = [0,0,z]
 
        coords.append ( vertex )
 
        edges.append ( [edgeIdx, (edgeIdx +1)] )
 
        edgeIdx += 1
 
    print ( edges )
 
    me_da.from_pydata ( coords, edges, [] )
 
    me_da.update ( )
 
 
if __name__ == "__main__":
    creation_mesh ( )
 

add this line to get the cause of your troubles…

me_da.validate(verbose=True)

it crashes because the second vert of the last edge you give to from_pydata does not exist, but is referenced in edges[-1].

for a line, if you have x vertices, you have x-1 edge :wink:

import bpy
 
def creation_mesh () :
 
    me_da = bpy.data.meshes.new ( 'mesh_data' )
 
    me_ob = bpy.data.objects.new ( 'MESH', me_da )
    me_ob.data = me_da
 
    scene = bpy.context.scene
    scene.objects.link ( me_ob )
 
    edgeIdx = 0
    edges = []
    coords = []
    vertex = []
 
    for z in range (0,500,10) :
 
        vertex = [0,0,z]
 
        coords.append ( vertex )
 
<b>        if z &lt; 490 :</b>
            edges.append ( [edgeIdx, (edgeIdx +1)] )
 
        edgeIdx += 1
 
    print ( edges )
 
    me_da.from_pydata ( coords, edges, [] )
 
    me_da.update ( )
 
 
if __name__ == "__main__":
    creation_mesh ( )
def Tri(spg, pnt):
    me=bpy.data.meshes.new('Tri')
    oj=bpy.data.objects.new('Tre',me)
    oj.location=spg
    scn=bpy.context.scene
    scn.objects.link(oj)
    scn.objects.active=oj
    scn.update()
    oj.select=True
    me.from_pydata(pnt,[],[])
    me.update(calc_edges=False)
    return oj

i used this… Try it :slight_smile:

Haaiii! Thanks, that is right! I have corrected … It solves the problem for small meshes. But going above some 20 000 pts, I got the same crash … until I did the following :

So thanks a lot! It works with that …
Have no idea why? Is it a memory issue ??

the point of that line is just reporting the problem -you are 1 vertex short- but then you should manually correct your code, don’t rely on blender fixing itself

see littleneo example, if you add 20000 vertices you can have up to 19999 edges… or it will crash :wink:

No it is not enough here. Indeed, I had corrected the code like:

remove last edge

edges = edges [:-1]
… That solves one problem. But this work only for small amount of points (some thousands), after it crashes. Putting your line it works then. I really tried it several times, same mesh (47000 points), if I remove your line it crashes again. That s why I am wondering what that line really does …

give a look to the console… that line validates mesh and reports to console

edit: see it worked here with 1.000.000 edges


import bpy
def creation_mesh () :
    me_da = bpy.data.meshes.new ('mesh_data') 
    me_ob = bpy.data.objects.new ('MESH', me_da)
    me_ob.data = me_da
    scene = bpy.context.scene
    scene.objects.link (me_ob)
    edgeIdx = 0
    edges = []
    coords = []
    vertex = []
 
    for z in range (0,1000000) : 
        vertex = [0,0,z*10] 
        coords.append (vertex) 
        edges.append ([edgeIdx, (edgeIdx +1)]) 
        edgeIdx += 1 
    
    edges = edges[:-1]
    
    me_da.from_pydata (coords,edges,[]) 
    me_da.update ()
    #me_da.validate(verbose=True)
 
if __name__ == "__main__":
    creation_mesh ()

this validate function is handy
a little mod of the liero code above (faulty data abort case), using the boolean that returns validate.

import bpy
def creation_mesh () :
    me_da = bpy.data.meshes.new ('mesh_data') 
    edges = []
    coords = []
    vertex = []
 
    for edgeIdx,z in enumerate(range (0,1000000)) : 
        vertex = [0,0,z*10] 
        coords.append (vertex) 
        edges.append ([edgeIdx, (edgeIdx +1)])
    
    #edges = edges[:-1] # won't validate if commented
    
    me_da.from_pydata (coords,edges,[]) 
    me_da.update ()
    if me_da.validate(verbose=True) : # True means datas are bad
        bpy.data.meshes.remove(me_da)
        print('this mesh is a bombshell. aborting.')
    else :
        me_ob = bpy.data.objects.new ('MESH', me_da)
        me_ob.data = me_da
        scene = bpy.context.scene
        scene.objects.link (me_ob)
 
if __name__ == "__main__":
    creation_mesh ()

Hi, Thanks to both of you liero and littleneo, I tested your code which worked even when pushing the number of pts and decimal in the coords, finally found out the error in my code reported from meh.update (verbose=True) - it was another one than “going one edge too far”.