New Script to apply random relocation to vertices

I have created a small script which allows you to apply a random
relocation to selected vertices.
The script must be used from edit mode, and it basically has two
modes of operation:

  1. apply the noise with given limits to the x, y, z coordinates
  2. apply the noise with limits to the vertex normal, and the
    directions orthogonal to it.

Maybe you’ll find it useful, but it’s my first script, so it will not be
perfect :wink:

I used it to make walls like more “natural”.

Best regards,

Name: 'Vertex Noise'
Blender: 242
Group: 'Mesh'
Tooltip: 'Apply random relocation to selected vertices.'

__author__ = ["Michael Bischoff"]
__url__ = ("blender", "eldorado", "")
__version__ = "0.1"
__bpydoc__ = """\
Vertex Noise

Apply random relocation to selected vertices.

# Script copyright (C) Michael Bischoff
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# --------------------------------------------------------------------------

import math
import Blender
from Blender import Mathutils, Window, NMesh, Draw, Scene, Noise
from Blender.Mathutils import *

import BPyMesh

def main():
        scn = Scene.GetCurrent()
        ob = scn.getActiveObject()

        is_editmode= Window.EditMode()

        if not is_editmode:
                Draw.PupMenu('Error! Must be in Edit mode%t|Please switch to edit mode, then call this script again.')

        if ob == None or ob.getType() != 'Mesh':
                Draw.PupMenu('Error! No active mesh selected%t|You must have a mesh object selected.')

        # Popup menu to obtain parameters #

        noise_mode_iso = Draw.Create(1)
        noise_dx = Draw.Create(0.05)
        noise_dy = Draw.Create(0.05)
        noise_dz = Draw.Create(0.05)
        noise_dn = Draw.Create(0.1)
        noise_do = Draw.Create(0.05)

        noise_falloff_exp = Draw.Create(0.0)

        noise_edge_factor_min = Draw.Create(0.75)
        noise_edge_factor_max = Draw.Create(1.25)

        # Get parameters from user

        pup_block= [\
        ('ISO mode', noise_mode_iso, 'use (dx,dy,dz) (else dn/do).'),\
        'ISO mode parameters:',
        ('dx', noise_dx, 0.0, 100.0, 'max. x relocation in ISO mode.'),\
        ('dy', noise_dy, 0.0, 100.0, 'max. y relocation in ISO mode.'),\
        ('dz', noise_dz, 0.0, 100.0, 'max. z relocation in ISO mode.'),\
        'n/o mode parameters:',
        ('dn', noise_dn, 0.0, 100.0, 'max. relocation along normal (in n/o mode).'),\
        ('do', noise_do, 0.0, 100.0, 'max. relocation perpendicular to normal (in n/o mode).'),\
        'Noise distribution:',
        ('falloff exponent e', noise_falloff_exp, 0.0, 100.0, '0 = constant noise, otherwise amplitude decreases by exp(e * D*D) where D is distance of vertex to 3D cursor.'),\
        #'Limit distance changes:',
        #('min factor', noise_edge_factor_min, 0.0, 0.999, 'any adjacent edge lenngth may not decrease by less than this factor (must be in interval 0 <= min < 1).'),\
        #('max factor', noise_edge_factor_max, 1.001, 100.0, 'any adjacent edge length may not increase by more than this factor (must be bigger than 1).'),\

        if not Draw.PupBlock('Randomly relocate vertices', pup_block):

        noise_mode_iso = noise_mode_iso.val
        noise_dx = noise_dx.val
        noise_dy = noise_dy.val
        noise_dz = noise_dz.val
        noise_dn = noise_dn.val
        noise_do = noise_do.val
        noise_falloff_exp     = noise_falloff_exp.val
        noise_edge_factor_min = noise_edge_factor_min.val
        noise_edge_factor_max = noise_edge_factor_max.val

        # leave edit mode before getting mesh (suggested by Python reference)

        me = ob.getData(mesh=1)
        cursor_pos = Vector(Window.GetCursorPos())
        count = 0

        for v in me.verts:
                if v.sel:
                        count += 1
                        noise_vec = Vector(Noise.randuvec())  # required in order to use Vector * scalar
                        noise_amp = Noise.random()   # TODO: use smarter distribution (higher offsets less likely)
                        # compute factor for falloff
                        if noise_falloff_exp > 0.0:
                                # stupid, we compute the root of the diff vector and square it again
                                dist_to_cursor = (cursor_pos -
                                noise_amp *= math.exp(-noise_falloff_exp * dist_to_cursor * dist_to_cursor)
                        noise_vec *= noise_amp
                        if noise_mode_iso == 1:
                                noise_vec[0] *= noise_dx
                                noise_vec[1] *= noise_dy
                                noise_vec[2] *= noise_dz
                                # compute normal and orthogonal parts
                                alpha = noise_vec *
                                # normal part = * alpha
                                noise_vec -= alpha *
                                # orthogonal part = noise_vec
                                noise_vec = noise_dn * alpha * + noise_do * noise_vec
                        # noise vector done
               += noise_vec

        # update mesh data

        # TODO: recalc normals. according to doc, a suitable parameter to
        # me.update() should be able to do this, but this did not work in 2.42a

        # return to edit mode

        statmsg = 'Processed %i vertices|' % count

if __name__ == '__main__':

ooops, any hints how I can preserve leading space in the post?

Best regards,

You must use the “[ code. ]” tags (the right button, looks like # ) and your code will look as code. Basically just edit your post, it’s easy.

Hi tedi,
thanks a lot, it worked!

Best regards,

Great script!

I was thinking that this would be a cool addition to the simple subdivide modifier or a cool modifier on its own. Btw, you can do something like this with modifiers by using displace and a cloud texture for displacement.

Nice script,
Its alredy possible to do random vert offsets with a modifier
Use the displacement modifier with a random texture after a subsurf.

These kinds of scripts are still realy usefull for testing different mothods of displacement and as examples.

some hints, small improvements. += noise_vec # should work rather then doing all 3 indervidualy.

Its good to avoid creating new vectors (allocating and deallocating and time spent in creation)
so you can do…
v_no= # then reuse that.

thanks a lot. I changed the component addition to the vector

I checked the existing blender displacement function -
I did not know that before. It has some other interesting
features (correlation between the vertex offsets, making
more a smooth deformation), so I’ll use that one and
my script both, I think.

Best regards,

Just yesterday broken added a new propertional falloff mode “random” so verts are randomly assigned a weight, thats mixed with linear falloff.
This probably does somthing closer to what the script does then the modifier.