5
$\begingroup$

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?

$\endgroup$
  • $\begingroup$ Related: 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. $\endgroup$ – gandalf3 Mar 24 '14 at 19:55
  • $\begingroup$ Thanks Gandalf3. the link has a number of good suggestions, as does blender.stackexchange.com/questions/7358. $\endgroup$ – cedorman Mar 24 '14 at 20:59
2
$\begingroup$

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() 
| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.