| 123456789101112131415161718192021222324252627282930313233343536373839404142434445 |
- import assert from 'node:assert/strict'
- import { register } from 'node:module'
- import { readFile } from 'node:fs/promises'
- import { pipeSurface } from '../../../src/modules/cockpit/domain/pipePhysical.js'
- register('../../cockpit-real-data-wayfinding/verify/t32-adapter-io-loader.mjs', import.meta.url)
- const { createCesiumPipeModels } = await import('../../../src/modules/cockpit/services/cesiumPipeModels.js')
- const { createPipeModelShader } = await import('../../../src/modules/cockpit/services/pipeModelShader.js')
- const { LightingModel } = await import('cesium')
- globalThis.t32Models = []
- globalThis.t32TerrainFails = false
- globalThis.window = { location: { href: 'http://test.invalid/cockpit/', origin: 'http://test.invalid' } }
- const nativeFetch = globalThis.fetch
- const source = { entities: { values: [] } }
- const viewer = { terrainProvider: {}, isDestroyed: () => false, scene: { requestRender() {}, primitives: { add() {}, remove(m) { m.destroy() } } } }
- const pipes = [
- { code: 'pe', industry: 'WATER_SUPPLY', diameter: 400, material: 'PE', positions: [[110.39, 28.44], [110.3901, 28.44]] },
- { code: 'steel', industry: 'WATER_SUPPLY', diameter: 200, material: '钢管', positions: [[110.39, 28.4401], [110.3901, 28.4401]] },
- ]
- function values(model, key) {
- const accessor = model.gltf.accessors[model.gltf.nodes[0].extensions.EXT_mesh_gpu_instancing.attributes[key]]
- const view = model.gltf.bufferViews[accessor.bufferView]
- const data = model.gltf.buffers[view.buffer].uri.split(',')[1]
- const bytes = Buffer.from(data, 'base64')
- return new Float32Array(bytes.buffer, bytes.byteOffset + (view.byteOffset || 0), accessor.count * 3)
- }
- let adapter
- try {
- globalThis.fetch = async (url) => String(url).startsWith('blob:') ? nativeFetch(url)
- : new Response(await readFile(new URL('../../../public/cockpit/models/pipes/spline.gltf', import.meta.url), 'utf8'))
- adapter = createCesiumPipeModels(viewer, { source })
- await adapter.sync({ pipes })
- assert.equal(globalThis.t32Models.length, 2, '同业不同材质必须拆为不同着色批次')
- const [pe, steel] = globalThis.t32Models
- assert.ok(Math.abs(values(pe, 'SCALE')[0] - 0.4) < 1e-6)
- assert.ok(Math.abs(values(steel, 'SCALE')[0] - 0.2) < 1e-6)
- assert.ok(values(pe, 'SCALE')[2] > 9 && values(pe, 'SCALE')[2] < 11, '轴向长度保持地理路径')
- const shader = createPipeModelShader('WATER_SUPPLY', pipeSurface('PE'))
- assert.equal(shader.lightingModel, LightingModel.PBR)
- assert.equal(shader.uniforms.u_pipeMetalness.value, 0)
- shader.destroy()
- await adapter.sync({ pipes: [{ ...pipes[0], material: '钢管' }, pipes[1]] })
- assert.ok(globalThis.t32Models.length > 2, '仅材质变化也触发3D更新')
- assert.equal(pe.isDestroyed(), true)
- console.log('PASS 主图GPU实例源直径和地理长度、按材质分组/PBR参数、仅材质更新与旧批次释放')
- } finally { adapter?.destroy(); globalThis.fetch = nativeFetch }
|