网站备案单位的联系方式,建设企业网站的申请,番禺厂家关键词优化,企业如何网络推广主要介绍倾斜摄影数据OSGB二进制数据的解析#xff0c;首先简单介绍一下OpenSceneGraph相关技术#xff0c;并介绍倾斜摄影数据的组织结构#xff0c;着重分析OSGB格式的相关字段#xff0c;最后逐字节对OSGB数据进行解析并通过OpenSceneGraph对数据进行可视化#xff0c;…主要介绍倾斜摄影数据OSGB二进制数据的解析首先简单介绍一下OpenSceneGraph相关技术并介绍倾斜摄影数据的组织结构着重分析OSGB格式的相关字段最后逐字节对OSGB数据进行解析并通过OpenSceneGraph对数据进行可视化并对倾斜摄影数据的可视化进行优化。 文章目录前言一、OpenSceneGraph1. OSGB数据的可视化2. OSGB数据查看3.OSG文档二、倾斜摄影数据1.数据组织结构2.OSGB格式解析3.倾斜摄影数据可视化调度优化4.多线程调试方法总结前言 OpenSceneGraph是一个开源的跨平台的高性能 3D 图形工具包它完全用标准 C 和 OpenGL 编写可以用来进行三维仿真OSG包含的多线程技术PagedLOD技术可以方便的处理大数据的三维模型的可视化及其调度。OSGB格式数据是OpenSceneGraph框架的自有格式是一种二进制数据。倾斜摄影数据是以OSGB格式来组织的树形结构的数据。 一、OpenSceneGraph
1. OSGB数据的可视化
1.1 如下OSGB数据可视化部分结果
2. OSGB数据查看
2.1 可通过OSG自带的数据转换工具osgconv将二进制的osgb数据转换为文本格式osgt、osg等即可直接打开查看osgb数据。某文件转换后的数如下
#Ascii Scene
#Version 161
#Generator OpenSceneGraph 3.6.5
osg::PagedLOD {UniqueID 1 CenterMode USER_DEFINED_CENTER UserCenter 11406.1 -2410.49 14.3884 34.9388 RangeMode PIXEL_SIZE_ON_SCREEN RangeList 2 {0 17.4694 17.4694 1e30 }DatabasePath TRUE E:\\Desktop\\Data\\Tile_154_009/ RangeDataList 2 { Tile_154_009_L15_0.osgb }PriorityList 2 {0 1 0 1 }Children 1 {osg::Geode {UniqueID 2 Drawables 1 {osg::Geometry {UniqueID 3 DataVariance STATIC StateSet TRUE {osg::StateSet {UniqueID 4 DataVariance STATIC AttributeList 1 {osg::Material {UniqueID 5 Ambient TRUE Front 1 1 1 1 Back 1 1 1 1 Diffuse TRUE Front 1 1 1 1 Back 1 1 1 1 Specular TRUE Front 0 0 0 1 Back 0 0 0 1 Emission TRUE Front 0 0 0 1 Back 0 0 0 1 Shininess TRUE Front 0 Back 0 }Value OFF }TextureModeList 1 {Data 1 {GL_TEXTURE_2D ON }}TextureAttributeList 1 {Data 1 {osg::Texture2D {UniqueID 6 DataVariance STATIC WRAP_S CLAMP WRAP_T CLAMP WRAP_R CLAMP MIN_FILTER LINEAR_MIPMAP_LINEAR MAG_FILTER LINEAR UnRefImageDataAfterApply TRUE Swizzle RGBA Image TRUE {ClassName osg::Image UniqueID 7 FileName Tile_154_009_0.jpg WriteHint 2 2 DataVariance STATIC }}Value OFF }}}}PrimitiveSetList 1 {osg::DrawElementsUInt {UniqueID 8 BufferObject TRUE {osg::ElementBufferObject {UniqueID 9 Target 34963 }}Mode TRIANGLES vector 249 {0 1 2 3 4 5 6 7 8 9 10 11 6 12 7 13 14 8 14 7 12 13 8 7 15 16 17 18 14 13 19 20 21 14 18 22 23 24 22 25 26 27 28 29 30 31 23 32 14 22 33 34 25 35 36 37 38 39 27 40 33 22 24 25 27 39 22 32 23 26 39 40 41 28 30 42 43 44 26 25 45 25 34 45 34 46 45 45 47 26 48 49 50 51 52 53 53 52 54 55 56 57 54 58 53 59 60 61 62 59 61 63 62 61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 78 77 79 80 48 50 81 82 83 78 84 85 86 87 88 76 78 85 89 90 91 81 92 82 93 94 48 72 95 96 95 97 96 93 98 94 72 99 70 95 71 100 71 95 72 101 102 95 97 95 102 91 103 104 105 102 106 107 108 109 110 82 92 111 112 113 94 98 114 106 101 97 101 106 102 71 106 97 74 73 115 116 73 88 117 118 119 82 120 83 121 108 107 104 122 91 71 105 106 123 86 88 48 80 93 91 90 103 116 115 73 73 123 88 124 119 118 120 82 125 }}}VertexArray TRUE {osg::Vec3Array {UniqueID 10 BufferObject TRUE {osg::VertexBufferObject {UniqueID 11 }}Binding BIND_PER_VERTEX vector 126 {11421.4 -2430.02 11.1509 11416 -2429.93 12.0398 11416.1 -2428.49 11.9536 11416.1 -2428.49 11.9536 11416.3 -2427.38 9.46918 11417 -2431.32 11.2052 11416 -2429.93 12.0398 11415.2 -2428.63 12.3225 11416.1 -2428.49 11.9536 11417 -2431.32 11.2052 11421.4 -2430.02 11.1509 11416.1 -2428.49 11.9536 11417 -2431.32 11.2052 11417.2 -2428.95 13.4176 11416.3 -2427.38 9.46918 11416.2 -2430.52 7.36804 11416.1 -2430.42 7.60243 11416 -2430.16 6.66749 11421.4 -2430.02 11.1509 11421.4 -2430.02 11.1509 11417.2 -2428.95 13.4176 11416 -2429.93 12.0398 11421.4 -2417.88 10.3103 11414 -2415.94 9.09115 11414.2 -2416 9.00664 11413.7 -2411.71 9.68296 11409.8 -2412.62 9.51062 11414.2 -2416 9.00664 11421.4 -2412.33 10.8725 11414.3 -2415.9 8.9807 11414.2 -2416 9.00664 11409.8 -2412.62 9.51062 11421.4 -2412.33 10.8725 11414.3 -2415.9 8.9807 11421.4 -2412.33 10.8725 11414.3 -2415.9 8.9807 11416.3 -2427.38 9.46918 11414.3 -2415.9 8.9807 11413.7 -2411.71 9.68296 11416.3 -2427.38 9.46918 11414 -2415.94 9.09115 11409.8 -2412.62 9.51062 11421.4 -2411.74 12.2718 11421.4 -2411.62 11.9188 11421.4 -2411.76 12.1873 11406.3 -2403.12 10.7203 11421.4 -2402.07 11.0026 11403 -2403.17 11.9259 11407.7 -2400.76 20.792 11408.6 -2406.5 20.017 11421.4 -2405.4 17.8293 11408.6 -2406.5 20.017 11406.3 -2403.12 10.7203 11421.4 -2405.4 17.8293 11421.4 -2402.07 11.0026 11421.4 -2402.14 14.4776 11421.4 -2402.04 14.7014 11421.4 -2402.31 14.7539 11421.4 -2399.19 11.9584 11407.7 -2400.76 20.792 11403.3 -2399.47 18.0124 11402.6 -2402.11 16.0169 11406.3 -2403.12 10.7203 11403.5 -2401.78 14.2324 11402.6 -2402.11 16.0169 11403 -2403.17 11.9259 11403.5 -2401.78 14.2324 11402.1 -2402.35 10.5813 11402 -2402.4 11.4244 11401.9 -2402.1 11.4328 11406 -2394.56 12.2159 11413.6 -2395.24 12.5957 11407 -2383.55 10.3011 11408.7 -2390.8 17.8375 11406 -2394.56 12.2159 11398.1 -2392.72 13.3419 11406.3 -2403.12 10.7203 11403.5 -2401.78 14.2324 11403.3 -2399.47 18.0124 11403 -2403.17 11.9259 11421.4 -2398.48 17.8706 11403 -2403.17 11.9259 11406 -2394.56 12.2159 11403.3 -2399.47 18.0124 11407.7 -2400.76 20.792 11413.6 -2395.24 12.5957 11421.4 -2399.19 11.9584 11421.4 -2402.07 11.0026 11417.6 -2396.89 10.3681 11421.4 -2402.07 11.0026 11421.4 -2393.37 11.0167 11417.6 -2396.89 10.3681 11406.3 -2403.12 10.7203 11408.7 -2390.8 17.8375 11407.4 -2395.19 18.3994 11419.2 -2393.09 11.0517 11421.4 -2382.84 9.16199 11421.4 -2393.37 11.0167 11398.1 -2392.72 13.3419 11398.1 -2392.72 13.3419 11419 -2393.87 10.3112 11419.8 -2394.49 10.5827 11419.5 -2394.39 10.7514 11419.8 -2394.49 10.5827 11419.2 -2393.09 11.0517 11417.6 -2396.89 10.3681 11419.5 -2394.49 10.9917 11413.6 -2395.24 12.5957 11419.5 -2394.39 10.7514 11419 -2393.87 10.3112 11413.6 -2395.24 12.5957 11419 -2393.87 10.3112 11419.5 -2394.39 10.7514 11417.6 -2396.89 10.3681 11403.3 -2399.47 18.0124 11409.7 -2395.95 16.3532 11413.6 -2395.24 12.5957 11413.6 -2395.24 12.5957 11407.7 -2400.76 20.792 11409.7 -2395.95 16.3532 11407.4 -2395.19 18.3994 11421.4 -2393.37 11.0167 11419 -2393.87 10.3112 11421.4 -2398.48 17.8706 11407.4 -2395.19 18.3994 11409.7 -2395.95 16.3532 }}}TexCoordArrayList 1 {osg::Vec2Array {UniqueID 12 BufferObject TRUE {osg::VertexBufferObject {UniqueID 11 }}Binding BIND_PER_VERTEX vector 126 {0.692426 0.855664 0.703011 0.856104 0.702753 0.861724 0.570732 0.609083 0.568671 0.599278 0.576501 0.605998 0.328366 0.857498 0.331044 0.855646 0.329737 0.852837 0.441758 0.855283 0.450283 0.850095 0.44346 0.866617 0.3252 0.858301 0.327577 0.854413 0.330703 0.845386 0.195902 0.353782 0.195705 0.354209 0.195467 0.355194 0.319499 0.845511 0.208773 0.844122 0.201316 0.85591 0.198636 0.849995 0.332787 0.808157 0.346856 0.815357 0.346555 0.815111 0.0910442 0.827874 0.0927779 0.813587 0.0994225 0.828423 0.0672952 0.362282 0.0812559 0.348427 0.0814619 0.34803 0.357319 0.814601 0.33887 0.79253 0.346497 0.814557 0.0922966 0.857352 0.0992241 0.828762 0.0720457 0.599278 0.0940807 0.599094 0.101988 0.602514 0.121655 0.836511 0.0993046 0.828032 0.0899589 0.361319 0.32333 0.364582 0.323332 0.36502 0.32333 0.36449 0.0742107 0.802832 0.0722694 0.857707 0.074282 0.793042 0.0856387 0.56386 0.0873095 0.541454 0.112424 0.545566 0.32318 0.610118 0.324436 0.572843 0.342956 0.603723 0.347425 0.576504 0.448395 0.355193 0.448395 0.355587 0.448393 0.354527 0.351276 0.579699 0.205769 0.602609 0.196975 0.591479 0.197885 0.580644 0.205193 0.561936 0.199157 0.574931 0.819516 0.855274 0.818829 0.838799 0.821246 0.848312 0.566881 0.354655 0.56682 0.35447 0.566539 0.355615 0.2075 0.556892 0.222176 0.554122 0.209448 0.599878 0.222347 0.863516 0.228093 0.838681 0.243193 0.848836 0.211664 0.318576 0.216188 0.334426 0.215268 0.351605 0.217788 0.324245 0.112475 0.572588 0.321275 0.324245 0.331548 0.338728 0.323795 0.351605 0.207751 0.356878 0.193749 0.335213 0.198898 0.820795 0.199349 0.809863 0.205922 0.824395 0.210728 0.866942 0.195963 0.854278 0.205604 0.848005 0.327399 0.318576 0.0876976 0.602792 0.0850185 0.585631 0.23329 0.56245 0.237614 0.60247 0.237531 0.561327 0.0670734 0.59545 0.192073 0.5642 0.2328 0.559397 0.234342 0.556989 0.233846 0.557384 0.199434 0.850614 0.197591 0.84838 0.230092 0.547641 0.233775 0.556984 0.333479 0.856571 0.321888 0.85038 0.322974 0.849073 0.345314 0.335213 0.824279 0.612617 0.823928 0.615871 0.817834 0.61363 0.0771236 0.568969 0.221239 0.844325 0.213566 0.835886 0.453171 0.810441 0.459564 0.852859 0.451968 0.83147 0.333637 0.358427 0.318287 0.852249 0.199158 0.846992 0.198804 0.837991 0.449074 0.842425 0.337638 0.348894 }}}}}}}
}
3.OSG文档
http://dei.isep.ipp.pt/~matos/cadeiras/cgra/OpenSceneGraphReferenceDocs/index.html 二、倾斜摄影数据
1.数据组织结构
1.1 如图数据的组织结构如下Data目录为数据入口目录目录下包含很多子目录如下每个子目录为一个根块每个根块是一个树形结构是一个LOD层级结构。 1.2 每个根块下面对应很多.osgb 文件子目录下与目录名同名的osgb文件为根文件如下
2.OSGB格式解析 2.1 OSGB二进制数据包含很多字段包含OpenSceneGraph框架的非关键字段主要用于OpenSceneGraph框架中还包含关键字段主要是是一个三维模型的顶点坐标法线坐标和纹理数据以及LOD信息。OSGB数据中包含很多不同的块(有多个字段组成)这些块在OSGB里面存在嵌套关系OSGB并不像一般的非嵌套关系数据因此OSGB数据格式显得比较复杂。
下面的数据读取过程是按照读取的顺序结构组织将其组合在一起即可读取整个OSGB格式数据。
2.2 读取OSGB文件头信息 是OSGB的头信息低位和高位分别为4个字节每一个是16Bit的MD5码。 unsigned int headerLow 0, headerHigh 0;fin.read((char*)headerLow, INT_SIZE);fin.read((char*)headerHigh, INT_SIZE);2.3 读取后面的块需要采用栈来辅助读取每个块。
读取文件类型: READ_UNKNOWN0READ_SCENE1READ_IMAGE2READ_OBJECT3,代表OSGB支持的类型可以认为倾斜摄影osgb格式总是1;读取文件版本号读取属性: 判断文件中是否使用_useSchemaData和是否支持_SupportBinaryBrackets全0时表示都不支持根据属性信息设置OSGB一些参数后面会根据参数的设置进行信息的读取 //栈读取时压入start_fields.push_back(Start);//读取文件类型_in-read((char*)i, osgDB::INT_SIZE); //unsigned int//读取文件版本号_in-read((char*)i, osgDB::INT_SIZE); //unsignde int//读取属性值_in-read((char*)attributes, osgDB::INT_SIZE); //unsignde int//根据属性值设置参数if (attributes 0x4) _SupportBinaryBrackets true;if (attributes 0x2) _useSchemaData true;//根据属性值读取信息if (attributes 0x1){_in-read((char*)number, osgDB::INT_SIZE); //unsignde int//根据number值循环读取后面的值forunsigned int i 0;inumber;i{//读取string_in-read((char*)size, osgDB::INT_SIZE); //int,读取string长度_in-read((char*)s.c_str(), size); //char数组//读取int_in-read((char*)i, osgDB::INT_SIZE); //int,读取string长度map[s] i; //采用集合存储他们的信息,主要是一些版本信息}}//字段出栈_fields.pop_back();2.4 读取压缩器的名称 //读取压缩器名称一般为0表示压缩格式也表示压缩器名称也可以采用zib压缩_in-read((char*)size, osgDB::INT_SIZE); //int,读取string长度_in-read((char*)compressorName .c_str(), size); //char数组//根据压缩器名称进行相应的读取,我在这篇文章中主要讨论compressorName 0的情况对于zlib的情况简单介绍下if (compressorName ! 0){//需要读取的数据datastd::string data;//入栈_fields.push_back(Decompression);BaseCompressor* compressor Registry::instance()-getObjectWrapperManager()-findCompressor(compressorName);if (!compressor){throwException(InputStream: Failed to decompress stream, No such compressor.);return;}//相关读取情况主要在decompress函数里面if (!compressor-decompress(*(_in-getStream()), data))throwException(InputStream: Failed to decompress stream.);if (getException()) return;_dataDecompress new std::stringstream(data);_in-setStream(_dataDecompress);//出栈_fields.pop_back();}2.5 根据_useSchemaData参数读取相应信息 if(_useSchemaData){//字段入栈_fields.push_back(SchemaData);//读取string_in-read((char*)size, osgDB::INT_SIZE); //int,读取string长度_in-read((char*)s.c_str(), size); //char数组//s字符串信息解析通过s构造一个std::istringstream对象//出栈_fields.pop_back();}2.6 后面就存在嵌套关系需要根据当前读取的string的值读取对应字段的信息每个字段里面包含有自己的读取方式。建以将每个字段元素组织成一个函数。 //读取string_in-read((char*)size, osgDB::INT_SIZE); //int_in-read((char*)s.c_str(), size); //char数组//BEGIN_BRACKET操作根据位置和大小用于移动读取位置if(_supportBinaryBrackets){//当前位置入栈_beginPositions.push_back(_in-tellg());if_in Version 148{_in-read((char*)size, osgDB::INT64_SIZE); //unsigned long long,8字节//size入栈_blockSizes.push_back(size);}else{_in-read((char*)size, osgDB::INT_SIZE); //int//size入栈_blockSizes.push_back(size);}}//PROPERTY操作_in-read((char*)value, osgDB::INT_SIZE); //int//读取ID_in-read((char*)id, osgDB::INT_SIZE); //unsigned int/*说明std::map unsigned int, osg::ref_ptrosg::Object IdentifierMap;IdentifierMap用来存储ID和ID对应的对象(块)*///判断ID对应的块是否存在IdentifierMap::iterator it _identifierMap.find(id);if(it ! _identifierMap.end()){//返回块return it-second;}//根据string className和id读取对应字段的信息osg::ref_ptrosg::Object obj readObjectFields(className, id, existingObj);
2.7 根据string className的值选择读取对应的字段。
读取osg::Object字段 //读取string_in-read((char*)size, osgDB::INT_SIZE); //int_in-read((char*)s.c_str(), size);_in-read((char*)i, osgDB::INT_SIZE); //int_in-read(c, osgDB::CHAR_SIZE); //boolosg::Node字段 //bool,一般读取一个char根据char设置bool值_in-read(c, osgDB::CHAR_SIZE); //bool_in-read(c, osgDB::CHAR_SIZE); //bool_in-read(c, osgDB::CHAR_SIZE); //bool_in-read(c, osgDB::CHAR_SIZE); //bool_in-read(c, osgDB::CHAR_SIZE); //bool_in-read(c, osgDB::CHAR_SIZE); //bool_in-read((char*)i, osgDB::INT_SIZE); //unsignde int_in-read(c, osgDB::CHAR_SIZE); //bool//注意根据前面bool的值如果为true还需要紧接着读取相关信息osg::LOD字段 _in-read((char*)i, osgDB::INT_SIZE); //int//bool值为false则return true_in-read(c, osgDB::CHAR_SIZE); //bool//读取中心点和半径_in-read((char*)d, osgDB::DOUBLE_SIZE); //double_in-read((char*)d, osgDB::DOUBLE_SIZE); //double_in-read((char*)d, osgDB::DOUBLE_SIZE); //double_in-read((char*)d, osgDB::DOUBLE_SIZE); //double_in-read((char*)i, osgDB::INT_SIZE); //int//RangList信息读取_in-read(c, osgDB::CHAR_SIZE); //bool,false则return true_in-read((char*)size, osgDB::INT_SIZE); //unsignde int//BEGIN_BRACKET操作,此处省略见上文...//根据size大小循环读取forint i 0isize;i){_in-read((char*)min, osgDB::FLOAT_SIZE); //float_in-read((char*)max, osgDB::FLOAT_SIZE); //float//osg::LOD node node.setRange(i,min,max);}//END_BRACKET 操作if (_supportBinaryBrackets){//栈非空就出栈_beginPositions.pop_back();_blockSizes.pop_back();}osg::PagedLOD子字段 _in-read(c, osgDB::CHAR_SIZE); //bool,false return true_in-read(havePath, osgDB::CHAR_SIZE); //bool//havePath为true还需读取string_in-read((char*)size, osgDB::INT_SIZE); //int_in-read((char*)s.c_str(), size); //stringosg::PagedLOD组合字段 读取osg::PagedLOD需要读取四个字段。 osg::Objectosg::Nodeosg::LODosg::PagedLOD子字段 osg::Geode组合字段 osg::Objectosg::Nodeosg::Geode子字段 osg::Geometry组合字段 osg::Objectosg::Drawableosg::Geometry osg::stateSet osg::Objectosg::stateSet osg::Material osg::Objectosg::stateAttributeosg::material osg::Texture2D osg::Objectosg::stateAttributeosg::Textureosg::Texture2D osg::Object osg::Object osg::Group osg::Objectosg::Nodeosg::Group osg::DrawElementsUint osg::Objectosg::PrimitiveSetosg::DrawElementsUint osg::Vec3Array osg::Objectosg::Arrayosg::Vec3Array osg::Vec2Array osg::Objectosg::Arrayosg::Vec2Array osg::Node osg::Objectosg::Node osg::MatrixTransform osg::Objectosg::Nodeosg::Grouposg::Transformosg::MatrixTransform osg::TexMat osg::Objectosg::StateAttributeosg::TexMat osg::DefaultUserData组合字段 osg::Objectosg::UserDataContainerosg::DefaultUserDataContainer osg::DrawElementsUshort组合字段 osg::Objectosg::PrimitiveSetosg::DrawElementsUshort
2.8 完整源码解读 可以通过源码关键部分代码可以分析OSGB格式的组成。注释部分为源码摘录部分用于辅助分析当前源码。
二进制文件OSGB写类定义
class BinaryOutputIterator : public osgDB::OutputIterator
{
public:BinaryOutputIterator(std::ostream* ostream) { _out ostream; }virtual ~BinaryOutputIterator() {}virtual bool isBinary() const { return true; }virtual void writeBool(bool b){char c b ? 1 : 0; _out-write(c, osgDB::CHAR_SIZE);}virtual void writeChar(char c){_out-write(c, osgDB::CHAR_SIZE);}virtual void writeUChar(unsigned char c){_out-write((char*)c, osgDB::CHAR_SIZE);}virtual void writeShort(short s){_out-write((char*)s, osgDB::SHORT_SIZE);}virtual void writeUShort(unsigned short s){_out-write((char*)s, osgDB::SHORT_SIZE);}virtual void writeInt(int i){_out-write((char*)i, osgDB::INT_SIZE);}virtual void writeUInt(unsigned int i){_out-write((char*)i, osgDB::INT_SIZE);}virtual void writeLong(long l){// On 64-bit systems a long may not be the same size as the file valueint32_t value (int32_t)l;_out-write((char*)value, osgDB::LONG_SIZE);}virtual void writeULong(unsigned long l){// On 64-bit systems a long may not be the same size as the file valueuint32_t value (int32_t)l;_out-write((char*)value, osgDB::LONG_SIZE);}virtual void writeInt64(int64_t ll){_out-write((char*)ll, osgDB::INT64_SIZE);}virtual void writeUInt64(uint64_t ull){_out-write((char*)ull, osgDB::INT64_SIZE);}virtual void writeInt(long long ll){_out-write((char*)ll, osgDB::INT64_SIZE);}virtual void writeUInt(unsigned long long ull){_out-write((char*)ull, osgDB::INT64_SIZE);}virtual void writeFloat(float f){_out-write((char*)f, osgDB::FLOAT_SIZE);}virtual void writeDouble(double d){_out-write((char*)d, osgDB::DOUBLE_SIZE);}virtual void writeString(const std::string s){int size s.size();_out-write((char*)size, osgDB::INT_SIZE);_out-write(s.c_str(), s.size());}virtual void writeStream(std::ostream (* /*fn*/)(std::ostream)) {}virtual void writeBase(std::ios_base (* /*fn*/)(std::ios_base)) {}virtual void writeGLenum(const osgDB::ObjectGLenum value){GLenum e value.get(); _out-write((char*)e, osgDB::GLENUM_SIZE);}virtual void writeProperty(const osgDB::ObjectProperty prop){if (prop._mapProperty) _out-write((char*)(prop._value), osgDB::INT_SIZE);}virtual void writeMark(const osgDB::ObjectMark mark){if (_supportBinaryBrackets){if (getOutputStream() getOutputStream()-getFileVersion() 148){if (mark._name {){uint64_t size 0;_beginPositions.push_back(_out-tellp());_out-write((char*)size, osgDB::INT64_SIZE);}else if (mark._name } _beginPositions.size() 0){std::streampos pos _out-tellp(), beginPos _beginPositions.back();_beginPositions.pop_back();_out-seekp(beginPos);std::streampos size64 pos - beginPos;uint64_t size (uint64_t)size64;_out-write((char*)size, osgDB::INT64_SIZE);_out-seekp(pos);}}else{if (mark._name {){int size 0;_beginPositions.push_back(_out-tellp());_out-write((char*)size, osgDB::INT_SIZE);}else if (mark._name } _beginPositions.size() 0){std::streampos pos _out-tellp(), beginPos _beginPositions.back();_beginPositions.pop_back();_out-seekp(beginPos);std::streampos size64 pos - beginPos;int size (int)size64;_out-write((char*)size, osgDB::INT_SIZE);_out-seekp(pos);}}}}virtual void writeCharArray(const char* s, unsigned int size){if (size 0) _out-write(s, size);}virtual void writeWrappedString(const std::string str){writeString(str);}
protected:std::vectorstd::streampos _beginPositions;
};二进制文件OSGB读类定义
inline void swapBytes( char* in, unsigned int size )
{char* start in;char* end startsize-1;while (startend){std::swap(*start,*end--);}
}class BinaryInputIterator : public osgDB::InputIterator
{
public:BinaryInputIterator(std::istream* istream, int byteSwap){_in istream;setByteSwap(byteSwap);}virtual ~BinaryInputIterator() {}virtual bool isBinary() const { return true; }virtual void readBool(bool b){char c 0;_in-read(c, osgDB::CHAR_SIZE);b (c ! 0);}virtual void readChar(char c){_in-read(c, osgDB::CHAR_SIZE);}virtual void readSChar(signed char c){_in-read((char*)c, osgDB::CHAR_SIZE);}virtual void readUChar(unsigned char c){_in-read((char*)c, osgDB::CHAR_SIZE);}virtual void readShort(short s){_in-read((char*)s, osgDB::SHORT_SIZE);if (_byteSwap) osg::swapBytes((char*)s, osgDB::SHORT_SIZE);}virtual void readUShort(unsigned short s){_in-read((char*)s, osgDB::SHORT_SIZE);if (_byteSwap) osg::swapBytes((char*)s, osgDB::SHORT_SIZE);}virtual void readInt(int i){_in-read((char*)i, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)i, osgDB::INT_SIZE);}virtual void readUInt(unsigned int i){_in-read((char*)i, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)i, osgDB::INT_SIZE);}virtual void readLong(long l){// On 64-bit systems a long may not be the same size as the file valueint32_t value;_in-read((char*)value, osgDB::LONG_SIZE);if (_byteSwap) osg::swapBytes((char*)value, osgDB::LONG_SIZE);l (long)value;}virtual void readULong(unsigned long l){uint32_t value;_in-read((char*)value, osgDB::LONG_SIZE);if (_byteSwap) osg::swapBytes((char*)value, osgDB::LONG_SIZE);l (unsigned long)value;}virtual void readFloat(float f){_in-read((char*)f, osgDB::FLOAT_SIZE);if (_byteSwap) osg::swapBytes((char*)f, osgDB::FLOAT_SIZE);}virtual void readDouble(double d){_in-read((char*)d, osgDB::DOUBLE_SIZE);if (_byteSwap) osg::swapBytes((char*)d, osgDB::DOUBLE_SIZE);}virtual void readString(std::string s){int size 0;readInt(size);if (size 0){s.resize(size);_in-read((char*)s.c_str(), size);}else if (size 0){throwException(InputStream::readString() error, negative string size read.);}}virtual void readStream(std::istream (* /*fn*/)(std::istream)) {}virtual void readBase(std::ios_base (* /*fn*/)(std::ios_base)) {}virtual void readGLenum(osgDB::ObjectGLenum value){GLenum e 0;_in-read((char*)e, osgDB::GLENUM_SIZE);if (_byteSwap) osg::swapBytes((char*)e, osgDB::GLENUM_SIZE);value.set(e);}virtual void readProperty(osgDB::ObjectProperty prop){int value 0;if (prop._mapProperty){_in-read((char*)value, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)value, osgDB::INT_SIZE);}prop.set(value);}virtual void readMark(osgDB::ObjectMark mark){if (_supportBinaryBrackets){if (mark._name {){_beginPositions.push_back(_in-tellg());// since version 149 (osg version 3.5.6) size is expressed // on 8 bytes rather than 4 bytes, // to accommodate any block size.if (getInputStream() getInputStream()-getFileVersion() 148){uint64_t size 0;_in-read((char*)size, osgDB::INT64_SIZE);if (_byteSwap) osg::swapBytes((char*)size, osgDB::INT64_SIZE);_blockSizes.push_back(size);}else{int size 0;_in-read((char*)size, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)size, osgDB::INT_SIZE);_blockSizes.push_back(size);}}else if (mark._name } _beginPositions.size() 0){_beginPositions.pop_back();_blockSizes.pop_back();}}}virtual void readCharArray(char* s, unsigned int size){if (size 0) _in-read(s, size);}virtual void readWrappedString(std::string str){readString(str);}virtual void advanceToCurrentEndBracket(){if (_supportBinaryBrackets _beginPositions.size() 0){std::streampos position(_beginPositions.back());position _blockSizes.back();_in-seekg(position);_beginPositions.pop_back();_blockSizes.pop_back();}}
protected:std::vectorstd::streampos _beginPositions;std::vectorstd::streampos _blockSizes;
};读取头文件通过倾斜摄影后缀名加载对应的读取插件
InputIterator* readInputIterator(std::istream fin, const Options* options)
{bool extensionIsAscii false, extensionIsXML false;if (options){const std::string optionString options-getPluginStringData(fileType);if (optionString Ascii) extensionIsAscii true;else if (optionString XML) extensionIsXML true;}if (!extensionIsAscii !extensionIsXML){unsigned int headerLow 0, headerHigh 0;fin.read((char*)headerLow, INT_SIZE);fin.read((char*)headerHigh, INT_SIZE);// OSG Header (MD5, 16Bit),摘录部分定义了头信息的MD5 码//#define OSG_HEADER_LOW 0x6C910EA1//#define OSG_HEADER_HIGH 0x1AFB4545if (headerLow OSG_HEADER_LOW headerHigh OSG_HEADER_HIGH){OSG_INFO Reading OpenSceneGraph binary file with the same endian as this computer. std::endl;return new BinaryInputIterator(fin, 0); // endian the same so no byte swap required}//#define OSG_REVERSE(value) ( ((value 0x000000ff)24) | ((value 0x0000ff00)8) | ((value 0x00ff0000)8) | ((value 0xff000000)24) ),摘录部分用于辅助分析源码else if (headerLow OSG_REVERSE(OSG_HEADER_LOW) headerHigh OSG_REVERSE(OSG_HEADER_HIGH)){OSG_INFO Reading OpenSceneGraph binary file with the different endian to this computer, doing byte swap. std::endl;return new BinaryInputIterator(fin, 1); // endian different so byte swap required}fin.seekg(0, std::ios::beg);}if (!extensionIsXML){std::string header; fin header;if (header #Ascii){return new AsciiInputIterator(fin);}fin.seekg(0, std::ios::beg);}if (1){std::string header; std::getline(fin, header);if (!header.compare(0, 5, ?xml)){return new XmlInputIterator(fin);}fin.seekg(0, std::ios::beg);}return NULL;
}读取属性信息
InputStream::ReadType InputStream::start(InputIterator* inIterator)
{_fields.clear();_fields.push_back(Start);ReadType type READ_UNKNOWN;_in inIterator;if (!_in)throwException(InputStream: Null stream specified.);if (getException()) return type;_in-setInputStream(this);// Check OSG header informationunsigned int version 0;if (isBinary()){unsigned int typeValue;*this typeValue version;type static_castReadType(typeValue);unsigned int attributes; *this attributes;if (attributes 0x4) inIterator-setSupportBinaryBrackets(true);if (attributes 0x2) _useSchemaData true;// Record custom domainsif (attributes 0x1){unsigned int numDomains; *this numDomains;for (unsigned int i 0; i numDomains; i){std::string domainName; *this domainName;int domainVersion; *this domainVersion;_domainVersionMap[domainName] domainVersion;}}}if (!isBinary()){std::string typeString; *this typeString;if (typeString Scene) type READ_SCENE;else if (typeString Image) type READ_IMAGE;else if (typeString Object) type READ_OBJECT;std::string osgName, osgVersion;*this PROPERTY(#Version) version;*this PROPERTY(#Generator) osgName osgVersion;while (matchString(#CustomDomain)){std::string domainName; *this domainName;int domainVersion; *this domainVersion;_domainVersionMap[domainName] domainVersion;}}// Record file version for back-compatibility checking of wrappers_fileVersion version;_fields.pop_back();return type;
}读取压缩器 一般压缩器名字都为0
void InputStream::decompress()
{if (!isBinary()) return;_fields.clear();std::string compressorName; *this compressorName;if (compressorName ! 0){//当压缩器为zlib或其他非0压缩器时将调用对应压缩器的decompress函数std::string data;_fields.push_back(Decompression);//通过包装管理器查找对象包装器读取对象的信息BaseCompressor* compressor Registry::instance()-getObjectWrapperManager()-findCompressor(compressorName);if (!compressor){throwException(InputStream: Failed to decompress stream, No such compressor.);return;}if (!compressor-decompress(*(_in-getStream()), data))throwException(InputStream: Failed to decompress stream.);if (getException()) return;_dataDecompress new std::stringstream(data);_in-setStream(_dataDecompress);_fields.pop_back();}if (_useSchemaData){_fields.push_back(SchemaData);std::string schemaSource; *this schemaSource;std::istringstream iss(schemaSource);readSchema(iss);_fields.pop_back();}
}null、zlib压缩器的decompress函数定义如下
class NullCompressor : public BaseCompressor
{
public:NullCompressor() {}virtual bool compress( std::ostream fout, const std::string src ){int size src.size();fout.write( (char*)size, INT_SIZE );fout.write( src.c_str(), src.size() );return true;}virtual bool decompress( std::istream fin, std::string target ){int size 0; fin.read( (char*)size, INT_SIZE );if ( size ){target.resize( size );fin.read( (char*)target.c_str(), size );}return true;}
};
REGISTER_COMPRESSOR( null, NullCompressor )
#ifdef USE_ZLIB
#include zlib.h
#define CHUNK 32768
// ZLib compressor
class ZLibCompressor : public BaseCompressor
{
public:ZLibCompressor() {}virtual bool compress( std::ostream fout, const std::string src ){int ret, flush Z_FINISH;unsigned have;z_stream strm;unsigned char out[CHUNK];int level 6;int stategy Z_DEFAULT_STRATEGY;/* allocate deflate state */strm.zalloc Z_NULL;strm.zfree Z_NULL;strm.opaque Z_NULL;ret deflateInit2( strm, level, Z_DEFLATED, 1516, // 16 to use gzip encoding8, // defaultstategy );if ( ret ! Z_OK ) return false;strm.avail_in src.size();strm.next_in (Bytef*)( (*src.begin()) );/* run deflate() on input until output buffer not full, finishcompression if all of source has been read in */do{strm.avail_out CHUNK;strm.next_out out;ret deflate(strm, flush); /* no bad return value */if ( ret Z_STREAM_ERROR ){OSG_NOTICE Z_STREAM_ERROR std::endl;return false;}have CHUNK - strm.avail_out;if ( have0 ) fout.write( (const char*)out, have );if ( fout.fail() ){(void)deflateEnd( strm );return false;}} while ( strm.avail_out0 );/* clean up and return */(void)deflateEnd( strm );return true;}virtual bool decompress( std::istream fin, std::string target ){int ret;unsigned have;z_stream strm;unsigned char in[CHUNK];unsigned char out[CHUNK];/* allocate inflate state */strm.zalloc Z_NULL;strm.zfree Z_NULL;strm.opaque Z_NULL;strm.avail_in 0;strm.next_in Z_NULL;ret inflateInit2( strm,15 32 ); // autodected zlib or gzip headerif ( ret!Z_OK ){OSG_INFO failed to init std::endl;return ret!0;}/* decompress until deflate stream ends or end of file */do{fin.read( (char *)in, CHUNK );strm.avail_in fin.gcount();if (strm.avail_in0 ) break;/* run inflate() on input until output buffer not full */strm.next_in in;do{strm.avail_out CHUNK;strm.next_out out;ret inflate( strm, Z_NO_FLUSH );switch (ret){case Z_NEED_DICT:case Z_DATA_ERROR:case Z_MEM_ERROR:(void)inflateEnd( strm );return false;}have CHUNK - strm.avail_out;target.append( (char*)out, have );} while ( strm.avail_out0 );/* done when inflate() says its done */} while ( ret!Z_STREAM_END );/* clean up and return */(void)inflateEnd( strm );return retZ_STREAM_END ? true : false;}
};
REGISTER_COMPRESSOR( zlib, ZLibCompressor )
#endif读取每个对象 根据每个组合对象的名称读取其子对象。
osg::ref_ptrosg::Object InputStream::readObject(osg::Object* existingObj)
{std::string className;unsigned int id 0;*this className;if (className NULL){return 0;}*this BEGIN_BRACKET PROPERTY(UniqueID) id;if (getException()) return 0;//每个对象对应一个id和名字根据id可以判断该id是否已经存在IdentifierMap::iterator itr _identifierMap.find(id);if (itr ! _identifierMap.end()){advanceToCurrentEndBracket();return itr-second;}std::cout className className std::endl;osg::ref_ptrosg::Object obj readObjectFields(className, id, existingObj);advanceToCurrentEndBracket();return obj;
}BEGIN_BRACKET 和END_BRACKET 操作 BEGIN_BRACKET 、END_BRACKET 为ObjectMark类对象不同的对象设置了不同的初始值。 类定义 class ObjectMark{public:ObjectMark() : _indentDelta(0) {}ObjectMark(const ObjectMark copy): _name(copy._name), _indentDelta(copy._indentDelta) {}void set(const char* name, int delta 0){_name name; _indentDelta delta;}std::string _name;int _indentDelta;};BEGIN_BRACKET 操作 BEGIN_BRACKET 是ObjectMark对象设定了对象的初始值{ virtual void readMark(osgDB::ObjectMark mark){if (_supportBinaryBrackets){if (mark._name {){_beginPositions.push_back(_in-tellg());// since version 149 (osg version 3.5.6) size is expressed // on 8 bytes rather than 4 bytes, // to accommodate any block size.if (getInputStream() getInputStream()-getFileVersion() 148){uint64_t size 0;_in-read((char*)size, osgDB::INT64_SIZE);if (_byteSwap) osg::swapBytes((char*)size, osgDB::INT64_SIZE);_blockSizes.push_back(size);}else{int size 0;_in-read((char*)size, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)size, osgDB::INT_SIZE);_blockSizes.push_back(size);}}else if (mark._name } _beginPositions.size() 0){_beginPositions.pop_back();_blockSizes.pop_back();}}}PROPERTY操作 类定义 class ObjectProperty{public:ObjectProperty() : _value(0), _mapProperty(false) {}ObjectProperty(const char* name, int value 0, bool useMap false): _name(name), _value(value), _mapProperty(useMap) {}ObjectProperty(const ObjectProperty copy): _name(copy._name), _value(copy._value), _mapProperty(copy._mapProperty) {}ObjectProperty operator()(const char* name){_name name; return *this;}void set(int v) { _value v; }int get() const { return _value; }std::string _name;int _value;bool _mapProperty;};读取操作 virtual void readProperty(osgDB::ObjectProperty prop){int value 0;if (prop._mapProperty){_in-read((char*)value, osgDB::INT_SIZE);if (_byteSwap) osg::swapBytes((char*)value, osgDB::INT_SIZE);}prop.set(value);}子字段读取 代码中getObjectWrapperManager()-findWrapper(className)通过查找对象的包装器每种包装器中封装了其子字段通过getAssociates()获取到包装器的子字段然后逐一读取。
osg::ref_ptrosg::Object InputStream::readObjectFields(const std::string className, unsigned int id, osg::Object* existingObj)
{ObjectWrapper* wrapper Registry::instance()-getObjectWrapperManager()-findWrapper(className);if (!wrapper){OSG_WARN InputStream::readObject(): Unsupported wrapper class className std::endl;return NULL;}int inputVersion getFileVersion(wrapper-getDomain());osg::ref_ptrosg::Object obj existingObj ? existingObj : wrapper-createInstance();_identifierMap[id] obj;if (obj.valid()){const ObjectWrapper::RevisionAssociateList associates wrapper-getAssociates();for (ObjectWrapper::RevisionAssociateList::const_iterator itr associates.begin(); itr ! associates.end(); itr){if (itr-_firstVersion inputVersion inputVersion itr-_lastVersion){ObjectWrapper* assocWrapper Registry::instance()-getObjectWrapperManager()-findWrapper(itr-_name);if (!assocWrapper){OSG_WARN InputStream::readObject(): Unsupported associated class itr-_name std::endl;continue;}_fields.push_back(assocWrapper-getName());std::cout _fileds add : assocWrapper-getName() std::endl;assocWrapper-read(*this, *obj);if (getException()) return NULL;_fields.pop_back();}else{/* OSG_INFO InputStream::readObject():className Ignoring associated class due to version mismatch itr-_name[itr-_firstVersion ,itr-_lastVersion ]for version inputVersion std::endl;*/}}}return obj;
}查找包装器函数如下
ObjectWrapper* ObjectWrapperManager::findWrapper( const std::string name )
{OpenThreads::ScopedLockOpenThreads::ReentrantMutex lock(_wrapperMutex);WrapperMap::iterator itr _wrappers.find( name );if ( itr!_wrappers.end() ) return itr-second.get();// Load external librariesstd::string::size_type posDoubleColon name.rfind(::);if ( posDoubleColon!std::string::npos ){std::string libName std::string( name, 0, posDoubleColon );ObjectWrapper* found0;std::string nodeKitLib osgDB::Registry::instance()-createLibraryNameForNodeKit(libName);if ( osgDB::Registry::instance()-loadLibrary(nodeKitLib)osgDB::Registry::LOADED )found findWrapper(name);std::string pluginLib osgDB::Registry::instance()-createLibraryNameForExtension(std::string(serializers_)libName);if ( osgDB::Registry::instance()-loadLibrary(pluginLib)osgDB::Registry::LOADED )found findWrapper(name);pluginLib osgDB::Registry::instance()-createLibraryNameForExtension(libName);if ( osgDB::Registry::instance()-loadLibrary(pluginLib)osgDB::Registry::LOADED )found findWrapper(name);if (found) found-setupAssociatesRevisionsInheritanceIfRequired();return found;}return NULL;
}包装器子字段读取函数如下通过对应的序列化函数读取相应的信息序列化函数负责读取信息
bool ObjectWrapper::read( InputStream is, osg::Object obj )
{bool readOK true;int inputVersion is.getFileVersion(_domain);for ( SerializerList::iterator itr_serializers.begin(); itr!_serializers.end(); itr ){BaseSerializer* serializer itr-get();if ( serializer-_firstVersion inputVersion inputVersion serializer-_lastVersion serializer-supportsReadWrite()){if ( !serializer-read(is, obj) ){OSG_WARN ObjectWrapper::read(): Error reading property _name :: (*itr)-getName() std::endl;readOK false;}}else{// OSG_NOTICEIgnoring serializer due to version mismatchstd::endl;}}for ( FinishedObjectReadCallbackList::iterator itr_finishedObjectReadCallbacks.begin();itr!_finishedObjectReadCallbacks.end();itr ){(*itr)-objectRead(is, obj);}return readOK;
}2.8 序列化机制
每种对象对应一个序列化机制下面通过PagedLOD介绍其序列化机制。
#include osg/PagedLOD
#include osgDB/ObjectWrapper
#include osgDB/InputStream
#include osgDB/OutputStream
#include osgDB/Options
// _databasePath
static bool checkDatabasePath( const osg::PagedLOD node )
{return true;
}
static bool readDatabasePath( osgDB::InputStream is, osg::PagedLOD node )
{bool hasPath; is hasPath;if ( !hasPath ){if ( is.getOptions() !is.getOptions()-getDatabasePathList().empty() ){const std::string optionPath is.getOptions()-getDatabasePathList().front();if ( !optionPath.empty() ) node.setDatabasePath( optionPath );}}else{std::string path; is.readWrappedString( path );node.setDatabasePath( path );}return true;
}
static bool writeDatabasePath( osgDB::OutputStream os, const osg::PagedLOD node )
{os (!node.getDatabasePath().empty());if ( !node.getDatabasePath().empty() )os.writeWrappedString( node.getDatabasePath() );os std::endl;return true;
}
// _perRangeDataList
static bool checkRangeDataList( const osg::PagedLOD node )
{return node.getNumFileNames()0;
}
static bool readRangeDataList( osgDB::InputStream is, osg::PagedLOD node )
{unsigned int size 0; is size is.BEGIN_BRACKET;for ( unsigned int i0; isize; i ){std::string name; is.readWrappedString( name );node.setFileName( i, name );}is is.END_BRACKET;size 0; is is.PROPERTY(PriorityList) size is.BEGIN_BRACKET;for ( unsigned int i0; isize; i ){float offset, scale;is offset scale;node.setPriorityOffset( i, offset );node.setPriorityScale( i, scale );}is is.END_BRACKET;return true;
}
static bool writeRangeDataList( osgDB::OutputStream os, const osg::PagedLOD node )
{unsigned int size node.getNumFileNames();os size os.BEGIN_BRACKET std::endl;for ( unsigned int i0; isize; i ){os.writeWrappedString( node.getFileName(i) );os std::endl;}os os.END_BRACKET std::endl;size node.getNumPriorityOffsets();os os.PROPERTY(PriorityList) size os.BEGIN_BRACKET std::endl;for ( unsigned int i0; isize; i ){os node.getPriorityOffset(i) node.getPriorityScale(i) std::endl;}os os.END_BRACKET std::endl;return true;
}
// _children
static bool checkChildren( const osg::PagedLOD node )
{return node.getNumChildren()0;
}
static bool readChildren( osgDB::InputStream is, osg::PagedLOD node )
{unsigned int size 0; is size;if (size 0){is is.BEGIN_BRACKET;for ( unsigned int i0; isize; i ){osg::ref_ptrosg::Node child is.readObjectOfTypeosg::Node();if ( child ) node.addChild( child );}is is.END_BRACKET;}return true;
}
static bool writeChildren( osgDB::OutputStream os, const osg::PagedLOD node )
{unsigned int sizenode.getNumFileNames(), dynamicLoadedSize0;for ( unsigned int i0; isize; i ){if ( !node.getFileName(i).empty() )dynamicLoadedSize;}unsigned int realSize size-dynamicLoadedSize; os realSize;if ( realSize0 ){os os.BEGIN_BRACKET std::endl;for ( unsigned int i0; isize; i ){if ( !node.getFileName(i).empty() ) continue;if ( inode.getNumChildren() )os node.getChild(i);}os os.END_BRACKET;}os std::endl;return true;
}
//封装对应的子字段名称
REGISTER_OBJECT_WRAPPER( PagedLOD,new osg::PagedLOD,osg::PagedLOD,osg::Object osg::Node osg::LOD osg::PagedLOD )
{// Note: osg::Group is not in the list to prevent recording dynamic loaded childrenADD_USER_SERIALIZER( DatabasePath ); // _databasePathADD_UINT_SERIALIZER( FrameNumberOfLastTraversal, 0 ); // _frameNumberOfLastTraversal, note, not required, removed from soversion 70 onwwards, see belowADD_UINT_SERIALIZER( NumChildrenThatCannotBeExpired, 0 ); // _numChildrenThatCannotBeExpiredADD_BOOL_SERIALIZER( DisableExternalChildrenPaging, false ); // _disableExternalChildrenPagingADD_USER_SERIALIZER( RangeDataList ); // _perRangeDataListADD_USER_SERIALIZER( Children ); // _children (which are not loaded from external){UPDATE_TO_VERSION_SCOPED( 70 )REMOVE_SERIALIZER( FrameNumberOfLastTraversal );}
}至此对osgb格式有了基本的了解但需要能解析其数据还需要分析其他对象的序列化机制因为涉及到迭代版本的兼容等问题因此可以直接将OSG源码中的读写源码抽出来作为项目的一部分就能很好的解决版本兼容问题。
3.倾斜摄影数据可视化调度优化
3.1 加载单个osgb文件并显示 osg::Group* root new osg::Group;//读取文件osg::ref_ptrosg::Node n osgDB::readNodeFile(E:/Desktop/Data/Tile_157_009/Tile_157_009.osgb);root-addChild(n);osg::ref_ptrosgViewer::Viewer viewer new osgViewer::Viewer;viewer-setSceneData(root);viewer-setUpViewInWindow(20, 20, 1400, 700);//相应常见的键盘按键功能viewer-addEventHandler(new osgGA::StateSetManipulator(viewer-getCamera()-getOrCreateStateSet()));viewer-addEventHandler(new osgViewer::WindowSizeHandler);viewer-addEventHandler(new osgViewer::StatsHandler);viewer-realize();return viewer-run();响应常用键盘按键需要将需选择美式键盘才能响应。
s显示模型统计信息包括帧率模型顶点数据等w显示模型三角网格f窗口放大缩小b模型遮挡(背面)剔除l光照控制
3.2 对于倾斜摄影大数据集可视化 需要对数据进行预处理主要采用
多根节点的合并可以进行多次(多级)合并最终合并为一个根节点控制合并节点的大小;LOD的生成可以采用多种策略包括模型简化模型重建等
4.多线程调试方法
4.1 多线程程序调试的时候会出现多个子线程交替切换会在同一个断点处中断程序因此调试程序变得复杂不容易调试程序问题。可以有两种方法来进行调试
采用单线程来调试程序指定特定子进程对其进行调试可以通过编写特定的子进程中断语句(在相关语句出添加断点)或者通过断点定位到特定子进程当定位到特定子进程然后取消断点就可以逐语句调试子进程 总结
OSG开源框架相关技术的学习主要学习OSGB倾斜摄影数据的解析以及可视化及其调度。