3dtiles数据解析

news2025/1/20 12:10:45

1.解析json文件

Tileset

2.解析b3dm模型

(1)b3dm模型文件时二进制文件,其中包含glTF文件:

img

img

当使用tiny_gltf库解析glTF时,需要减去(28byte + featuretable的byte + batchTable的byte ):

 bool TinyGLTF::ExtractGltfFromMemory(Model *model,
                                     std::string *err,
                                     std::string *warn,
                                     const unsigned char *bytes,
                                     unsigned int size,
                                     const std::string &base_dir,
                                     unsigned int check_sections) {
     if (size < 28) {
        if (err) {
          (*err) = "Too short data size for b3dm Binary.";
        }
        return false;
      }
 
      if (bytes[0] == 'b' && bytes[1] == '3' && bytes[2] == 'd' &&
          bytes[3] == 'm') {
        // ok
      } else {
        if (err) {
          (*err) = "Invalid magic.";
        }
        return false;
      }
 
      unsigned int version;                     // 4 bytes
      unsigned int byteLength;                  // 4 bytes
      unsigned int featureTableJSONByteLength;  // 4 bytes
      unsigned int featureTableBinaryByteLength;// 4 bytes;
      unsigned int batchTableJSONByteLength;    // 4 bytes
      unsigned int batchTableBinaryByteLength;  // 4 bytes;
 
      // @todo { Endian swap for big endian machine. }
      memcpy(&version, bytes + 4, 4);
      swap4(&version);
      memcpy(&byteLength, bytes + 8, 4);
      swap4(&byteLength);
      memcpy(&featureTableJSONByteLength, bytes + 12, 4);
      swap4(&featureTableJSONByteLength);
      memcpy(&featureTableBinaryByteLength, bytes + 16, 4);
      swap4(&featureTableBinaryByteLength);
      memcpy(&batchTableJSONByteLength, bytes + 20, 4);
      swap4(&batchTableJSONByteLength);
      memcpy(&batchTableBinaryByteLength, bytes + 24, 4);
      swap4(&batchTableBinaryByteLength);
 
      if ((byteLength != size) || (byteLength < 1) ) {
        if (err) {
          (*err) = "Invalid b3dm binary.";
        }
        return false;
      }
 
     const int byteOffset = 28 + featureTableJSONByteLength + batchTableJSONByteLength;
     
   // 解析glTF二进制
     bool ret = LoadBinaryFromMemory(
           model, err, warn, &bytes[byteOffset],
           byteLength - byteOffset, base_dir, check_sections);
     
      if (!ret) {
        return ret;
      }
 
      return true;
 }

(2)使用tiny_gltf库只需要3个文件stb_image.h,stb_image_write.h,json.hpptiny_gltf.h。

使用时需要注意,在调用#include "tiny_gltf.h"文件中的函数时,需要添加三个宏,如:

 // Define these only in *one* .cc file.
 #define TINYGLTF_IMPLEMENTATION
 #define STB_IMAGE_IMPLEMENTATION
 #define STB_IMAGE_WRITE_IMPLEMENTATION
 // #define TINYGLTF_NOEXCEPTION // optional. disable exception handling.
 #include "tiny_gltf.h"
 
 using namespace tinygltf;
 
 Model model;
 TinyGLTF loader;
 std::string err;
 std::string warn;
 
 bool ret = loader.LoadASCIIFromFile(&model, &err, &warn, argv[1]);
 //bool ret = loader.LoadBinaryFromFile(&model, &err, &warn, argv[1]); // for binary glTF(.glb)
 
 if (!warn.empty()) {
   printf("Warn: %s\n", warn.c_str());
 }
 
 if (!err.empty()) {
   printf("Err: %s\n", err.c_str());
 }
 
 if (!ret) {
   printf("Failed to parse glTF\n");
   return -1;
 }

3.关于glTF格式详解

 {
   "scenes" : [ // 只包含了一个场景
     {
       "nodes" : [ 0, 1]
     }
   ],
   "nodes" : [ // 将mesh对象附着到两个不同的node对象,将其渲染了两次
     {
       "mesh" : 0
     },
     {
       "mesh" : 0,
       "translation" : [ 1.0, 0.0, 0.0 ] // 使用translation属性来将mesh对象的渲染位置移动到其它地方
       "rotation": [ 0.259, 0.0, 0.0, 0.966 ], // 四元数
       "scale": [ 2.0, 1.0, 0.5 ] // x,y和z轴的缩放系数
       // 或者只给出一个matrix进行变换
       "matrix": [ // 描述了一个缩放(2,1,0.5),绕x轴旋转30度,平移(10,20,30)的matrix属性
         2.0,    0.0,    0.0,    0.0,
         0.0,    0.866,  0.5,    0.0,
         0.0,   -0.25,   0.433,  0.0,
         10.0,   20.0,   30.0,    1.0
     ]
     } 
   ],
   
   "meshes" : [
     {
       "primitives" : [ {
         "attributes" : {
           "POSITION" : 1, // 引用了索引为1的accessor对象
           "NORMAL" : 2 // "NORMAL"属性引用了索引为2的accessor对象
         },
         "indices" : 0
       } ]
     }
   ],
 
   "buffers" : [ // 表示了一个没有任何层次结构和意义的二进制数据块
     {
       "uri" : "data:application/octet-stream;base64,AAA为了排版而删除,可以使用英文原文中的代码=",
       "byteLength" : 80 // 使用了大小为80字节的经过编码的数据URI作为缓冲的数据
     }
   ],
   "bufferViews" : [ // 一个bufferView对象代表了一个buffer对象的部分数据
     {
       "buffer" : 0,
       "byteOffset" : 0,
       "byteLength" : 6, // 引用了索引为0的buffer对象的前6个字节的数据
       "target" : 34963 // 表示数据使用方式的常量,ELEMENT_ARRAY_BUFFER
     },
     {
       "buffer" : 0,
       "byteOffset" : 8,
       "byteLength" : 72, // 从偏移值8开始的36个字节的buffer对象的数据
       "target" : 34962 // ARRAY_BUFFER
     }
   ],
   "accessors" : [
     {  // 表示顶点索引数据是unsigned short类型的标量
       "bufferView" : 0, // 引用了索引为0的bufferView,这一bufferView对象描述了buffer数据中的顶点索引数据
       "byteOffset" : 0,  // 指定了accessor所访问数据的开始位置
       "componentType" : 5123, // 定义了数据分量的基础类型,5123代表UNSIGNED_SHORT。同short占用2个字节
       "count" : 3, // count属性指定了数据元素的数量,对应三角形的3个顶点的索引值
       "type" : "SCALAR", 
       "max" : [ 2 ],
       "min" : [ 0 ]
     },
     {  // 这一accessor对象描述了分量类型为float的3D向量数据
       "bufferView" : 1,
       "byteOffset" : 0,  // 指定了accessor所访问数据的开始位置
       "componentType" : 5126, // 5126代表FLOAT,一个float类型值占4个字节
       "count" : 3, // count属性指定了数据元素的数量
       "type" : "VEC3",
       "max" : [ 1.0, 1.0, 0.0 ], // min和max属性定义了3D对象的包围盒
       "min" : [ 0.0, 0.0, 0.0 ]
     },
     {
       "bufferView" : 1,
       "byteOffset" : 36,
       "componentType" : 5126, // 5126代表FLOAT
       "count" : 3, // count属性指定了数据元素的数量
       "type" : "VEC3",
       "max" : [ 0.0, 0.0, 1.0 ], // min和max属性定义了3D对象的包围盒
       "min" : [ 0.0, 0.0, 1.0 ]
     }
   ],
   
   "asset" : {
     "version" : "2.0"
   }
 }

参考资料

1.解析json文件

Reference:

RapidJSON的简单使用示例:

RapidJSON简介及使用

2.解析3dtile-b3dm格式

Reference:

(1)对相关资料做了总结和推荐:

Cesium之b3dm格式_全栈空间-程序员秘密

image-20220414105546750

(2)对b3dm二进制结构做了详细的解析:

[3dTiles 数据规范详解4.1] b3dm瓦片二进制数据文件结构 _

image-20220414105705179

(3)官网对Batched3DModel的介绍

3d-tiles/specification/TileFormats/Batched3DModel/

layout.png

(4)3dtiles官方规范

3d-tiles/specification

(5)

3dTile 数据文件格式说明

img

img

(6)3dtiles规范中文版pdf

链接: https://pan.baidu.com/s/1hhbvD_2DXrPCTOs7slsNHA 提取码: ejm7

3.glTF

(1)glTF官方github:

KhronosGroup/glTF

(2)glTF规范:

Specification.adoc

(3)对glTF格式的详细介绍,教程(glTF官方文档翻译)

glTF格式详解(glTF格式基本结构)

(4)博主的github写了一个解析glTF的工具:

模型导入之优雅姿势——glTF

songchaow/toy-renderer

(5)解析b3dm模型的库tiny_gltf(项目中用这个库解析)

https://github.com/fanvanzh/3dtiles

(6)tiny_gltf原始项目出处:

chainblocks/tinygltf

(7)glTF模型文件讲解(B站)

【日常 | 学习Vlog | 程序媛乐乐】数字孪生基础 | 三维模型 | What is glTF?

image-20220415101428317


文章出自:http://www.whnw.com.cn/news/1710037.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/105982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM - 内存区域划分 类加载机制 垃圾回收机制

目录 1. 内存区域划分 2. 类加载 2.1 双亲委派模型 3. 垃圾回收机制 (GC) 3.1 如何判断一个对象是否为 "垃圾" 3.1 可达性分析 3.2 垃圾回收算法 1. 内存区域划分 JVM 作本质上是一个 Java 进程, 它启动的时候, 就会从操作系统申请一大块内存, 并且把这一大块…

CSS学习(七):盒子模型,圆角边框,盒子阴影和文字阴影

原文链接&#xff1a;CSS学习&#xff08;七&#xff09;&#xff1a;盒子模型&#xff0c;圆角边框&#xff0c;盒子阴影和文字阴影 1. 盒子模型 页面布局要学习三大核心&#xff1a;盒子模型&#xff0c;浮动和定位。学习好盒子模型能非常好的帮助我们页面布局。 1.1 看透…

肽基脯氨酰异构酶底物:1926163-51-0,WFY-pSer-PR-AMC

WFYpSPR-AMC, Pin1底物类似显色底物H- trp - phi - tir - ser (PO₃H₂)-Pro-Arg-pNA。 磷酸肽在生命过程中发挥重要作用&#xff0c;磷酸化的位置在多肽上的Tyr、Ser&#xff0c;Thr&#xff0c;。目前磷酸肽合成一般都采用磷酸化氨基酸&#xff0c;目前使用的都是单苄基磷酸化…

Kafka Producer - 分区机制实战

Kafka Producer - 分区机制实战 上一篇介绍了kafka Producer 生产者发送数据的程序代码&#xff0c;以及对生产者分区机制的相关介绍&#xff0c;今天继续深入的了解下分区机制的原理、测试验证、自定义分区。 在学习之前先在本地机器搭建一个单机版的双节点集群环境&#xf…

80.【Spring5】

Spring《解耦》(一)、Spring 简介1.历史:2.Spring 目的3.Spring 引入4.优点5.Spring 七大模块组成:6.扩展&#xff08;约定大于配置&#xff09;(二)、IOC理论推导(Inversion of Contro)1.以前的三层分级2.现在对三层架构的更新3.什么是IOC(三)、HelloSpring1.怎么使用Spring?…

技术分享 | 缓存穿透 - Redis Module 之布隆过滤器

作者&#xff1a;贲绍华 爱可生研发中心工程师&#xff0c;负责项目的需求与维护工作。其他身份&#xff1a;柯基铲屎官。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 一、场景案例 假…

设计模式-抽象工厂模式

1、什么是抽象工厂模式 抽象工厂&#xff08;AbstractFactory&#xff09;模式的定义&#xff1a;是一种为访问类提供一个创建一组相关或相互依赖对象的接口&#xff0c;且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的…

Tiny ImageNet 数据集分享

ImageNet官网上的数据集&#xff0c;动辄就100G&#xff0c;真的是太大了。 有需要Tiny Image Net 数据集的小伙伴可以点击这个下载链接&#xff1a; http://cs231n.stanford.edu/tiny-imagenet-200.zip数据集简介&#xff1a; Tiny ImageNet Challenge 来源于斯坦福 CS231N …

uwb无线定位系统的原理和介绍

uwb无线定位系统是在 uwb平台上部署的定位基站&#xff0c;通过发射无线信号&#xff0c;将 uwb定位系统部署在需要安装的位置&#xff0c;同时结合定位基站所支持工作环境条件&#xff08;如&#xff1a;温度、湿度、光照等&#xff09;和定位算法&#xff0c;实现在不同的地理…

使用elesticsearch-7.10.0版本连接elasticsearch-head

背景&#xff1a; 由于esasticsearch-5.5.1中没有登录&#xff0c;登出的安全校验&#xff0c;在安全测评时&#xff0c;经常被检查到高危漏洞&#xff0c;因此项目经常要升级到es7版本。 问题一&#xff1a;jdk版本不满足要求&#xff0c;提示如下 future versions of Elasti…

Js实现轮盘抽奖功能,一招帮你解决选择困难症

不知道今天自己该吃什么&#xff0c;一招帮你解决选择困难症。 通过htmlcssjs实现一个轮盘抽奖功能。我们可以将平时吃的饭菜输入到代码中&#xff0c;每到纠结的时候只需点开抽一次就可以了。 实现步骤 html代码&#xff1a; 整体实现的结构是一个大的圆形&#xff0c;分成…

热门项目披露:成都双流板桥轨道城市发展有限公司100%股权转让

热门项目披露&#xff1a;成都双流板桥轨道城市发展有限公司100%股权转让&#xff1b;该项目由 西南联合产权交易所 发布&#xff0c;于2022年12月9日被塔米狗平台收录。 项目方 成都双流板桥轨道城市发展有限公司&#xff0c; 成立于 2021年9月7日 &#xff0c; 注册资金 100…

域控制器交付量「翻番」,汽车中间件赛道竞争升级

作为软件定义汽车的关键环节&#xff0c;智能汽车中间件赛道&#xff0c;正在成为兵家必争之地。 从传统IT架构的角度看&#xff0c;中间件位于上层应用和底层操作系统之间&#xff1b;除了基础的通信交互外&#xff0c;中间件还承载着屏蔽底层复杂性的功能&#xff0c;向下适配…

005:UITableView

介绍&#xff1a; 提示&#xff1a;数据量大、样式较为统一、分组的需要以及滚动的需求。 图示&#xff1a; UITableViewDataSource&#xff1a; 提示UITableView作为视图&#xff0c;只负责展示&#xff0c;协助管理&#xff0c;不管数据需要开发者为UITableView提供展示需…

Framework底层原理——Binder调用流程分析

binder是一个非常好的跨进程通信工具&#xff0c;Android对其进行了各种封装&#xff0c;虽然我们用起来简单&#xff0c;但是理解起来却比较困难。 1.自己设计一个跨进程通信机制 在理解binder之前呢&#xff0c;首先我们想一下&#xff0c;如果我们自己设计一个跨进程通信的…

简单Thinkphp5.1如何使用Topsdk\Topapi

一淘模板&#xff08;56admin.cn&#xff09;给大家介绍tp5.1相关知识&#xff0c;其中主要记录tp5.1是怎么使用Topsdk\Topapi&#xff08;对接淘宝客开放平台&#xff09;&#xff0c;希望对需要的朋友有所帮助&#xff01; 1、公司有一项目需要对接淘宝开放平台 先去申请帐号…

tensorrt debug问题汇总

目录 1. Dynamic dimensions required for input: input, but no shapes were provided. Automatically overriding 2. sampleMNIST.obj : error LNK2019: 无法解析的外部符号 cudaStreamCreate 3. Assertion failed: (smVersion &#xff1c; SM_VERSION_A100) &&…

条码管理系统,助力企业打造轻量级数字化车间

在原辅材料供应、生产管理、仓储物流、市场营销等相关业务环节中&#xff0c;采取适当的软硬件技术手段&#xff0c;实时记录产品信息。通过查询可以随时跟踪产品的生产状态、仓储状态和流向&#xff0c;达到可追溯管理的目的。随着制造企业对精细化管理要求的提高&#xff0c;…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.7 画笔设置

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV16W4y1g7dM 经过前面几节课的讲解&#xff0c;学会了绘制点、线、多段线、多边形、矩形、圆角矩形 到这里就可以学习画笔和画刷的设置了&#xff0c;本节先讲解画笔的设置 Qt 中画笔的类是 QPen…

正则表达式验证合集

1.定义封装的公共js 在src下定义一个util文件夹&#xff0c;并且定义个validate.js(当然你想取什么名字就什么名字哈哈哈哈) 2.上代码 //邮箱 /*** 邮箱* param {*} s*/ export function isEmail(s) {return /^([a-zA-Z0-9_-])([a-zA-Z0-9_-])((.[a-zA-Z0-9_-]{2,3}){1,2}…