Hello @del,
so, I had a look at your data, and I cannot see any UVW vertex component values there which are 1
in the UI, but when accessed in Python are -1.1102230246251565e-16
, i.e., almost 0
. There are however a few values which are -1.1102230246251565e-16
which are shown as 0
in the UI and when printing out a c4d.Vector
instance. Because vectors round their value when printed. Internally they will always work with the true values and when one wants to print out the true values, one must access the components individually.
# A vector where all three components are very close to zero.
v = c4d.Vector(1E-10)
# Printing out the vector will show the rounded components.
print (f"{v = }")
# Accessing them directly will provide the true values.
print (f"{v.x = }, {v.y = }, {v.z = }")
v = Vector(0, 0, 0)
v.x = 1e-10, v.y = 1e-10, v.z = 1e-10
So, your data is fine, it is just that the UVW data was either created by an artist who rightfully did not care if some values are 0
or 'almost zero', or that the data was created at lower precision and then converted at some point, which lead to these rounding errors.
Below you can find a script which prints out all the UVW data for a selected object and then quantizes the data with a given precision, running QuantizeUvwTag
from my script will persistently fix an Uvw tag in the context of very small values and also quantize other values. You would have to implement yourself what you want to be fixed and what not, this is a purely cosmetic issue after all.
Cheers,
Ferdinand
An excerpt from the script output for your file:
Uvw-Data:
uvw polygon 0: {'a': Vector(0.25, 0.152, 0), 'b': Vector(0.433, 0.152, 0), 'c': Vector(0.25, 0.174, 0), 'd': Vector(0, 0, 0)}
0: a(0)=0.25
0: a(1)=0.15186521410942078
0: a(2)=0.0
0: b(0)=0.4333333373069763
0: b(1)=0.15186521410942078
0: b(2)=0.0
0: c(0)=0.25
0: c(1)=0.17397046089172363
0: c(2)=0.0
0: d(0)=0.0
0: d(1)=0.0
0: d(2)=0.0
...
uvw polygon 8: {'a': Vector(0.433, 0, 0), 'b': Vector(0.433, 0.111, 0), 'c': Vector(0.25, 0.111, 0), 'd': Vector(0.25, 0, 0)}
8: a(0)=0.4333333373069763
8: a(1)=-1.1102230246251565e-16
8: a(2)=0.0
8: b(0)=0.4333333373069763
8: b(1)=0.11077965795993805
8: b(2)=0.0
8: c(0)=0.25
8: c(1)=0.11081257462501526
8: c(2)=0.0
8: d(0)=0.25
8: d(1)=-1.1102230246251565e-16
8: d(2)=0.0
uvw polygon 9: {'a': Vector(0.433, 0.174, 0), 'b': Vector(0.433, 0.152, 0), 'c': Vector(0.477, 0.152, 0), 'd': Vector(0.25, 0, 0)}
9: a(0)=0.4333333373069763
9: a(1)=0.17397046089172363
9: a(2)=0.0
9: b(0)=0.4333333373069763
9: b(1)=0.15186521410942078
9: b(2)=0.0
9: c(0)=0.476666659116745
9: c(1)=0.15186521410942078
9: c(2)=0.0
9: d(0)=0.25
9: d(1)=-1.1102230246251565e-16
9: d(2)=0.0
...
Quantized Uvw-Data:
uvw polygon 0: {'a': Vector(0.25, 0.152, 0), 'b': Vector(0.433, 0.152, 0), 'c': Vector(0.25, 0.174, 0), 'd': Vector(0, 0, 0)}
0: a(0)=0.25
0: a(1)=0.15186521410942078
0: a(2)=0.0
0: b(0)=0.4333333373069763
0: b(1)=0.15186521410942078
0: b(2)=0.0
0: c(0)=0.25
0: c(1)=0.17397046089172363
0: c(2)=0.0
0: d(0)=0.0
0: d(1)=0.0
0: d(2)=0.0
...
uvw polygon 8: {'a': Vector(0.433, 0, 0), 'b': Vector(0.433, 0.111, 0), 'c': Vector(0.25, 0.111, 0), 'd': Vector(0.25, 0, 0)}
8: a(0)=0.4333333373069763
8: a(1)=-0.0
8: a(2)=0.0
8: b(0)=0.4333333373069763
8: b(1)=0.11077965795993805
8: b(2)=0.0
8: c(0)=0.25
8: c(1)=0.11081257462501526
8: c(2)=0.0
8: d(0)=0.25
8: d(1)=-0.0
8: d(2)=0.0
uvw polygon 9: {'a': Vector(0.433, 0.174, 0), 'b': Vector(0.433, 0.152, 0), 'c': Vector(0.477, 0.152, 0), 'd': Vector(0.25, 0, 0)}
9: a(0)=0.4333333373069763
9: a(1)=0.17397046089172363
9: a(2)=0.0
9: b(0)=0.4333333373069763
9: b(1)=0.15186521410942078
9: b(2)=0.0
9: c(0)=0.476666659116745
9: c(1)=0.15186521410942078
9: c(2)=0.0
9: d(0)=0.25
9: d(1)=-0.0
9: d(2)=0.0
...
The script:
"""Showcases how to quantize data in a UvwTag.
"""
import c4d
def InspectUvwTag(tag: c4d.UVWTag):
"""Prints out the uvw data for the passed UVWTag.
Args:
tag: The tag to inspect.
"""
if not isinstance(tag, c4d.UVWTag):
raise TypeError(f"Unexpected argument type: {tag = }")
countGenerator = range(tag.GetDataCount())
for i, uvwPolygon in ((i, tag.GetSlow(i)) for i in countGenerator):
print (f"uvw polygon {i}: {uvwPolygon}")
for vertexName, vertex in uvwPolygon.items():
for componentName, component in enumerate((vertex.x,
vertex.y,
vertex.z)):
print (f"\t{i}: {vertexName}({componentName})={component}")
def QuantizeUvwTag(tag: c4d.UVWTag, digits: int = 12):
"""Quantizes the uvw data in #tag with a stride of #digits.
Args:
tag: The tag to modify.
digits (optional): The number of digits of precision, defaults
to 12.
"""
if not isinstance(tag, c4d.UVWTag):
raise TypeError(f"Unexpected argument type: {tag = }")
countGenerator = range(tag.GetDataCount())
for i, uvwPolygon in ((i, tag.GetSlow(i)) for i in countGenerator):
quantizedUvwPolygon = {}
for key, vertex in uvwPolygon.items():
# I am only modifying the precision of the values here, I am
# not clamping them. Which will lead to values of -0.0 to be
# written. Modify this to your requirements, this is a very
# cosmetic task after all. -1.1e-16 is when push comes to shove
# the same as 0.0 in the context of UVW data. So this quantization
# is not really required, unless you want 'nice' data.
quantizedUvwPolygon[key] = c4d.Vector(round(vertex.x, digits),
round(vertex.y, digits),
round(vertex.z, digits))
tag.SetSlow(i,
quantizedUvwPolygon["a"],
quantizedUvwPolygon["b"],
quantizedUvwPolygon["c"],
quantizedUvwPolygon["d"])
def main():
"""Entry point.
"""
if op is None:
raise RuntimeError("Please select an object.")
tag = op.GetTag(c4d.Tuvw)
if tag is None:
raise AttributeError(f"Selected object {op} has no uvw tag.")
# Inspect the tag. This will only print out different results than the
# second call of InspectUvwTag() the first time the script is being run,
# because after that the tag will already have been quantized.
print ("Uvw-Data:")
InspectUvwTag(tag)
# Quantize its data.
QuantizeUvwTag(tag)
# And inspect it again.
print ("\n\nQuantized Uvw-Data:")
InspectUvwTag(tag)
if __name__=='__main__':
main()