Prepare/Evaluate Protocol

There are a few Package Interfaces which can be used to get the values of channels in order to create an instance of the surface object for the item. The Prepare/Evaluate methods do the same thing, but using a different scheme to get channel values.

Basic Usage

The Prepare() method takes an Evaluation Interface as argument. This is used to let the item declare which channels it needs to read in order to compute the surface object. The index returned is typically the index of the first evaluation channel.

1
2
3
4
5
6
        LxResult
 CMySurfaceItem::isurf_Prepare (
        ILxUnknownID             evalObj,
        unsigned                *index)
 {
        CLxUser_Evaluation       eval (evalObj);
1
2
3
4
        index[0] =
          eval.AddChan (m_item, Cs_MYCHANNEL1);
          eval.AddChan (m_item, Cs_MYCHANNEL2);
          eval.AddChan (m_item, Cs_MYCHANNEL3);
1
2
        return LXe_OK;
 }

The Evaluate() method is called zero or more times after preparation. This gets an Attributes Interface which is used to read channel values using the indices from preparation.

1
2
3
4
5
6
7
8
        LxResult
 CMySurfaceItem::isurf_Evaluate (
        ILxUnknownID             attrObj,
        unsigned                 index,
        void                   **ppvObj)
 {
        CLxUser_Attributes       attr (attrObj);
        CMySurface              *surf = surf_spawn.Alloc (ppvObj);
1
2
3
        surf->val1 = attr.Float (index + 0);
        surf->val2 = attr.Float (index + 1);
        surf->val3 = attr.Float (index + 2);
1
2
        return LXe_OK;
 }

Using an EvalModifier

The Prepare/Evaluate protocol can be used directly in only limited circumstances. Specifically if the item always reads the same set of channels and they are all from the item itself. A surface that depends on channels from other items – or which needs to read different sets of channels depending on the configuration or topology of the scene – needs to use an EvalModifier Interface server to deal with the additional complexity.

The item will need a channel to store the result of the modifier. This will be of the OBJREF type (which allows it to store any object, or none) and set to internal to prevent it from appearing in the channel list.

1
        CLxUser_AddChannel       ac (addChan);
1
2
        ac.NewChannel  (Cs_SURFCACHE, LXsTYPE_OBJREF);
        ac.SetInternal ();

The EvalModifier will read the necessary channels from all over the scene and store the result object in a channel on the item. This can for example be done with a Modifier (lxu-modifier.hpp)#CLxObjectRefModifierCore for creating item modifiers. Since the heavy lifting has already been done, the Prepare/Evaluate method just needs to read that one channel.

1
2
3
4
5
6
        LxResult
 CMySurfaceItem::isurf_Prepare (
        ILxUnknownID             evalObj,
        unsigned                *index)
 {
        CLxUser_Evaluation       eval (evalObj);
1
2
3
        index[0] = eval.AddChan (m_item, Cs_SURFCACHE);
        return LXe_OK;
 }
1
2
3
4
5
6
7
8
        LxResult
 CMySurfaceItem::isurf_Evaluate (
        ILxUnknownID             attrObj,
        unsigned                 index,
        void                   **ppvObj)
 {
        CLxUser_Attributes       attr (attrObj);
        CLxUser_ValueReference   ref;
1
2
3
        attr.ObjectRO (index, ref);
        return ref.GetObject (ppvObj);
 }