关于 cesiumjs-models-particles
面向 CesiumJS 开发者的 glTF/GLB 模型与粒子效果技能指南,涵盖模型加载、动画、节点变换、样式设置和粒子系统配置。
主要功能
- 01加载并定位 glTF/GLB 模型
- 02控制模型动画与节点
- 03设置模型样式并拾取要素
- 04创建粒子效果
适用场景
- 01在 CesiumJS 场景中放置并动画化模型
- 02设置带要素 ID 的模型内容样式
- 03制作烟雾、火焰或雨效
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cesiumgs/ cesiumjs-skills --skill cesiumjs-models-particles安装后在 Claude Code 中输入/cesiumjs-models-particles确认已加载。
附带文件REFERENCE.md
详细介绍
CesiumJS 模型、glTF 与粒子效果
基准版本:CesiumJS v1.144。
快速参考
| 类 | 用途 |
|---|---|
Model | 底层 glTF/GLB 基元;通过 modelMatrix 定位 |
ModelAnimation | 模型上的活动动画实例 |
ModelAnimationCollection | model.activeAnimations 中的集合 |
ModelNode | 可修改变换的命名节点 |
ModelFeature | 面向要素 ID 模型的逐要素样式设置与拾取 |
EdgeDisplayMode | 控制 Model/Cesium3DTileset 上草稿 glTF 边缘可见性渲染 |
ParticleSystem | 基于广告牌的粒子管理器(火焰、烟雾、雨) |
Particle | 单个粒子,具有位置、速度和生命周期 |
ParticleBurst | 定时发射的一组粒子 |
BoxEmitter / CircleEmitter | 在盒体体积内 / 平面圆盘内发射 |
ConeEmitter / SphereEmitter | 从圆锥顶点 / 球体内发射 |
Entity API 通过 ModelGraphics 提供模型(参见 cesiumjs-entities)。Primitive API 使用 Model.fromGltfAsync,以全面控制 modelMatrix、动画和节点变换。
加载 glTF/GLB 模型
始终使用异步工厂——切勿直接调用构造函数。
import { Model, Cartesian3, Transforms, HeadingPitchRoll, Math as CesiumMath } from "cesium";
const model = await Model.fromGltfAsync({ url: "path/to/model.glb" });
viewer.scene.primitives.add(model);
公共示例模型
CesiumJS 附带可在无需 ion 令牌的情况下使用的示例模型:
https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumAir/Cesium_Air.glb
https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumMan/Cesium_Man.glb
https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumMilkTruck/CesiumMilkTruck.glb
CesiumJS 1.143 会自动解码 KHR_meshopt_compression,包括 v1 属性编解码器和 COLOR 滤镜。请勿导入解码器或私有加载器辅助函数。加载压缩 glTF、CAD 风格的线条/点/边缘或恒定 LOD 纹理时,请参阅 REFERENCE.md,了解完整的支持与创作矩阵。相同的加载器行为也适用于 3D Tiles 内的 glTF 内容。
带航向角的定位模型
const position = Cartesian3.fromDegrees(-123.074, 44.050, 5000);
const hpr = new HeadingPitchRoll(CesiumMath.toRadians(135), 0, 0);
const model = await Model.fromGltfAsync({
url: "CesiumAir.glb",
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, hpr),
minimumPixelSize: 128, // never smaller than 128 px on screen
maximumScale: 20000, // cap for minimumPixelSize enlargement
scale: 2.0, // uniform scale multiplier
});
viewer.scene.primitives.add(model);
**视觉评估构图:**模型截图中,模型必须完整位于画面内且清晰可辨,不能被底部边缘裁切。公共示例飞机模型的
minimumPixelSize设为 256-400,添加柔和的silhouetteColor/silhouetteSize,并使用显式坐标定位相机,使其朝向已知的模型位置。避免采用较小的俯仰角,导致模型出现在画面下方;也不要依赖viewer.flyTo(model),因为它对Model基元的行为会因版本而异。
避免模型外观失真
非均匀缩放或方向矩阵构造错误时,模型可能会显得拉伸或扭曲。常见问题包括:
- **地面对齐方向始终使用
Transforms.headingPitchRollToFixedFrame(或 Entity API 的headingPitchRollQuaternion)。**手动构造的四元数经常会反转俯仰/滚转轴,导致轮廓垂直拉伸。 - **使用(均匀)
scale调整尺寸,不要使用非均匀的Matrix4.fromScale。**烘焙到modelMatrix中的非均匀缩放会使模型失真。Matrix4.fromScale应用于逐节点微调(例如拉伸单个炮塔),而非整个模型。 - **将
minimumPixelSize与合理的maximumScale配合使用。**如果没有上限,远处的小模型可能会膨胀到占满画面,并在相机靠近时显得细长。
Model.fromGltfAsync 的关键选项
| 选项 | 类型 | 默认值 |
|---|---|---|
url | string|Resource | 必填 |
modelMatrix | Matrix4 | IDENTITY |
scale | number | 1.0 |
minimumPixelSize | number | 0.0 |
maximumScale | number | -- |
show | boolean | true |
color / colorBlendMode / colorBlendAmount | Color / ColorBlendMode / number | -- / HIGHLIGHT / 0.5 |
edgeDisplayMode | EdgeDisplayMode | SURFACES_ONLY |
silhouetteColor / silhouetteSize | Color / number | RED / 0.0 |
shadows | ShadowMode | ENABLED |
heightReference | HeightReference | NONE |
customShader | CustomShader | -- |
id | any | -- |
allowPicking | boolean | true |
就绪状态和生命周期
fromGltfAsync 会在解析完 glTF JSON 后完成,但 WebGL 资源可能仍在加载。在访问动画、节点或 boundingSphere 前,请等待 readyEvent。
const model = await Model.fromGltfAsync({ url: "robot.glb" });
viewer.scene.primitives.add(model);
model.readyEvent.addEventListener(() => {
console.log("Bounding sphere:", model.boundingSphere);
});
// Synchronous check
if (model.ready) { const bs = model.boundingSphere; }
动画
通过 model.activeAnimations(ModelAnimationCollection)管理。
按名称播放 / 播放全部
model.readyEvent.addEventListener(() => {
// Single animation
const anim = model.activeAnimations.add({
name: "Walk", // glTF animation name
loop: Cesium.ModelAnimationLoop.REPEAT, // NONE | REPEAT | MIRRORED_REPEAT
multiplier: 1.0, // playback speed (must be > 0)
});
anim.start.addEventListener((m, a) => console.log(`Started: ${a.name}`));
// Or play all animations at once
model.activeAnimations.addAll({
loop: Cesium.ModelAnimationLoop.REPEAT,
multiplier: 0.5,
});
});
其他 add 选项:index、reverse、startTime、stopTime、delay、removeOnStop、animationTime(自定义时间回调)。
动画需要 viewer.clock.shouldAnimate = true 才会推进。 如果时钟已停止,行走中的角色会看起来定格在某个姿势(或在关键帧交界处显得扭曲)。
动画事件
animation.start.addEventListener((model, animation) => { });
animation.update.addEventListener((model, animation, time) => { });
animation.stop.addEventListener((model, animation) => { });
// Collection-level
model.activeAnimations.animationAdded.addEventListener((model, anim) => { });
model.activeAnimations.remove(animation); // remove one
model.activeAnimations.removeAll(); // remove all
模型节点
覆盖命名节点的变换,用于程序化动画(例如炮塔旋转)。
model.readyEvent.addEventListener(() => {
const node = model.getNode("Turret");
node.matrix = Cesium.Matrix4.fromScale(
new Cesium.Cartesian3(5.0, 1.0, 1.0), node.matrix
);
});
属性:name(只读)、id(只读索引)、show(布尔值)、matrix(Matrix4——设为 undefined 可恢复原始变换并重新启用 glTF 动画)。
着色、轮廓和要素拾取
// Tint + silhouette
model.color = Cesium.Color.RED.withAlpha(0.5);
model.colorBlendMode = Cesium.ColorBlendMode.MIX;
model.colorBlendAmount = 0.5;
model.silhouetteColor = Cesium.Color.YELLOW;
model.silhouetteSize = 2.0;
边缘显示模式(实验性,1.142+)
对于使用草案版 EXT_mesh_primitive_edge_visibility 扩展的 glTF 资源,
EdgeDisplayMode 用于控制隐藏扩展提供的边缘、将其叠加显示在表面上,还是仅渲染边缘。不含该扩展的模型不受影响。
import { EdgeDisplayMode, Model } from "cesium";
const model = await Model.fromGltfAsync({
url: "/models/cad-part.glb",
edgeDisplayMode: EdgeDisplayMode.SURFACES_AND_EDGES,
});
viewer.scene.primitives.add(model);
model.edgeDisplayMode = EdgeDisplayMode.EDGES_ONLY; // CAD-style wireframe
model.edgeDisplayMode = EdgeDisplayMode.SURFACES_ONLY; // default
当 glTF 含有 EXT_mesh_features 或 EXT_structural_metadata 时,拾取会返回一个 ModelFeature:
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((movement) => {
const picked = viewer.scene.pick(movement.endPosition);
if (picked instanceof Cesium.ModelFeature) {
picked.getPropertyIds().forEach((name) => {
console.log(`${name}: ${picked.getProperty(name)}`);
});
picked.color = Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
高度参考
// Primitive API -- scene is required for height reference
const model = await Model.fromGltfAsync({
url: "truck.glb",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
scene: viewer.scene,
});
// Entity API
viewer.entities.add({
position: Cartesian3.fromDegrees(-75.59, 40.03),
model: { uri: "truck.glb", heightReference: Cesium.HeightReference.CLAMP_TO_GROUND },
});
取值:NONE、CLAMP_TO_GROUND、RELATIVE_TO_GROUND、CLAMP_TO_TERRAIN、RELATIVE_TO_TERRAIN、CLAMP_TO_3D_TILE、RELATIVE_TO_3D_TILE。
粒子系统
ParticleSystem 用于渲染基于广告牌的效果。使用 modelMatrix(世界坐标)和 emitterModelMatrix(局部偏移)设置位置。
添加粒子系统前,务必设置 viewer.clock.shouldAnimate = true——只有时钟运行时,粒子才会移动。时钟停止时,发射器原点处只会出现静止的“团块”,而非有方向性的羽流。
生成清晰可辨的垂直羽流
常见的问题是渲染出弥散的球状团块,而不是清晰可辨、向上升起的柱状效果。若要让羽流呈现垂直形态:
- 使用
CircleEmitter或窄角度的ConeEmitter来产生向上的速度。SphereEmitter和BoxEmitter会向各个方向发射粒子,产生类似团块的形状。 - 让速度明显偏向上方——在
modelMatrix坐标系中,发射器的局部 +Z 轴朝上;请通过Transforms.eastNorthUpToFixedFrame设置modelMatrix,使 +Z 轴朝向局部上方。 - 将
minimumParticleLife/maximumParticleLife设为数秒(例如 1.5-4.0),让粒子在淡出前移动足够远,形成可见的柱状效果。 - 让粒子在生命周期内逐渐放大(
startScale设小,endScale设为其 3-6 倍),使羽流随高度逐渐变宽,符合真实烟雾的形态。 - 让发射器的占地范围小于羽流的可见范围。 对于火山口烟雾,使用小圆盘或点源;过大的地面椭圆会喧宾夺主,看起来像主体而不是源标记。
- 不要通过放大羽流来解决裁切问题。 如果顶部被裁切,请先增大相机距离,或减小粒子寿命、速度或
endScale;不要让羽流占满画面的四条边。 - 截图前等待数秒的模拟时间——羽流需要时间才能形成。推进时钟,或设置
viewer.clock.shouldAnimate = true后等待。
烟雾轨迹
import { ParticleSystem, CircleEmitter, Color, Cartesian2, Transforms, Cartesian3 } from "cesium";
viewer.clock.shouldAnimate = true; // required -- particles don't move on a stopped clock
const smokeSystem = new ParticleSystem({
image: "smoke.png",
startColor: Color.LIGHTGRAY.withAlpha(0.7),
endColor: Color.WHITE.withAlpha(0.0),
startScale: 1.0,
endScale: 5.0,
emissionRate: 10,
minimumSpeed: 1.0,
maximumSpeed: 4.0,
minimumParticleLife: 1.2,
maximumParticleLife: 3.0,
imageSize: new Cartesian2(25, 25), // pixel size
emitter: new CircleEmitter(2.0), // radius in meters
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.157, 39.978)),
lifetime: 16.0,
loop: true,
});
viewer.scene.primitives.add(smokeSystem);
火山/火山口烟雾校准
对于圣海伦斯山这类地形尺度的烟雾,应使用倾斜视角,并谨慎设置源标记。标记应指出发射器位置,但不能变成巨大的地面圆盘;烟柱应完整位于画面内,且下方可见地形。
import { ParticleSystem, CircleEmitter, Color, Cartesian2, Transforms, Cartesian3 } from "cesium";
viewer.clock.shouldAnimate = true;
const sourcePosition = Cartesian3.fromDegrees(-122.1944, 46.1914, 2549);
viewer.entities.add({
position: sourcePosition,
point: {
pixelSize: 10,
color: Color.ORANGE,
outlineColor: Color.BLACK,
outlineWidth: 2,
},
});
const craterSmoke = new ParticleSystem({
image: createRadialParticle(48, "rgba(180,180,180,0.75)"),
startColor: Color.LIGHTGRAY.withAlpha(0.65),
endColor: Color.WHITE.withAlpha(0.0),
startScale: 0.8,
endScale: 4.0,
emissionRate: 35,
minimumSpeed: 20.0,
maximumSpeed: 45.0,
minimumParticleLife: 2.0,
maximumParticleLife: 4.0,
imageSize: new Cartesian2(22, 22),
emitter: new CircleEmitter(35.0),
modelMatrix: Transforms.eastNorthUpToFixedFrame(sourcePosition),
lifetime: 20.0,
loop: true,
});
viewer.scene.primitives.add(craterSmoke);
viewer.trackedEntity = undefined;
viewer.camera.lookAt(
sourcePosition,
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(35),
Cesium.Math.toRadians(-22),
6500
)
);
当提示词要求在指定地理位置上方显示烟雾时,使用以下模式:
- 优先使用
point或小型公告牌标记,除非提示词明确要求显示地面范围,否则不要使用ellipse。 - 确保烟柱顶部、底部和源标记同时可见。 即使粒子正在渲染,烟柱被裁切或标记缺失也属于取景失败。
- 高烟柱使用倾斜俯仰角。 接近天底的视角会将垂直体积压扁成灰色团块。
发射器类型
import { BoxEmitter, CircleEmitter, ConeEmitter, SphereEmitter } from "cesium";
new BoxEmitter(new Cesium.Cartesian3(10, 10, 10)); // 3D box, velocity outward
new CircleEmitter(2.0); // flat disk, velocity +Z
new ConeEmitter(Cesium.Math.toRadians(30)); // cone tip, velocity toward base
new SphereEmitter(5.0); // sphere, velocity radiates out
粒子爆发
const firework = new ParticleSystem({
image: getParticleCanvas(),
startColor: Color.RED,
endColor: Color.RED.withAlpha(0.0),
particleLife: 1.0,
speed: 100.0,
imageSize: new Cartesian2(7, 7),
emissionRate: 0, // bursts only
emitter: new SphereEmitter(0.1),
bursts: [
new Cesium.ParticleBurst({ time: 0.0, minimum: 100, maximum: 200 }),
new Cesium.ParticleBurst({ time: 2.0, minimum: 50, maximum: 100 }),
new Cesium.ParticleBurst({ time: 4.0, minimum: 200, maximum: 300 }),
],
lifetime: 6.0,
loop: false,
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.597, 40.038)),
});
viewer.scene.primitives.add(firework);
更新回调(重力/风)
对于重力等作用力,updateCallback 会逐帧对每个粒子运行。
const gravityScratch = new Cesium.Cartesian3();
function applyGravity(particle, dt) {
Cesium.Cartesian3.normalize(particle.position, gravityScratch);
Cesium.Cartesian3.multiplyByScalar(gravityScratch, -9.8 * dt, gravityScratch);
particle.velocity = Cesium.Cartesian3.add(particle.velocity, gravityScratch, particle.velocity);
}
const system = new ParticleSystem({
image: "smoke.png",
emissionRate: 20,
emitter: new ConeEmitter(Cesium.Math.toRadians(45)),
updateCallback: applyGravity,
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-105, 40, 1000)),
});
viewer.scene.primitives.add(system);
对粒子效果取景,让地图清晰可见
粒子效果应在下方地图的衬托下突出显示,而不是在天空或毫无特征的背景下突出显示。两种常见的取景失败情况:
- 相机距离太近 + 俯仰角太小 → 烟柱占满画面,地图被遮挡。
- 相机角度太陡/接近天底 → 高烟柱被压扁成团块,源几何形状显示不正确。
使用 viewer.camera.lookAt 和 HeadingPitchRange 锚定发射器,并调整到合适的倾斜视角,以保留地图环境信息:
const position = Cartesian3.fromDegrees(-122.1944, 46.1914, 2549);
viewer.trackedEntity = undefined;
viewer.camera.lookAt(
position,
new Cesium.HeadingPitchRange(
Cesium.Math.toRadians(35), // heading
Cesium.Math.toRadians(-22), // oblique pitch preserves plume height
6500 // increase range until top and base fit
)
);
指南:
- 对于短小、贴近地面的效果,若地图环境信息比垂直范围更重要,俯仰角应设为 -35° 至 -60°。
- 对于需要体现垂直体积的高烟柱(例如火山烟柱),俯仰角应设为 -10° 至 -30°。
- 确认标记/源位于画面内:在发射器位置添加公告牌或点;如果相机位置不正确,截图中就会看不到标记,问题一目了然。
- 确保烟柱周围可见背景地形。 如果粒子触及多个画面边缘,请在截图前缩小粒子比例、缩短生命周期、降低速度或增大相机距离。
- 在调用
lookAt前将viewer.trackedEntity = undefined重置,否则被跟踪实体的参考坐标系会覆盖相机变换。
将粒子附加到移动模型
通过 scene.preUpdate 每帧同步 modelMatrix。使用 emitterModelMatrix 设置局部偏移(例如排气管)。
const entity = viewer.entities.add({
position: sampledPosition,
orientation: new Cesium.VelocityOrientationProperty(sampledPosition),
model: { uri: "truck.glb", minimumPixelSize: 64 },
});
// Local offset to exhaust pipe
const trs = new Cesium.TranslationRotationScale();
trs.translation = new Cesium.Cartesian3(-4.0, 0.0, 1.4);
const emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
const exhaust = new ParticleSystem({
image: "smoke.png",
startColor: Color.GRAY.withAlpha(0.7),
endColor: Color.TRANSPARENT,
emissionRate: 8,
speed: 2.0,
particleLife: 1.5,
imageSize: new Cartesian2(20, 20),
emitter: new CircleEmitter(0.5),
emitterModelMatrix: emitterModelMatrix,
});
viewer.scene.primitives.add(exhaust);
viewer.scene.preUpdate.addEventListener((scene, time) => {
exhaust.modelMatrix = entity.computeModelMatrix(time, new Cesium.Matrix4());
});
基于 Canvas 的粒子图像
动态生成粒子纹理,而不是加载图像文件。径向渐变可以为烟雾和水效果生成柔和、逼真的边缘。
// Soft radial-gradient particle (smoke, water, fog)
function createRadialParticle(size = 32, colorStop = "rgba(200,200,200,0.9)") {
const c = document.createElement("canvas");
c.width = c.height = size;
const ctx = c.getContext("2d");
const half = size / 2;
const grad = ctx.createRadialGradient(half, half, 0, half, half, half);
grad.addColorStop(0, colorStop);
grad.addColorStop(1, "rgba(0,0,0,0)");
ctx.fillStyle = grad;
ctx.fillRect(0, 0, size, size);
return c;
}
// Solid circle (high-contrast, fireworks, sparks)
function createCircleImage(size = 20) {
const c = document.createElement("canvas");
c.width = c.height = size;
const ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
ctx.fillStyle = "#fff";
ctx.fill();
return c;
}
// Pass canvas directly as image
new ParticleSystem({ image: createRadialParticle(), /* ...other options */ });
当命名颜色无法满足需求时,可使用 Color.fromCssColorString 设置特定的粒子颜色:
startColor: Cesium.Color.fromCssColorString("#66ccff").withAlpha(0.95),
endColor: Cesium.Color.WHITE.withAlpha(0.0),
Entity API 模型(ModelGraphics)
对于较简单的用例,可通过 Entity API 添加模型(完整说明请参阅 cesiumjs-entities)。
const entity = viewer.entities.add({
name: "Aircraft",
position: Cartesian3.fromDegrees(-123.074, 44.050, 5000),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cartesian3.fromDegrees(-123.074, 44.050, 5000),
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(135), 0, 0)
),
model: {
uri: "CesiumAir.glb",
minimumPixelSize: 128,
maximumScale: 20000,
silhouetteColor: Color.RED,
silhouetteSize: 2.0,
},
});
viewer.trackedEntity = entity;
使用 viewer.trackedEntity 时的取景权衡: 跟踪会将模型居中,但会根据包围球自动计算距离,这通常会导致镜头太近、环境信息不足。对于既要求显示模型又要求保留地图环境信息(地形、地标、标签)的提示词,优先使用 viewer.camera.flyTo / lookAt 移动到手动选择的位置,并先清除 viewer.trackedEntity = undefined。
GPM 扩展(NGA_gpm_local)
CesiumJS 以实验性方式支持 NGA Geospatial Positioning Metadata glTF 扩展。类型:AnchorPointDirect、AnchorPointIndirect、CorrelationGroup、GltfGpmLocal、Spdcf。加载带有 NGA_gpm_local 的 glTF 时会自动解析——该 API 处于实验阶段,可能发生变化。
性能提示
- 优先使用
.glb而非.gltf—— 二进制格式可避免额外的 HTTP 请求,传输的数据也更小。 - 启用 Draco 压缩(
KHR_draco_mesh_compression),可将网格体积缩小 80-90%。 - 使用 KTX2/Basis 纹理(
KHR_texture_basisu)实现 GPU 压缩纹理;尺寸保持为 2 的幂。 - 谨慎设置
minimumPixelSize—— 较大的值会强制放大远处的模型,增加绘制开销。 - 限制轮廓效果 —— 每个带轮廓的模型都会增加一次渲染过程;超过 256 个可能导致模板缓冲区伪影。
- 重复使用临时
Matrix4对象 —— 将粒子系统同步到移动实体时,避免每帧都分配对象。 - 根据效果密度匹配发射率 —— 高密度喷射效果(喷泉、火焰)可能需要 200-1000/s 的发射率;稀疏烟雾使用 10-60/s 效果良好。请在目标硬件上进行性能分析。
- 优先使用像素大小的粒子(
sizeInMeters: false,默认值)—— 近距离下,以米为单位的粒子开销较大。 - 为粒子系统设置有限的
lifetime——Number.MAX_VALUE(默认值)会阻止清理对象池。 - 为装饰性模型禁用拾取 —— 对无需交互的模型设置
allowPicking: false可节省 GPU 内存。 - 用完后销毁 —— 先执行
viewer.scene.primitives.remove(model),再执行model.destroy(),以释放 WebGL 资源。
另请参阅
- cesiumjs-custom-shader —— 为
Model.customShader编写 GLSL(结构体参考、要素 ID、元数据、顶点位移) - cesiumjs-materials-shaders —— ImageBasedLighting、模型的后处理阶段
- cesiumjs-entities —— Entity API ModelGraphics、数据源、随时间动态变化的属性
- cesiumjs-3d-tiles —— Cesium3DTileset(内部使用 Model)、裁剪、样式