Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    instance objects onto points with arbitrary attributes (python)

    Cinema 4D SDK
    python
    2
    3
    432
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      tom_01
      last edited by

      I have a list of thousands of points where I'd like to add a brightness value to each of them to drive material emission and instance spheres onto the points. I've been reading posts like this and this--how would you approach this type of task in python?

      I can setup a cloner object in multi instance mode but I'm not clear if it's possible to pass the brightness values to the (invisible) motagdata tag... Would a python generator be a better way to go?

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @tom_01
        last edited by ferdinand

        Hello @tom_01,

        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:

        1. 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.
        2. 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).
        3. 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.

        1. Create a MoGraph cloner called Cloner.
        2. Create a clone called Sphere and clone target called Target.
        3. Parent Sphere to Cloner
        4. In Cloner:
          a. Set Mode to Object.
          b. Set Object to Target.
          c. Set Distribution to Vertex.
        5. Create a material called Material.
        6. 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.

        1. Add a random effector called Random to the setup.
        2. 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.

        Cheers,
        Ferdinand

        The result:

        The file: vertexmap_clones.c4d
        The code:

        """Example for driving the color of clones with a vertex map.
        """
        
        import c4d
        
        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:
                return False
        
            vertexMap: c4d.VariableTag = op[c4d.ID_USERDATA, 1]
            if not isinstance(vertexMap, c4d.VariableTag):
                return False
        
            # Get the data, the weights, from the vertex map and bail if they do not match the number of
            # clones.
            weights: list[float] = vertexMap.GetAllHighlevelData()
            if len(weights) != moData.GetCount():
                return False
        
            # 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)
        
            return True
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • T
          tom_01
          last edited by

          Hi Ferdinand. Thank you for the thorough response. Apologies for the ambiguity on my part.

          For a test project I wanted to fetch star coordinates (for ~100K–1M+ stars) and their brightness values. Then instance Redshift spheres onto them with a material where the brightness of each point is piped into the material's emission.

          This was a test project to get started with python. I also wanted to see if c4d has a way of working with points and attributes. I don't think the real-world (galaxy?) data is available, but ideally each star would also have a radius, which would drive the sphere scales/sizes.

          I'm familiar with cloner/effector/field setups, but I was looking for a programatic approach. I don't know how to pass specific values to each point (brightness in this case) and then to clones with effectors/fields.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post