5

I would like to render many buildings (say, about 50000) as simple columns on a flat plain in Blender. I have values for location (X,Y) and a height value. However, if I try to add more than a couple of thousand columns, I run out of memory.

I think that I want to use the particle / hair system since each building is not independent. they are all simple 4 sided columns, so they can use the same textures, etc. I can add 50,000 columns, using the techniques discussed in the video http://www.youtube.com/watch?v=mCEQYyesxLg. However, I need to be able to set the location and scale of each one based on my data. How can I do this?

The end result should be something like: http://ekisto.sq.ro/ which is a beautiful visualization of stack overflow data.

Update: I'm close! The following updates my particle locations and scales:

scalesize = 10
scalexy = 50

object = bpy.context.object
cols = object.particle_systems[0].particles

def setColumn(index, name, xval, yval, heightval):
    cols[index].location.x = float(xval) / scalexy
    cols[index].location.y = float(yval) / scalexy
    cols[index].location.z = 0 
    cols[index].size = float(heightval) / scalesize

ii = 0
f = open('input.data', 'r')
for line in f:
    values = line.split()
    setColumn(ii, values[0], values[1], values[2], values[3])
    ii = ii + 1
f.close()

However, when I hit 'F12' to do the render, the particle system updates all the locations and un-does the setting of the locations. How do I tell the particle system to not update?

cedorman
  • 171
  • 4
  • Related: http://blender.stackexchange.com/q/7581/599. Try adding the columns all inside a single object (there is a difference between 50000 individual objects and 50000 cubes inside the same mesh). Also try instancing (dupli objects) or linked data. – gandalf3 Mar 24 '14 at 19:55
  • Thanks Gandalf3. the link has a number of good suggestions, as does http://blender.stackexchange.com/questions/7358. – cedorman Mar 24 '14 at 20:59

1 Answers1

2

I was unable do this using the technique above, because I could not figure out how to prevent re-setting of the location. Therefore, I used the following technique: create a single object, copy it with ob.copy, put copies into scene object list, and then update the scene.

bpy.ops.mesh.primitive_cylinder_add(vertices=numVertices, radius=columnSize,
    depth=height,location=loc)
ob = bpy.context.object
obs = []
sce = bpy.context.scene

f = open('input.data', 'r')
for line in f:
    values = line.split()

    x = float(values[1]) / scaleXY
    y = float(values[2]) / scaleXY
    height = float(values[3]) / scaleHeight

    copy = ob.copy()
    copy.location += Vector((x,y, 0))
    # copy.data = copy.data.copy() 
    copy.scale.x = copy.scale.x * height / 2 
    copy.scale.y = copy.scale.y * height / 2 
    copy.scale.z = copy.scale.z * height
    obs.append(copy)

for ob in obs:
    sce.objects.link(ob)

sce.update() 
cedorman
  • 171
  • 4