Thank you for reaching out to us.
Would a python generator be a better way to go?
It depends a bit on how this question is meant. In general, it is not advisable to try to recreate a MoGraph cloner implementation from scratch in Python, as the result would likely not be very fast. But if you want to just write a thin wrapper, i.e., a generator which uses a MoGraph cloner in its output to simplify a specific setup, there is nothing which prevents you from doing this.
The rest of your question is unfortunately a bit ambiguous. It is unclear to me:
- If the 'add a brightness value to each [vertex]' part is already done. You should store that data in a vertex map and I will not consider the generation of that data of the problem.
- If 'to drive material emission' means driving the emission of a material assigned to the polygon object (you could just use the vertex map here).
- Or if 'to drive material emission' means the spheres you want to clone. I.e., that you want to assign a material with an emission equal to the brightness data attached to the vertex the sphere is being cloned onto.
If you want to go route 2, I do not really understand what the question is. If you want to go route 3, this can be almost entirely done with out of the box MoGraph.
- Create a MoGraph cloner called Cloner.
- Create a clone called Sphere and clone target called Target.
- Parent Sphere to Cloner
- In Cloner:
a. Set Mode to Object.
b. Set Object to Target.
c. Set Distribution to Vertex.
- Create a material called Material.
- In Material:
a. Disable all channels except Luminance.
b. Add a MoGraph Color Shader to the Luminance texture channel.
c. Set the the Color Shader to Channel: Color.
- Add a random effector called Random to the setup.
- In Random in the tab Parameter:
a. Set Color Mode to Custom Color
b. Enable Use Alpha/Strength.
Which will give you a set of Sphere clones cloned onto Target where the luminance of each clone is driven by the effector Random. You now just have to replace steps 7 and 8, the random effector, with a custom Python effector setup which sets the color of a clone depending on your data. Find an example which does that at the end of this posting.
The file: vertexmap_clones.c4d
"""Example for driving the color of clones with a vertex map.
op: c4d.BaseObject # The python effector
def main() -> bool:
"""Executed by Cinema 4D to evaluate the clones of the cloner.
This code assumes the Python effector to be in "Full Control" mode.
# Get the MoData from the cloner and and the vertex map which has been linked in the user data
# of the Python effector.
moData: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op)
if moData is None:
vertexMap: c4d.VariableTag = op[c4d.ID_USERDATA, 1]
if not isinstance(vertexMap, c4d.VariableTag):
# Get the data, the weights, from the vertex map and bail if they do not match the number of
weights: list[float] = vertexMap.GetAllHighlevelData()
if len(weights) != moData.GetCount():
# We now simply write the weights as an array of vectors. This works because in this setup the
# clones are cloned onto the same mesh for which the vertex map has been generated for. The
# vertex map and clones therefore share an index order, i.e., both the n-th weight and clone
# will have been constructed for the same vertex.
# If necessary, this relation could also be given up (to for example use vertex maps/input data
# which has not been generated for the same mesh), but then one would have to perform closest
# element lookups which are quite expensive to do.
colors: list[c4d.Vector] = [c4d.Vector(w, w, w) for w in weights]
# Write the data as the color array into the clone data.
moData.SetArray(c4d.MODATA_COLOR, colors, False)