Open Search
    UVWTag Manual

    About

    A UVWTag stores UVW coordinates for a (polygon) object. For each polygon a set of four UVW coordinates is stored (UVWStruct). The class UVWTag is based on VariableTag so the typical workflows on handling tags apply, see BaseTag and VariableTag Manual.

    UVWTag objects are an instance of Tuvw.

    Access

    A UVWTag is typically attached to a polygon object.

    Note
    A polygon object can host multiple UVW tags.

    Allocation/Deallocation

    UVWTag instances are created with the usual tools.

    A UVW tag with projection-based UVs can be created with:

    // This example checks if the given object hosts a UVW tag.
    // If not, a UVW tag is created.
    BaseTag* const foundTag = object->GetTag(Tuvw);
    UVWTag* uvwTag = static_cast<UVWTag*>(foundTag);
    if (uvwTag == nullptr)
    {
    // check if the given object is a polygon object
    if (object->IsInstanceOf(Opolygon))
    {
    PolygonObject* const polyObject = static_cast<PolygonObject*>(object);
    const Int32 polyCount = polyObject->GetPolygonCount();
    uvwTag = UVWTag::Alloc(polyCount);
    if (uvwTag == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    polyObject->InsertTag(uvwTag);
    }
    }
    PyObject * object
    Definition: asdl.h:7
    void InsertTag(BaseTag *tp, BaseTag *pred=nullptr)
    Definition: c4d_basetag.h:48
    Definition: c4d_baseobject.h:1630
    Int32 GetPolygonCount(void) const
    Definition: c4d_baseobject.h:1784
    Definition: c4d_basetag.h:387
    static UVWTag * Alloc(Int32 count)
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define Opolygon
    Polygon - PolygonObject.
    Definition: ge_prepass.h:1026
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define Tuvw
    UVW data - UVWTag.
    Definition: ge_prepass.h:1393
    Definition: object.h:105

    Access Data

    There are two ways to edit the data stored inside a UVWTag. The "slow" way is to access every set of UVW coordinate independently. The "fast" way works with a data handle that allows direct access to the internal memory.

    Slow

    The UVW coordinates stored in a UVWTag can be accessed with:

    // This example loops through the UVW data stored in the given UVW tag.
    const Int32 count = uvwTag->GetDataCount();
    for (Int32 i = 0; i < count; ++i)
    {
    const UVWStruct uvwData = uvwTag->GetSlow(i);
    }
    Py_ssize_t i
    Definition: abstract.h:645
    Py_ssize_t count
    Definition: abstract.h:640
    static String IntToString(Int32 v)
    Definition: c4d_string.h:495
    static String VectorToString(const Vector32 &v, Int32 nnk=-1)
    Definition: c4d_string.h:571
    UVWStruct GetSlow(Int32 i)
    Definition: c4d_basetag.h:419
    Int32 GetDataCount(void) const
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210
    Definition: operatingsystem.h:473
    Vector c
    The UVW coordinate for the third point.
    Definition: operatingsystem.h:512
    Vector b
    The UVW coordinate for the second point.
    Definition: operatingsystem.h:511
    Vector a
    The UVW coordinate for the first point.
    Definition: operatingsystem.h:510
    Vector d
    The UVW coordinate for the fourth point.
    Definition: operatingsystem.h:513

    Fast

    The fast access to the UVW coordinates stored in the UVWTag is provided by a data handle and static functions:

    // This example calculates UVW coordinates based on the polygon's world space position.
    UVWHandle handle = uvwTag->GetDataAddressW();
    const Int32 count = uvwTag->GetDataCount();
    for (Int32 i = 0; i < count; ++i)
    {
    UVWStruct uvwData;
    // get points in world space
    CPolygon polygon = polygons[i];
    const Vector a = mg * points[polygon.a];
    const Vector b = mg * points[polygon.b];
    const Vector c = mg * points[polygon.c];
    const Vector d = mg * points[polygon.d];
    // define UV coordinates based on the world space position
    // CalculateUVCoordinates() is a custom function
    CalculateUVCoordinates(a, uvwData.a);
    CalculateUVCoordinates(b, uvwData.b);
    CalculateUVCoordinates(c, uvwData.c);
    CalculateUVCoordinates(d, uvwData.d);
    UVWTag::Set(handle, i, uvwData);
    }
    polyObject->Message(MSG_UPDATE);
    Bool Message(Int32 type, void *data=nullptr)
    Definition: c4d_baselist.h:1439
    static void Set(UVWHandle dataptr, Int32 i, const UVWStruct &s)
    Definition: c4d_basetag.h:503
    UVWHandle GetDataAddressW(void)
    Py_UNICODE c
    Definition: unicodeobject.h:1200
    #define MSG_UPDATE
    Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
    Definition: c4d_baselist.h:341
    void * UVWHandle
    Handle for UVW data. See also: UVWTag.
    Definition: operatingsystem.h:461
    Represents a polygon that can be either a triangle or a quadrangle.
    Definition: c4d_baseobject.h:44
    Int32 d
    Index of the fourth point in the polygon.
    Definition: c4d_baseobject.h:48
    Int32 b
    Index of the second point in the polygon.
    Definition: c4d_baseobject.h:46
    Int32 c
    Index of the third point in the polygon.
    Definition: c4d_baseobject.h:47
    Int32 a
    Index of the first point in the polygon.
    Definition: c4d_baseobject.h:45

    Pin

    Pin are stored by UV tag, you can access them with:

    // This example sets the current active Point Selection to the UV Point pinned.
    // Get object
    BaseObject* const obj = doc->GetActiveObject();
    if (obj == nullptr || ! obj->IsInstanceOf(Opoint))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Should be a Point Object"_s);
    // Retrieves the fist uvwtag
    UVWTag* uvTag = static_cast<UVWTag*>(obj->GetTag(Tuvw));
    if (uvTag == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves the Pin Selection Stored in the uvTag
    const BaseSelect& pinSelection = uvTag->GetPinSelection();
    if (pinSelection.GetCount() == 0)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves the current Point Selection stored in the PointObject
    BaseSelect* ptSelect = ToPoint(obj)->GetPointS();
    if (ptSelect == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    ptSelect->DeselectAll();
    // Convert UV Point baseSelect to PointObject BaseSelect
    // UV Points are indexed by 4 * polygon + point where @c polygon is the polygon index and c point is the point index between 0 and 3 (a, b, c, d).
    const CPolygon* polys = ToPoly(obj)->GetPolygonR();
    Int32 seg = 0, smin, smax, idx;
    while (pinSelection.GetRange(seg++, LIMIT<Int32>::MAX, &smin, &smax))
    {
    // For each sequance of range
    for (idx = smin; idx <= smax; idx++)
    {
    // Retrieves the polygon ID and the Cpolygon ID
    Int32 polyId = idx / 4;
    Int32 cpolyPtId = idx % 4;
    // Retrieve the real PtID from the Cpolygon
    Int32 ptId = polys[polyId][cpolyPtId];
    ptSelect->Select(ptId);
    }
    }
    #define ToPoint(op)
    Casts a BaseObject* to a PointObject*.
    Definition: c4d_baseobject.h:2203
    #define ToPoly(op)
    Casts a BaseObject* to a PolygonObject*.
    Definition: c4d_baseobject.h:2206
    void EventAdd(EVENT eventflag=EVENT::NONE)
    Definition: c4d_baseobject.h:225
    Definition: c4d_baseselect.h:32
    Bool DeselectAll(void)
    Bool Select(Int32 num)
    Int32 GetCount(void) const
    Bool GetRange(Int32 seg, Int32 maxElements, Int32 *a, Int32 *b) const
    Definition: apibasemath.h:34
    BaseSelect & GetPinSelection()
    Definition: c4d_basetag.h:535
    PyObject * obj
    Definition: complexobject.h:60
    #define Opoint
    Point - PointObject.
    Definition: ge_prepass.h:1075
    const char * doc
    Definition: pyerrors.h:226
    // This example sets the UV Point pinned to the current active Point Selection.
    // Get object
    BaseObject* const obj = doc->GetActiveObject();
    if (obj == nullptr || ! obj->IsInstanceOf(Opoint))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Should be a Point Object"_s);
    // Retrieves the fist uvwtag
    UVWTag* uvTag = static_cast<UVWTag*>(obj->GetTag(Tuvw));
    if (uvTag == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves the current Point Selection stored in the PointObject
    BaseSelect* ptSelect = ToPoint(obj)->GetPointS();
    if (ptSelect == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Allocate a new pinSelection To Set
    // Convert PointObject BaseSelect to Uv Point baseSelect
    // UV Points are indexed by 4 * polygon + point where c polygon is the polygon index and c point is the point index between 0 and 3 (a, b, c, d).
    // Retrieves the read array of all Cpolygon
    const CPolygon* poly = ToPoly(obj)->GetPolygonR();
    if (poly == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves an array of the selection state
    const maxon::AutoMem<UChar> ptArray = ptSelect->ToArray(ToPoint(obj)->GetPointCount());
    if (ptArray == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    for (Int32 i = 0; i < ToPoly(obj)->GetPolygonCount(); ++i)
    {
    const CPolygon* pp = poly + i;
    if (pp == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    if (ptArray[pp->a])
    pinsToSet->Select(i * 4 + 0);
    if (ptArray[pp->b])
    pinsToSet->Select(i * 4 + 1);
    if (ptArray[pp->c])
    pinsToSet->Select(i * 4 + 2);
    if (ptArray[pp->d])
    pinsToSet->Select(i * 4 + 3);
    }
    // Clears the current Pin Selection
    // Adds the built selection to the current pin selection
    uvTag->AddToPinSelection(pinsToSet);
    Definition: ge_autoptr.h:37
    UChar * ToArray(Int32 count) const
    void ClearPinSelection()
    Clears the pin point selection for this tag.
    Definition: c4d_basetag.h:522
    Bool AddToPinSelection(const BaseSelect &pinSelection)
    Definition: c4d_basetag.h:548
    Definition: baseref.h:62
    // This example removes from the UV Point pinned, the current active Point Selection.
    // Get object
    BaseObject* const obj = doc->GetActiveObject();
    if (obj == nullptr || ! obj->IsInstanceOf(Opoint))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Should be a Point Object"_s);
    // Retrieves the fist uvwtag
    UVWTag* uvTag = static_cast<UVWTag*>(obj->GetTag(Tuvw));
    if (uvTag == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves the current Point Selection stored in the PointObject
    BaseSelect* ptSelect = ToPoint(obj)->GetPointS();
    if (ptSelect == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Allocate a new pinSelection To Set
    // Convert PointObject BaseSelect to Uv Point baseSelect
    // UV Points are indexed by 4 * polygon + point where c polygon is the polygon index and c point is the point index between 0 and 3 (a, b, c, d).
    // Retrieves the read array of all Cpolygon
    const CPolygon* poly = ToPoly(obj)->GetPolygonR();
    if (poly == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves an array of the selection state
    const maxon::AutoMem<UChar> ptArray = ptSelect->ToArray(ToPoint(obj)->GetPointCount());
    if (ptArray == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    for (Int32 i = 0; i < ToPoly(obj)->GetPolygonCount(); ++i)
    {
    const CPolygon* pp = poly + i;
    if (pp == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    if (ptArray[pp->a])
    pinsToSet->Select(i * 4 + 0);
    if (ptArray[pp->b])
    pinsToSet->Select(i * 4 + 1);
    if (ptArray[pp->c])
    pinsToSet->Select(i * 4 + 2);
    if (ptArray[pp->d])
    pinsToSet->Select(i * 4 + 3);
    }
    // Removes the built selection to the current pin selection
    uvTag->RemoveFromPinSelection(pinsToSet);
    Bool RemoveFromPinSelection(const BaseSelect &pinSelection)
    Definition: c4d_basetag.h:556

    While it's not stored directly in the UVWTag you may need to retrieve UV seems of an object:

    // This example select edge corresponding to the UV seams of the current object
    // Gets object
    BaseObject* const obj = doc->GetActiveObject();
    if (obj == nullptr || ! obj->IsInstanceOf(Opoint))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Should be a Point Object"_s);
    const EdgeBaseSelect* uvSeams = GetUVSeams(obj);
    if (uvSeams == nullptr || uvSeams->GetCount() == 0)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Retrieves the current Edge Selection stored in the Polygon Object
    BaseSelect* edgeSelect = ToPoly(obj)->GetEdgeS();
    if (edgeSelect == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Deselect all the currently selected edge
    edgeSelect->DeselectAll();
    // Copies the UV seams to the Polygon Edge selection.
    uvSeams->CopyTo(edgeSelect);
    const EdgeBaseSelect * GetUVSeams(const BaseObject *obj)
    Bool CopyTo(BaseSelect *dest, Bool alwaysDirty=true) const
    Definition: c4d_baseselect.h:325

    Further Reading