Skip to content

Commit e443602

Browse files
committed
feat: support terrain block & zoomTo
1 parent 0a79d1e commit e443602

File tree

11 files changed

+123
-85
lines changed

11 files changed

+123
-85
lines changed

example/src/components/ControlPanel.tsx

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { QuestionCircleOutlined } from '@ant-design/icons';
55
import ColorTableInput from './ColorTableInput';
66
import styled from 'styled-components';
77
import { GithubOutlined } from '@ant-design/icons';
8+
import { ZoomInOutlined } from '@ant-design/icons';
89

910
const { Text } = Typography;
1011

@@ -125,13 +126,10 @@ const CardTitle = styled.div`
125126
&:hover {
126127
opacity: 0.8;
127128
}
128-
129-
span {
130-
flex: 1;
131-
overflow: hidden;
132-
text-overflow: ellipsis;
133-
white-space: nowrap;
134-
}
129+
`;
130+
131+
const TitleText = styled.span`
132+
flex: 1;
135133
`;
136134

137135
const ControlPanelContainer = styled.div`
@@ -210,6 +208,35 @@ const GithubLink = () => (
210208
</GithubBadge>
211209
);
212210

211+
const TitleActions = styled.div`
212+
display: flex;
213+
align-items: center;
214+
gap: 8px;
215+
`;
216+
217+
const TitleButton = styled.button`
218+
display: flex;
219+
align-items: center;
220+
justify-content: center;
221+
width: 24px;
222+
height: 24px;
223+
padding: 0;
224+
background: transparent;
225+
border: none;
226+
cursor: pointer;
227+
color: rgba(0, 0, 0, 0.45);
228+
transition: all 0.3s;
229+
230+
&:hover {
231+
color: rgba(0, 0, 0, 0.85);
232+
background: rgba(0, 0, 0, 0.04);
233+
}
234+
235+
&:active {
236+
background: rgba(0, 0, 0, 0.08);
237+
}
238+
`;
239+
213240
interface ControlPanelProps {
214241
windLayer: WindLayer | null;
215242
initialOptions?: Partial<WindLayerOptions>;
@@ -231,7 +258,7 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
231258
...WindLayer.defaultOptions,
232259
...initialOptions,
233260
});
234-
}, [windLayer]);
261+
}, [windLayer, initialOptions]);
235262

236263
const renderLabel = (label: string, tooltip: string) => (
237264
<div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>
@@ -257,17 +284,28 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
257284
<StyledCard
258285
title={
259286
<CardTitle onClick={() => setCollapsed(!collapsed)}>
260-
<span>Wind Layer Controls</span>
261-
<CollapseButton $collapsed={collapsed}>
262-
<svg
263-
viewBox="0 0 24 24"
264-
width="12"
265-
height="12"
266-
fill="currentColor"
287+
<TitleText>Wind Layer Controls</TitleText>
288+
<TitleActions>
289+
<TitleButton
290+
onClick={(e) => {
291+
e.stopPropagation();
292+
windLayer?.zoomTo(1);
293+
}}
294+
title="Zoom to Wind Field"
267295
>
268-
<path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" />
269-
</svg>
270-
</CollapseButton>
296+
<ZoomInOutlined />
297+
</TitleButton>
298+
<CollapseButton $collapsed={collapsed}>
299+
<svg
300+
viewBox="0 0 24 24"
301+
width="12"
302+
height="12"
303+
fill="currentColor"
304+
>
305+
<path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" />
306+
</svg>
307+
</CollapseButton>
308+
</TitleActions>
271309
</CardTitle>
272310
}
273311
size="small"
@@ -302,7 +340,7 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
302340
'Height of particles above the ground in meters.'
303341
)}
304342
>
305-
<Slider min={0} max={100000} step={100} />
343+
<Slider min={-1000} max={10000} step={100} />
306344
</CompactFormItem>
307345

308346
<CompactFormItem
@@ -312,7 +350,7 @@ export const ControlPanel: React.FC<ControlPanelProps> = ({
312350
'Width of particle trails in pixels. Controls the width of the particles.'
313351
)}
314352
>
315-
<Slider min={1} max={10} step={0.5} />
353+
<Slider min={0.1} max={10} step={0.1} />
316354
</CompactFormItem>
317355

318356
<CompactFormItem

example/src/pages/earth.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { useEffect, useRef, useState } from 'react';
2-
import { Viewer, Rectangle, ArcGisMapServerImageryProvider, ImageryLayer } from 'cesium';
2+
import { Viewer, Rectangle, ArcGisMapServerImageryProvider, ImageryLayer, Ion, CesiumTerrainProvider } from 'cesium';
33
import { WindLayer, WindLayerOptions, WindData } from 'cesium-wind-layer';
44
import { ControlPanel } from '@/components/ControlPanel';
55
import styled from 'styled-components';
66
import { colorSchemes } from '@/components/ColorTableInput';
77

8+
Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhY2IzNzQzNi1iOTVkLTRkZjItOWVkZi1iMGUyYTUxN2Q5YzYiLCJpZCI6NTUwODUsImlhdCI6MTcyNTQyMDE4NX0.yHbHpszFexPrxX6_55y0RgNrHjBQNu9eYkW9cXKUTPk';
9+
810
const CesiumContainer = styled.div`
911
width: 100vw;
1012
height: 100vh;
@@ -14,6 +16,7 @@ const CesiumContainer = styled.div`
1416
const defaultOptions: Partial<WindLayerOptions> = {
1517
particlesTextureSize: 200,
1618
dropRate: 0.003,
19+
particleHeight: 1000,
1720
dropRateBump: 0.01,
1821
speedFactor: 10.0,
1922
lineWidth: 3.0,
@@ -50,7 +53,16 @@ export function Earth() {
5053
sceneModePicker: true,
5154
});
5255
}
56+
// Add terrain
57+
CesiumTerrainProvider.fromIonAssetId(1).then(terrainProvider => {
58+
if (viewerRef.current) {
59+
viewerRef.current.terrainProvider = terrainProvider;
60+
}
61+
});
5362

63+
viewerRef.current.scene.globe.depthTestAgainstTerrain = true;
64+
// Optional: Add exaggeration to make terrain features more visible
65+
viewerRef.current.scene.verticalExaggeration = 2;
5466
// Load wind data
5567
const loadWindData = async () => {
5668
// Skip if wind layer already exists or viewer is not initialized

packages/cesium-wind-layer/readme.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ A Cesium plugin for GPU-accelerated visualization of wind field data with partic
77

88
[中文文档](/packages/cesium-wind-layer/readme.zh-CN.md) | [Live Demo](https://cesium-wind-layer.opendde.com/)
99

10-
![Wind Layer Demo](/pictures/wind.gif)
10+
<div style="display: flex; justify-content: space-between;">
11+
<img src="/pictures/wind.gif" alt="Wind Layer Demo" style="width: 48%;">
12+
<img src="/pictures/terrain.gif" alt="Terrain Demo" style="width: 48%;">
13+
</div>
1114

1215
## 📚 Table of Contents
1316

@@ -23,7 +26,7 @@ A Cesium plugin for GPU-accelerated visualization of wind field data with partic
2326
- 🚀 GPU-accelerated particle computation and rendering
2427
- 🎨 Customizable particle appearance and behavior
2528
- 🌍 Support for both 2D and 3D views
26-
- 🔄 Compatible with Cesium 3D globe
29+
- 🏔️ Terrain occlusion support, particles are blocked by terrain
2730

2831
## 📦 Installation
2932

@@ -107,6 +110,7 @@ interface WindLayerOptions {
107110
| `show: boolean` | Get or set the visibility of the wind layer |
108111
| `updateWindData(data: WindData)` | Update the wind field data |
109112
| `updateOptions(options: Partial<WindLayerOptions>)` | Update the options of the wind layer |
113+
| `zoomTo(duration?: number)` | Zoom the camera to fit the wind field extent |
110114
| `isDestroyed(): boolean` | Check if the wind layer has been destroyed |
111115
| `destroy()` | Clean up resources and destroy the wind layer |
112116

packages/cesium-wind-layer/readme.zh-CN.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
[English](/packages/cesium-wind-layer/readme.md) | [在线演示](https://cesium-wind-layer.opendde.com/)
99

10-
![Wind Layer Demo](/pictures/wind.gif)
10+
<div style="display: flex; justify-content: space-between;">
11+
<img src="/pictures/wind.gif" alt="Wind Layer Demo" style="width: 48%;">
12+
<img src="/pictures/terrain.gif" alt="Terrain Demo" style="width: 48%;">
13+
</div>
1114

1215
## 📚 目录
1316

@@ -23,7 +26,7 @@
2326
- 🚀 GPU 加速的粒子计算和渲染
2427
- 🎨 可自定义粒子外观和行为
2528
- 🌍 支持 2D 和 3D 视图
26-
- 🔄 兼容 Cesium 3D 地球
29+
- 🏔️ 支持地形遮挡,粒子会被地形阻挡
2730

2831
## 📦 安装
2932

@@ -107,6 +110,7 @@ interface WindLayerOptions {
107110
| `show: boolean` | 获取或设置风场图层的可见性 |
108111
| `updateWindData(data: WindData)` | 更新风场数据 |
109112
| `updateOptions(options: Partial<WindLayerOptions>)` | 更新风场图层的选项 |
113+
| `zoomTo(duration?: number)` | 缩放相机以适应风场范围 |
110114
| `isDestroyed(): boolean` | 检查风场图层是否已被销毁 |
111115
| `destroy()` | 清理资源并销毁风场图层 |
112116

packages/cesium-wind-layer/src/index.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
BoundingSphere,
88
Ellipsoid,
99
SceneMode,
10-
Math as CesiumMath
10+
Math as CesiumMath,
11+
Rectangle
1112
} from 'cesium';
1213

1314
import { WindLayerOptions, WindData } from './types';
@@ -193,6 +194,21 @@ export class WindLayer {
193194
this.viewer.scene.requestRender();
194195
}
195196

197+
zoomTo(duration: number = 0): void {
198+
if (this.windData.bounds) {
199+
const rectangle = Rectangle.fromDegrees(
200+
this.windData.bounds.west,
201+
this.windData.bounds.south,
202+
this.windData.bounds.east,
203+
this.windData.bounds.north
204+
);
205+
this.viewer.camera.flyTo({
206+
destination: rectangle,
207+
duration,
208+
});
209+
}
210+
}
211+
196212
add(): void {
197213
this.primitives = this.particleSystem.getPrimitives();
198214
this.primitives.forEach(primitive => {

packages/cesium-wind-layer/src/shaderManager.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { updatePositionShader } from './shaders/updatePosition';
33
import { calculateSpeedShader } from './shaders/calculateSpeed';
44
import { postProcessingPositionFragmentShader } from './shaders/postProcessingPosition';
55
import { renderParticlesFragmentShader, renderParticlesVertexShader } from './shaders/segmentDraw';
6-
import { fullscreenQuadVertexShader } from './shaders/fullscreenQuad';
7-
import { screenDrawFragmentShader } from './shaders/screenDraw';
86

97
export class ShaderManager {
108
static getCalculateSpeedShader(): ShaderSource {
@@ -37,17 +35,4 @@ export class ShaderManager {
3735
});
3836
}
3937

40-
static getFullscreenQuadVertexShader(): ShaderSource {
41-
return new ShaderSource({
42-
defines: ['DISABLE_GL_POSITION_LOG_DEPTH'],
43-
sources: [fullscreenQuadVertexShader]
44-
});
45-
}
46-
47-
static getScreenDrawFragmentShader(): ShaderSource {
48-
return new ShaderSource({
49-
defines: ['DISABLE_LOG_DEPTH_FRAGMENT_WRITE'],
50-
sources: [screenDrawFragmentShader]
51-
});
52-
}
5338
}

packages/cesium-wind-layer/src/shaders/fullscreenQuad.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

packages/cesium-wind-layer/src/shaders/screenDraw.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)