0
$\begingroup$

I want to randomly place animated characters on a mesh using Python. I currently have them in a collection called 'Pedestrians', where all characters have an empty as a parent object.

I tried using a particle system with the option 'Render as Collection' and 'Pick Random' but that is just picking some random objects without regards to the hierarchy. There is of course the possibility of creating a particle system for each of the character objects, but that would make other parts of my program a bit messy.

I am looking for some ideas on how I can do this. I thought of maybe first creating a particle system with some emtpy objects (or something else) and then replacing them by random characters, but I am also not really sure how that could be done.

Manually placing the characters is not an option. Also, it doesn't necessarily have to be done using particles.

Thank you for your help!

enter image description here

$\endgroup$

1 Answer 1

0
$\begingroup$

I think the reply will depend on what kind of arrangement you want to use. (e.g. I want to rotate the object).

For example,

here is a script. The way to do it is to apply weight paint to the part of the mesh you want to place.

Only the empties in the specified collection will move with the distribution of the weight paint on the mesh.

enter image description here enter image description here

import bpy
import random
import numpy as np

# Set the names of the collection and mesh object
collection_name = "Pedestrians"
mesh_object_name = "YourMeshObjectName"
vertex_group_name = "YourVertexGroupName"  # Name of the vertex group with weight painting

# Get the collection and mesh object
collection = bpy.data.collections.get(collection_name)
mesh_object = bpy.data.objects.get(mesh_object_name)

# Check if the collection and mesh object exist
if collection is None or mesh_object is None:
    print("Collection or mesh object not found.")
else:
    # Get the weights from the weight painting
    vertex_group = mesh_object.vertex_groups.get(vertex_group_name)
    if vertex_group is None:
        print("Vertex group not found.")
    else:
        weights = []
        mesh = mesh_object.data

        for vertex in mesh.vertices:
            for group in vertex.groups:
                if group.group == vertex_group.index:
                    weights.append(group.weight)
                    break
            else:
                weights.append(0)

        weights = np.array(weights)
        weights /= weights.sum()  # Normalize to make the sum 1

        # Randomly place the empties in the collection
        for obj in collection.objects:
            if obj.type == 'EMPTY':
                # Randomly select a vertex based on the weights
                vertex_index = np.random.choice(len(mesh.vertices), p=weights)
                vertex = mesh.vertices[vertex_index]
                location = mesh_object.matrix_world @ vertex.co  # Convert to world coordinates

                # Move the object
                obj.location = location

        print("Placement of empties is complete.")

Supplementation

if the person is the same mesh, it is better to make an instance collection.

If the person is the same mesh, it would be more memory efficient to make instance collections memory efficiency.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .