3535op : typing .Optional [c4d .BaseObject ] # The selected object within that active document. Can be None.
3636
3737def GenerateUvwData (geometries : tuple [c4d .PolygonObject ]) -> None :
38- """Demonstrates how to generate UVW data for polygon objects..
38+ """Demonstrates how to generate UVW data for polygon objects.
3939 """
4040 def MapVector (value : c4d .Vector , inMin : c4d .Vector , inMax : c4d .Vector ) -> c4d .Vector :
4141 """Maps a vector from a given range to the positive unit quadrant.
4242 """
43- # We swizzle the vector to only consider the x and z components, as UV are the relevant c
44- # components for us and the x and z components happened to be the relevant ones for this
45- # example (the plane object) .
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 .
4646 return c4d .Vector (
4747 c4d .utils .RangeMap (value .x , inMin .x , inMax .x , 0 , 1 , True ),
4848 c4d .utils .RangeMap (value .z , inMin .z , inMax .z , 0 , 1 , True ), 0 )
4949
5050 def ProjectIntoPlane (p : c4d .Vector , q : c4d .Vector , normal : c4d .Vector ) -> c4d .Vector :
5151 """Projects the point #p orthogonally into the plane defined by #q and #normal.
52-
53- Args:
54- p: The point to project.
55- q: A point in the plane.
56- normal: The normal of the plane (expected to be a normalized vector).
57-
58- Returns:
59- The projected point.
6052 """
6153 # The distance from the point #p to its orthogonal projection #p' on the plane. Or, in short,
6254 # the length of the shortest path (in Euclidean space) from #p to the plane.
@@ -72,11 +64,11 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
7264 sphere : c4d .PolygonObject = geometries [1 ]
7365 cylinder : c4d .PolygonObject = geometries [2 ]
7466
75- # The simplest way to generate UVW data is the simple planar layout which can be directly
76- # derived from point or construction data. An example is of course a plane object, but similar
77- # techniques can also be applied when extruding or lofting a line, as we then can also associate
78- # each point with a percentage of the total length of the line, and a percentage of the total
79- # extrusion height or lofting rotation, the uv coordinates of that point.
67+ # A simple way to generate UVW data is a planar layout which can be directly derived from point
68+ # 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.
8072
8173 # Create a UVW tag for the plane object and get the points of the plane object.
8274 uvwTag : c4d .UVWTag = plane .MakeVariableTag (c4d .Tuvw , plane .GetPolygonCount ())
@@ -88,10 +80,9 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
8880 for i , poly in enumerate (plane .GetAllPolygons ()):
8981 # Calculate the uvw data for each point of the polygon. We operate here on the implicit
9082 # knowledge that the plane object is centered on its origin, e.g., goes form -radius to
91- # radius in all three dimensions. We then just map -radius to radius to 0 to 1, as UV data
92- # is always placed in the positive quadrant unit square ('goes' from 0 to 1). The reason why
93- # always calculate uvw data for four points, is because Cinema 4D always handles polygons as
94- # quads, even if they are triangles or n-gons.
83+ # radius in all three dimensions. We then just map [-radius, radius] to [0, 1], as UV data
84+ # always 'goes' from 0 to 1. The reason why we always calculate uvw data for four points,
85+ # is because Cinema 4D always handles polygons as quads, even if they are triangles or n-gons.
9586 a : c4d .Vector = MapVector (points [poly .a ], - radius , radius )
9687 b : c4d .Vector = MapVector (points [poly .b ], - radius , radius )
9788 c : c4d .Vector = MapVector (points [poly .c ], - radius , radius )
@@ -105,24 +96,25 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
10596 # components of each point to get a top-down uvw projection on the sphere. But we make it a
10697 # bit more interesting by projecting each point into a plane defined by the normal of (1, 1, 0),
10798 # resulting in planar projection from that angle. This is a bit more formal than projecting by
108- # just discarding a component (the y component in our case).
99+ # just discarding a component (the y component in the former case).
109100
110101 # Our projection orientation and point, there is nothing special about these values, they are
111102 # just look good for this example.
112103 projectionNormal : c4d .Vector = c4d .Vector (1 , 1 , 0 ).GetNormalized ()
113- projectionPoint : c4d .Vector = c4d .Vector (0 )
104+ projectionOrigin : c4d .Vector = c4d .Vector (0 )
114105
115106 uvwTag : c4d .UVWTag = sphere .MakeVariableTag (c4d .Tuvw , sphere .GetPolygonCount ())
116107 points : typing .List [c4d .Vector ] = sphere .GetAllPoints ()
117108
118109 radius : c4d .Vector = sphere .GetRad ()
119110 poly : c4d .CPolygon
120111 for i , poly in enumerate (sphere .GetAllPolygons ()):
121-
122- a : c4d .Vector = ProjectIntoPlane (points [poly .a ], projectionPoint , projectionNormal )
123- b : c4d .Vector = ProjectIntoPlane (points [poly .b ], projectionPoint , projectionNormal )
124- c : c4d .Vector = ProjectIntoPlane (points [poly .c ], projectionPoint , projectionNormal )
125- d : c4d .Vector = ProjectIntoPlane (points [poly .d ], projectionPoint , projectionNormal )
112+ # We project each point of the polygon into the plane define by the projection plane origin
113+ # and normal.
114+ a : c4d .Vector = ProjectIntoPlane (points [poly .a ], projectionOrigin , projectionNormal )
115+ b : c4d .Vector = ProjectIntoPlane (points [poly .b ], projectionOrigin , projectionNormal )
116+ c : c4d .Vector = ProjectIntoPlane (points [poly .c ], projectionOrigin , projectionNormal )
117+ d : c4d .Vector = ProjectIntoPlane (points [poly .d ], projectionOrigin , projectionNormal )
126118
127119 # We must still map the projected points to the unit square. What we do here is not quite
128120 # mathematically correct, as there is no guarantee that the projected points have the same
@@ -138,7 +130,6 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
138130 # Doing this comes with the huge disadvantage that we must be in a certain GUI state, i.e., the
139131 # UV tools only work if the object is in the active document and the UV tools are in a certain
140132 # state. This makes it impossible to use the UV tools inside a generator object's GetVirtualObjects
141-
142133 uvwTag : c4d .UVWTag = cylinder .MakeVariableTag (c4d .Tuvw , cylinder .GetPolygonCount ())
143134
144135 # Boiler plate code for UV commands to work.
@@ -177,13 +168,13 @@ def ProjectIntoPlane(p: c4d.Vector, q: c4d.Vector, normal: c4d.Vector) -> c4d.Ve
177168
178169 return None
179170
180- # The following code is boilerplate code to create a plane and sphere object , generate UVW data for
181- # them, and apply a material to them. This is all boilerplate code and not the focus of this example .
171+ # The following code is boilerplate code to create geometry , generate UVW data for it, and apply
172+ # materials. It is not relevant for the the subject of UVW mapping .
182173
183174def BuildGeometry (doc : c4d .documents .BaseDocument ) -> tuple [c4d .PolygonObject , c4d .PolygonObject ]:
184175 """Constructs a plane and sphere polygon object.
185176 """
186- # Instantiate a plane and sphere generator .
177+ # Instantiate the generators .
187178 planeGen : c4d .BaseObject = mxutils .CheckType (c4d .BaseObject (c4d .Oplane ), c4d .BaseObject )
188179 sphereGen : c4d .BaseObject = mxutils .CheckType (c4d .BaseObject (c4d .Osphere ), c4d .BaseObject )
189180 cylinderGen : c4d .BaseObject = mxutils .CheckType (c4d .BaseObject (c4d .Ocylinder ), c4d .BaseObject )
@@ -193,12 +184,10 @@ def BuildGeometry(doc: c4d.documents.BaseDocument) -> tuple[c4d.PolygonObject, c
193184 temp .InsertObject (planeGen )
194185 temp .InsertObject (sphereGen )
195186 temp .InsertObject (cylinderGen )
196-
197- # Build the caches of the plane and sphere generators.
198187 if not temp .ExecutePasses (None , False , False , True , c4d .BUILDFLAGS_0 ):
199188 raise RuntimeError ("Could not build the cache for plane and sphere objects." )
200189
201- # Retrieve the caches of the plane and sphere generators.
190+ # Retrieve the caches of the generators.
202191 planeCache : c4d .PolygonObject = mxutils .CheckType (planeGen .GetCache (), c4d .PolygonObject )
203192 sphereCache : c4d .PolygonObject = mxutils .CheckType (sphereGen .GetCache (), c4d .PolygonObject )
204193 cylinderCache : c4d .PolygonObject = mxutils .CheckType (cylinderGen .GetCache (), c4d .PolygonObject )
@@ -217,7 +206,7 @@ def BuildGeometry(doc: c4d.documents.BaseDocument) -> tuple[c4d.PolygonObject, c
217206 sphere .SetMg (c4d .Matrix (off = c4d .Vector (0 , 0 , 0 )))
218207 cylinder .SetMg (c4d .Matrix (off = c4d .Vector (300 , 0 , 0 )))
219208
220- # Insert the plane and sphere into the active document and return them.
209+ # Insert the result the passed document and return them.
221210 doc .InsertObject (plane )
222211 doc .InsertObject (sphere )
223212 doc .InsertObject (cylinder )
0 commit comments