0
$\begingroup$

I am trying to copy Cube and set different random origins to the copies. I use the following code:

import bpy
import random

C = bpy.context
src_obj = bpy.data.objects['Cube']


for i in range (0,5):
    new_obj = src_obj.copy()
    new_obj.data = src_obj.data.copy()
    new_obj.animation_data_clear()
    C.collection.objects.link(new_obj)
    new_origin = (0.0+random.randint(1, 9)/100,0.0+random.randint(1, 9)/100,0.0+random.randint(1, 9)/100)
    print(new_origin)
    C.scene.cursor.location = new_origin
    new_obj.select_set(True)
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

The objects are successfully copied, but their origins are always the same: they are equal to last generated coordinates. I added print to make sure that new_origin is always different, but the last value of new_origin is applied. What I am doing wrong? How to make the origins to be different?

$\endgroup$
2
$\begingroup$

The reason all of them use the same location is because you are leaving them all selected.

bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

will set the object origin to ORIGIN_CURSOR for all selected objects.

Add:

new_obj.select_set(False)

as the last line in your for loop.

$\endgroup$
1
$\begingroup$

API Methods.

Using the method shown here https://blender.stackexchange.com/a/134460/15543

import bpy
from mathutils import Matrix, Vector
from random import randint
from bpy import context

ob = context.object
mw = ob.matrix_world 

def randloc():
    return Vector((randint(0, 9) / 100 for i in range(3)))
 
for i in range(5):
    copy = ob.copy()
    me = copy.data = copy.data.copy()
    ds = randloc() # locally moved by random
    T = Matrix.Translation(-ds)
    # transform the origin
    me.transform(T)
    # move back globally
    copy.matrix_world.translation = mw @ ds
    # link to collection
    context.collection.objects.link(copy)

When run with Cube as context object, the result is cube and its 5 copies all occupying same bounding box, however there origins and locations are moved

>>> cubes = [o for o in C.scene.objects if o.name.startswith("Cube")]
>>> for cube in cubes:
...     cube.name, cube.location
...     
('Cube', Vector((0.0, 0.0, 0.0)))
('Cube.001', Vector((0.029999999329447746, 0.03999999910593033, 0.05000000074505806)))
('Cube.002', Vector((0.03999999910593033, 0.05000000074505806, 0.0)))
('Cube.003', Vector((0.009999999776482582, 0.07999999821186066, 0.03999999910593033)))
('Cube.004', Vector((0.07000000029802322, 0.09000000357627869, 0.05000000074505806)))
('Cube.005', Vector((0.009999999776482582, 0.07999999821186066, 0.09000000357627869)))

Note in question code you are setting the global location of the scene cursor randomly, to use a random global instead within the range and method above convert the global random location

global_rand_loc = randloc()
ds = mw.inverted() @ global_rand_loc # local shift
... (as above)

copy.matrix_world.translation = global_rand_loc
$\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.