|
|
@ -4,10 +4,12 @@ import { Text } from 'troika-three-text' |
|
|
import MoveLinePointPng from '@/assets/images/moveline_point.png' |
|
|
import MoveLinePointPng from '@/assets/images/moveline_point.png' |
|
|
import SimSunTTF from '@/assets/fonts/simsunb.ttf' |
|
|
import SimSunTTF from '@/assets/fonts/simsunb.ttf' |
|
|
import { getLineId } from '@/core/ModelUtils.ts' |
|
|
import { getLineId } from '@/core/ModelUtils.ts' |
|
|
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' |
|
|
|
|
|
import { numberToString } from '@/utils/webutils.ts' |
|
|
|
|
|
import Constract from '@/core/Constract.ts' |
|
|
import Constract from '@/core/Constract.ts' |
|
|
import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry' |
|
|
import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry' |
|
|
|
|
|
import InstancePointManager from '@/core/manager/InstancePointManager.ts' |
|
|
|
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|
|
|
|
|
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' |
|
|
|
|
|
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 辅助测量工具渲染器 |
|
|
* 辅助测量工具渲染器 |
|
|
@ -17,166 +19,184 @@ export default class WayRenderer extends BaseRenderer { |
|
|
static POINT_NAME = 'way_point' |
|
|
static POINT_NAME = 'way_point' |
|
|
static LINE_NAME = 'way_line' |
|
|
static LINE_NAME = 'way_line' |
|
|
|
|
|
|
|
|
|
|
|
pointGeometry: THREE.BufferGeometry |
|
|
pointMaterial: THREE.Material |
|
|
pointMaterial: THREE.Material |
|
|
lineMaterial = new THREE.MeshBasicMaterial({ |
|
|
lineMaterial: LineMaterial = new LineMaterial({ |
|
|
color: 0xa0cfff, |
|
|
color: 0xa0cfff, |
|
|
transparent: true, |
|
|
linewidth: 0.8, |
|
|
opacity: 0.2, |
|
|
vertexColors: false, |
|
|
side: THREE.DoubleSide |
|
|
dashed: false, |
|
|
|
|
|
gapSize: 0, |
|
|
|
|
|
worldUnits: true |
|
|
}) |
|
|
}) |
|
|
|
|
|
// lineMaterial = new THREE.MeshBasicMaterial({
|
|
|
|
|
|
// color: 0xa0cfff,
|
|
|
|
|
|
// transparent: true,
|
|
|
|
|
|
// opacity: 0.2,
|
|
|
|
|
|
// side: THREE.DoubleSide
|
|
|
|
|
|
// })
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 默认点的高度, 防止和地面重合 |
|
|
* 默认点的高度, 防止和地面重合 |
|
|
*/ |
|
|
*/ |
|
|
readonly defulePositionY: number = Constract.HEIGHT_WAY |
|
|
readonly defulePositionY: number = Constract.HEIGHT_WAY |
|
|
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1) |
|
|
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.5, 0.1, 0.5) |
|
|
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0) |
|
|
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) |
|
|
|
|
|
|
|
|
constructor(itemTypeName: string) { |
|
|
|
|
|
super(itemTypeName) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async init() { |
|
|
async init() { |
|
|
return Promise.all([ |
|
|
return Promise.all([ |
|
|
super.init(), |
|
|
super.init(), |
|
|
this.loadFont() |
|
|
new THREE.TextureLoader().loadAsync(MoveLinePointPng) |
|
|
]) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async loadFont() { |
|
|
|
|
|
return new Promise<void>((resolve, reject) => { |
|
|
|
|
|
new THREE.TextureLoader().load( |
|
|
|
|
|
MoveLinePointPng, |
|
|
|
|
|
(texture) => { |
|
|
|
|
|
this.pointMaterial = new THREE.SpriteMaterial({ |
|
|
|
|
|
map: texture, |
|
|
|
|
|
transparent: true, |
|
|
|
|
|
side: THREE.DoubleSide |
|
|
|
|
|
}) |
|
|
|
|
|
resolve() |
|
|
|
|
|
}, |
|
|
|
|
|
undefined, |
|
|
|
|
|
function(err) { |
|
|
|
|
|
reject(err) |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 所有的点,必须使用同一个尺寸, 改属性也无效 |
|
|
|
|
|
*/ |
|
|
|
|
|
override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) { |
|
|
|
|
|
super.afterCreateOrUpdatePoint(item, option, object) |
|
|
|
|
|
|
|
|
|
|
|
const point = object |
|
|
|
|
|
point.position.y = this.defulePositionY |
|
|
|
|
|
point.scale.set(this.defaultScale.x, this.defaultScale.y, this.defaultScale.z) |
|
|
|
|
|
point.rotation.set( |
|
|
|
|
|
THREE.MathUtils.degToRad(this.defaultRotation.x), |
|
|
|
|
|
THREE.MathUtils.degToRad(this.defaultRotation.y), |
|
|
|
|
|
THREE.MathUtils.degToRad(this.defaultRotation.z) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private _createOrUpdateLine(startPosition: THREE.Vector3, endPosition: THREE.Vector3, type: LinkType) { |
|
|
|
|
|
const width = 1 |
|
|
|
|
|
const halfWidth = width / 2 |
|
|
|
|
|
|
|
|
|
|
|
const path = new THREE.LineCurve3( |
|
|
|
|
|
new THREE.Vector3(startPosition.x, startPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE), |
|
|
|
|
|
new THREE.Vector3(endPosition.x, endPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const shape = new THREE.Shape() |
|
|
]).then(([_, texture]) => { |
|
|
shape.moveTo(halfWidth, -halfWidth) |
|
|
texture.flipY = false |
|
|
shape.lineTo(halfWidth, halfWidth) |
|
|
|
|
|
|
|
|
|
|
|
const extrudeSettings: ExtrudeGeometryOptions = { |
|
|
this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) |
|
|
steps: 2, // 沿路径的分段数
|
|
|
this.pointGeometry.center() |
|
|
depth: 1, // 实际由路径长度决定
|
|
|
|
|
|
bevelEnabled: false, // 禁用倒角
|
|
|
|
|
|
extrudePath: path // 挤出路径
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) |
|
|
|
|
|
extrudedGeometry.rotateX(Math.PI / 2) |
|
|
|
|
|
|
|
|
|
|
|
return new THREE.Mesh(extrudedGeometry, this.lineMaterial) |
|
|
this.pointMaterial = new THREE.MeshBasicMaterial({ |
|
|
|
|
|
map: texture, |
|
|
|
|
|
transparent: true, |
|
|
|
|
|
depthWrite: false, |
|
|
|
|
|
side: THREE.DoubleSide |
|
|
|
|
|
}) |
|
|
|
|
|
this.pointMaterial.needsUpdate = true |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { |
|
|
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike { |
|
|
const startPosition = new THREE.Vector3(start.tf[0][0], 0, start.tf[0][2]) |
|
|
// 不允许改变高度/角度/大小
|
|
|
const endPosition = new THREE.Vector3(end.tf[0][0], 0, end.tf[0][2]) |
|
|
item.tf = [ |
|
|
|
|
|
[item.tf[0][0], this.defulePositionY, item.tf[0][2]], |
|
|
const group = new THREE.Group() |
|
|
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z], |
|
|
const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) |
|
|
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z] |
|
|
group.add(lineMesh) |
|
|
] |
|
|
|
|
|
return this.pointManager.createPoint(item) |
|
|
|
|
|
|
|
|
const midPoint = new THREE.Vector3() |
|
|
|
|
|
.addVectors(startPosition, endPosition) |
|
|
|
|
|
.multiplyScalar(0.5) |
|
|
|
|
|
|
|
|
|
|
|
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) |
|
|
|
|
|
|
|
|
|
|
|
const label = new Text() |
|
|
|
|
|
label.text = distance |
|
|
|
|
|
label.font = SimSunTTF |
|
|
|
|
|
label.fontSize = 0.2 |
|
|
|
|
|
label.color = '#5f5f5f' |
|
|
|
|
|
label.opacity = 0.8 |
|
|
|
|
|
label.anchorX = 'center' |
|
|
|
|
|
label.anchorY = 'middle' |
|
|
|
|
|
label.depthOffset = 1 |
|
|
|
|
|
label.material.depthTest = false |
|
|
|
|
|
label.name = WayRenderer.LABEL_NAME |
|
|
|
|
|
label.quaternion.copy(this.tempViewport.camera.quaternion) |
|
|
|
|
|
label.sync() |
|
|
|
|
|
label.position.set(midPoint.x, Constract.HEIGHT_WAY_LABEL, midPoint.z) |
|
|
|
|
|
|
|
|
|
|
|
group.add(label) |
|
|
|
|
|
|
|
|
|
|
|
return group |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { |
|
|
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike { |
|
|
super.updateLine(start, end, type, option) |
|
|
|
|
|
|
|
|
|
|
|
const startPosition = new THREE.Vector3(start.tf[0][0], 0.01, start.tf[0][2]) |
|
|
|
|
|
const endPosition = new THREE.Vector3(end.tf[0][0], 0.01, end.tf[0][2]) |
|
|
|
|
|
|
|
|
|
|
|
const lineId = getLineId(start.id, end.id, type) |
|
|
const lineId = getLineId(start.id, end.id, type) |
|
|
const group = this.tempViewport.entityManager.findLineObjectById(lineId) |
|
|
return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color) |
|
|
|
|
|
|
|
|
// 清空group里的元素
|
|
|
|
|
|
const label: Text = group.children[1] |
|
|
|
|
|
group.clear() |
|
|
|
|
|
|
|
|
|
|
|
const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) |
|
|
|
|
|
group.add(lineMesh) |
|
|
|
|
|
|
|
|
|
|
|
const midPoint = new THREE.Vector3() |
|
|
|
|
|
.addVectors(startPosition, endPosition) |
|
|
|
|
|
.multiplyScalar(0.5) |
|
|
|
|
|
|
|
|
|
|
|
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) |
|
|
|
|
|
label.text = distance |
|
|
|
|
|
label.quaternion.copy(this.tempViewport.camera.quaternion) |
|
|
|
|
|
label.sync() |
|
|
|
|
|
label.position.set(midPoint.x, midPoint.y, midPoint.z) |
|
|
|
|
|
group.add(label) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { |
|
|
// private _createOrUpdateLine(startPosition: THREE.Vector3, endPosition: THREE.Vector3, type: LinkType) {
|
|
|
const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial) |
|
|
// const width = 1
|
|
|
obj.name = WayRenderer.POINT_NAME |
|
|
// const halfWidth = width / 2
|
|
|
return obj |
|
|
//
|
|
|
} |
|
|
// const path = new THREE.LineCurve3(
|
|
|
|
|
|
// new THREE.Vector3(startPosition.x, startPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE),
|
|
|
|
|
|
// new THREE.Vector3(endPosition.x, endPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE)
|
|
|
|
|
|
// )
|
|
|
|
|
|
//
|
|
|
|
|
|
// const shape = new THREE.Shape()
|
|
|
|
|
|
// shape.moveTo(halfWidth, -halfWidth)
|
|
|
|
|
|
// shape.lineTo(halfWidth, halfWidth)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const extrudeSettings: ExtrudeGeometryOptions = {
|
|
|
|
|
|
// steps: 2, // 沿路径的分段数
|
|
|
|
|
|
// depth: 1, // 实际由路径长度决定
|
|
|
|
|
|
// bevelEnabled: false, // 禁用倒角
|
|
|
|
|
|
// extrudePath: path // 挤出路径
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
|
|
|
|
|
|
// extrudedGeometry.rotateX(Math.PI / 2)
|
|
|
|
|
|
//
|
|
|
|
|
|
// return new THREE.Mesh(extrudedGeometry, this.lineMaterial)
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D {
|
|
|
|
|
|
// const startPosition = new THREE.Vector3(start.tf[0][0], 0, start.tf[0][2])
|
|
|
|
|
|
// const endPosition = new THREE.Vector3(end.tf[0][0], 0, end.tf[0][2])
|
|
|
|
|
|
//
|
|
|
|
|
|
// const group = new THREE.Group()
|
|
|
|
|
|
// const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type)
|
|
|
|
|
|
// group.add(lineMesh)
|
|
|
|
|
|
//
|
|
|
|
|
|
//
|
|
|
|
|
|
// const midPoint = new THREE.Vector3()
|
|
|
|
|
|
// .addVectors(startPosition, endPosition)
|
|
|
|
|
|
// .multiplyScalar(0.5)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const label = new Text()
|
|
|
|
|
|
// label.text = distance
|
|
|
|
|
|
// label.font = SimSunTTF
|
|
|
|
|
|
// label.fontSize = 0.2
|
|
|
|
|
|
// label.color = '#5f5f5f'
|
|
|
|
|
|
// label.opacity = 0.8
|
|
|
|
|
|
// label.anchorX = 'center'
|
|
|
|
|
|
// label.anchorY = 'middle'
|
|
|
|
|
|
// label.depthOffset = 1
|
|
|
|
|
|
// label.material.depthTest = false
|
|
|
|
|
|
// label.name = WayRenderer.LABEL_NAME
|
|
|
|
|
|
// label.quaternion.copy(this.tempViewport.camera.quaternion)
|
|
|
|
|
|
// label.sync()
|
|
|
|
|
|
// label.position.set(midPoint.x, Constract.HEIGHT_WAY_LABEL, midPoint.z)
|
|
|
|
|
|
//
|
|
|
|
|
|
// group.add(label)
|
|
|
|
|
|
//
|
|
|
|
|
|
// return group
|
|
|
|
|
|
// }
|
|
|
|
|
|
//
|
|
|
|
|
|
// updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) {
|
|
|
|
|
|
// super.updateLine(start, end, type, option)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const startPosition = new THREE.Vector3(start.tf[0][0], 0.01, start.tf[0][2])
|
|
|
|
|
|
// const endPosition = new THREE.Vector3(end.tf[0][0], 0.01, end.tf[0][2])
|
|
|
|
|
|
//
|
|
|
|
|
|
// const lineId = getLineId(start.id, end.id, type)
|
|
|
|
|
|
// const group = this.tempViewport.entityManager.findLineObjectById(lineId)
|
|
|
|
|
|
//
|
|
|
|
|
|
// // 清空group里的元素
|
|
|
|
|
|
// const label: Text = group.children[1]
|
|
|
|
|
|
// group.clear()
|
|
|
|
|
|
//
|
|
|
|
|
|
// const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type)
|
|
|
|
|
|
// group.add(lineMesh)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const midPoint = new THREE.Vector3()
|
|
|
|
|
|
// .addVectors(startPosition, endPosition)
|
|
|
|
|
|
// .multiplyScalar(0.5)
|
|
|
|
|
|
//
|
|
|
|
|
|
// const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0)
|
|
|
|
|
|
// label.text = distance
|
|
|
|
|
|
// label.quaternion.copy(this.tempViewport.camera.quaternion)
|
|
|
|
|
|
// label.sync()
|
|
|
|
|
|
// label.position.set(midPoint.x, midPoint.y, midPoint.z)
|
|
|
|
|
|
// group.add(label)
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
dispose() { |
|
|
dispose() { |
|
|
super.dispose() |
|
|
super.dispose() |
|
|
this.pointMaterial?.dispose() |
|
|
this.pointMaterial?.dispose() |
|
|
this.lineMaterial?.dispose() |
|
|
this.lineMaterial?.dispose() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get lineSegmentManager(): LineSegmentManager { |
|
|
|
|
|
if (!this.tempViewport) { |
|
|
|
|
|
throw new Error('tempViewport is not set.') |
|
|
|
|
|
} |
|
|
|
|
|
return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () => |
|
|
|
|
|
// 构建 LineSegment.points 代理对象
|
|
|
|
|
|
LineSegmentManager.create(this.itemTypeName, |
|
|
|
|
|
this.tempViewport, |
|
|
|
|
|
this.lineMaterial) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get pointManager(): InstancePointManager { |
|
|
|
|
|
if (!this.tempViewport) { |
|
|
|
|
|
throw new Error('tempViewport is not set.') |
|
|
|
|
|
} |
|
|
|
|
|
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () => |
|
|
|
|
|
// 构建 InstanceMesh 代理对象
|
|
|
|
|
|
InstancePointManager.create(this.itemTypeName, |
|
|
|
|
|
this.tempViewport, |
|
|
|
|
|
this.pointGeometry, |
|
|
|
|
|
this.pointMaterial, |
|
|
|
|
|
Constract.MAX_WAY_INSTANCES) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|