基于 ThreeJS 的 DTE 库使用 - 云图 shaderMesh

三葉Leaves Author

本文是我在某中厂任职时的学习笔记,用到 DTE 库是基于 ThreeJS 实现的闭源的公司内部库,替代方案和说明可见 DTE 库的开源替代方案(ThreeJS 等)

[!quote]
DTE封装了ShaderMesh 进行云图渲染。

  • 所谓云图,就是根据每个顶点所携带的数据 来渲染颜色。 顶点上的数据,一般由DTE后端仿真计算而来,代表各种物理量的分布。
  • 在数字孪生项目中,这些数据可能代表一个模型上的温度(或者压强、应力、位移等),我们可以将这些物理量数据配合色带进行可视化。

一台发动机,它不同部位的温度是不同的;一座桥梁,它不同位置承受的压力也不同。

我们的目标,就是要在三维模型上,把这些看不见的物理数据(温度、压力、速度等)用直观的方式可视化出来。

最常见的方式,就是用颜色。比如,温度高的地方显示为红色,温度低的地方显示为蓝色。这种根据数据渲染颜色的图,我们通常称之为云图(Heatmap / Contour Map)**。

示例代码

这里用到的测试资源是一个模拟的人体头部温度分布的数据:

  • URL:https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/json/pressure.json
  • 包含了头部的几何模型,也包含了每个顶点上的一个名为 ‘pressure’ 的数据属性。
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
// ================ 场景部分  

// 创建DTE容器实例
const container3D = new CommonContainer({
domId: 'my-3d-container',
});

// 保存引用以便后续清理
container3DRef.current = container3D;

// 获取"铁三角":场景、相机、渲染器
const { scene, camera, renderer } = container3D;

// 验证是否成功创建
if (scene && camera && renderer) {
console.log('成功创建了一个三维空间!');
}

// ================ 加载器部分

// 1. 创建 JSON 加载器实例
const loader = new JsonLoader();

// 随便找了个 JSON 在线 Urlconst dataUrl =
'https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/models/json/pressure.json';

// 2. 使用回调函数方式加载数据
loader.loadDataMesh(dataUrl, (meshData) => {
// 当第一个参数里传入的 URL 的 JSON 数据解析完成后,这里的代码会执行
console.log('数据几何体加载成功!', meshData);
console.log('几何体携带的属性数据:', meshData.attributes);
console.log('几何体携带的元数据 (比如最大最小值):', meshData.userData);

// 3. 准备创建 shaderMesh // 要可视化哪一个物理量?这里我选择 pressure const attrName = 'pressure';
// 为了让颜色映射正确,我们需要告诉 ShaderMesh 数据的范围。
// 比如速度范围是 0 到 100。
// 这个信息通常也保存在 `meshData.userData` 中,非常方便。
const minValue = meshData.userData[attrName].minValue;
const maxValue = meshData.userData[attrName].maxValue;
console.log(
`准备根据属性 '${attrName}' 创建云图,数据范围: ${minValue} ~ ${maxValue}`,
);

// 4. 创建 ShaderMesh 实例
const shaderMesh = new ShaderMesh(meshData, attrName, {
minValue,
maxValue,
});

container3D.scene.add(shaderMesh);
});

代码中有两个核心步骤:

1. 数据哪里来?

代码中可见我们创建了 JsonLoader 实例,它的作用和 ModelLoader 有点像,但更专注于加载一种特殊的JSON文件。这种JSON文件不仅包含了模型的几何形状(Geometry),还捆绑了与之对应的物理数据

我们解析后得到的 meshData,其中的 meshData.attributes 就可能包含了每个点的重要物理信息,例如:

1
2
3
4
5
6
meshData.attributes = {
position: [x1, y1, z1, x2, y2, z2, ...], // 顶点位置数组
Velocity: [v1, v2, v3, ...], // 每个顶点的速度数据
Pressure: [p1, p2, p3, ...], // 每个顶点的压力数据
// ... 其他物理量
}

position 数组里的第1个坐标 (x1, y1, z1),就对应 Velocity 数组里的第1个速度值 v1,和 Pressure 数组里的第1个压力值 p1。它们是强关联的。

2. 数据怎么画

现在我们有了一个包含了丰富数据的 Geometry (meshData)。但普通的 MeshBasicMaterial 只会用一种颜色(比如绿色)去涂满整个模型,它根本不关心 Velocity 或 Pressure 这些数据。

我们需要一个更聪明的“画家”,它能:

  1. 读取到每个顶点上绑定的特定数据(比如 Velocity)。

  2. 根据这个数据的大小,去一个色带(Color Ramp / Gradient) 上查询对应的颜色。

  3. 用查到的颜色给这个顶点上色。

这个聪明的“画家”,在DTE里就是 ShaderMesh。

Shader(着色器)这个词听起来很高级,但你现在可以把它简单理解为一段能在显卡(GPU)上运行的、用来计算像素最终颜色的小程序。ShaderMesh 就是一个内置了这种“数据-颜色”映射逻辑的、高度封装好的 Mesh。

userData 并不符合预期?

不同的数据源,其 userData 的结构可能略有不同。DTE 体系内生成的数据,其 userData 结构会非常规范(比如 userData.Velocity.minValue)。

而我们现在用的这个社区测试文件,它的元数据可能藏在别处,或者需要我们自己遍历一遍数据来计算最大最小值。

下面的代码,我们手动计算出需要用到的最大值和最小值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// --- 手动计算最大最小值 ---
const pressureArray = meshData.attributes.pressure.array;
let calculatedMin = pressureArray[0]; // 暂时假设第一个数是最小值
let calculatedMax = pressureArray[0]; // 暂时假设第一个数是最大值

// 遍历整个数组来寻找真正的最大最小值
for (let i = 1; i < pressureArray.length; i++) {
const value = pressureArray[i];
if (value < calculatedMin) {
calculatedMin = value;
}
if (value > calculatedMax) {
calculatedMax = value;
}
}

console.log(`手动计算出的 '${attrName}' 范围: ${calculatedMin} ~ ${calculatedMax}`);

// --- 使用我们自己计算出的值 ---
const minValue = calculatedMin;
const maxValue = calculatedMax;

本课小结

  • 我们理解了数字孪生中数据可视化的核心思想:将不可见的物理数据通过颜色等视觉元素在三维模型上呈现出来。

  • 我们学会了使用 JsonLoader 来加载一种特殊的、几何与数据绑定的模型

  • 我们了解了 meshData.attributes 的结构,知道了 position 和其他自定义属性(如 pressure)是如何一一对应的。

  • 我们认识了强大的 ShaderMesh,它是一个专门用于渲染云图的物料,能够自动完成“数据值 -> 颜色”的映射。

  • 我们明白了 minValue 和 maxValue 的重要性,它们定义了数据映射到色带的范围,是保证颜色正确呈现的标尺

  • 标题: 基于 ThreeJS 的 DTE 库使用 - 云图 shaderMesh
  • 作者: 三葉Leaves
  • 创建于 : 2025-07-31 00:00:00
  • 更新于 : 2025-08-13 16:31:27
  • 链接: https://blog.oksanye.com/bebd76f5c7de/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
基于 ThreeJS 的 DTE 库使用 - 云图 shaderMesh