@@ -38,11 +38,12 @@ def GenerateUvwData(geometries: tuple[c4d.PolygonObject]) -> None:
3838 """Demonstrates how to generate UVW data for polygon objects.
3939 """
4040 def MapVector (value : c4d .Vector , inMin : c4d .Vector , inMax : c4d .Vector ) -> c4d .Vector :
41- """Maps a vector from a given range to the positive unit quadrant .
41+ """Maps a vector from a given range to the values 0 to 1 .
4242 """
43- # We swizzle the vector to only consider the x and z components, as u and v are the relevant
44- # components in UVW data for us and the x and z of points components happened to be the
45- # relevant ones for this example.
43+ # Put the z component of our input into the x component of the output, because UV are the
44+ # relevant components for a 2D UV(W) vector, and because the points in the planes in this
45+ # example lie in the x/z plane, so we move z to y(v) and then leave z(w) empty as we are
46+ # not generating 3D texture mapping data.
4647 return c4d .Vector (
4748 c4d .utils .RangeMap (value .x , inMin .x , inMax .x , 0 , 1 , True ),
4849 c4d .utils .RangeMap (value .z , inMin .z , inMax .z , 0 , 1 , True ), 0 )
@@ -52,11 +53,11 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
5253 """
5354 # The distance from the point #p to its orthogonal projection #p' on the plane. Or, in short,
5455 # the length of the shortest path (in Euclidean space) from #p to the plane.
55- distance = (p - q ) * normal
56+ distance : float = (p - q ) * normal
5657 # Calculate #p' by moving #p #distance units along the inverse plane normal.
5758 return p - normal * distance
5859
59- # Check our inputs for being what we think they are, at least two PolygonObjects.
60+ # Check our inputs for being what we think they are, at least three PolygonObjects.
6061 mxutils .CheckIterable (geometries , c4d .PolygonObject , minCount = 3 )
6162
6263 # Give the three inputs meaningful names.
@@ -66,11 +67,11 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
6667
6768 # A simple way to generate UVW data is a planar layout which can be directly derived from point
6869 # or construction data. An example is of course a plane object, but similar techniques can also
69- # be applied when extruding or lofting a line, as we then can also associate each point with a
70- # percentage of the total length of the line, and a percentage of the total extrusion height or
71- # lofting rotation, the uv coordinates of that point.
70+ # be applied when extruding or lathing/rotating a line, as we then can also associate each point
71+ # with a percentage of the total length of the line (u) , and a percentage of the total extrusion
72+ # height or lathing rotation (v) , the uv coordinates of that point.
7273
73- # Create a UVW tag for the plane object and get the points of the plane object.
74+ # Create a UVW tag for the plane object and get all the points of the plane object.
7475 uvwTag : c4d .UVWTag = plane .MakeVariableTag (c4d .Tuvw , plane .GetPolygonCount ())
7576 points : typing .List [c4d .Vector ] = plane .GetAllPoints ()
7677
@@ -88,8 +89,8 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
8889 c : c4d .Vector = MapVector (points [poly .c ], - radius , radius )
8990 d : c4d .Vector = MapVector (points [poly .d ], - radius , radius )
9091
91- # Set the uvw data for the polygon, nothing special here, just setting the uvw data for the
92- # polygon #i to the calculated values .
92+ # Set the four uvw coordinates for the uvw- polygon #i which corresponds to the geometry
93+ # polygon #i.
9394 uvwTag .SetSlow (i , a , b , c , d )
9495
9596 # Now we basically do the same for the sphere object. We could also just take the x and z
@@ -98,7 +99,7 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
9899 # resulting in planar projection from that angle. This is a bit more formal than projecting by
99100 # just discarding a component (the y component in the former case).
100101
101- # Our projection orientation and point, there is nothing special about these values, they are
102+ # Our projection orientation and point, there is nothing special about these values, they
102103 # just look good for this example.
103104 projectionNormal : c4d .Vector = c4d .Vector (1 , 1 , 0 ).GetNormalized ()
104105 projectionOrigin : c4d .Vector = c4d .Vector (0 )
@@ -109,8 +110,7 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
109110 radius : c4d .Vector = sphere .GetRad ()
110111 poly : c4d .CPolygon
111112 for i , poly in enumerate (sphere .GetAllPolygons ()):
112- # We project each point of the polygon into the plane define by the projection plane origin
113- # and normal.
113+ # We project each point of the polygon into the projection plane.
114114 a : c4d .Vector = ProjectIntoPlane (points [poly .a ], projectionOrigin , projectionNormal )
115115 b : c4d .Vector = ProjectIntoPlane (points [poly .b ], projectionOrigin , projectionNormal )
116116 c : c4d .Vector = ProjectIntoPlane (points [poly .c ], projectionOrigin , projectionNormal )
@@ -132,7 +132,7 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
132132 # state. This makes it impossible to use the UV tools inside a generator object's GetVirtualObjects
133133 uvwTag : c4d .UVWTag = cylinder .MakeVariableTag (c4d .Tuvw , cylinder .GetPolygonCount ())
134134
135- # Boiler plate code for UV commands to work.
135+ # Boiler plate code for UV commands to work, see dedicated #CallUVCommand example for details .
136136 doc : c4d .documents .BaseDocument = mxutils .CheckType (sphere .GetDocument ())
137137 doc .SetActiveObject (cylinder )
138138
@@ -149,8 +149,9 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
149149 handle : c4d .modules .bodypaint .TempUVHandle = mxutils .CheckType (
150150 c4d .modules .bodypaint .GetActiveUVSet (doc , c4d .GETACTIVEUVSET_ALL ))
151151
152- # Retrieve the internal UVW data for the currently opened texture view and then invoke
152+ # Retrieve the internal UVW data for the current texture view and then invoke
153153 # the #UVCOMMAND_OPTIMALCUBICMAPPING command, mapping our cylinder object.
154+
154155 uvw : list [dict ] = mxutils .CheckType (handle .GetUVW ())
155156 settings : c4d .BaseContainer = c4d .BaseContainer ()
156157 if not c4d .modules .bodypaint .CallUVCommand (
@@ -159,20 +160,20 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
159160 c4d .UVCOMMAND_OPTIMALCUBICMAPPING , settings ):
160161 raise RuntimeError ("CallUVCommand failed." )
161162
162- # Write the updated uvw data back and close the texture view we opened above .
163+ # Write the updated uvw data back.
163164 if not handle .SetUVWFromTextureView (uvw , True , True , True ):
164165 raise RuntimeError ("Failed to write Bodypaint uvw data back." )
165166
166167 c4d .modules .bodypaint .FreeActiveUVSet (handle )
167168 doc .SetMode (oldMode )
168169
169- return None
170+ return
170171
171172# The following code is boilerplate code to create geometry, generate UVW data for it, and apply
172173# materials. It is not relevant for the the subject of UVW mapping.
173174
174175def BuildGeometry (doc : c4d .documents .BaseDocument ) -> tuple [c4d .PolygonObject , c4d .PolygonObject ]:
175- """Constructs a plane and sphere polygon object .
176+ """Constructs the plane, sphere, and cylinder geometry .
176177 """
177178 # Instantiate the generators.
178179 planeGen : c4d .BaseObject = mxutils .CheckType (c4d .BaseObject (c4d .Oplane ), c4d .BaseObject )
0 commit comments