OSGB格式解析

主要介绍倾斜摄影数据OSGB二进制数据的解析,首先简单介绍一下OpenSceneGraph相关技术,并介绍倾斜摄影数据的组织结构,着重分析OSGB格式的相关字段,最后逐字节对OSGB数据进行解析并通过OpenSceneGraph对数据进行可视化,并对倾斜摄影数据的可视化进行优化。


前言

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 1e+30 
  }
  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_UNKNOWN=0,READ_SCENE=1,READ_IMAGE=2,READ_OBJECT=3,代表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;i<number;++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")
	{
		//需要读取的数据data
		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;
		}
		//相关读取情况主要在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_ptr<osg::Object> > IdentifierMap;
	IdentifierMap用来存储ID和ID对应的对象(块)
	*/
	//判断ID对应的块是否存在
	IdentifierMap::iterator it = _identifierMap.find(id);
	if(it != _identifierMap.end())
	{
		
		//返回块
		return it->second;
	}

	//根据string className和id读取对应字段的信息
	osg::ref_ptr<osg::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);							//bool
  • osg::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 = 0;i<size;++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);							//string
  • osg::PagedLOD组合字段
    读取osg::PagedLOD需要读取四个字段。

    • osg::Object
    • osg::Node
    • osg::LOD
    • osg::PagedLOD子字段
  • osg::Geode组合字段

    • osg::Object
    • osg::Node
    • osg::Geode子字段
  • osg::Geometry组合字段

    • osg::Object
    • osg::Drawable
    • osg::Geometry
  • osg::stateSet

    • osg::Object
    • osg::stateSet
  • osg::Material

    • osg::Object
    • osg::stateAttribute
    • osg::material
  • osg::Texture2D

    • osg::Object
    • osg::stateAttribute
    • osg::Texture
    • osg::Texture2D
  • osg::Object

    • osg::Object
  • osg::Group

    • osg::Object
    • osg::Node
    • osg::Group
  • osg::DrawElementsUint

    • osg::Object
    • osg::PrimitiveSet
    • osg::DrawElementsUint
  • osg::Vec3Array

    • osg::Object
    • osg::Array
    • osg::Vec3Array
  • osg::Vec2Array

    • osg::Object
    • osg::Array
    • osg::Vec2Array
  • osg::Node

    • osg::Object
    • osg::Node
  • osg::MatrixTransform

    • osg::Object
    • osg::Node
    • osg::Group
    • osg::Transform
    • osg::MatrixTransform
  • osg::TexMat

    • osg::Object
    • osg::StateAttribute
    • osg::TexMat
  • osg::DefaultUserData组合字段

    • osg::Object
    • osg::UserDataContainer
    • osg::DefaultUserDataContainer
  • osg::DrawElementsUshort组合字段

    • osg::Object
    • osg::PrimitiveSet
    • osg::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 value
		int32_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 value
		uint32_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::vector<std::streampos> _beginPositions;
};
  • 二进制文件OSGB读类定义
inline void swapBytes( char* in, unsigned int size )
{
    char* start = in;
    char* end = start+size-1;
    while (start<end)
    {
        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 value
		int32_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::vector<std::streampos> _beginPositions;
	std::vector<std::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 0x1AFB4545
		if (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 information
	unsigned int version = 0;
	if (isBinary())
	{
		unsigned int typeValue;
		*this >> typeValue >> version;
		type = static_cast<ReadType>(typeValue);
		unsigned int attributes; *this >> attributes;
		if (attributes & 0x4) inIterator->setSupportBinaryBrackets(true);
		if (attributes & 0x2) _useSchemaData = true;
		// Record custom domains
		if (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, 15+16, // +16 to use gzip encoding
                           8, // default
                           stategy );
        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, finish
           compression 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 ( have>0 ) fout.write( (const char*)out, have );
            if ( fout.fail() )
            {
                (void)deflateEnd( &strm );
                return false;
            }
        } while ( strm.avail_out==0 );
        /* 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 header
        if ( 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_in==0 ) 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_out==0 );
            /* done when inflate() says it's done */
        } while ( ret!=Z_STREAM_END );
        /* clean up and return */
        (void)inflateEnd( &strm );
        return ret==Z_STREAM_END ? true : false;
    }
};
REGISTER_COMPRESSOR( "zlib", ZLibCompressor )
#endif
  • 读取每个对象
    根据每个组合对象的名称,读取其子对象。
osg::ref_ptr<osg::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_ptr<osg::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_ptr<osg::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_ptr<osg::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::ScopedLock<OpenThreads::ReentrantMutex> lock(_wrapperMutex);
    WrapperMap::iterator itr = _wrappers.find( name );
    if ( itr!=_wrappers.end() ) return itr->second.get();
    // Load external libraries
    std::string::size_type posDoubleColon = name.rfind("::");
    if ( posDoubleColon!=std::string::npos )
    {
        std::string libName = std::string( name, 0, posDoubleColon );
        ObjectWrapper* found=0;
        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_NOTICE<<"Ignoring serializer due to version mismatch"<<std::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 i=0; i<size; ++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 i=0; i<size; ++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 i=0; i<size; ++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 i=0; i<size; ++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 i=0; i<size; ++i )
        {
            osg::ref_ptr<osg::Node> child = is.readObjectOfType<osg::Node>();
            if ( child ) node.addChild( child );
        }
        is >> is.END_BRACKET;
    }
    return true;
}
static bool writeChildren( osgDB::OutputStream& os, const osg::PagedLOD& node )
{
    unsigned int size=node.getNumFileNames(), dynamicLoadedSize=0;
    for ( unsigned int i=0; i<size; ++i )
    {
        if ( !node.getFileName(i).empty() )
            dynamicLoadedSize++;
    }
    unsigned int realSize = size-dynamicLoadedSize; os << realSize;
    if ( realSize>0 )
    {
        os << os.BEGIN_BRACKET << std::endl;
        for ( unsigned int i=0; i<size; ++i )
        {
            if ( !node.getFileName(i).empty() ) continue;
            if ( i<node.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 children
    ADD_USER_SERIALIZER( DatabasePath );  // _databasePath
    ADD_UINT_SERIALIZER( FrameNumberOfLastTraversal, 0 );  // _frameNumberOfLastTraversal, note, not required, removed from soversion 70 onwwards, see below
    ADD_UINT_SERIALIZER( NumChildrenThatCannotBeExpired, 0 );  // _numChildrenThatCannotBeExpired
    ADD_BOOL_SERIALIZER( DisableExternalChildrenPaging, false );  // _disableExternalChildrenPaging
    ADD_USER_SERIALIZER( RangeDataList );  // _perRangeDataList
    ADD_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_ptr<osg::Node> n = osgDB::readNodeFile("E:/Desktop/Data/Tile_+157_+009/Tile_+157_+009.osgb");
	root->addChild(n);
	osg::ref_ptr<osgViewer::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倾斜摄影数据的解析,以及可视化及其调度。

  • 28
    点赞
  • 124
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
### 回答1: OSGB格式是一种英国国家坐标系(Ordnance Survey Great Britain)的地理数据格式,主要用于描述英国领土范围内的地理信息。DAE格式则是一种开放的三维图形文件格式,常用于存储三维模型和场景。 OSGB格式转换器DAE是指将OSGB格式的地理数据转换为DAE格式的三维模型的工具或软件。通过OSGB格式转换器,可以将OSGB格式的地理信息数据转换为DAE格式的三维模型,让其在相关软件或平台上进行显示、编辑、分析等操作。 OSGB格式数据转换为DAE格式的过程主要包括以下几个步骤: 1. 读取OSGB格式数据:使用OSGB格式转换器,打开或导入OSGB格式的地理数据文件。 2. 解析OSGB数据:解析OSGB格式数据结构,提取其中的地理数据信息,例如地形、建筑物、道路等。 3. 构建三维模型:将解析得到的OSGB数据转换为三维模型的数据结构,并按照DAE格式的要求,构建DAE格式的三维模型。 4. 导出DAE格式文件:将构建好的DAE格式的三维模型数据导出为DAE格式的文件,以便在其他支持DAE格式的软件或平台上使用。 通过OSGB格式转换器DAE,可以实现OSGB格式地理数据向DAE格式三维模型的转换,方便进行三维可视化、虚拟仿真等领域的应用。这样,用户可以更方便地使用和展示OSGB格式的地理数据,将其应用于相关领域的研究、分析和决策等工作中。 ### 回答2: OSGB格式是英国标准建模的一种地理空间数据格式,常用于地理信息系统(GIS)的导入和导出。DAE格式则是一种开放的3D建模格式,常用于三维模型的存储和交换。 想要将OSGB格式转换为DAE格式,可以借助专门的格式转换工具。这些工具能够读取OSGB格式的数据,并将其转换为DAE格式的数据。在转换过程中,工具会将OSGB格式的数据转换为DAE格式所需的结构和属性,并保留原始数据中的几何形状、纹理贴图等信息。 实际操作时,可通过以下步骤进行OSGB格式到DAE格式的转换:首先,打开OSGB格式转换器软件,加载待转换的OSGB格式文件。然后选择输出格式为DAE,并设置相关转换选项,比如选择转换坐标系、解析度等。最后,点击转换按钮开始转换,等待转换过程完成。 转换完成后,可以得到一个DAE格式的文件,该文件已经包含了原始OSGB格式文件中的几何形状和纹理贴图等信息。这样,我们就可以在支持DAE格式的三维建模软件中打开该文件,并对其进行进一步的编辑和操作,比如旋转、缩放、添加动画等。 总之,OSGB格式转换器DAE是一种能够将OSGB格式数据转换为DAE格式数据的工具,可以帮助我们实现不同格式之间的数据转换和共享。 ### 回答3: OSGB格式是一种地理信息数据格式,主要用于存储和交换地理空间数据。而DAE是一种3D场景描述文件格式,常用于存储和交换三维模型数据。 由于OSGB格式和DAE格式所表示的数据结构和特性不同,所以我们需要一个OSGB格式转换器来将OSGB格式的地理空间数据转换为DAE格式的三维模型数据。 OSGB格式转换器DAE是一种可以将OSGB格式文件转换为DAE格式文件的工具或软件。它可以读取OSGB格式文件中的地理空间数据,并将其转换为DAE格式所支持的三维模型数据,包括模型的几何形状、纹理、材质等信息。 在使用OSGB格式转换器DAE时,我们需要先加载OSGB格式文件,并设定转换的参数和目标DAE文件的保存路径。然后,转换器会根据设定的参数将OSGB格式文件中的地理空间数据转换为DAE格式的三维模型数据,并保存为一个新的DAE文件。 通过OSGB格式转换器DAE,我们可以轻松地将OSGB格式的地理空间数据转换为DAE格式的三维模型数据,从而实现地理信息数据和三维模型数据的互相转换和集成。这对于需要在三维可视化环境中分析和展示地理信息数据的应用场景来说,是非常有用和方便的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秘境之眼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值