Faster access to mesh.verts?

I have a mesh with 38000 verts and a list (here named vertsToMove) of indexes and new coords of about 25000 vertices that I have to move (every element in that list looks like this: [index, x,y,z]. Is there more efficient (read: faster) way to do that than this one:


myMesh = Blender.Object.GetSelected()[0].getData(mesh=True)

allVerts = mesh.verts

for item in vertsToMove:
    allVerts(item[0]).co = item[1]

This is just too slow and I don’t know is there a way to speed up things :frowning:

me.transform(matrix) is very fast but operates on the whole mesh.
seems like a good use for a new keyword.

me.transform(matrix, selected_only = True)

Well, matrix would be great for moving and rotation of a block of verts in the same direction. But my case is that I must move all those verts in exact direction and that’s why I need to access them individually.

hi
I am new to this forum and I am new to python-
scripting.
I just found this thread, because I`m looking for some help for a script - the script should do exatly the same as the script Damir was talking about
(move verts discriped in a list to a new location)

All I got in my fist script up to now is - to retrive
a list of all verts in the mesh - now I`m trying in
a hard “learnig by doing process” to get this moving-verts part done.
So Damir if you are still watching this thread :yes:
please share your script :wink: !
HELP please

You’ll find things are much faster if you use list comprehensions in Python:
http://www.secnetix.de/olli/Python/list_comprehensions.hawk

Its a pretty stunning increase, really. I don’t think you can assignments ("=") in list comprehensions, though.

RS


##################################################################################
# Here is the script that will export verts from selected mesh in to a text file #
# in [x y z] format, without braces. It will also read data form file in the     #
# same format.                                                                   #
#                                                                                #
# For example:                                                                   #
#                                                                                #
# If you export default cube, exported text file will contain this:              #
#                                                                                #
# 1.000000 1.000000 -1.000000                                                    #
# 1.000000 -1.000000 -1.000000                                                   #
# -1.000000 -1.000000 -1.000000                                                  #
# -1.000000 1.000000 -1.000000                                                   #
# 1.000000 0.999999 1.000000                                                     #
# 0.999999 -1.000001 1.000000                                                    #
# -1.000000 -1.000000 1.000000                                                   #
# -1.000000 1.000000 1.000000                                                    #
#                                                                                #
# Script doesn't export or imort vert indexes so, when importing, target mesh    #
# should have the same vert indexes as the source mesh or result can be quite    #
# scrambled :D                                                                   #
#                                                                                #
# Script is not optimized, but on my system exports a cube subdivided 7 times,   #
# that's 98306 verts, in 1.4 seconds and imports the same file in 1.8 seconds    #
#                                                                                #
# And finally, script is tested on WinXP only so I don't know does it work on    #
# any other system.                                                              #
#                                                                                #
# Cheers,                                                                        #
#                                                                                #
# Damir                                                                          #
##################################################################################

import Blender
from Blender import Draw, BGL, Window, sys, Mathutils
from Blender.BGL import *
from Blender.sys import time
from Blender.Mathutils import *

###### window drawing and event defs ######

Event_Button_Import = 10
Event_Button_Export = 11
Button_Import = Draw.Create(0)
Button_Export = Draw.Create(0)
Messages = ""

def draw():
    global Event_Button_Import
    global Event_Button_Export
    global Button_Import
    global Messages

    BGL.glClearColor(0.5, 0.5, 0.5, 0.0)
    BGL.glClear(GL_COLOR_BUFFER_BIT)

    BGL.glColor3f(0.0,0.0,0.0)
    Button_Import = Draw.Button("IMPORT", Event_Button_Import, 8, 22, 98, 20, "")
    Button_Export = Draw.Button("EXPORT", Event_Button_Export, 110, 22, 98, 20, "")
    BGL.glColor3f(0.0,0.0,0.0)
    BGL.glRasterPos2i(8,8)
    Draw.Text("Messages:")
    BGL.glColor3f(1.0,1.0,1.0)
    BGL.glRasterPos2i(70,8)
    Draw.Text(Messages)

def event(event, value):
    _Input_Events_Callback(event, value)

def b_event(event):
    global Event_Button_Import
    global Event_Button_Export
    global Button_Import
    global Button_Export

    if event == 0: pass
    elif event == Event_Button_Import:
        Button_Import_Callback()
    elif event == Event_Button_Export:
        Button_Export_Callback()
    Draw.Draw()

Draw.Register(draw, event, b_event)

###### keypress and button click callbacks ######

def _Input_Events_Callback(Event, Value):
    if Event == Draw.ESCKEY and not Value: Draw.Exit()

def Button_Import_Callback():
    Blender.Window.FileSelector(prep_import, 'Import', "*.txt")

def Button_Export_Callback():
    Blender.Window.FileSelector(prep_export, 'Export', "*.txt")

###### import/export defs ######

def prep_import(path):
    global Messages
    
    Messages = ""
    Window.WaitCursor(1)
    t1 = time()
    do_import(path)
    if not Messages:
        Messages= "Imported in %.3f seconds" % (time()-t1)
    Window.WaitCursor(0)

def prep_export(path):
    global Messages
    
    Messages = ""
    Window.WaitCursor(1)
    t1 = time()
    do_export(path)
    if not Messages:
        Messages= "Exported in %.3f seconds" % (time()-t1)
    Window.WaitCursor(0)

def do_import(path):
    global Messages
    
    scn = Blender.Scene.GetCurrent()
    object = scn.objects.active
    if object:
        if object.getType() != "Mesh":
            Messages = "Selected object is not a valid mesh object"
            return
    else:
        Messages = "Select mesh object first"
        return

    try:
        vecFile = open(path)
    except:
        Messages = "Failed to open %s" % path
        return

    vertList = []

    vertListappend = vertList.append

    for line in vecFile:
        vec = getVecFromLine(line)
        if vec == []:
            continue
        elif vec == "invalid":
            Messages = "Invalid format of vector data"
            vecFile.close()
            return
        else:
            vertListappend(Vector(vec))
    vecFile.close()

    if not vertList:
        Messages = "Selected file doesn't contain any vector data!"
        return

    editmode = Window.EditMode()
    if editmode:
        Window.EditMode(0)

    meVerts = object.getData(mesh=1).verts

    ignored = len(vertList) - len(meVerts)

    if ignored > 0:
        Messages = "Selected file has %i more elements than selected model has vertices" % ignored
        for x in xrange(len(meVerts)):
            meVerts[x].co = vertList[x]
    elif ignored < 0:
        Messages = "Selected file has %i less elements than selected model has vertices" % -ignored
        for x in xrange(len(vertList)):
            meVerts[x].co = vertList[x]
    else:
        for x in xrange(len(meVerts)):
            meVerts[x].co = vertList[x]

    if editmode:
        Window.EditMode(1)

    Window.Redraw()

def do_export(path):

    scn = Blender.Scene.GetCurrent()
    object = scn.objects.active
    if object:
        if object.getType() != "Mesh":
            Messages = "Selected object is not a valid mesh object"
            return
    else:
        Messages = "Select mesh object first"
        return

    editmode = Window.EditMode()
    if editmode:
        Window.EditMode(0)

    meVerts = object.getData(mesh=1).verts

    try:
        vecFile = file(path, 'w')
    except:
        Messages = "Failed to open %s" % path
        return

    write = vecFile.write

    for vec in meVerts:
        write("%.6f %.6f %.6f
" % tuple(vec.co))

    if editmode:
        Window.EditMode(1)

###### helper defs ######

def getVecFromLine(line):
    line_seg = line.split()
    vec = []
    if len(line_seg) == 0:
        return vec
    else:
        while len(vec) < 3:
            try:
                if len(line_seg) < 3:
                    vec.append(0.0)
                else:
                    vec.append(float(line_seg[len(vec)]))
            except:
                if len(vec) == 0:
                    return "invalid"
                else:
                    vec.append(0.0)
    return vec

many thanks damir

I will have a look at it

me.transform(matrix) is very fast but operates on the whole mesh.
seems like a good use for a new keyword.

me.transform(matrix, selected_only = True)

Good idea! What about other methods?
I can think of several good places for such a keyword as well:
mesh.calcNormals(selected_only = True) would be the first one that comes to my mind.
Even if you moved only a single vertex, you currently have to update the vertex normals of the whole mesh…

Michael