Trying to programmatically create vertex color tag
-
Hi,
I am making a python script to import a mesh in OBJ format, and want to programmatically set the colors on a per-vertex basis.I am currently playing around, have imported the mesh using File->Merge Project, set a single material for all objects (there is only one object), and got a reference to the polygons by dragging into the python command line (op = Default below).
I followed examples I found (code below) to make a vertex color tag, and just to experiment set the vertices to red. The issues :
-
I have to select the vertex color tag in the Objects panel for the coloring to show up, otherwise the color is just default white
-
When the tag is selected there is no shading, color is 'flat'
-
Rendering just shows the white underlying material coloring
Code is below, what am I missing?
Thanks,
Randy
op = Default red = c4d.Vector4d(1.0, 0.0, 0.0, 1.0) pointCount = op.GetPointCount() tag = c4d.VertexColorTag(pointCount) tag.SetPerPointMode(True) dataW = tag.GetDataAddressW() for idx in range(pointCount) : c4d.VertexColorTag.SetPoint(dataW, None, None, idx, red) op.InsertTag(tag) tag.SetBit(c4d.BIT_ACTIVE) c4d.EventAdd()
-
-
Hello @zauhar,
thank you for reaching out to us. Your code does look mostly fine and is working for me. The line
op = Default
makes little sense and you are of course missing things like imports, a context guard and a main function. Not all of them are absolutely necessary, but it is strongly advised to use them all, especially for novice users. Find a code example below.Vertex colors are also not automatically rendered as the diffuse color in Cinema 4D, one must use a VertexMap shader for that. Please consult the user manual or end-user support for end-user questions, we cannot deliver such support here.
Cheers,
FerdinandThe result for two polygon objects, the color of a vertex depends on its position in global space.
Code
"""Creates vertex-color tag on the currently selected polygon object and makes it the active tag. Must be run as a Script Manager scrip with a polygon object selected. The color of each vertex will depend on its position in global space. """ import c4d import typing GRADIENT_MIN: float = -200.0 # The lower boundary of the gradient. GRADIENT_MAX: float = 200.0 # The upper boundary of the gradient. op: typing.Optional[c4d.BaseObject] # The active object, can be `None`. def main() -> None: """Runs the example. """ # Check that there is indeed a selected object and that it is a polygon object. if not isinstance(op, c4d.PolygonObject): raise TypeError("Please select a polygon object.") # Get its point count and allocate a vertex color tag with that count. count: int = op.GetPointCount() tag: c4d.VertexColorTag = c4d.VertexColorTag(count) if not isinstance(tag, c4d.VertexColorTag): raise MemoryError("Could not allocate tag.") # We are going to make it a little bit more exciting and write a gradient based on the global # coordinate y-component of a vertex. # Set the tag to defining colors only once per vertex instead of having N colors per vertex, # where N is the number of polygons attached to it. tag.SetPerPointMode(True) # Get the global matrix of the polygon object and all its points in global space. mg: c4d.Matrix = op.GetMg() globalPoints: list[c4d.Vector] = [mg * p for p in op.GetAllPoints()] # Define a callable with which we can get the gradient color of a point over its index. GetGradientColor = lambda i : c4d.Vector4d( c4d.utils.RangeMap(globalPoints[i].y, GRADIENT_MIN, GRADIENT_MAX, 0, 1, True), 0, 0, 1) # Get the data pointer of the tag and start writing data. dataW: object = tag.GetDataAddressW() for i in range(count): c4d.VertexColorTag.SetPoint(dataW, None, None, i, GetGradientColor(i)) # Insert the tag into the selected object, make it the active tag, and push an update event. op.InsertTag(tag) tag.SetBit(c4d.BIT_ACTIVE) c4d.EventAdd() if __name__ == "__main__": main()
-