0

i have a file containing ~ 10thousands coordinates and I need to create an object that is 1 gold sphere for each coordinate.

I realized that if I do something like:

def createsphere(name, position, size):
    #bpy.ops.mesh.primitive_uv_sphere_add( location=position, size=size )
    bpy.ops.surface.primitive_nurbs_surface_sphere_add( location=position, size=size )

    ob = bpy.context.object
    ob.name = name
    ob.show_name = False
    me = ob.data
    me.name = name+'Mesh'
    return ob

p=read("/home/cpi/BLENDER/terrazze.xyz")

for i in p:

    if i.symbol == "C"  :
        createsphere('C', i.position,0.4)
        setMaterial(bpy.context.object, rubber)
    elif i.symbol == "H" :
        createsphere('H', i.position,0.2)
        setMaterial(bpy.context.object, gold)
    elif i.symbol == "Au" :
        createsphere('Au', i.position,1.2)
        setMaterial(bpy.context.object, gold)

I can hanlde max ~100 spheres... What should I do to create my terraces made of gold spheres?

Thanks for your help

Carlo

Dear all, i found something that works although I am not sure to understand all details:

 def qsphere( position, size):
   bpy.ops.mesh.primitive_uv_sphere_add( location=position, size=size )

   ob = bpy.context.active_object
   return ob

 def returnScene (passedIndex = 0):
  try:
   return bpy.data.scenes[passedIndex]
  except:
  return None

 p=read(filei)


 ob = qsphere(p[0].position,1.4) # NOTE: We only mess with the context one time.
 ob.name = geoname
 me = ob.data
  me.name = geoname
 print(me.name)
localScene = returnScene()

 for i in p[1:]:

    if i.symbol == "C"  :
       createsphere('C', i.position,0.4)
       bpy.ops.object.shade_smooth()
       setMaterial(bpy.context.object, rubber)
    elif i.symbol == "H" :
       createsphere('H', i.position,0.2)
       bpy.ops.object.shade_smooth()
      setMaterial(bpy.context.object, gold)
   elif i.symbol == "Au" :
       tempObjectName = i.symbol + returnNameForNumber(i)
      ob_temp = bpy.data.objects.new(tempObjectName, me)
       ob_temp.location=i.position
     localScene.objects.link(ob_temp)
  • do you run out of memory? – DrBwts Mar 03 '16 at 13:55
  • 1
    I don't know the Python for it, but you it sounds like you should make all the spheres instances of each other (i.e. use the same mesh data), rather than creating whole new spheres. – PGmath Mar 03 '16 at 14:15
  • Somewhat related http://blender.stackexchange.com/questions/39721/how-can-i-create-many-objects-quickly – batFINGER Mar 03 '16 at 14:44
  • dera all, thank you very much. I found a solution that work and I added it to my original post. I definitely do not run out of memory, I have plnety. However something funny happens now: if i work in (RENDERED" mode (SHIFT + Z) I can easily rotate the scene. If I work in "SOLID" mode it is very very slow when rotating. Which settings can I change in the GUI to speedup transformations in the "SOLID" mode? – carlo antonio pignedoli Mar 03 '16 at 19:50
  • Maybe activate MATCAP, see if that helps? – Rick Riggs Mar 03 '16 at 20:51

1 Answers1

3

Blender can handle a million vertices in one object better than it can handle 10,000 objects in one scene. This means you should get better performance if you create all the vertices in one object instead of many individual objects.

Using blender 2.7x -

import bpy
import bmesh
import mathutils

# create the materials used
# simple BI materials used
MatAu = bpy.data.materials.new('Mat.Au')
MatAu.diffuse_color = Color((0.8,0.7,0.2))
MatC  = bpy.data.materials.new('Mat.C')
MatC.diffuse_color = Color((0.1,0.1,0.1))
MatH  = bpy.data.materials.new('Mat.H')
MatH.diffuse_color = Color((0.8,0.7,0.2))

# create an empty mesh object and add it to the scene
sphereMesh = bpy.data.meshes.new('AllSpheres')
sphereObj  = bpy.data.objects.new('AllSpheres', sphereMesh)
bpy.context.scene.objects.link(sphereObj)
bpy.context.scene.objects.active = sphereObj

# create slots for each material then add each material to the object
while len(sphereObj.material_slots) < 3:
    bpy.ops.object.material_slot_add()
sphereObj.material_slots[0].material = MatAu
sphereObj.material_slots[1].material = MatC
sphereObj.material_slots[2].material = MatH

# test data to be swapped for data in file
# type, location, scale
data = [('C', (1.0, 1.0, 1.0), 0.2),
        ('H', (2.0, 2.0, 2.0), 0.4),
        ('Au',(3.0, 3.0, 3.0), 0.8),
        ('C', (4.0, 4.0, 4.0), 1.2),
        ('H', (5.0, 5.0, 5.0), 0.2),
        ('Au',(6.0, 6.0, 6.0), 0.8),
        ('C', (7.0, 7.0, 7.0), 0.4),
        ('H', (8.0, 8.0, 8.0), 0.8),
        ('Au',(9.0, 9.0, 9.0), 1.2),
]

bm = bmesh.new()
for i in data:
    locMatrix = mathutils.Matrix.Translation(i[1])
    scaleMatrix = mathutils.Matrix.Scale(i[2], 4)
    mesh = bmesh.ops.create_uvsphere(bm, u_segments=8, v_segments=8,
                    diameter=1.0, matrix=locMatrix*scaleMatrix)
    for v in mesh['verts']:
        for f in v.link_faces:
            if i[0] == 'Au':
                f.material_index = 0 # material_index matches material_slots[x]
            elif i[0] == 'C':
                f.material_index = 1
            elif i[0] == 'H':
                f.material_index = 2

bm.to_mesh(sphereMesh)
bm.free()

For 2.80+ some small changes are needed

import bpy
import bmesh
import mathutils

# create the materials used
# simple BI materials used
MatAu = bpy.data.materials.new('Mat.Au')
MatAu.diffuse_color = (0.8,0.7,0.2,1.0)
MatC  = bpy.data.materials.new('Mat.C')
MatC.diffuse_color = (0.1,0.1,0.1,1.0)
MatH  = bpy.data.materials.new('Mat.H')
MatH.diffuse_color = (0.8,0.7,0.2,1.0)

# create an empty mesh object and add it to the scene
sphereMesh = bpy.data.meshes.new('AllSpheres')
sphereObj  = bpy.data.objects.new('AllSpheres', sphereMesh)
bpy.context.collection.objects.link(sphereObj)
bpy.context.view_layer.objects.active = sphereObj

# create slots for each material then add each material to the object
while len(sphereObj.material_slots) < 3:
    bpy.ops.object.material_slot_add()
sphereObj.material_slots[0].material = MatAu
sphereObj.material_slots[1].material = MatC
sphereObj.material_slots[2].material = MatH

# test data to be swapped for data in file
# type, location, scale
data = [('C', (1.0, 1.0, 1.0), 0.2),
        ('H', (2.0, 2.0, 2.0), 0.4),
        ('Au',(3.0, 3.0, 3.0), 0.8),
        ('C', (4.0, 4.0, 4.0), 1.2),
        ('H', (5.0, 5.0, 5.0), 0.2),
        ('Au',(6.0, 6.0, 6.0), 0.8),
        ('C', (7.0, 7.0, 7.0), 0.4),
        ('H', (8.0, 8.0, 8.0), 0.8),
        ('Au',(9.0, 9.0, 9.0), 1.2),
]

bm = bmesh.new()
for i in data:
    locMatrix = mathutils.Matrix.Translation(i[1])
    scaleMatrix = mathutils.Matrix.Scale(i[2], 4)
    mesh = bmesh.ops.create_uvsphere(bm, u_segments=8, v_segments=8,
                    diameter=1.0, matrix=locMatrix @ scaleMatrix)
    for v in mesh['verts']:
        for f in v.link_faces:
            if i[0] == 'Au':
                f.material_index = 0 # material_index matches material_slots[x]
            elif i[0] == 'C':
                f.material_index = 1
            elif i[0] == 'H':
                f.material_index = 2

bm.to_mesh(sphereMesh)
bm.free()
sambler
  • 55,387
  • 3
  • 59
  • 192