double type from now on for all time variables.
OP_Node virtual const UT_DMatrix4 &getWorldTransform(OP_Context &);virtual const UT_DMatrix4 &getIWorldTransform(OP_Context &);
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 &);
OBJ_SubNet const UT_DMatrix4 &getSubnetTransform(OP_Context &);
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:
OP_Node::getWorldTransform()OP_Node::getIWorldTransform()OP_Node::getRelativeTransform()OP_Node::getRelativeCaptureTransform()This may require significant changes to existing source code.
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; }
int Cd_offset; UT_Vector3 *Cd; 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)) {... }
The example file SOP_SParticle.C has been modified to compile with either 10.0 or newer versions of the HDK.
// Old code int offset;
// New code
GB_AttributeRef offset;
// 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))
// Old code
offset = -1;
// New code offset.clear();
// Alternative new code for compatibility with H10.0
GBclearAttributeRef(offset);
// 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); }
// Old code int offset = gdp.findNormalAttribute(..); if (offset < 0) return -1;
// New code int offset = gdp.findNormalAttribute(..); if (offset.isInvalid() return GB_AttributeRef();
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<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.
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); } }
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); } }
There are new methods available on GB_AttributeElem which more than make up for the methods on GB_AttributeData
In addition there are short-cut methods which are now available on GB_AttributeElem which required multiple operations when accessing GB_AttributeData.
1.5.9