liyihongcug 发表于 2020-3-9 17:28:54

osgearth如何加载倾斜摄影测量数据

本帖最后由 liyihongcug 于 2020-4-1 09:53 编辑

osgearth2.8 load 倾斜摄影测量数据 开发思路如下:
首先c++解析metadata.xml获得
<SRS>ENU:34.2196,108.9594</SRS>
<SRSOrigin>0,0,0</SRSOrigin>
这个很重要。这个是整个group的定位的基准点。
之后遍历文件夹,这里截取第一个文件夹做简要分析
Tile_+000_+000 文件下有3个文件
Tile_+000_+000.osgb               -143.628 -197.907 438.413
Tile_+000_+000_L16_0.osgb    -143.633 -197.363 438.183
Tile_+000_+000_L17_00.osgb-143.426 -197.965 438.297
从后缀简要分析就知道做了LOD 3级别,从上到下包含关系。
因为每个osdb里面已经有了偏移,所以下面真简单了。我们只需要加载放到放到一个geode 里就可以。
有一些osg osgearth基础大体能看懂上面讲的意思,一般倾斜摄影文件较多,所以肯定要用到多线程来处理数据。
考虑Qt比较流行直接QThread使用这个就可以。大体结束编写操作。

具体实现细节可以这样来实现经过测试成功哦。 前提必须对osg类库了解 而且osgearth地理信息有熟悉
不见得要用其他第三方插件或商品,自己琢磨有时会有意想不到收获       
测试osgearth的方法
GeoTransform* transform = new GeoTransform();
比osg的方法ew osg::PositionAttitudeTransform 要慢8秒左右。无多线程。
性能优化 必须区别sg::MatrixTransform和osg::PositionAttitudeTransform异同

choa 发表于 2020-4-9 18:40:52

liyihongcug 发表于 2020-4-1 10:32
去除某一个模型中的重复区域,比如压平之类的。这样另一个模型叠加上去时就只显示另一个模型的样子了。   ...

前辈,那您是如何实现的呢?

liyihongcug 发表于 2020-3-9 21:13:25

.osg文件内容:

Group {
name "root"
nodeMask 0xffffffff
cullingActive TRUE
num_children 3
Group {
    UniqueID Group_0
    name "grp1"
    nodeMask 0xffffffff
    cullingActive TRUE
    num_children 2
    Geode {
      UniqueID Geode_1
      name "geode1"
      nodeMask 0xffffffff
      cullingActive TRUE
      num_drawables 1
      Geometry {
      useDisplayList TRUE
      useVertexBufferObjects FALSE
      PrimitiveSets 1
      {
          DrawArrays LINE_STRIP 0 3
      }
      VertexArray Vec3Array 3
      {
          0 1 0
          0 0 0
          1 1 0
      }
      }
    }
    Geode {
      UniqueID Geode_2
      name "geode2"
      nodeMask 0xffffffff
      cullingActive TRUE
      num_drawables 1
      Geometry {
      useDisplayList TRUE
      useVertexBufferObjects FALSE
      PrimitiveSets 1
      {
          DrawArrays LINE_STRIP 0 3
      }
      VertexArray Vec3Array 3
      {
          1 0 0
          2 1 0
          2 0 0
      }
      }
    }
}
Group {
    UniqueID Group_3
    name "grp2"
    nodeMask 0xffffffff
    cullingActive TRUE
    num_children 1
    Use Geode_2
}
Use Geode_2
}
-----------------------------------------------------------------------------------------

osg程序代码:

#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Point>
#include <osg/LineWidth>
#include <osgDB/WriteFile>

// 根据一组点集生成一个Geode对象
osg::ref_ptr< osg::Geode > createProfileGeode( int size, osg::Vec3 *points )
{
osg::ref_ptr< osg::Geode > geode = new osg::Geode();
osg::ref_ptr< osg::Geometry > pointsGeom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array( size, points);
pointsGeom->setVertexArray(vertices);

pointsGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP,0,vertices->size()));
geode->addDrawable(pointsGeom);

return geode.release();
}
int main( int argc, char** argv )
{
osg::Vec3 myCoords1[]=
{
osg::Vec3(0,1,0),
osg::Vec3(0,0,0),
osg::Vec3(1,1,0)
};
osg::Vec3 myCoords2[]=
{
osg::Vec3(1,0,0),
osg::Vec3(2,1,0),
osg::Vec3(2,0,0)
};


osg::ref_ptr< osg::Geode > geode1 = createProfileGeode( sizeof(myCoords1)/sizeof(myCoords1), myCoords1 );
osg::ref_ptr< osg::Geode > geode2 = createProfileGeode( sizeof(myCoords2)/sizeof(myCoords2), myCoords2 );
geode1->setName("geode1");
geode2->setName("geode2");

osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Group> grp1 = new osg::Group;
osg::ref_ptr<osg::Group> grp2 = new osg::Group;
root->setName("root");
grp1->setName("grp1");
grp2->setName("grp2");

grp1->addChild(geode1);
grp1->addChild(geode2);//geode2的第一个父节点
grp2->addChild(geode2);//geode2的第二个父节点

root->addChild( grp1 );
root->addChild( grp2 );
root->addChild(geode2);//geode2的第三个父节点

osgDB::writeNodeFile( *root, "test.osg" );

osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
return viewer.run();
}



OSG第二代文件序列化存储分析



我们以将节点写入文件为例,节点读取与此相同,看看究竟是如何将节点写入文件的,我们从文件读写插件的最顶层入口函数来看,即
virtual WriteResult writeNode( const osg::Node& node, const std::string& fileName, const Options* options ) const
因为osg第二代文件格式读写插件同时支持文本、二进制以及XML格式的文件,所以,在写文件前要确定具体要写入什么文件,读写不同的文件格式需要用到的序列化器不同,文件打开方式也不同,
进入writeNode后会调用Options* prepareWriting( WriteResult& result, const std::string& fileName, std::ios::penmode& mode, const Options* options ) const
该函数就完成上面的工作,该函数根据文件扩展名判断如果是osgt格式,就向options中添加文本格式的参数选项,如果是osgx格式,就添加XML格式选项,以让后续的写入操作根据该选项进行相应文件格式的读写,否则以二进制格式读写;
做好以上准备工作后,就像以前一样将文件数据读入文件流开始向文件流写入数据,即进入virtual WriteResult writeNode( const osg::Node& node, std::stream& fout, const Options* options ) const
针对文本、XML、二进制格式的文件分别对应三种不同的输出指示器,在OutputStream类中进行数据写入时要调用相应的输出指示器,所以,首先要获取相应类型的输出指示器;该工作通过函数OutputIterator* writeOutputIterator( std::stream& fout, const Options* options )来完成,该函数从options中查找是否有文本或者XML的文件格式选项(从刚才的分析我们已经知道,如果是osgt或osgx格式的话,在prepareWriting中已经添加进来),如果有对应的选项,就创建相应的输出指示器,如果两种都没有,就创建二进制格式的输出指示器,除文本格式之外,对于XML格式和二进制格式,该函数除了创建相应的输出指示器外,同时还像文件流写入了文件头信息,对于XML格式,直接写入XML文件头,对于二进制格式,写入MD5码;从上面的分析我们不难看出,对于文本和XML格式的文件,我们简单的添加supportsExtension来让插件支持我们自己的扩展名文件类型是做不到的,插件会把它当做二进制来对待,无法正确处理,所以,扩展名得扩展只适用于二进制格式;
得到输出指示器后构造一个OutputStream对象开始写数据。
首先是调用void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType type ),将输出指示器传给OutputStream并向文件流写入文件的标志信息,如文件内容类型标示(如场景、对象、图像)、版本号等信息,接下来调用void OutputStream::writeObject( const osg::Object* obj )从节点对象读取节点数据。下面进入该函数,首先获取一个对象唯一ID,然后向流中写入对象类名(如osg::Group),然后写入开始大括号’{’,接下来写入对象的数据,写入对象数据后写入结束大括号’}’;上面的写入操作都是通过刚才传入的输出指示器来完成;
      下面我们将如何写入对象数据来分解开进行分析,这是写入操作的核心所在。该过程在void OutputStream::writeObjectFields( const osg::Object* obj )中完成,我们现在就来看看writeObjectFields都玩了哪些花样;一定要看仔细,正是它玩的花样,才使得我们可以在不修改该文件操作插件的情况下通过扩展的方式让自己的节点对象也可以读写的,所以一定要看仔细了;
首先要根据类名获取该类的wrapper(所有要能够将数据写入文件的类都要对应有一个该类的包装类wrapper,所有的wrapper统一由wrapper管理器来管理,每添加一个wrapper类型,自己要将自己注册到该管理器,否则无法对该类型的对象进行读写操作),如果要让自己的对象能够进行文件读写,需要扩展自己的类的wrapper类,在wrapper类中定义要读写哪些数据字段;
类是有继承关系的,那么在进行读写操作时,还是需要各个类自己操作自己本身的成员,一个子类只负责自己扩展出来的成员字段的读写操作,父类的那些成员又父类的wrapper去处理,各司其职。而系统本身是没有办法知道一个子类上面都有哪些父类、祖父类等关联类信息的,所以需要我们告诉它,该工作通过在构造wrapper时指定,将该子类关联的所有上层类名称传进去,即associates参数,在每个wrapper类中有一个associates的数组。
继续上面的分析过程,在writeObjectFields中获取到要写入文件的节点对象(根据类名获得,所以,自己派生的对象要能像osg对象那样能够用这种方式进行读写操作,必须从osg::Object派生,且必须实现ClassName接口)对应的wrapper后,遍历该wrapper的关联类数组,然后再根据关联类获取对应的wrapper进行数据写入工作。在继续该写入过程详细分析之前,需要补充说明一下,注册wrapper时向该wrapper传入的管理类信息包含了该类本身,所以,这里的写入操作统一在遍历关联类数组过程中进行,所以,在注册wrapper时,一定要在最后将类自身也添加到关联类信息里,否则只能读写上层类的数据,本类本身的信息会丢失。
接下来的分析就相对要集中了,就是针对具体的类类型进行数据的写入操作了。如果需要向文件中写入每个类的字段刚要信息,就将每个类的属性字段名称及类型以刚要的形式写入,然后再写该类的数据信息,默认情况下不写入;那么我们接着看写对象的数据字段的内容。该过程由bool ObjectWrapper::write( OutputStream& os, const osg::Object& obj )完成,下面我们来进到里面探个究竟。
在分析之前我们需要插入一段前奏,然后才能继续下面的过程。通过上面的分析,我们知道怎么让插件能够读写每种类对象了(通过扩展wrapper并注册),也知道了怎么区别对待不同类型的文件(Txt、XML、Binary,通过不同的指示器),还有一个重要的问题没有提到,那就是如何知道要读写一个类的哪些数据成员,以及如何调用数据获取接口。在注册wrapper时,除了给wrapper设置其对应的类名、类对象原型、关联类描述之外,还要设置通过何种序列化器对哪些字段进行读写操作。我们通过代码不难看到ADD_USER_SERIALIZER、ADD_OBJECT_SERIALIZER、ADD_DOUBLE_SERIALIZER等等身影,通过这些宏就设定好了要读写该wrapper对应的类的数据字段。一个对象有多少属性字段,就会对应多少序列化器,每个序列化器负责该属性字段的具体的读写操作,wrapper对象会将所有加入的序列化器保存在一个数组中。此外,对于不同的字段数据类型,对应有相应类型的序列化器,如int、double、osg::Vec3d以及对象类型等等,操作相应类型的属性字段要选择正确的序列化器。
通过上面的分析,我们应该知道了如何设定类的哪些属性数据可进行文件存储,接下来我们来看看是如何调用相关的属性访问接口来进行数据存取的。方法用的就是函数指针,在添加序列化器时,相应的序列化器会根据传入的属性字段名称自动创建对应的属性访问函数指针(getter、setter)或字段读写函数指针(reader、writer)并将其传递给序列化器的构造函数(函数指针作为函数参数传递,这些函数都不会有重载函数,基本都是getXXX、setXXX,大可放心使用),然后序列化器会记录下来这些函数指针,在序列化器进行数据字段的读写时调用该函数指针来进行数据字段的读写操作;
好了,前奏到此为止,不要忘了我们还没有进入bool ObjectWrapper::write( OutputStream& os, const osg::Object& obj )呢。现在我们来看这个函数就很简单了,它也就是遍历该wrapper对象的所有序列化器,调用序列化器的write函数将每个属性字段写进去。对于UserSerializer是传递属性字段读写函数指针,对于其他类型的序列化器,传递的是属性字段的访问函数指针,两者最终都是通过OutputStream的”<<”重载操作符将字段值写入到流中,进一步我们可以看到OutputStream的”<<”重载操作符函数最终通过调用最开始时传入OutputStream的输出指示器的类型写入函数来完成最终的写入操作;针对不同类型的格式控制(txt、XML、Binary)都是在相应的输出指示器中完成。
现在我们知道,通过该插件,我们要让该插件支持我们自己扩展的对象类型,只要创建相应的wrapper并注册进来就OK,非常方便。另外一方面,可能在开发自己的应用系统时,需要定义自己的文件格式,这时,如果是二进制的格式的话,直接通过supportsExtension添加自己的扩展名支持即可,在应用系统中通过addFileExtensionAlias来指定一下。此外还有一个重要的扩展可能对我们开发自己的系统更为重要,那就是文件数据的加密存储,简单起见我们可以重写插件的writeOutputIterator和readOutputIterator,在文件头中加入自己的加密数据,如base64/md5加密数据,并做相应的检测处理,通过派生新的compressor我们就可以实现对文件内容的压缩和解压缩,或者加密和解密,或者加入自己的头信息等等,都非常方便;







转一个别人细读cow.osg的



对,就是那只著名的奶牛。

//Group节点,可有子节点。
Group {

UniqueID Group_0         //Gourp名称
DataVariance STATIC   //不知道用来干嘛,一般都是static
cullingActive TRUE      //参与culling?
num_children 1               //子节点数

Geode {   //子节点是Geode节点(Geode节点是叶节点,它不会再有子节点,可以与任意多个Drawable的对象关联)

    DataVariance DYNAMIC
    name "cow.osg"            //Geode名称,应该是模型路径吧
    cullingActive TRUE       //参与culling
    num_drawables 1         //可绘制元素Drawable对象的数目,1

    Geometry {   //Drawable :Gemetry,是可绘制对象类型之一。用指定顶点数据,绘制几何体。

      DataVariance DYNAMIC

      StateSet {   //渲染状态。分为渲染属性和渲染模式两部分。是个状态值,直到子节点重新设置前,它的值一直沿节点树向下有效。
      DataVariance STATIC
      rendering_hint OPAQUE_BIN    //和渲染有关的
      renderBinMode INHERIT            //和渲染有关的
      GL_CULL_FACE OFF               //和裁剪有关的
      GL_LIGHTING ON                     //和裁剪有关的

      Material {   //材质
          DataVariance STATIC
          ColorMode OFF                  //光的啥啥
          ambientColor 0.5 0.5 0.5 1   //环境光
          diffuseColor 1 1 1 1               //漫反射
          specularColor 1 1 1 1             //镜面反射
          emissionColor 0 0 0 1            //自发光
          shininess 1                              //????????
         } ////材质结束

      textureUnit 0 { //纹理单元,1,可以多个。序数依次。

          GL_TEXTURE_GEN_S ON   //啥啥啥???
          GL_TEXTURE_GEN_T ON   //啥啥啥???
          GL_TEXTURE_2D ON         //啥啥啥???

          Texture2D {    //2D的贴图
            DataVariance STATIC
            file "Images/reflect.rgb" //贴图文件
            wrap_s REPEAT             //repeat嘛,很容易懂
            wrap_t REPEAT
            wrap_r REPEAT
            min_filter NEAREST_MIPMAP_LINEAR //什么filter
            mag_filter LINEAR                                        //另一个filter
            internalFormatMode USE_IMAGE_DATA_FORMAT //??
            subloadMode OFF                                                               //??
          }////Texture结束

          TexGen {   //贴图坐标?
            DataVariance STATIC
            mode SPHERE_MAP   //啥啥球面?——"环境反射贴图,选球面就可以了"?
          }////贴图坐标结束

      }////纹理单元1结束

      }////Geometry的stateset结束

      useDisplayList TRUE    //显示模型的列表????

      Primitives 1   //貌似是Gemotry的图元信息
      {
      DrawArrayLengths TRIANGLE_STRIP 0 984    //画几何面?985个?
      {
          3
          // 略一堆面?的数值。。。3是指3边形么?@v@
      }
      } ////primitives完

      VertexArray 7772   //顶点坐标
      {
      // 略一堆表示顶点的数值。
      0.701499 2.00244e-05 0.71267
      0.501693 4.00296e-05 0.865046
      0.465203 0.372921 0.802818
      }

      NormalBinding PER_VERTEX   //法向量绑定方式,每个顶点
      NormalArray 7772                        //法向量数组
      {
      0.254622 -0.918791 -0.301648
      0.440603 -0.85537 -0.272417
      0.244499 -0.920072 -0.306084
      }

      ColorBinding OVERALL      //Geometry的颜色绑定,啥意思我也不知。

      ColorArray Vec4Array 1   //颜色的值
      {
      0.8 0.8 0.8 1
      }

      TexCoordArray 0 Vec2Array 7772 //应该是修饰顶点的啥东西=.=
      {
      0 0
      // 略一堆。。。。。。数值。
      }

    }////Geometry完

}////Geode完

}////Group完











1   总结一下

一个根节点Group,名字叫Group0,它的属性和参数包括:
UniqueID
DataVariance
cullingActive
num_children
1个Geode

Geode,名字叫"cow.osg",它的属性参数包括

   DataVariance
    name "cow.osg"
    cullingActive
    num_drawables
    1个Geometry

这1个Geometry的属性参数包括

      DataVariance
      StateSet
      useDisplayList
      Primitives
      VertexArray
      NormalBinding
      NormalArray
      ColorBinding
      ColorArray
      TexCoordArray

其中StateSet又有

      DataVariance STATIC
      rendering_hint
      renderBinMode
      GL_CULL_FACE
      GL_LIGHTING
      Material
         1个textureUnit

Material和textureUnit又有各自的blablabla.....

liyihongcug 发表于 2020-3-11 08:43:28

本帖最后由 liyihongcug 于 2020-3-11 09:34 编辑

osg文件格式主要遵循以下几个准则:

对象类型、属性类型、属性值之间使用空格键和回车键进行分割;
父子节点,以及页节点与可绘制体之间的层次关系有大括号来区分;
渲染状态集,顶点数组,图元祖等包含了多种类型的属性值,使用大括号包含多个属性;一些全局属性可能在大括号之外表达;
属性值可以为布尔值、数字或者字符串等;如果属性字符串中包含空格,则使用双引号进行包含;
类型和值必须以一一对应;
OSG文件中保存的节点和属性名称与实际类名称相同,属性关键字则通常与成员中set*()/get*()系列名称相似;


站心直角(N,E,U) .这里意思是以这个点指用户所在位置点P为坐标原点,三个坐标轴分别指向相互垂直的东向、北向和天向,因而站心坐标系又称东北天(ENU)坐标系。站心坐标系的三个分量比地心地固坐标系的X、Y和Z三个分量更具有物理意义。

        站心坐标系的一个重要应用在于计算卫星在用户处的观测矢量和仰角。
center radius
#include <sstream>
#include <osg/Image>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/Shape>
#include <osg/ShapeDrawable>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/fstream>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <iostream>

using namespace osg;
using namespace osgDB;


class FSReaderWriter :public ReaderWriter
{
public:
        FSReaderWriter()
        {
                supportsExtension("fs", "FreeSouth's format");
        }
        virtual const char* className() const
        {
                return "FSReaderWriter";
        }
        virtual ReadResult readNode(const std::string& file, const Options* opt) const
        {
                std::string ext = osgDB::getLowerCaseFileExtension(file);
                if (!acceptsExtension(ext))
                        return ReadResult::FILE_NOT_HANDLED;
                std::string fileName = osgDB::findDataFile(file, opt);
                if (fileName.empty())
                        return ReadResult::FILE_NOT_FOUND;
                osgDB::ifstream fin(fileName.c_str());
                if (fin)
                        return readNode(fin, opt);
                return 0L;
        }
       
       
        virtual ReadResult readNode(std::istream& fin, const Options* opt) const
        {
                Input fr;
                fr.attach(&fin);

                osg::ref_ptr<osg::Geode> gnode = new osg::Geode;
                osg::Vec3 center;
                float radius;

                while (!fr.eof())
                {
                        std::cout << "out" << std::endl;
                        if (fr.matchSequence("%f %f %f %f"))
                        {
                                std::cout << "in" << std::endl;
                                fr.readSequence(center);
                                fr.readSequence(radius);
                                std::cout << "Center is :" << center.x() << "" << center.y() << " " << center.z() << " " << std::endl;
                                std::cout << "Radius is " << radius << std::endl;
                                gnode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(center, radius)));
                        }
                        else
                        {
                                std::cout << "fr is NULL" << std::endl;
                                ++fr;
                        }
                }
                return gnode;
        }
};

REGISTER_OSGPLUGIN(fs, FSReaderWriter)

liyihongcug 发表于 2020-3-11 10:03:21

Lod "
centerSet how the center of object should be determined when computing which child is active
radiusSet the object-space reference radius of the volume enclosed by the LOD.
          Used to determine the bounding sphere of the LOD in the absence of any children.

PagedLOD {
name "Tile_+000_+000.osgb"
nodeMask 0xffffffff
cullingActive TRUE
Center -143.628 -197.907 438.413
Radius 36.6513
RangeMode PIXEL_SIZE_ON_SCREEN
RangeList 2 {
    0 36.6513
    36.6513 1e+30
}

NumChildrenThatCannotBeExpired 0
DisableExternalChildrenPaging 0
FileNameList 2 {
    ""
    Tile_+000_+000_L16_0.osgb
}
num_children 1
Geode {
    nodeMask 0xffffffff
    cullingActive TRUE
    num_drawables 2
    Geometry {
      DataVariance STATIC
      StateSet {
      DataVariance STATIC
      rendering_hint DEFAULT_BIN
      renderBinMode INHERIT
      Material {
          ColorMode OFF
          ambientColor 1 1 1 1
          diffuseColor 1 1 1 1
          specularColor 0 0 0 1
          emissionColor 0 0 0 1
          shininess 0
      }
      textureUnit 0 {
          GL_TEXTURE_2D ON
          Texture2D {
            DataVariance STATIC
            file "Tile_+000_+000_0.jpg"
            wrap_s CLAMP
            wrap_t CLAMP
            wrap_r CLAMP
            min_filter LINEAR_MIPMAP_LINEAR
            mag_filter LINEAR
            maxAnisotropy 1
            borderColor 0 0 0 0
            borderWidth 0
            useHardwareMipMapGeneration TRUE
            unRefImageDataAfterApply TRUE
            internalFormatMode USE_IMAGE_DATA_FORMAT
            resizeNonPowerOfTwo TRUE
            shadowComparison FALSE
            shadowCompareFunc GL_LEQUAL
            shadowTextureMode GL_LUMINANCE
          }
      }
      }
      useDisplayList TRUE
      useVertexBufferObjects FALSE
      PrimitiveSets 1
      {
      DrawElementsUInt TRIANGLES 336
      {
          0 1 2 3 4 5 6 7 8 9   
   
      0.31866 0.584678
      }
    }
    Geometry {
      DataVariance STATIC
      StateSet {
      DataVariance STATIC
      rendering_hint DEFAULT_BIN
      renderBinMode INHERIT
      Material {
          ColorMode OFF
          ambientColor 0.501961 0.501961 0.501961 1
          diffuseColor 0.501961 0.501961 0.501961 1
          specularColor 0 0 0 1
          emissionColor 0 0 0 1
          shininess 0
      }
      }
      useDisplayList TRUE
      useVertexBufferObjects FALSE
      PrimitiveSets 1
      {
      DrawElementsUInt TRIANGLES 6
      {
          0 1 2 3 4 5
      }
      }
      VertexArray Vec3Array 6
      {
      -161.257 -198.592 439.423
      -161.152 -198.421 439.325
      -160.316 -198.026 439.298
      -132.295 -199.855 439.109
      -128.971 -198.181 437.805
      -136.784 -209.794 439.044
      }
    }
}
}

liyihongcug 发表于 2020-3-19 09:44:48

本帖最后由 liyihongcug 于 2020-3-19 09:52 编辑

海量数据分析处理 。 做过类似开发能看懂下面的东西,可以按照定义格式自己做这个文件
第一部分物理文件处理建筑模 型文件
b {"BATCH_LENGTH":6}      {"height":{"byteOffset":72,"componentType":"FLOAT","type":"SCALAR"},"objectid":["21","22","23","24","25","26"],"shape_area":{"byteOffset":24,"componentType":"FLOAT","type":"SCALAR"},"shape_len":{"byteOffset":48,"componentType":"FLOAT","type":"SCALAR"},"xzqdm":["娴嬭瘯1","娴嬭瘯2","娴嬭瘯3","娴嬭瘯4","娴嬭瘯5","娴嬭瘯6"],"xzqmc":["name1","name2","name3","name4","name5","name6"],"xzqmj":{"byteOffset":0,"componentType":"FLOAT","type":"SCALAR"}}                                                                           窤鯞 B   A侭燖glTF   ?   JSON{"asset":{"generator":"lab","version":"2.0"},"scenes":[{"nodes":}],"scene":0,"nodes":[{"mesh":0,"matrix":}],"meshes":[{"primitives":[{"attributes":{"NORMAL":1,"POSITION":2,"_BATCHID":3},"indices":0,"mode":4,"material":0}]}],"accessors":[{"bufferView":0,"byteOffset":0,"componentType":5123,"count":243,"max":,"min":,"type":"SCALAR"},{"bufferView":1,"byteOffset":0,"componentType":5126,"count":155,"max":,"min":[-0.9908678531646729,-0.9997218251228333,0.0],"type":"VEC3"},{"bufferView":1,"byteOffset":1860,"componentType":5126,"count":155,"max":,"min":[-118.55101013183594,-119.96600341796875,-0.350239634513855],"type":"VEC3"},{"bufferView":2,"byteOffset":0,"componentType":5123,"count":155,"max":,"min":,"type":"SCALAR"}],"materials":[{"pbrMetallicRoughness":{"metallicFactor":0.30000001192092898,"roughnessFactor":0.699999988079071}}],"bufferViews":[{"buffer":0,"byteOffset":4030,"byteLength":486,"target":34963},{"buffer":0,"byteOffset":0,"byteLength":3720,"byteStride":12,"target":34962},{"buffer":0,"byteOffset":3720,"byteLength":310,"byteStride":2,"target":34962}],"buffers":[{"byteLength":4516}]}    ?BIN         

第二部分瓦片结构
r {_content: T, _batchId: 6, _color: undefined}
_batchId
:
6
_color
:
undefined
_content
:
T
featurePropertiesDirty
:
false
_batchIdAttributeName
:
"a_batchId"
_batchTable
:
L {featuresLength: 7, _translucentFeaturesLength: 0, _extensions: {…}, _properties: {…}, _batchTableHierarchy: undefined, …}
_contentModelMatrix
:
c {0: -0.898458234112383, 1: -0.439058995529824, 2: 0, 3: 0, 4: 0.219147513328513, 5: -0.448447452027847, 6: 0.866527120274756, 7: 0, 8: -0.380456527027185, 9: 0.778538426292546, 10: 0.499129992916012, 11: 0, 12: -2424569.26045182, 13: 4961461.30339503, 14: 3180850.24654401, 15: 1}
_diffuseAttributeOrUniformName
:
{0: "u_baseColorFactor"}
_features
:
(7)
_model
:
Te {_cacheKey: undefined, _cachedGltf: undefined, _releaseGltfJson: true, _resource: R, show: true, …}
_resource
:
R {_url: "http:///sampledata/shp3dtiles2/0/0/0.b3dm", _templateValues: {…}, _queryParameters: {…}, headers: {…}, request: n, …}
_rtcCenterTransform
:
c {0: 1, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 0, 7: 0, 8: 0, 9: 0, 10: 1, 11: 0, 12: 0, 13: 0, 14: 0, 15: 1}
_tile
:
B {_tileset: H, _header: {…}, transform: c, _initialTransform: c, computedTransform: c, …}
_tileset
:
H {_url: "./sampledata/shp3dtiles2/tileset.json", _basePath: "./sampledata/shp3dtiles2/", _root: B, _asset: {…}, _properties: undefined, …}
batchTable
:
(...)
batchTableByteLength
:
(...)
featuresLength
:
(...)
geometryByteLength
:
(...)
innerContents
:
(...)
pointsLength
:
(...)
readyPromise
:
(...)
texturesByteLength
:
(...)
tile
:
(...)
tileset
:
(...)
trianglesLength
:
(...)
url
:
(...)
__proto__
:
Object
color
:
(...)
content
:
(...)
pickId
:
(...)
primitive
:
(...)
show
:
(...)
tileset
:
(...)
__proto__
:
Object

choa 发表于 2020-3-29 16:34:09

看到楼主发的感觉受益良多,请教下倾斜摄影模型的压平有什么思路吗

ago 发表于 2020-3-31 09:12:10

用osgearth编辑器了解一下,有倾斜摄影加载、测量、压平工具

下载地址 sxsim.com

liyihongcug 发表于 2020-4-1 10:32:45

去除某一个模型中的重复区域,比如压平之类的。这样另一个模型叠加上去时就只显示另一个模型的样子了。    这块也是刚接触 也在看。现在能做到就是去掉选中的模型。或者在若干中选择一个。从包围盒
页: [1]
查看完整版本: osgearth如何加载倾斜摄影测量数据