5.9. Special Considerations for Caching

Elements do all of the work for caching in Inventor. If you are creating a node or an action that uses existing elements, you don't need to worry about caching. However, if you are creating a new element, you need to provide the necessary information so that caching continues to work. (You might want to reread Section 1.4, “Caching” before continuing with this section.)

A cache is essentially a faster representation of the data you're trying to generate or compute in Inventor. What the cache contains depends on the action. A GL render cache contains an OpenGL display list. A bounding-box cache contains the bounding box itself. Using the cache speeds up subsequent traversal of the scene graph. In addition, the cache contains a list of the elements outside the cache that the information inside the cache depends on. For efficiency, the cache does not make an exact copy of each element it depends on. Instead, it copies only enough information to determine later on whether the cache is still valid.

The form of this information depends on the element. For some elements, such as those derived from SoFloatElement( C++ | Java | .NET ) or SoLongElement, the value of the element is compared. For others, the node ID of the node that set the element's value is compared. For elements such as those derived from SoAccumulatedElement( C++ | Java | .NET ), the list of node IDs for all nodes that affect the instance of the element is compared. The copyMatchInfo() method should copy just enough information so that matches() can work properly.

Inventor uses an element's copyMatchInfo() method to copy the comparison data for the element into the cache. Then, to determine whether a cache is valid, Inventor compares each element in the cache with the corresponding element in the state by calling the element's matches() method.

You can inherit the matches() and copyMatchInfo() methods from the base classes, or for efficiency, you can write routines that are tailored to your new element class. The following sections explain in more detail how those routines work for the base classes.

In many cases, you need to store only the value of the element in the cache. It doesn't matter which node has set the value. If the value of the element in the cache matches the value of the element in the state, the cache is still valid. The matches() and copyMatchInfo() methods for the SoFloatElement( C++ | Java | .NET ) and SoLongElement classes function in this way.

SoReplacedElement( C++ | Java | .NET ) redefines the getElement() method of SoElement( C++ | Java | .NET ) to store the node ID of the node that is about to set the value in the element. (Recall that a node's ID is unique and changes whenever the node changes.) SoReplacedElement( C++ | Java | .NET ) also redefines matches() to compare the node IDs and return TRUE if the node IDs of the two elements match, as follows:


C++
SbBool
SoReplacedElement::matches(const SoElement *elt) const
{
    return (nodeId == ((const SoReplacedElement *)
            elt)->nodeId);
}

An example of such an element is the coordinate element, which stores multiple coordinate values. Rather than compare all the values, this element simply compares the node IDs. The copyMatchInfo() method for this class copies only the node ID, since that is the information used to determine if the cache matches the state:


C++
SoElement *
SoReplacedElement::copyMatchInfo() const
{
    SoReplacedElement *result =
        (SoReplacedElement *)getTypeId().createInstance();

    result->nodeId = nodeId;

    return result;
}

Elements that accumulate values need to keep a list of node IDs for all nodes that affect an instance of the element. To determine whether a cache is valid for an accumulated element, the node ID list for the element in the cache is compared with the node ID list for the element in the state.

The SoAccumulatedElement( C++ | Java | .NET ) class redefines the matches() method to compare lists of node IDs. If they plan to use the standard matches() method, subclasses of SoAccumulatedElement( C++ | Java | .NET ) need to use the following methods provided by this parent class to keep the list of node IDs up to date: