DisplaceModifier.texture causing major memory increase?

I have a for loop which is successfully loading in images and creating a new plane mesh for each image and giving it a displace modifier. I am loading in images and creating a texture for each image and when I try to assign it to a displace modifier on each plane I get a massive increase in memory. It goes from 1.5gb to over 8gb in memory in seconds.

I am using

bpy.data.objects[ob_name].modifiers[‘Displace’].texture = bpy.data.textures[ob_name]

to set the displace modifiers texture to each texture. While everything does work, it takes a very long time and leaves me with my memory completely full. and blender then crashes soon after. I am loading in 196 images, each image around 1.2mb. The images are 317mb in total.

Loading in the images and everything works fine and relatively fast, until I add the line above, then my problems begin.

Here is the full script I am trying (its small), the problem line is right at the bottom :slight_smile:

http://www.pasteall.org/39954/python

Hopefully I am just missing something simple, any help would be great.

Thanks

Interesting little script.

I got this to work ok and my memory did not balloon. You may have to play around with the layout code, I did not have any files in your naming convention so I made a grid style layout.


import os
import bpy
import bmesh

MAX_NAME_SIZE = 21

def returnDisplaceModifier(passedName, passedObject, passedStrength=0.26):
    # Create or fetch a named displace modifier.
    try:
        # See if our modifier exists.
        mod_name = passedName
        mod_name = mod_name[:MAX_NAME_SIZE]
        my_modifier = passedObject.constraints.get(mod_name)
        if my_modifier == None:
            # Create a new modifier.
            my_modifier = passedObject.modifiers.new(mod_name, 'DISPLACE')
            my_modifier.name = mod_name
        my_modifier.strength = passedStrength
        result = my_modifier
    except:
       print("returnDisplaceModifier: Problem assigning constraint [%s]." % passedName)
       result = None
    return result 
 
#dir = 'C:/Users/Nick/3D/bge mollo/tests/terrain/imgs'
#dir ='E:/Documents and Settings/Admin/My Documents/Footage/ash_tree_tour'
dir = 'E:/Documents and Settings/Admin/My Documents/Footage/ap_dot'
filelist = os.listdir(dir)
 
 
terrain_size = 12000
num_tiles = 14
 
plane_scale = terrain_size / num_tiles
 
x_index = 0
y_index = 1
for file in filelist:  
    x_index = x_index + 1
    if x_index > 6:
        y_index = y_index + 1
        x_index = 0   
    ob_name = file[:-4]
   
    # Mesh and object datablocks the terrain tiles will use
    me = bpy.data.meshes.new(ob_name + "_mesh")
    ob = bpy.data.objects.new(ob_name, me)
 
   
    # Create a plane for the mesh
    verts = [(-1.0,-1.0,0.0), (-1.0,1.0,0.0), (1.0,1.0,0.0), (1.0,-1.0,0.0)]
    edges = [(0,1), (1,2), (2,3), (3,0)]
    faces = [(0,1,2,3)]    
    me.from_pydata(verts, edges, faces)
 
    # Add the object to the scene
    bpy.context.scene.objects.link(ob)    
   
    #Update the mesh
    me.update(calc_edges=True)
   
   
    # Subdivide the mesh appropriately and create a UV map
    bpy.context.scene.objects.active = ob    
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.subdivide(number_cuts=10)  
    bpy.ops.uv.unwrap(method='ANGLE_BASED', fill_holes=True, correct_aspect=True, use_subsurf_data=False, margin=0.001)
 
    bpy.ops.object.mode_set(mode='OBJECT')
   
    # Scale the plane up to the corrext size
    ob.scale = (plane_scale / 2, plane_scale / 2, 1.0)    
   
    # Position the plane, based on the name of the image file (e.g tile_x01_y_03)
    #x_loc = file.index('x')
    #y_loc = file.index('y')    
    #x_index = int(file[x_loc + 1:x_loc + 3])
    #y_index = int(file[y_loc + 1:y_loc + 3])  
   
    x_pos = (x_index * plane_scale) - (terrain_size / 2)
    y_pos = (y_index * plane_scale) - (terrain_size / 2)
         
    ob.location = [x_pos, y_pos, 0]
   
       
 
    # Create a new material for the plane
    mat = bpy.data.materials.new(ob_name)    
    ob.data.materials.append(mat)
   
    # Load the heightmap image and assign it to a texture slot.
    tex = None
    try:
        src = dir + '/' + file
        print("Loading Image: " + file)
        img = bpy.data.images.load(src)
    except:
        img = None
        print("Cannot load image %s" % src)
    if img != None:   
        tex = bpy.data.textures.new(file[:-4], type = 'IMAGE')
        tex.image = img

        tex_slot = mat.texture_slots.add()
        tex_slot.texture = tex
        tex_slot.texture_coords = 'UV'

    # Add a Displace modifier to handle the terrain deformation
    tmp_mod = returnDisplaceModifier('height_field', ob, 1.0)   #Strength.
    if tmp_mod != None:
        tmp_mod.texture_coords = 'UV'
        if tex != None:
            tmp_mod.texture = tex
   
    #bpy.data.objects[ob_name].modifiers['Displace'].texture = bpy.data.textures[ob_name]

Thank you for having a look at the script. I tried your version but I’m still getting a huge memory increase, I think I am trying to load too many high res images. If I reduce the resolutions of all the images, it seems to work ok. You helped me understand how to use modifiers with scripts, many thanks for that.

I am now trying to loop through all the vertices on the plane and get the UV coords for rach vertex. Are there any code snippets on the wiki or anything on how to do this? I have been googling for a while now and cant really seem to find what I am looking for. Anyone got some tips?

You may want to take a look at the official OBJ or 3DS importer. Those mesh importers have to deal with generating UV coordinates. Per vertex sounds like the way .3DS works.

Ok, thanks again. I’ll take a look at those scripts and piece it together.