Skip to content

Commit d8accd5

Browse files
committed
Python SDK: Further minor fixes for the uvw data generation code example.
1 parent 071840b commit d8accd5

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

scripts/04_3d_concepts/modeling/geometry/geometry_uvw_2025.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

174175
def 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

Comments
 (0)