snap mesh-vertices to grid

for blender-2.61 (2.60, 2.62 without new mesh-type)
i had to snap the vertices of my mesh to some fixed positions
(its for this md3/mdm/mdx and q3map-exporter thread)
because the editing in blender with the “magnetic snap to grid-size”
option did not work like i thought it should.
(maybe i still miss some usability option of it?)

So i use this snippet to “clamp” the vertex-positions of the
active object to fixed settings.
I am shure this is not the best way and wonder if someone has
a better idea.
The calculation uses a grid of size 0.04 - but i use smaller for small
objects too. It has to be so small, because the export to the quake3-style-map
uses a scaling-factor of 100.
Anyhow, was there already a kind of architectural snapping option i did not notice?
And any idea to do this vertex-snapping to variable grid-size without this “ugly” calculation?
And it should work same way for positive-negative positions (thats why cutting of some digits is not working).


import bpy

def clamp(pos):
    grid = 4 #gridsize of my export map
    val = round(100. * pos)
#    val -= 2
#    if val < 0: val += -4
#    pos = pos + 0.5
    val = int(val/grid)
    print(val)
    val = int(grid*val)
    print(val)
    val = val/100.
    print(pos, "->", val)
    return (val)

def clamp_vector(v): #the vertex-round function
    return v.to_tuple(2)

if True:
    print("--- set vertices to grid ---")
    print(bpy.context.selected_objects)
#    for ob in bpy.context.selected_objects:
    if True:
        ob = bpy.context.active_object
        print(ob.name)
        if ob.type == "MESH":
            bpy.ops.object.mode_set(mode="OBJECT") #do i need all this toggeling..?
            bpy.ops.object.mode_set(mode="EDIT")
            bpy.ops.object.mode_set(mode="OBJECT")
            for vert in ob.data.vertices:
#                print(vert.co, vert.co.to_tuple(2))
#                vert.co = vert.co.to_tuple(2) #first rounding try with internal func
                for i in range(3):
                    vert.co[i] = clamp(vert.co[i])
                    print(i, ":", vert.co[i])
#                vert.co = vert.co.to_tuple(2)
            bpy.ops.object.mode_set(mode="OBJECT")
#            ob.data.update()  #do i need update?
            bpy.ops.object.mode_set(mode="EDIT")

the editing in blender with the “magnetic snap to grid-size”
option did not work like i thought it should.

What do you expect it to do?

Magnetic to Increment seems work fine, you can set the grid scale in N panel to e.g. 0.04

But i wonder what the “Subdivisions” property is for… it doesn’t seem to have any effect on the grid nor snapping

in blender-2.61 the snapping works only partial like this,
i select a vertex, move it and then it moves in increments according to the grid-setting.
But this does not re-position a vertex to the grid-raster-locations. The offset is always the same(to the next grid-line).
For example: i select a few vertices and scale those along z-axis to 0 - now all have the same z-axis-value. But when moving those selected vertices it does not snap to the grid, the movement only goes in increments of the grid-raster-size.
Up to now i dont know if i use a wrong setting or if it is how it should work.

ok - i think i found the problem.
Its the same old thing about the differences in object-mode and edit-mode.

First the magnetic-snapping is useless for my problem to fix the vertices position to decent grid-settings.
What i now do is following:

With a new object - or if the object was moved (! not rotated)
i first scale the view till the grid-raster is the resolution i want,
then i do a
shift-S (=selection to current grid view)
with the object (to make shure a later translation of the object
will always not destroy my grid-fixed vertices settings).

In Edit-mode i use this
shift-S (=selection to current grid view) again to reposition
the selected vertices to my grid-locations.
The only problem now is, i always have to check the current grid-view
on screen, because with larger selections its easy to zoom out and get
a wider grid and then the shift-S would snap to this wider grid (what
can be useful to work with bigger resolutions, but would easy destroy
all little selected mesh-parts)

The big problems i had, did happen for rotations of such an object.
The rotation has to be always in 90 degrees steps only and a rotation
not made with the direct input of the degree-angle ends up with a lot
of vertices no more on the grid-spacing.
Same goes to the object location if the edit-mode was done with the object
location not fixed to the grid-spacing too. Then a later movement
would always end up with slightly shifted vertex-positions away from the
grid-spacing.

Why i need so decent grid-spacings?
This may be useful to those doing some kind of architectural editing too, but
i needed it for the quake/etxreal-map export to have all vertices on my grid setting
for the later export.

I forgot to note, the Shift-S (snap selected to grid) should only be made in an orthogonal screen-view or the lowest grid-resolution will not be used and is not shown on screen too.