How can my script ensure the dupliverted meshes on an icosphere faces, and on its vertices will all be facing "outwards". There is an excellent answer that describes using a different technique using an "all-in-one" or a single multi-monkey-faced larger mesh, but that makes it more difficult to animate the shape mesh.
I'd like to understand the logic and/or math behind how
bpy.context.object.use_dupli_vertices_rotation actually works. If I understand it, then I will be able to script the desired behavior in more complex situations every time without trial-and-error.
Here's an example. How can I adjust the script so that all the monkeys will reliably face "out" - in the direction of the vertex or face normals? (and which one is it exactly?)
note: I will not always use monkeys on icospheres - this is an abstraction. I'm working towards correctly animating this constellation of 4,425 Earth-facing satellites where I'll have roughly eighty rotating circles with sixty "monkeys" each. However I will also be using 2D meshes in a second project (rather than circles), so I really want to understand the underlying logic/math of the orientations, both on 1D (circles) and 2D meshes.
edit: Here is one of the images from the linked satellite question to help illustrate why I want to learn to use dupliverts, and not create and keyframe four thousand individual "monkeys":
Potentially adjustable things:
# monkey.rotation_euler = 0, 0, pi # ?? bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) # keep_transform ?? bpy.context.object.use_dupli_vertices_rotation = True # ??
Ok here is a basic script:
import bpy, math pi = math.pi loco_f, loco_v = (-5, 0, 5), (+5, 0, 5) bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete(use_global=False) bpy.ops.mesh.primitive_ico_sphere_add(location=loco_f, size=4, subdivisions=2) shape_mesh_f = bpy.context.active_object bpy.ops.mesh.primitive_ico_sphere_add(location=loco_v, size=4, subdivisions=2) shape_mesh_v = bpy.context.active_object bpy.ops.mesh.primitive_monkey_add(radius=1, location=loco_f) monkey_f = bpy.context.active_object # monkey.rotation_euler = 0, 0, pi bpy.ops.mesh.primitive_monkey_add(radius=1, location=loco_v) monkey_v = bpy.context.active_object # monkey.rotation_euler = 0, 0, pi bpy.ops.object.select_all(action='DESELECT') monkey_f.select = True bpy.context.scene.objects.active = shape_mesh_f bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) bpy.context.object.dupli_type = 'FACES' bpy.context.object.use_dupli_vertices_rotation = True bpy.ops.object.select_all(action='DESELECT') monkey_v.select = True bpy.context.scene.objects.active = shape_mesh_v bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) bpy.context.object.dupli_type = 'VERTS' bpy.context.object.use_dupli_vertices_rotation = True