HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
11.0: Major Changes In The HDK

Table Of Contents

Custom Expressions

Custom expression callback functions now take an extra "func_flags" parameter. Please see the expr/channel.C and expr/functions.C for the recommended method of declaring them in a backwards compatible manner using the EV_START_FN macro.

Time Data Type

Parameter and channel evaluation time values have been changed from single to double precision. This type conversion is still an ongoing process so not all places in the HDK have been modified yet. Please use the double type from now on for all time variables.

Thread Safety

If you are manually spawning threads, then a UT_TaskScope object is now probably required to created in your parent thread. See Creating Child Threads for more info.

See Also

Node Transform Interface

In an effort to make the interfaces more thread-safe, the following class methods that deal with obtaining transforms have been removed. At the same time, alternate versions of the functions are provided that return the transform matrix in an output reference parameter as well as returning a bool indicating success.

  • Removed methods from OP_Node
    • virtual const UT_DMatrix4 &getWorldTransform(OP_Context &);
    • virtual const UT_DMatrix4 &getIWorldTransform(OP_Context &);
  • Removed methods from OBJ_Node
    • virtual const UT_DMatrix4 &getTransform(OP_Context &);
    • virtual const UT_DMatrix4 &getWorldTransform(OP_Context &);
    • virtual const UT_DMatrix4 &getIWorldTransform(OP_Context &);
    • const UT_DMatrix4 &getInverseLocalToWorldTransform(OP_Context &);
    • const UT_DMatrix4 &getLocalToWorldTransform(OP_Context &);
  • Removed methods from OBJ_SubNet
    • const UT_DMatrix4 &getSubnetTransform(OP_Context &);
  • Removed methods ROP_RenderableThing
    • virtual const UT_DMatrix4 &getWorldTransform(OP_Context &) = 0; (and corresponding subclassed methods)

The alternate forms of these functions now behave differently. Previously, for nodes which did not support transforms, they would return false and then leave their output matrix parameters uninitialized. To unify the semantics of the two function forms, the alternate forms for such nodes now return true instead, and initialize their output matrix parameters to the identity. The affected functions are:

GB_AttributeRef - Attribute References

In earlier versions of the HDK, attributes were referenced by an integer value. Houdini 11.0 replaces this with the new GB_AttributeRef class.

This may require significant changes to existing source code.

Deferring Code Changes

We realize that you may not have the time or resources to change all your code at the current time. In order to facilitate making the change, you can define HDK_RELAXED_GB in your make (or in your code).

This will provide convenience methods which should allow integer values to be used transparently with GB_AttributeRef objects.

If you need your code to compile with earlier versions of Houdini as well, you can include <GB/GB_AttributeRef.h> (which was added in 10.0.XXX. The salient parts of this file are:

typedef int GB_AttributeRef;
static inline bool GBisAttributeRefValid(const GB_AttributeRef &a)
{ return a >= 0; }
static inline bool GBisAttributeRefInvalid(const GB_AttributeRef &a)
{ return a < 0; }
static inline GB_AttributeRef GBmakeInvalidAttributeRef()
{ return -1; }
static inline void GBclearAttributeRef(GB_AttributeRef &a)
{ a = -1; }
Warning
You will have to change your code eventually.

How To Update Code

Old attribute code looks something like:

int Cd_offset;
Cd_offset = gdp->findDiffuseAttribute(GEO_POINT_DICT);
if (Cd_offset >= 0)
{
FOR_ALL_GPOINTS(gdp, pp)
{
Cd = ppt->castAttribData<UT_Vector3>(Cd_offset);
Cd->assign(1, 0, 0); // Set to red
}
}

The equivalent new code would look like:

GB_AttributeRef Cd_ref;
Cd_ref = gdp->findNormalAttribute(GEO_POINT_DICT);
if (Cd_ref.isValid())
{
FOR_ALL_GPOINTS(gdp, pp)
{
ppt->setValue<UT_Vector3>(Cd_ref, UT_Vector3(1, 0, 0));
}
}

The method isValid() is not backward compatible with earlier versions of Houdini. If you need to compile your code with earlier versions, please use the global function GBisAttributeRefValid()

if (GBisAttributeRefValid(Cd_ref)) {... }

This code will compile in 10.0 if you include <GB/GB_AttributeRef.h>

The example file SOP_SParticle.C has been modified to compile with either 10.0 or newer versions of the HDK.

Common Code Patterns

While making changes in the Houdini baseline, we noticed some of the following common code patterns:

  • Declaration of attribute references
    // Old code
    int offset;
    // New code
    GB_AttributeRef offset;
  • Checking whether reference was valid or invalid
    // Old code
    if ((offset = gdp.findPointAttribute(...)) >= 0) { }
    if (offset < 0)
    // New code
    if ((offset = gdp.findPointAttribute(...)).isValid()) { }
    if (offset.isInvalid())
    // Alternative new code for compatibility with H10.0
    if (GBisAttributeRefValid(offset = gdp.findPointAttribute(...))) { }
    if (GBisAttributeRefInvalid(offset))
  • Making an attribute reference invalid
    // Old code
    offset = -1;
    // New code
    offset.clear();
    // Alternative new code for compatibility with H10.0
    GBclearAttributeRef(offset);
  • Manually computing offsets based on iterating over the attribute dictionary. This is really a bad practice and we are certain that your code never did this.
    // Old code
    for (offset = 0, atr = (GB_Attribute *)dict.head(); atr;
    atr = (GB_Attribute *)atr->next())
    {
    if (matchAttribute(atr))
    return offset;
    offset += atr->getAllocSize();
    }
    // New code
    offset.clear();
    for (atr = (GB_Attribute *)dict.head(); atr;
    atr = (GB_Attribute *)atr->next())
    {
    if (matchAttribute(atr))
    return dict.getOffset(atr);
    }
  • Returning an invalid offset
    // Old code
    int offset = gdp.findNormalAttribute(..);
    if (offset < 0)
    return -1;
    // New code
    int offset = gdp.findNormalAttribute(..);
    if (offset.isInvalid()
    return GB_AttributeRef();

GB_AttributeData Becomes Private Data

In earlier versions of the HDK, it was possible to access the GB_AttributeData associated with a GB_AttributeElem object. In H11.0, this data is now private.

As with the changes to GB_AttributeRef, it is possible to defer these changes. However, a future release of Houdini will see radical changes with attribute data so it is important to make these changes at some point.

The changes for the privatization of GB_AttributeData are fairly straightforward.

castAttribData<>

Until 11.0, the only way to access attribute data was by using the castAttribData<T>() method. This method gave the caller direct access to the storage of the attribute data. While efficient, this method makes assumptions about how the data is stored inside attributes.

castAttribData() should be replaced with the newer get/set or the attribute handle interfaces.

See Also
getsetAttributes, handleAccessAttributes

GB_AttributeTable as a GB_AttributeElem

One of the reasons why you might have had to use GB_AttributeData rather than GB_AttributeElem is that your code needed to handle detail attributes. These are stored in a GB_AttributeTable object which had attribute data. The GB_AttributeTable object now stores a GB_AttributeElem object which can be used to access attribute data.

For example, old code:

static int
getValue(GB_AttributeData &data, const GB_AttributeRef &offset)
{
return data.castAttribData<int>(offset)[0];
}
...
{
switch (type)
{
case POINT: return getValue(pt->getAttrib(), offset);
case VERTEX: return getValue(vtx->getAttrib(), offset);
case PRIMITIVE: return getValue(prim->getAttrib(), offset);
case DETAIL: return getValue(gdp->attribs().getAttrib(), offset);
}
}

This should be replaced with:

static int
getValue(GB_AttributeElem &data, const GB_AttributeRef &offset)
{
return data.getValue<int>(offset);
}
...
{
switch (type)
{
case POINT: return getValue(*pt, offset);
case VERTEX: return getValue(*vtx, offset);
case PRIMITIVE: return getValue(*prim, offset);
case DETAIL: return getValue(gdp->attribs().getElement(), offset);
}
}

Operations on GB_AttributeData

Often, code would perform operations on attribute data. This was often used when performing interpolation of attribute data, etc.

There are new methods available on GB_AttributeElem which more than make up for the methods on GB_AttributeData

  • GB_AttributeData::changeSize()
    Replace with GB_AttributeElem::allocateAttributeValues()
  • GB_AttributeData::hasData()
    Replace with GB_AttributeElem::hasAllocatedAttributeValues()
  • GB_AttributeData::setData()
    Replace with GB_AttributeElem::copyAttributeValues()
  • GB_AttributeData::scaleData()
    Replace with GB_AttributeElem::scaleAttributeValues()
  • GB_AttributeData::sumData()
    Replace with GB_AttributeElem::addAttributeValues()

In addition there are short-cut methods which are now available on GB_AttributeElem which required multiple operations when accessing GB_AttributeData.

  • GB_AttributeElem::lerpAttributeValues()
    Perform linear interpolation between two attribute objects
  • GB_AttributeElem::baryAttributeValues()
    Perform Barycentric interpolation between three attribute objects
  • GB_AttributeElem::bilinearAttributeValues()
    Perform bilinear interpolation between four attribute objects

Geometry Deprecations

There have been several deprecations in the geometry library. These methods will disappear in the future, so please make your code future compatible by using the future-proof replacements

  • GB_AttributeElem::copyAttribData(const GB_AttributeElem *, int )
    Replace with GB_AttributeElem::copyAttributeValues()
  • GEO_Point::copyAttributeData(const GEO_Point *src, int sz)
    Replace with GB_AttributeElem::copyAttributeValues()
  • GEO_Point::copyPoint(const GEO_Point *src, int sz)
    Replace with GEO_Point::copyPoint(const GEO_Point &, const GB_AttributeDict &);
  • GEO_Vertex::copyAttributeData(const GEO_Vertex *src, int sz)
    Replace with GB_AttributeElem::copyAttributeValues()
  • GEO_Point::copyVertex(const GEO_Vertex &, GEO_Point *src, int sz)
    Replace with GEO_Point::copyVertex(const GEO_Vertex *, GEO_Point *, const GB_AttributeDict &);
  • GEO_Point::copyVertex(const GEO_Vertex *src, int sz)
    Replace with GEO_Point::copyVertex(const GEO_Vertex &, const GB_AttributeDict &);
  • GEO_Primitive::copyAttributeData(const GEO_Primitive *src, int sz)
    Replace with GB_AttributeElem::copyAttributeValues()
  • GEO_Primitive::copyAttributeData(const GEO_Primitive *src)
    Replace with GEO_Primitive::copyAttribData(const GEO_Primitive &);