原文链接及内容

效果如下图所示:

示例代码如下:

  1. GLB模型数据构造,手动构建符合glTF 2.0标准的JSON对象;
  2. 数据编码与传输:将整个glTF对象序列化为字符串并进行Base64编码,创建可直接嵌入CZML的内联资源;
  3. CZML定义立方体;
  4. 可视化立方体。

本文定义的CZML数据的语法请参考:

  1. https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/CZML-Structure
  2. https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/Packet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
const gltf = {
//accessors: 定义定点、法线、索引的数据格式
accessors: [
{
name: "cube_1_0_positions",
componentType: 5126,//表示浮点型数据(顶点/法线)
count: 24,
min: [-1, -1, -1],
max: [1, 1, 1],
type: "VEC3",
bufferView: 0,
byteOffset: 0,
},
{
name: "cube_1_0_normals",
componentType: 5126,
count: 24,
min: [-1, -1, -1],
max: [1, 1, 1],
type: "VEC3",
bufferView: 1,
byteOffset: 0,
},
{
name: "cube_1_0_indices",
componentType: 5123,//表示无符号短整型索引
count: 36,
min: [0],
max: [23],
type: "SCALAR",
bufferView: 2,
byteOffset: 0,
},
],
asset: { generator: "obj2gltf", version: "2.0" },
//buffers: 包含Base64编码的二进制几何数据
buffers: [
{
name: "19bd138d-63f9-4012-890c-30ab6b478824",
byteLength: 648,
uri: "data:application/octet-stream;base64,AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAABAAIAAAADAAEABAAFAAYABAAHAAUACAAJAAoACAALAAkADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA",
},
],
/**
* bufferViews: 管理缓冲区分段(顶点/法线/索引各自独立),
* 通过bufferViews实现单缓冲区多段复用
*/
bufferViews: [
{
name: "bufferView_0",
buffer: 0,
byteLength: 288,
byteOffset: 0,
byteStride: 12,//精确控制顶点数据步长(每个VEC3占12字节)
target: 34962,//ARRAY_BUFFER
},
{
name: "bufferView_1",
buffer: 0,
byteLength: 288,
byteOffset: 288,
byteStride: 12,
target: 34962,//ARRAY_BUFFER
},
{
name: "bufferView_2",
buffer: 0,
byteLength: 72,
byteOffset: 576,
target: 34963,//ELEMENT_ARRAY_BUFFER
},
],
//灰色金属质感材质(metallicFactor=0表示无金属感)
materials: [
{
name: "default",
pbrMetallicRoughness: {
baseColorFactor: [0.5, 0.5, 0.5, 1],
metallicFactor: 0,
roughnessFactor: 1,
},
emissiveFactor: [0, 0, 0],
alphaMode: "OPAQUE",
doubleSided: false,
},
],
//meshs: 翻译为网格,网孔,关联几何数据与材质,定义三角面绘制模式(mode=4对应TRIANGLES)
meshes: [
{
name: "cube_1",
primitives: [
{
attributes: { POSITION: 0, NORMAL: 1 },
indices: 2,
material: 0,
mode: 4,
},
],
},
],
// 根节点关联网格
nodes: [{ name: "cube", mesh: 0 }],
scene: 0,
scenes: [{ nodes: [0] }],
};

//将整个glTF对象序列化为字符串并进行Base64编码
const encoded = btoa(JSON.stringify(gltf));

//创建可直接嵌入CZML的内联资源
const dataUrl = `data:application/json;charset=utf-8;base64,${encoded}`;

const czml = [
// 文档元数据
{
id: "document",
name: "CZML Model",
version: "1.0",
},
// 立方体实体定义
{
id: "cube",
name: "Cube",
position: {
cartographicDegrees: [-77, 37, 10000],
},
model: {
gltf: dataUrl,
scale: 2.0,//模型放大2倍
minimumPixelSize: 128,
},
},
];

const viewer = new Cesium.Viewer("cesiumContainer", { shouldAnimate: true });

const dataSourcePromise = viewer.dataSources.add(
Cesium.CzmlDataSource.load(czml)
);

dataSourcePromise
.then(function (dataSource) {
//自动锁定视角到立方体实体
viewer.trackedEntity = dataSource.entities.getById("cube");
})
.catch(function (error) {
window.alert(error);
});