@anov/gis-skills-cli 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +618 -0
- package/INSTALL.md +478 -0
- package/LICENSE +15 -0
- package/README.md +148 -2
- package/RELEASING.md +160 -0
- package/bin/anov-gis-skills.mjs +408 -0
- package/lib/mcp-config.mjs +273 -0
- package/package.json +42 -4
- package/skills/anovgis-analysis/SKILL.md +585 -0
- package/skills/anovgis-effects/SKILL.md +260 -0
- package/skills/anovgis-imagery-terrain/SKILL.md +505 -0
- package/skills/anovgis-layers/SKILL.md +627 -0
- package/skills/anovgis-materials/SKILL.md +635 -0
- package/skills/anovgis-models-3dtiles/SKILL.md +448 -0
- package/skills/anovgis-pitfalls/SKILL.md +561 -0
- package/skills/anovgis-popup-widget/SKILL.md +474 -0
- package/skills/anovgis-primitives/SKILL.md +482 -0
- package/skills/anovgis-vector-graphics/SKILL.md +602 -0
- package/skills/anovgis-viewer/SKILL.md +618 -0
- package/skills/using-anovgis/DEMO-MAP.md +64 -0
- package/skills/using-anovgis/DEMO-SKILL-MAP.md +248 -0
- package/skills/using-anovgis/DOMAINS.md +183 -0
- package/skills/using-anovgis/REFERENCE.md +114 -0
- package/skills/using-anovgis/SKILL.md +392 -0
- package/skills/using-anovgis/templates/README.md +154 -0
- package/skills/using-anovgis/templates/combo1-vue3-vite.md +295 -0
- package/skills/using-anovgis/templates/combo2-vue2-cli.md +119 -0
- package/skills/using-anovgis/templates/combo3-html-cdn.md +107 -0
- package/skills/using-anovgis/templates/combo4-vanilla-webpack.md +91 -0
- package/skills/using-anovgis/templates/wizard-profiles.md +105 -0
- package/vendor/cesiumjs-skills/LICENSE +201 -0
- package/vendor/cesiumjs-skills/NOTICE +18 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-3d-tiles/SKILL.md +465 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-camera/SKILL.md +500 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-core-utilities/SKILL.md +403 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/REFERENCE.md +397 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/SKILL.md +351 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/01-diffuse-tint.js +38 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/02-texture-swap.js +42 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/03-feature-id-tileset.js +29 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/04-translucent-override.js +37 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/05-vertex-displacement.js +49 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/06-metadata-ramp.js +34 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/07-voxel-shader.js +27 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/README.md +19 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/_sandcastle-template.html +9 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-entities/SKILL.md +389 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-imagery/SKILL.md +471 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-interaction/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-materials-shaders/SKILL.md +292 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-models-particles/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-primitives/SKILL.md +537 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-spatial-math/SKILL.md +358 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-terrain-environment/SKILL.md +401 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-time-properties/SKILL.md +353 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-viewer-setup/SKILL.md +434 -0
- package/vendor/cesiumjs-skills/skills/using-cesiumjs-skills/SKILL.md +35 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cesiumjs-models-particles
|
|
3
|
+
description: "CesiumJS models, glTF, and particle effects - Model, EdgeDisplayMode, ModelAnimation, ModelNode, ParticleSystem, emitters, GPM extensions. Use when loading glTF/GLB 3D models, controlling edge rendering, playing model animations, positioning particle effects like fire or smoke, or working with geospatial positioning metadata."
|
|
4
|
+
---
|
|
5
|
+
# CesiumJS Models, glTF & Particle Effects
|
|
6
|
+
|
|
7
|
+
Version baseline: CesiumJS v1.142.
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
| Class | Purpose |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `Model` | Low-level glTF/GLB primitive; positioned via `modelMatrix` |
|
|
14
|
+
| `ModelAnimation` | Active animation instance on a model |
|
|
15
|
+
| `ModelAnimationCollection` | Collection at `model.activeAnimations` |
|
|
16
|
+
| `ModelNode` | Named node with modifiable transform |
|
|
17
|
+
| `ModelFeature` | Per-feature styling/picking for feature-ID models |
|
|
18
|
+
| `EdgeDisplayMode` | Controls draft glTF edge-visibility rendering on Model/Cesium3DTileset |
|
|
19
|
+
| `ParticleSystem` | Billboard-based particle manager (fire, smoke, rain) |
|
|
20
|
+
| `Particle` | Single particle with position, velocity, life |
|
|
21
|
+
| `ParticleBurst` | Scheduled burst of particles |
|
|
22
|
+
| `BoxEmitter` / `CircleEmitter` | Emit within box volume / flat disk |
|
|
23
|
+
| `ConeEmitter` / `SphereEmitter` | Emit from cone tip / within sphere |
|
|
24
|
+
|
|
25
|
+
The Entity API exposes models through `ModelGraphics` (see cesiumjs-entities). The Primitive API uses `Model.fromGltfAsync` for full control over `modelMatrix`, animations, and node transforms.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Loading a glTF/GLB Model
|
|
30
|
+
|
|
31
|
+
Always use the async factory -- never call the constructor directly.
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { Model, Cartesian3, Transforms, HeadingPitchRoll, Math as CesiumMath } from "cesium";
|
|
35
|
+
|
|
36
|
+
const model = await Model.fromGltfAsync({ url: "path/to/model.glb" });
|
|
37
|
+
viewer.scene.primitives.add(model);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Positioned Model with Heading
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const position = Cartesian3.fromDegrees(-123.074, 44.050, 5000);
|
|
44
|
+
const hpr = new HeadingPitchRoll(CesiumMath.toRadians(135), 0, 0);
|
|
45
|
+
|
|
46
|
+
const model = await Model.fromGltfAsync({
|
|
47
|
+
url: "CesiumAir.glb",
|
|
48
|
+
modelMatrix: Transforms.headingPitchRollToFixedFrame(position, hpr),
|
|
49
|
+
minimumPixelSize: 128, // never smaller than 128 px on screen
|
|
50
|
+
maximumScale: 20000, // cap for minimumPixelSize enlargement
|
|
51
|
+
scale: 2.0, // uniform scale multiplier
|
|
52
|
+
});
|
|
53
|
+
viewer.scene.primitives.add(model);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Key `Model.fromGltfAsync` Options
|
|
57
|
+
|
|
58
|
+
| Option | Type | Default |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `url` | `string\|Resource` | required |
|
|
61
|
+
| `modelMatrix` | `Matrix4` | `IDENTITY` |
|
|
62
|
+
| `scale` | `number` | `1.0` |
|
|
63
|
+
| `minimumPixelSize` | `number` | `0.0` |
|
|
64
|
+
| `maximumScale` | `number` | -- |
|
|
65
|
+
| `show` | `boolean` | `true` |
|
|
66
|
+
| `color` / `colorBlendMode` / `colorBlendAmount` | `Color` / `ColorBlendMode` / `number` | -- / `HIGHLIGHT` / `0.5` |
|
|
67
|
+
| `edgeDisplayMode` | `EdgeDisplayMode` | `SURFACES_ONLY` |
|
|
68
|
+
| `silhouetteColor` / `silhouetteSize` | `Color` / `number` | `RED` / `0.0` |
|
|
69
|
+
| `shadows` | `ShadowMode` | `ENABLED` |
|
|
70
|
+
| `heightReference` | `HeightReference` | `NONE` |
|
|
71
|
+
| `customShader` | `CustomShader` | -- |
|
|
72
|
+
| `id` | `any` | -- |
|
|
73
|
+
| `allowPicking` | `boolean` | `true` |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Readiness and Lifecycle
|
|
78
|
+
|
|
79
|
+
`fromGltfAsync` resolves once glTF JSON is parsed, but WebGL resources may still load. Wait for `readyEvent` before accessing animations, nodes, or `boundingSphere`.
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
const model = await Model.fromGltfAsync({ url: "robot.glb" });
|
|
83
|
+
viewer.scene.primitives.add(model);
|
|
84
|
+
|
|
85
|
+
model.readyEvent.addEventListener(() => {
|
|
86
|
+
console.log("Bounding sphere:", model.boundingSphere);
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
// Synchronous check
|
|
92
|
+
if (model.ready) { const bs = model.boundingSphere; }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Animations
|
|
98
|
+
|
|
99
|
+
Managed through `model.activeAnimations` (`ModelAnimationCollection`).
|
|
100
|
+
|
|
101
|
+
### Play by Name / Play All
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
model.readyEvent.addEventListener(() => {
|
|
105
|
+
// Single animation
|
|
106
|
+
const anim = model.activeAnimations.add({
|
|
107
|
+
name: "Walk", // glTF animation name
|
|
108
|
+
loop: Cesium.ModelAnimationLoop.REPEAT, // NONE | REPEAT | MIRRORED_REPEAT
|
|
109
|
+
multiplier: 1.0, // playback speed (must be > 0)
|
|
110
|
+
});
|
|
111
|
+
anim.start.addEventListener((m, a) => console.log(`Started: ${a.name}`));
|
|
112
|
+
|
|
113
|
+
// Or play all animations at once
|
|
114
|
+
model.activeAnimations.addAll({
|
|
115
|
+
loop: Cesium.ModelAnimationLoop.REPEAT,
|
|
116
|
+
multiplier: 0.5,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Additional `add` options: `index`, `reverse`, `startTime`, `stopTime`, `delay`, `removeOnStop`, `animationTime` (custom time callback).
|
|
122
|
+
|
|
123
|
+
### Animation Events
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
animation.start.addEventListener((model, animation) => { });
|
|
127
|
+
animation.update.addEventListener((model, animation, time) => { });
|
|
128
|
+
animation.stop.addEventListener((model, animation) => { });
|
|
129
|
+
// Collection-level
|
|
130
|
+
model.activeAnimations.animationAdded.addEventListener((model, anim) => { });
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
model.activeAnimations.remove(animation); // remove one
|
|
135
|
+
model.activeAnimations.removeAll(); // remove all
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Model Nodes
|
|
141
|
+
|
|
142
|
+
Override named node transforms for procedural animation (e.g., turret rotation).
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
model.readyEvent.addEventListener(() => {
|
|
146
|
+
const node = model.getNode("Turret");
|
|
147
|
+
node.matrix = Cesium.Matrix4.fromScale(
|
|
148
|
+
new Cesium.Cartesian3(5.0, 1.0, 1.0), node.matrix
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Properties: `name` (read-only), `id` (read-only index), `show` (boolean), `matrix` (Matrix4 -- set to `undefined` to restore original and re-enable glTF animations).
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Coloring, Silhouettes, and Feature Picking
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
// Tint + silhouette
|
|
161
|
+
model.color = Cesium.Color.RED.withAlpha(0.5);
|
|
162
|
+
model.colorBlendMode = Cesium.ColorBlendMode.MIX;
|
|
163
|
+
model.colorBlendAmount = 0.5;
|
|
164
|
+
model.silhouetteColor = Cesium.Color.YELLOW;
|
|
165
|
+
model.silhouetteSize = 2.0;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Edge Display Mode (Experimental, 1.142+)
|
|
169
|
+
|
|
170
|
+
For glTF assets using the draft `EXT_mesh_primitive_edge_visibility` extension,
|
|
171
|
+
`EdgeDisplayMode` controls whether extension-provided edges are hidden, composited
|
|
172
|
+
over surfaces, or rendered alone. Models without the extension are unaffected.
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
import { EdgeDisplayMode, Model } from "cesium";
|
|
176
|
+
|
|
177
|
+
const model = await Model.fromGltfAsync({
|
|
178
|
+
url: "/models/cad-part.glb",
|
|
179
|
+
edgeDisplayMode: EdgeDisplayMode.SURFACES_AND_EDGES,
|
|
180
|
+
});
|
|
181
|
+
viewer.scene.primitives.add(model);
|
|
182
|
+
|
|
183
|
+
model.edgeDisplayMode = EdgeDisplayMode.EDGES_ONLY; // CAD-style wireframe
|
|
184
|
+
model.edgeDisplayMode = EdgeDisplayMode.SURFACES_ONLY; // default
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
When a glTF has `EXT_mesh_features` or `EXT_structural_metadata`, picking returns a `ModelFeature`:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|
191
|
+
handler.setInputAction((movement) => {
|
|
192
|
+
const picked = viewer.scene.pick(movement.endPosition);
|
|
193
|
+
if (picked instanceof Cesium.ModelFeature) {
|
|
194
|
+
picked.getPropertyIds().forEach((name) => {
|
|
195
|
+
console.log(`${name}: ${picked.getProperty(name)}`);
|
|
196
|
+
});
|
|
197
|
+
picked.color = Cesium.Color.YELLOW;
|
|
198
|
+
}
|
|
199
|
+
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Height Reference
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
// Primitive API -- scene is required for height reference
|
|
208
|
+
const model = await Model.fromGltfAsync({
|
|
209
|
+
url: "truck.glb",
|
|
210
|
+
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|
211
|
+
scene: viewer.scene,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Entity API
|
|
215
|
+
viewer.entities.add({
|
|
216
|
+
position: Cartesian3.fromDegrees(-75.59, 40.03),
|
|
217
|
+
model: { uri: "truck.glb", heightReference: Cesium.HeightReference.CLAMP_TO_GROUND },
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Values: `NONE`, `CLAMP_TO_GROUND`, `RELATIVE_TO_GROUND`, `CLAMP_TO_TERRAIN`, `RELATIVE_TO_TERRAIN`, `CLAMP_TO_3D_TILE`, `RELATIVE_TO_3D_TILE`.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Particle Systems
|
|
226
|
+
|
|
227
|
+
`ParticleSystem` renders billboard-based effects. Position with `modelMatrix` (world) and `emitterModelMatrix` (local offset).
|
|
228
|
+
|
|
229
|
+
### Smoke Trail
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
import { ParticleSystem, CircleEmitter, Color, Cartesian2, Transforms, Cartesian3 } from "cesium";
|
|
233
|
+
|
|
234
|
+
const smokeSystem = new ParticleSystem({
|
|
235
|
+
image: "smoke.png",
|
|
236
|
+
startColor: Color.LIGHTGRAY.withAlpha(0.7),
|
|
237
|
+
endColor: Color.WHITE.withAlpha(0.0),
|
|
238
|
+
startScale: 1.0,
|
|
239
|
+
endScale: 5.0,
|
|
240
|
+
emissionRate: 10,
|
|
241
|
+
minimumSpeed: 1.0,
|
|
242
|
+
maximumSpeed: 4.0,
|
|
243
|
+
minimumParticleLife: 1.2,
|
|
244
|
+
maximumParticleLife: 3.0,
|
|
245
|
+
imageSize: new Cartesian2(25, 25), // pixel size
|
|
246
|
+
emitter: new CircleEmitter(2.0), // radius in meters
|
|
247
|
+
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.157, 39.978)),
|
|
248
|
+
lifetime: 16.0,
|
|
249
|
+
loop: true,
|
|
250
|
+
});
|
|
251
|
+
viewer.scene.primitives.add(smokeSystem);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Emitter Types
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
import { BoxEmitter, CircleEmitter, ConeEmitter, SphereEmitter } from "cesium";
|
|
258
|
+
|
|
259
|
+
new BoxEmitter(new Cesium.Cartesian3(10, 10, 10)); // 3D box, velocity outward
|
|
260
|
+
new CircleEmitter(2.0); // flat disk, velocity +Z
|
|
261
|
+
new ConeEmitter(Cesium.Math.toRadians(30)); // cone tip, velocity toward base
|
|
262
|
+
new SphereEmitter(5.0); // sphere, velocity radiates out
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Particle Bursts
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
const firework = new ParticleSystem({
|
|
269
|
+
image: getParticleCanvas(),
|
|
270
|
+
startColor: Color.RED,
|
|
271
|
+
endColor: Color.RED.withAlpha(0.0),
|
|
272
|
+
particleLife: 1.0,
|
|
273
|
+
speed: 100.0,
|
|
274
|
+
imageSize: new Cartesian2(7, 7),
|
|
275
|
+
emissionRate: 0, // bursts only
|
|
276
|
+
emitter: new SphereEmitter(0.1),
|
|
277
|
+
bursts: [
|
|
278
|
+
new Cesium.ParticleBurst({ time: 0.0, minimum: 100, maximum: 200 }),
|
|
279
|
+
new Cesium.ParticleBurst({ time: 2.0, minimum: 50, maximum: 100 }),
|
|
280
|
+
new Cesium.ParticleBurst({ time: 4.0, minimum: 200, maximum: 300 }),
|
|
281
|
+
],
|
|
282
|
+
lifetime: 6.0,
|
|
283
|
+
loop: false,
|
|
284
|
+
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.597, 40.038)),
|
|
285
|
+
});
|
|
286
|
+
viewer.scene.primitives.add(firework);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Update Callback (Gravity / Wind)
|
|
290
|
+
|
|
291
|
+
The `updateCallback` runs per-particle per-frame for forces like gravity.
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
const gravityScratch = new Cesium.Cartesian3();
|
|
295
|
+
function applyGravity(particle, dt) {
|
|
296
|
+
Cesium.Cartesian3.normalize(particle.position, gravityScratch);
|
|
297
|
+
Cesium.Cartesian3.multiplyByScalar(gravityScratch, -9.8 * dt, gravityScratch);
|
|
298
|
+
particle.velocity = Cesium.Cartesian3.add(particle.velocity, gravityScratch, particle.velocity);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const system = new ParticleSystem({
|
|
302
|
+
image: "smoke.png",
|
|
303
|
+
emissionRate: 20,
|
|
304
|
+
emitter: new ConeEmitter(Cesium.Math.toRadians(45)),
|
|
305
|
+
updateCallback: applyGravity,
|
|
306
|
+
modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-105, 40, 1000)),
|
|
307
|
+
});
|
|
308
|
+
viewer.scene.primitives.add(system);
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Attaching Particles to a Moving Model
|
|
314
|
+
|
|
315
|
+
Sync `modelMatrix` each frame via `scene.preUpdate`. Use `emitterModelMatrix` for a local offset (e.g., exhaust pipe).
|
|
316
|
+
|
|
317
|
+
```js
|
|
318
|
+
const entity = viewer.entities.add({
|
|
319
|
+
position: sampledPosition,
|
|
320
|
+
orientation: new Cesium.VelocityOrientationProperty(sampledPosition),
|
|
321
|
+
model: { uri: "truck.glb", minimumPixelSize: 64 },
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Local offset to exhaust pipe
|
|
325
|
+
const trs = new Cesium.TranslationRotationScale();
|
|
326
|
+
trs.translation = new Cesium.Cartesian3(-4.0, 0.0, 1.4);
|
|
327
|
+
const emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());
|
|
328
|
+
|
|
329
|
+
const exhaust = new ParticleSystem({
|
|
330
|
+
image: "smoke.png",
|
|
331
|
+
startColor: Color.GRAY.withAlpha(0.7),
|
|
332
|
+
endColor: Color.TRANSPARENT,
|
|
333
|
+
emissionRate: 8,
|
|
334
|
+
speed: 2.0,
|
|
335
|
+
particleLife: 1.5,
|
|
336
|
+
imageSize: new Cartesian2(20, 20),
|
|
337
|
+
emitter: new CircleEmitter(0.5),
|
|
338
|
+
emitterModelMatrix: emitterModelMatrix,
|
|
339
|
+
});
|
|
340
|
+
viewer.scene.primitives.add(exhaust);
|
|
341
|
+
|
|
342
|
+
viewer.scene.preUpdate.addEventListener((scene, time) => {
|
|
343
|
+
exhaust.modelMatrix = entity.computeModelMatrix(time, new Cesium.Matrix4());
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Canvas-Based Particle Images
|
|
350
|
+
|
|
351
|
+
Generate particle textures dynamically instead of loading image files.
|
|
352
|
+
|
|
353
|
+
```js
|
|
354
|
+
function createCircleImage() {
|
|
355
|
+
const c = document.createElement("canvas");
|
|
356
|
+
c.width = c.height = 20;
|
|
357
|
+
const ctx = c.getContext("2d");
|
|
358
|
+
ctx.beginPath();
|
|
359
|
+
ctx.arc(10, 10, 10, 0, Math.PI * 2);
|
|
360
|
+
ctx.fillStyle = "#fff";
|
|
361
|
+
ctx.fill();
|
|
362
|
+
return c;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Pass canvas directly as image
|
|
366
|
+
new ParticleSystem({ image: createCircleImage(), /* ...other options */ });
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Entity API Model (ModelGraphics)
|
|
372
|
+
|
|
373
|
+
For simpler use cases, add a model through the Entity API (see cesiumjs-entities for full coverage).
|
|
374
|
+
|
|
375
|
+
```js
|
|
376
|
+
const entity = viewer.entities.add({
|
|
377
|
+
name: "Aircraft",
|
|
378
|
+
position: Cartesian3.fromDegrees(-123.074, 44.050, 5000),
|
|
379
|
+
orientation: Cesium.Transforms.headingPitchRollQuaternion(
|
|
380
|
+
Cartesian3.fromDegrees(-123.074, 44.050, 5000),
|
|
381
|
+
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(135), 0, 0)
|
|
382
|
+
),
|
|
383
|
+
model: {
|
|
384
|
+
uri: "CesiumAir.glb",
|
|
385
|
+
minimumPixelSize: 128,
|
|
386
|
+
maximumScale: 20000,
|
|
387
|
+
silhouetteColor: Color.RED,
|
|
388
|
+
silhouetteSize: 2.0,
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
viewer.trackedEntity = entity;
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## GPM Extension (NGA_gpm_local)
|
|
397
|
+
|
|
398
|
+
CesiumJS experimentally supports the NGA Geospatial Positioning Metadata glTF extension. Types: `AnchorPointDirect`, `AnchorPointIndirect`, `CorrelationGroup`, `GltfGpmLocal`, `Spdcf`. Parsed automatically when loading a glTF with `NGA_gpm_local` -- the API is experimental and subject to change.
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Performance Tips
|
|
403
|
+
|
|
404
|
+
1. **Use `.glb` over `.gltf`** -- binary format avoids extra HTTP requests and is smaller on the wire.
|
|
405
|
+
2. **Enable Draco compression** (`KHR_draco_mesh_compression`) for 80-90% smaller meshes.
|
|
406
|
+
3. **Use KTX2/Basis textures** (`KHR_texture_basisu`) for GPU-compressed textures; keep dimensions power-of-two.
|
|
407
|
+
4. **Set `minimumPixelSize` carefully** -- large values force enlargement of distant models, increasing draw cost.
|
|
408
|
+
5. **Limit silhouettes** -- extra rendering pass per silhouetted model; more than 256 may cause stencil artifacts.
|
|
409
|
+
6. **Reuse scratch `Matrix4` objects** -- avoid allocating every frame when syncing particle systems to moving entities.
|
|
410
|
+
7. **Keep emission rates low** -- each particle is a billboard; rates above 200/s can hurt frame rate. Use bursts for short effects.
|
|
411
|
+
8. **Prefer pixel-sized particles** (`sizeInMeters: false`, default) -- meter-sized particles are expensive at close range.
|
|
412
|
+
9. **Set finite `lifetime`** on particle systems -- `Number.MAX_VALUE` (default) prevents pool cleanup.
|
|
413
|
+
10. **Disable picking for decorations** -- `allowPicking: false` saves GPU memory on models that need no interaction.
|
|
414
|
+
11. **Destroy when done** -- `viewer.scene.primitives.remove(model)` then `model.destroy()` to free WebGL resources.
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## See Also
|
|
419
|
+
|
|
420
|
+
- **cesiumjs-custom-shader** -- GLSL authoring for `Model.customShader` (struct reference, feature IDs, metadata, vertex displacement)
|
|
421
|
+
- **cesiumjs-materials-shaders** -- ImageBasedLighting, post-processing stages for models
|
|
422
|
+
- **cesiumjs-entities** -- Entity API ModelGraphics, data sources, time-dynamic properties
|
|
423
|
+
- **cesiumjs-3d-tiles** -- Cesium3DTileset (uses Model internally), clipping, styling
|