Re: .pfb format and pfUserData (again)

New Message Reply Date view Thread view Subject view Author view

Rob Mace (mace++at++lum.engr.sgi.com)
Wed, 11 Jun 1997 16:38:29 -0700


> It seems that saving a database in the .pfb format (using pfconv) will also
> save pfUserData attached to nodes. However I suspect that if the pfUserData
> containts *pointers* to other data that is not saved. e.g. if my pfUserData
> structure looks like
>
> typedef struct {
> pfNode *centerNode; /* pointer to some node */
> pfList *observers; /* pointer to list of "observer" structures */
> } MyUserData;
>
> and is attached to a node, the pointers are saved but 1) are invalid when read
> in (centerNode above) or 2) the data pointed to is not saved (observers list
> above).
>
> Is this true?

This is true of pfb in Peroformer 2.0 and 2.1.

> Is there any way to save this kind of data in the .pfb format?

Wait for Performer 2.2. In 2.2 I have put extensive support in for saving
user data. It can save things such as your structure above but you have
to tell it how. You do this by supplying a number of callback routines
that the pfdStoreFile_pfb can call when user data is encountered.

Here are some exerpts from the 2.2 pfb man page:

     int pfdUserData_pfb(pfdDescendUserDataFuncType_pfb descend_func,
                                   pfdStoreUserDataFuncType_pfb store_func,
                                   pfdLoadUserDataFuncType_pfb load_func);

     size_t pfdLoadData_pfb(void *data, int size, void *handle);

     size_t pfdStoreData_pfb(void *data, int size, void *handle);

     int pfdDescendObject_pfb(pfObject *obj, void *handle);

     int pfdLoadObjectRef_pfb(pfObject **obj, void *handle);

     int pfdStoreObjectRef_pfb(pfObject *obj, void *handle);

     typedef int (*pfdDescendUserDataFuncType_pfb)(void *udata,
                          pfObject *parent, void *handle);

     typedef int (*pfdStoreUserDataFuncType_pfb)(void *udata,
                          pfObject *parent, void *handle);

     typedef void * (*pfdLoadUserDataFuncType_pfb)(void *handle);

     There are some portions of a performer scene graph that it can be
     impossible to know how to store or load without application specific
     knowledge. Two examples of this are pfUserData and custom pfTypes. For
     this reason one can set up call backs for the pfdStoreFile_pfb and
     pfdLoadFile_pfb to call to handle this data. The functions
     pfdLoadData_pfb, pfdStoreData_pfb, pfdDescendObject_pfb,
     pfdLoadObjectRef_pfb, and pfdStoreObjectRef_pfb are meant to be called by
     these call backs.

          pfdLoadData_pfb reads size bytes of data into data from the pfb file
          that is specified by handle. It should be called by the store_func
          of pfdUserData_pfb and pfdCustomNode_pfb.

          pfdStoreData_pfb writes size bytes of data from data into the pfb
          file that is specified by handle. It should be called by the
          store_func of pfdUserData_pfb and pfdCustomNode_pfb.

          pfdDescendObject_pfb descends a pfObject pointer and adds it and any
          of its children to the lists of items to be stored into the pfb file
          that is specified by handle. It returns 0 if it can store an object
          and -1 if it can not. Generally any pfObject that normally can
          reside in a Performer scene graph can be stored.
          pfdDescendObject_pfb should be called by the descend_func of
          pfdUserData_pfb and pfdCustomNode_pfb.

          pfdStoreObjectRef_pfb writes a reference to the pfObject pointed to
          by obj into the pfb file that is specified by handle. It should be
          called by the store_func of pfdUserData_pfb and pfdCustomNode_pfb.
          It should only be called for those pfObject that
          pfdDescendObject_pfb returned 0 on.

          pfdLoadObjectRef_pfb reads a reference to a pfObject from the pfb
          file that is specified by handle. At some later time, but before
          the completion of pfdLoadFile_pfb, the address of the pfObject that
          was referenced will be written into the pointer location pointed to
          by obj. This is done because at the time that pfdLoadObjectRef_pfb
          is called the referenced object might not have been read from the
          pfb file. pfdLoadObjectRef_pfb should be called by the load_func of
          pfdUserData_pfb and pfdCustomNode_pfb.

     pfUserData can be of many forms. It can be a pointer to a block of
     memory, a pointer to some pfObject, or a pointer to a complex structure
     containing many other pointers. pfdUserData_pfb can be called to set up
     call backs to handle the storing and loading of complex user data. To
     set up a custom user data store descend_func and store_func must be
     defined. To set up a custom load load_func must be defined.

     The descend_func must be of the type pfdDescendUserDataFuncType_pfb. If
     defined it will get called for each piece of user data that is not a
     pointer to a savable pfObject. udata is the pointer to the user data.
     parent is the parent pfObject of the user data. handle defines the
     current pfb file. The descend_func should call pfdDescendObject_pfb for
     any pfObjects that are referenced by the user data. It should return 0
     if it wants to store this user data. It should return -1 if this user
     data should not be stored.

     The store_func must be of the type pfdStoreUserDataFuncType_pfb. If
     defined it will get called for each piece of user data that the
     descend_func said should be stored. udata is the pointer to the user
     data. parent is the parent pfObject of the user data. handle defines
     the current pfb file. The store_func should call pfdStoreData_pfb and
     pfdStoreObjectRef_pfb zero or more times each to store the data and
     pfObject references of this user data.

     The load_func must be of the type pfdLoadUserDataFuncType_pfb. It will
     get called for each piece of user data that is not a pointer to a
     pfObject. handle defines the current pfb file. The load_func should
     call pfdLoadData_pfb and pfdLoadObjectRef_pfb zero or more times each to
     load the data and pfObject references of this user data.

     pfUserData is descended based on the following scheme:

               if (user_data is a pointer to savable pfObject)
               {
                   mark it for storing;
                   descend the pfObject;
               }
               else if (descend_func)
               {
                   if (descend_func(user_data))
                    mark it for storing;
               }
               else if (pfGetSize(user_data) > 0)
                   mark it for storing;

     pfUserData is stored based on the following scheme:

               if (user_data is a pointer to savable pfObject)
                   store the a reference to that object;
               else if (store_func)
                   store_func(user_data);
               else if (pfGetSize(user_data) > 0)
                   store pfGetSize(user_data) bytes of data;

I hope that helps,

Rob Mace
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
            Submissions: info-performer++at++sgi.com
        Admin. requests: info-performer-request++at++sgi.com
   SGI DevForum 97 info: http://www.sgi.com/Forum97/


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:55:25 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.