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);
}
}

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)
{
ApplicationOutput("UVW Polygon " + String::IntToString(i));
const UVWStruct uvwData = uvwTag->GetSlow(i);
}

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);

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);
}
}
// 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);
// 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);

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);

Further Reading

UVWStruct::b
Vector b
The UVW coordinate for the second point.
Definition: operatingsystem.h:501
Opolygon
#define Opolygon
Polygon - PolygonObject.
Definition: ge_prepass.h:975
ToPoint
#define ToPoint(op)
Casts a BaseObject* to a PointObject*.
Definition: c4d_baseobject.h:2171
BaseSelect::ToArray
UChar * ToArray(Int32 count) const
VariableTag::GetDataCount
Int32 GetDataCount(void) const
UVWStruct::c
Vector c
The UVW coordinate for the third point.
Definition: operatingsystem.h:502
UVWHandle
void * UVWHandle
Handle for UVW data. See also: UVWTag.
Definition: operatingsystem.h:451
UVWTag::AddToPinSelection
Bool AddToPinSelection(const BaseSelect &pinSelection)
Definition: c4d_basetag.h:541
UVWTag::RemoveFromPinSelection
Bool RemoveFromPinSelection(const BaseSelect &pinSelection)
Definition: c4d_basetag.h:549
CPolygon::b
Int32 b
Index of the second point in the polygon.
Definition: c4d_baseobject.h:46
BaseObject
Definition: c4d_baseobject.h:225
BaseSelect::CopyTo
Bool CopyTo(BaseSelect *dest) const
BaseSelect::GetCount
Int32 GetCount(void) const
UVWTag::GetSlow
UVWStruct GetSlow(Int32 i)
Definition: c4d_basetag.h:412
CPolygon
Represents a polygon that can be either a triangle or a quadrangle.
Definition: c4d_baseobject.h:44
BaseTag
Definition: c4d_basetag.h:47
GetUVSeams
const EdgeBaseSelect * GetUVSeams(const BaseObject *obj)
CPolygon::d
Int32 d
Index of the fourth point in the polygon.
Definition: c4d_baseobject.h:48
UVWTag::GetPinSelection
BaseSelect & GetPinSelection()
Definition: c4d_basetag.h:528
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
ToPoly
#define ToPoly(op)
Casts a BaseObject* to a PolygonObject*.
Definition: c4d_baseobject.h:2174
Opoint
#define Opoint
Point - PointObject.
Definition: ge_prepass.h:1022
MSG_UPDATE
#define MSG_UPDATE
Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
Definition: c4d_baselist.h:340
String::IntToString
static String IntToString(Int32 v)
Definition: c4d_string.h:495
UVWTag
Definition: c4d_basetag.h:380
maxon::Vec3< maxon::Float64, 1 >
UVWTag::Alloc
static UVWTag * Alloc(Int32 count)
PolygonObject::GetPolygonCount
Int32 GetPolygonCount(void) const
Definition: c4d_baseobject.h:1752
UVWStruct
Definition: operatingsystem.h:463
LIMIT
Definition: apibasemath.h:34
BaseSelect
Definition: c4d_baseselect.h:32
UVWTag::Set
static void Set(UVWHandle dataptr, Int32 i, const UVWStruct &s)
Definition: c4d_basetag.h:496
Tuvw
#define Tuvw
UVW data - UVWTag.
Definition: ge_prepass.h:1245
Int32
maxon::Int32 Int32
Definition: ge_sys_math.h:58
BaseSelect::DeselectAll
Bool DeselectAll(void)
UVWTag::ClearPinSelection
void ClearPinSelection()
Clears the pin point selection for this tag.
Definition: c4d_basetag.h:515
ApplicationOutput
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:207
BaseSelect::Select
Bool Select(Int32 num)
C4DAtom::Message
Bool Message(Int32 type, void *data=nullptr)
Definition: c4d_baselist.h:1394
PolygonObject
Definition: c4d_baseobject.h:1598
BaseObject::GetTag
BaseTag * GetTag(Int32 type, Int32 nr=0)
Definition: c4d_baseobject.h:674
CPolygon::c
Int32 c
Index of the third point in the polygon.
Definition: c4d_baseobject.h:47
UVWStruct::d
Vector d
The UVW coordinate for the fourth point.
Definition: operatingsystem.h:503
EventAdd
void EventAdd(EVENT eventflag=EVENT::NONE)
AutoAlloc
Definition: ge_autoptr.h:37
BaseDocument::GetActiveObject
BaseObject * GetActiveObject(void)
C4DAtom::IsInstanceOf
Bool IsInstanceOf(Int32 id) const
Definition: c4d_baselist.h:1373
UVWStruct::a
Vector a
The UVW coordinate for the first point.
Definition: operatingsystem.h:500
String::VectorToString
static String VectorToString(const Vector32 &v, Int32 nnk=-1)
Definition: c4d_string.h:571
EdgeBaseSelect
Definition: c4d_baseselect.h:317
CPolygon::a
Int32 a
Index of the first point in the polygon.
Definition: c4d_baseobject.h:45
maxon::BaseRef
Definition: apibase.h:1509
BaseSelect::GetRange
Bool GetRange(Int32 seg, Int32 maxElements, Int32 *a, Int32 *b) const
UVWTag::GetDataAddressW
UVWHandle GetDataAddressW(void)
BaseObject::InsertTag
void InsertTag(BaseTag *tp, BaseTag *pred=nullptr)