Hi all, Yesterday the osgWrappers/serializers/osg/Object.cpp was modified to add a new UserData property. This changes the osgb reader/writer format and makes it fail to read older .osgb files. That's because the new Object wrapper will traverse its serializers, which are reading/writing of their own behaviors. The UserData serializer, which was not supported by older versions, tried to read value from the old .osgb file and then caught an exception and crashed. The .osgt and .osgx don't have such problem for the reason that they both use matchString() to check if the to-be-read property exists. However, the string-based matchString() function, requiring the property string to be saved in file, is not usable, and not recommended to be implemented in .osgb format.
This raise the issue that: how to keep backwards and forwards compatibility in osgb format? It is important to maintain the native fil format among different revisions, otherwise users should always painfully re-generate their scene files when updating to new OSG releases. I would like to first give a description of some of my solutions and thoughts, with finger crossed. And wish to start a freely discussion of the COMPATIBILITY topic, in whole osg community. Before our discussion, I suppose there were 4 kinds of changes which may break the compatibility: [ADD] - New version adds a property serializer. [DEL] - New version removes a property serializer. [MOD] - New version modifies the type or content of a property, for instance, ADD_FLOAT_SERIALIZER to ADD_DOUBLE_SERIALZIER. [CLS] - New version misses a class wrapper, perhaps because of not loading related shared library. And my schemes as following: /**************/ 1. The present solution - using an external schema file /**************/ Right now, the InputStream/OutputStream classes have a schema mechanism to prevent incompatibility between distributions. Take the UserData issue as an example, we could first generate a schema file from the older version, just type: # osgconv example.osg old_example.osgb -O SchemaFile=old_schema.txt And an old_schema.txt file is created in the form of INI format. It records all classes, their properties and traverse orders for use. Now we change to newer OSG version, which has already added the UserData serializer, type: # osgviewer new_example.osgb # osgviewer old_example.osgb -O SchemaFile=old_schema.txt To view the two files separately. To evaluate it: [ADD] - OK, with the old schema file. [DEL] - Failed, old version has more properties but can't be read. [MOD] - Failed, of course. [CLS] - Failed, can't decide what to read then. It will work and the generated osgb files are clean, but always with an awkward extra text file, and fallible operations. /**************/ 2. Using inbuilt schema data /**************/ Based on the idea of schema files, we could implement an 'inbuilt' schema machanism. That is, to save classes and properties information at the header of the generated osgb file, and read and apply them before reading each file. These will make osgb files from various version work together, with the file size a little larger. /**************/ 3. Using predefined schema data /**************/ Continue the discussion of schema data. We could also define schemas for stable versions, like 3.0, 3.2, etc. while reading input file version, the ReaderWriter could automatically apply corresponding schema to files and try to main compatibility in a limited way. There is no need to evaluate the above two ideas again. /**************/ 4. Writing wrapper size as fallback /**************/ I have tested this method before: While writing osgb files, put a '0' value at the beginning of a class object; after finishing writing the object and its children, seek back and write the real size from beginning to end. This will help if you are going to read this object in a different version, because the written size will be checked before reading a property to prevent handling unrecognized properties, and it could also be used to jump to next element if the object wrapper itself is unknown. To evaluate it: [ADD] - Partly, if the read size exceeds the recorded one. [DEL] - Failed, because the read size 'should' be less. [MOD] - Failed, of course. [CLS] - OK, the unknown class object will be ingored, and we'll jump to next. /**************/ 5. Maintaining revisions of wrappers and serializers /**************/ The last idea in my mind is to maintain a number of revisions of modified class wrappers and specified serializers. This also works for the ive plugin currently. We could have two ADD_..._SERIALZIER macro for the same property and set their working version number, such like: ... ADD_INT_SERIALIZER( Width, 0 ); FOR_VERSION( 2, 9, 8 ); ADD_DOUBLE_SERIALIZER( Width, 0.0 ); FOR_VERSION( 3, 0, 0 ); ADD_FLOAT_SERIALIZER( Width, 0.0f ); ... The example code above means that we have a setWidth()/getWidth() pair in certain class, which uses an INT parameter in and before 2.9.8, and changes to use DOUBLE in 3.0.0, and finally changes to FLOAT in latest versions. Different serializer will be used according to the osgb file version, and thus keeps the compatibility. To evaluate it: [ADD] - OK, use a version-specified serializer. [DEL] - OK, use a version-specified serializer. [MOD] - OK, use a multi-version serializer. [CLS] - OK, use a multi-version wrapper. The only problem is how to maintain it. But it is believed to be in better management than the ive plugin, if we could design a series of clear macrodefinitions. /**************/ Ha, that's all. I'm a little exhausted. :) A physical examination just shows that I need more exercise besides sitting down at the computer, and the allergic rhinitis is afflicting me, too. Any solutions for it? :D I'd like to join the discussion later tonight and try to work out a better solution as soon as possible, with the help of community. Any thoughts and advices will be appreciated. Cheers, Wang Rui _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

