| 3 | | The format reader writer plugin is located at src/osgPlugins/osg/ReaderWriterOSG2.cpp and wrappers at src/osgWrappers/serializers. |
| 4 | | |
| 5 | | It supports two extensions at present:: |
| 6 | | * .osgb The binary format |
| 7 | | * .osgt The ascii format |
| 8 | | |
| 9 | | Supported options are:: |
| 10 | | * !WriteImageHint=<hint> |
| 11 | | (Export option) Hint of writing image to stream. |
| 12 | | * <!IncludeData> writes Image::data() directly; |
| 13 | | * <!IncludeFile> writes the image file itself to stream; |
| 14 | | * <!UseExternal> writes only the filename; |
| 15 | | * <!WriteOut> writes Image::data() to disk as external file. |
| 16 | | The first two hints only affect binary formats. By default, the image writer will check osg::Image::getWriteHint() to decide if save data or only the filename. |
| 17 | | |
| 18 | | * Compressor=<name> |
| 19 | | (Export option) Use an inbuilt or user-defined compressor to encode the stream. These only affect binary formats. |
| 20 | | |
| 21 | | * !SchemaFile=<file> |
| 22 | | (Import/Export option) Record an ascii schema file of writing properties orders, and use it while reading if necessary. |
| 23 | | |
| 24 | | * ForceReadingImage |
| 25 | | (Import option) Load an empty image with specified filename instead if required file missed. This is useful when converting from other formats. Image information won't be erased even without the external reference. |
| 26 | | |
| 27 | | * Ascii |
| 28 | | (Import/Export option) By default, the reading/writing format is guessed from the extension, and this option will force using the ascii format directly. |
| 29 | | |
| 30 | | Main features:: |
| 31 | | * Serialization I/O: Serialization is used for writing objects into memory buffer and "resurrected" them in the same or another computer environment, enabling simple and common input/output interfaces to be utilized. See osgDB/Serializer header for details. |
| 32 | | |
| 33 | | * Binary/ascii file format: A dual binary/ascii format is supported based on different implementations of I/O classes in the osgDB/!StreamOperator header. These implementations could be found at osgPlugins/osg directory. The cross-format compatibility is provided by the object wrappers and their reader/writer classes. |
| 34 | | |
| 35 | | * Object wrappers: Every class in the scene graph should have a corresponding wrapper, in which a series of templated serializers are used to bind reading and writing members. The wrapper should record all necessary setting/getting members of the object class, as well as the I/O order of these properties. See osgDB/!ObjectWrapper header for details. |
| 36 | | |
| 37 | | * Compressors and decompressors: The compressor is used while the whole scene graph is already recorded, to reduce data size and encrypt the result buffer for variant reasons. A decompressor method should also be provided for decoding. See the osgDB/!ObjectWrapper header again. And the total output/input managers are declared in osgDB/!OutputStream and osgDB/!InputStream headers. |
| 38 | | |
| 39 | | * Extendability: The object wrappers and compressors are always extendable. You may easily write wrappers for user-customized class derived from osg::Object base class and load them from applications or dynamic libraries. The wrapper may contain a series of predefined and custom serializers. |
| 40 | | |
| 41 | | * Schema Definitions: The sequence of a class' properties is recorded in its wrapper class. These sequences could be write out as a "schema" list, which indicates the reading/writing orders of all existing classes in current OSG version. The schema may be used to force resort wrappers in another environment. According to the schema, any unrecognizable property name and disrupted orders will be automatically fixed while reading an external file. These will help applications to be backwards and forward compatible. |
| | 3 | The format reader writer plugin is located at `src/osgPlugins/osg/ReaderWriterOSG2.cpp` and wrappers at `src/osgWrappers/serializers`. |
| | 4 | |
| | 5 | It supports two extensions at present: |
| | 6 | * `.osgb` The binary format |
| | 7 | * `.osgt` The ascii format |
| | 8 | |
| | 9 | Supported options are: |
| | 10 | * `WriteImageHint=<hint>` (Export option) Hint of writing image to stream. |
| | 11 | * `<IncludeData>` writes Image::data() directly; |
| | 12 | * `<IncludeFile>` writes the image file itself to stream; |
| | 13 | * `<UseExternal>` writes only the filename; |
| | 14 | * `<WriteOut>` writes Image::data() to disk as external file. |
| | 15 | The first two hints only affect binary formats. By default, the image writer will check `osg::Image::getWriteHint()` to decide if save data or only the filename. |
| | 16 | |
| | 17 | * `Compressor=<name>` (Export option) Use an inbuilt or user-defined compressor to encode the stream. These only affect binary formats. |
| | 18 | |
| | 19 | * `SchemaFile=<file>` (Import/Export option) Record an ascii schema file of writing properties orders, and use it while reading if necessary. |
| | 20 | |
| | 21 | * `ForceReadingImage` (Import option) Load an empty image with specified filename instead if required file missed. This is useful when converting from other formats. Image information won't be erased even without the external reference. |
| | 22 | |
| | 23 | * `Ascii` (Import/Export option) By default, the reading/writing format is guessed from the extension, and this option will force using the ascii format directly. |
| | 24 | |
| | 25 | Main features: |
| | 26 | * '''Serialization I/O''': Serialization is used for writing objects into memory buffer and "resurrected" them in the same or another computer environment, enabling simple and common input/output interfaces to be utilized. See `osgDB/Serializer` header for details. |
| | 27 | |
| | 28 | * '''Binary/ascii file format''': A dual binary/ascii format is supported based on different implementations of I/O classes in the `osgDB/StreamOperator` header. These implementations could be found at `osgPlugins/osg` directory. The cross-format compatibility is provided by the object wrappers and their reader/writer classes. |
| | 29 | |
| | 30 | * '''Object wrappers''': Every class in the scene graph should have a corresponding wrapper, in which a series of templated serializers are used to bind reading and writing members. The wrapper should record all necessary setting/getting members of the object class, as well as the I/O order of these properties. See `osgDB/ObjectWrapper` header for details. |
| | 31 | |
| | 32 | * '''Compressors and decompressors''': The compressor is used while the whole scene graph is already recorded, to reduce data size and encrypt the result buffer for variant reasons. A decompressor method should also be provided for decoding. See the `osgDB/ObjectWrapper` header again. And the total output/input managers are declared in `osgDB/OutputStream` and `osgDB/InputStream` headers. |
| | 33 | |
| | 34 | * '''Extendability''': The object wrappers and compressors are always extendable. You may easily write wrappers for user-customized class derived from `osg::Object` base class and load them from applications or dynamic libraries. The wrapper may contain a series of predefined and custom serializers. |
| | 35 | |
| | 36 | * '''Schema Definitions''': The sequence of a class' properties is recorded in its wrapper class. These sequences could be write out as a "schema" list, which indicates the reading/writing orders of all existing classes in current OSG version. The schema may be used to force resort wrappers in another environment. According to the schema, any unrecognizable property name and disrupted orders will be automatically fixed while reading an external file. These will help applications to be backwards and forward compatible. |
| 133 | | A lot of macrodefinitions are used here to provide an easy to read structure. REGISTER_OBJECT_WRAPPER will automatically add the wrapper to a global manager at initial time. And the ADD_*_SERIALIZER statements will bring different serializers for reading/writing class members in sequence of names, which may be output as part of schema file. |
| 134 | | |
| 135 | | Notice that the "osg::" prefix in the inheritance string is important. It indicates the system that osgdb_serializers_osg.so library should be loaded and all its wrappers will be put into use. A different namespace, like osgParticle, will cause a different library to be loaded and made use of. |
| 136 | | |
| 137 | | 2.2 Predefined serializers:: |
| 138 | | |
| 139 | | Obviously, the ADD_BOOL_SERIALIZER(CullingActive) above is sure to call setCullingActive() and getCullingActive() methods of osg::Node class to set/get a boolean property. and ADD_HEXINT_SERIALIZER(NodeMask) similarly calls setNodeMask() and getNodeMask() to operate on an integer one. There are some more predefined serializers to do such repeated work, on the premise that the class methods' naming styles are acceptable. |
| 140 | | |
| 141 | | * ADD_BOOL_SERIALIZER( NAME, DEF ) |
| 142 | | Input/output with __void setNAME(bool)__ and __bool getNAME() const__ methods. DEF is the default value of the proto, which will not be saved into files. |
| 143 | | |
| 144 | | * ADD_SHORT_SERIALIZER( NAME, DEF ) |
| 145 | | Input/output with __void setNAME(short)__ and __short getNAME() const__ methods. |
| 146 | | |
| 147 | | * ADD_USHORT_SERIALIZER( NAME, DEF ) |
| 148 | | Input/output with __void setNAME(unsigned short)__ and __unsigned short getNAME() const__ methods. |
| 149 | | |
| 150 | | * ADD_HEXSHORT_SERIALIZER( NAME, DEF ) |
| 151 | | Same as ADD_USHORT_SERIALIZER, but use hex values instead. |
| 152 | | |
| 153 | | * ADD_USHORT_SERIALIZER( NAME, DEF ) |
| 154 | | Input/output with __void setNAME(unsigned short)__ and __unsigned short getNAME() const__ methods. |
| 155 | | |
| 156 | | * ADD_INT_SERIALIZER( NAME, DEF ) |
| 157 | | Input/output with __void setNAME(int)__ and __int getNAME() const__ methods. |
| 158 | | |
| 159 | | * ADD_UINT_SERIALIZER( NAME, DEF ) |
| 160 | | Input/output with __void setNAME(unsigned int)__ and __unsigned int getNAME() const__ methods. |
| 161 | | |
| 162 | | * ADD_HEXINT_SERIALIZER( NAME, DEF ) |
| 163 | | Same as ADD_UINT_SERIALIZER, but use hex values instead. |
| 164 | | |
| 165 | | * ADD_FLOAT_SERIALIZER( NAME, DEF ) |
| 166 | | Input/output with __void setNAME(float)__ and __float getNAME() const__ methods. |
| 167 | | |
| 168 | | * ADD_DOUBLE_SERIALIZER( NAME, DEF ) |
| 169 | | Input/output with __void setNAME(double)__ and __double getNAME() const__ methods. |
| 170 | | |
| 171 | | * ADD_VEC3F_SERIALIZER( NAME, DEF ) |
| 172 | | Input/output with __void setNAME(const Vec3f&)__ and __const Vec3f& getNAME() const__ methods. |
| 173 | | |
| 174 | | * ADD_VEC3D_SERIALIZER( NAME, DEF ) |
| 175 | | Input/output with __void setNAME(const Vec3d&)__ and __const Vec3d& getNAME() const__ methods. |
| 176 | | |
| 177 | | * ADD_VEC3_SERIALIZER( NAME, DEF ) |
| 178 | | Same as ADD_VEC3F_SERIALIZER. |
| 179 | | |
| 180 | | * ADD_VEC4F_SERIALIZER( NAME, DEF ) |
| 181 | | Input/output with __void setNAME(const Vec4f&)__ and __const Vec4f& getNAME() const__ methods. |
| 182 | | |
| 183 | | * ADD_VEC4D_SERIALIZER( NAME, DEF ) |
| 184 | | Input/output with __void setNAME(const Vec4d&)__ and __const Vec4d& getNAME() const__ methods. |
| 185 | | |
| 186 | | * ADD_VEC4_SERIALIZER( NAME, DEF ) |
| 187 | | Same as ADD_VEC4F_SERIALIZER. |
| 188 | | |
| 189 | | * ADD_QUAT_SERIALIZER( NAME, DEF ) |
| 190 | | Input/output with __void setNAME(const Quat&)__ and __const Quat& getNAME() const__ methods. |
| 191 | | |
| 192 | | * ADD_PLANE_SERIALIZER( NAME, DEF ) |
| 193 | | Input/output with __void setNAME(const Plane&)__ and __const Plane& getNAME() const__ methods. |
| 194 | | |
| 195 | | * ADD_MATRIXF_SERIALIZER( NAME, DEF ) |
| 196 | | Input/output with __void setNAME(const Matrixf&)__ and __const Matrixf& getNAME() const__ methods. |
| 197 | | |
| 198 | | * ADD_MATRIXD_SERIALIZER( NAME, DEF ) |
| 199 | | Input/output with __void setNAME(const Matrixd&)__ and __const Matrixd& getNAME() const__ methods. |
| 200 | | |
| 201 | | * ADD_MATRIX_SERIALIZER( NAME, DEF ) |
| 202 | | Input/output with __void setNAME(const Matrix&)__ and __const Matrix& getNAME() const__ methods. |
| 203 | | |
| 204 | | * ADD_STRING_SERIALIZER( NAME, DEF ) |
| 205 | | Input/output with __void setNAME(const std::string&)__ and __const std::string& getNAME() const__ methods. |
| 206 | | |
| 207 | | * ADD_GLENUM_SERIALIZER( NAME, TYPE, DEF ) |
| 208 | | Input/output with __void setNAME(TYPE)__ and __TYPE getNAME() const__ methods. TYPE here could be GLenum, GLbitfield, GLint and so on, to fit different method parameters. In ascii format, this serializer gets numerical values and saves corresponding OpenGL enumeration names to the buffer, and read it back in the opposite way. For example, it will map GL_NEVER to the string "NEVER", and vice versa. |
| 209 | | |
| 210 | | * ADD_OBJECT_SERIALIZER( NAME, TYPE, DEF ) |
| 211 | | Input/output with __void setNAME(TYPE*)__ and __const TYPE* getNAME() const__ methods. This serializer is used to record another object attached, that is, the wrapper of another object class will be called inside current reading/writing function and cause iteration of functions. |
| 212 | | |
| 213 | | * ADD_IMAGE_SERIALIZER( NAME, TYPE, DEF ) |
| 214 | | Same as ADD_OBJECT_SERIALIZER, but only read osg::Image* and inherited instances. |
| 215 | | |
| 216 | | * ADD_LIST_SERIALIZER( NAME, TYPE ) |
| 217 | | Input/output with __void setNAME(const TYPE&)__ and __const TYPE& getNAME() const__ methods. TYPE should be a std::vector like typename, because the serializer will assume a TYPE::const_iterator internal to traverse all elements. |
| 218 | | |
| 219 | | * BEGIN_ENUM_SERIALIZER( NAME, DEF ) |
| 220 | | Input/output with __void setNAME(NAME)__ and __NAME getNAME() const__ methods. This is used only for enum values, and the enum name and methods' names should strictly obey the naming rules. Another two macros ADD_ENUM_VALUE and END_ENUM_SERIALIZER will be also used to form a complete serializer. For example, in the osg::Object wrapper: |
| | 128 | A lot of macro definitions are used here to provide an easy to read structure. `REGISTER_OBJECT_WRAPPER` will automatically add the wrapper to a global manager at initial time. And the `ADD_*_SERIALIZER` statements will bring different serializers for reading/writing class members in sequence of names, which may be output as part of schema file. |
| | 129 | |
| | 130 | Notice that the "osg::" prefix in the inheritance string is important. It indicates the system that `osgdb_serializers_osg.so` library should be loaded and all its wrappers will be put into use. A different namespace, like `osgParticle`, will cause a different library to be loaded and made use of. |
| | 131 | |
| | 132 | === 2.2 Predefined serializers === |
| | 133 | |
| | 134 | Obviously, the `ADD_BOOL_SERIALIZER(CullingActive)` above is sure to call `setCullingActive()` and `getCullingActive()` methods of `osg::Node` class to set/get a boolean property. and `ADD_HEXINT_SERIALIZER(NodeMask)` similarly calls `setNodeMask()` and `getNodeMask()` to operate on an integer one. There are some more predefined serializers to do such repeated work, on the premise that the class methods' naming styles are acceptable. |
| | 135 | |
| | 136 | || `ADD_BOOL_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(bool)__ and __bool getNAME() const__ methods. DEF is the default value of the proto, which will not be saved into files. || |
| | 137 | || `ADD_SHORT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(short)__ and __short getNAME() const__ methods. || |
| | 138 | || `ADD_USHORT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(unsigned short)__ and __unsigned short getNAME() const__ methods. || |
| | 139 | || `ADD_HEXSHORT_SERIALIZER( NAME, DEF )` || Same as ADD_USHORT_SERIALIZER, but use hex values instead. || |
| | 140 | || `ADD_USHORT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(unsigned short)__ and __unsigned short getNAME() const__ methods. || |
| | 141 | || `ADD_INT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(int)__ and __int getNAME() const__ methods. || |
| | 142 | || `ADD_UINT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(unsigned int)__ and __unsigned int getNAME() const__ methods. || |
| | 143 | || `ADD_HEXINT_SERIALIZER( NAME, DEF )` || Same as ADD_UINT_SERIALIZER, but use hex values instead. || |
| | 144 | || `ADD_FLOAT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(float)__ and __float getNAME() const__ methods. || |
| | 145 | || `ADD_DOUBLE_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(double)__ and __double getNAME() const__ methods. || |
| | 146 | || `ADD_VEC3F_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Vec3f&)__ and __const Vec3f& getNAME() const__ methods. || |
| | 147 | || `ADD_VEC3D_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Vec3d&)__ and __const Vec3d& getNAME() const__ methods. || |
| | 148 | || `ADD_VEC3_SERIALIZER( NAME, DEF )` || Same as ADD_VEC3F_SERIALIZER. || |
| | 149 | || `ADD_VEC4F_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Vec4f&)__ and __const Vec4f& getNAME() const__ methods. || |
| | 150 | || `ADD_VEC4D_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Vec4d&)__ and __const Vec4d& getNAME() const__ methods. || |
| | 151 | || `ADD_VEC4_SERIALIZER( NAME, DEF )` || Same as ADD_VEC4F_SERIALIZER. || |
| | 152 | || `ADD_QUAT_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Quat&)__ and __const Quat& getNAME() const__ methods. || |
| | 153 | || `ADD_PLANE_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Plane&)__ and __const Plane& getNAME() const__ methods. || |
| | 154 | || `ADD_MATRIXF_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Matrixf&)__ and __const Matrixf& getNAME() const__ methods. || |
| | 155 | || `ADD_MATRIXD_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Matrixd&)__ and __const Matrixd& getNAME() const__ methods. || |
| | 156 | || `ADD_MATRIX_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const Matrix&)__ and __const Matrix& getNAME() const__ methods. || |
| | 157 | || `ADD_STRING_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(const std::string&)__ and __const std::string& getNAME() const__ methods. || |
| | 158 | || `ADD_GLENUM_SERIALIZER( NAME, TYPE, DEF )` || Input/output with __void setNAME(TYPE)__ and __TYPE getNAME() const__ methods. TYPE here could be `GLenum`, `GLbitfield`, `GLint` and so on, to fit different method parameters. In ascii format, this serializer gets numerical values and saves corresponding OpenGL enumeration names to the buffer, and read it back in the opposite way. For example, it will map `GL_NEVER` to the string "NEVER", and vice versa. || |
| | 159 | || `ADD_OBJECT_SERIALIZER( NAME, TYPE, DEF )` || Input/output with __void setNAME(TYPE*)__ and __const TYPE* getNAME() const__ methods. This serializer is used to record another object attached, that is, the wrapper of another object class will be called inside current reading/writing function and cause iteration of functions. || |
| | 160 | || `ADD_IMAGE_SERIALIZER( NAME, TYPE, DEF )` || Same as ADD_OBJECT_SERIALIZER, but only read osg::Image* and inherited instances. || |
| | 161 | || `ADD_LIST_SERIALIZER( NAME, TYPE )` || Input/output with __void setNAME(const TYPE&)__ and __const TYPE& getNAME() const__ methods. TYPE should be a `std::vector` like typename, because the serializer will assume a TYPE::const_iterator internal to traverse all elements. || |
| | 162 | || `ADD_USER_SERIALIZER( NAME )` || Add a user-customizied serializer, with at least 3 static user functions for checking, reading and writing properties. See Chapter 2.3 for details. || |
| | 163 | || `BEGIN_ENUM_SERIALIZER( NAME, DEF )` || Input/output with __void setNAME(NAME)__ and __NAME getNAME() const__ methods. This is used only for enum values, and the enum name and methods' names should strictly obey the naming rules. Another two macros `ADD_ENUM_VALUE` and `END_ENUM_SERIALIZER` will be also used to form a complete serializer. || |
| | 164 | |
| | 165 | An example of `BEGIN_ENUM_SERIALIZER` is in the `osg::Object` wrapper: |