2
$\begingroup$

I ran across this script on another forum and would like to implement it. However, I'm running into a major bottle neck (performance-wise) when it gets to linking the new objects back to the scene because in my actual implementation I'm attempting to generate about 1000 cubes.

From my understanding, it sounds as though there is a way to duplicate the object, but keep the duplicate as a part of the original object as is done in Edit Mode when using Shift+D.

import bpy
from mathutils import Vector

ob = bpy.context.object
obs = []
sce = bpy.context.scene

for i in range(-48, 48, 3):
    for j in range(-48, 48, 3):
        copy = ob.copy()
        copy.location += Vector((i, j, 0))
        copy.data = copy.data.copy()
        obs.append(copy)

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

sce.update()

How would I go about implementing a similar script but instead of creating separate copies of the object just add them to the existing object eliminating the need for the loop that links objects back to the scene?

$\endgroup$
  • 1
    $\begingroup$ Why have the list and the loop? You could sce.objects.link(...) instead of append to obs. Also consider whether you need a new mesh with each copy. $\endgroup$ – batFINGER Aug 17 '16 at 4:49
  • $\begingroup$ @batFINGER You are correct. "sce.objects.link(ob)" could be a part of the previous loop. "obs" is needed for a part of the script later on that isn't shown here and therefore exists for that reason. I have done a few tests and noticed that running all of the .link methods in a concise loop executes a little faster than adding it after "obs.append(copy)". However, the issue that my question is addressing pertains to the last sentence of your comment. I don't need separate mesh objects. So, the question is, how do I achieve that? I just want the object copied but as part of the same mesh. $\endgroup$ – GeoJohn Aug 18 '16 at 14:16
  • 1
    $\begingroup$ I did mean you don't need copy.data.copy(), all objects created could share the same mesh. This will speed up your OP code immensely. And it appears you don't need obs after all. $\endgroup$ – batFINGER Aug 19 '16 at 3:22
3
$\begingroup$

If it's speed you are going for

import bpy
from bpy import context

obj = context.active_object

# add two array modifiers
count = 32
arrays = {"x": (1.5, 0, 0),
          "y": (0, 1.5, 0)}

for axis, displace in arrays.items():          
    mod = obj.modifiers.new(axis, 'ARRAY')
    mod.count = count
    mod.relative_offset_displace = displace
    bpy.ops.object.modifier_apply(modifier=mod.name)

bpy.ops.object.origin_set()
$\endgroup$
  • 1
    $\begingroup$ Confirmed. This is incredibly fast! Definitely the fastest of all things I've tried. ...And you just taught me how to add modifiers in code! $\endgroup$ – GeoJohn Aug 19 '16 at 14:07
  • 1
    $\begingroup$ simple and damn clever... $\endgroup$ – p2or Aug 30 '16 at 7:56
2
$\begingroup$

To get multiple cubes that are all part of one mesh object you would use bmesh.

One way is to use bmesh.ops.create_cube()

import bpy, bmesh

size_x = 16
size_y = 16

bpy.ops.mesh.primitive_cube_add()
bm = bmesh.new()
for x in range(size_x):
    for y in range(size_y):
        ret = bmesh.ops.create_cube(bm,size=2.0)
        bmesh.ops.translate(bm, verts=ret['verts'], vec=(x*3.0,y*3.0,1.0))
bm.to_mesh(bpy.context.object.data)
bm.free()
$\endgroup$
  • $\begingroup$ This is exactly what I'm looking for. However, is there a way to use .copy with this magical bmesh module so as to avoid scene updates between each cube addition? I'm assuming anything that pulls from ops innately updates the scene? $\endgroup$ – GeoJohn Aug 18 '16 at 14:20

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.