You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.3 KiB
130 lines
3.3 KiB
import * as THREE from 'three'
|
|
import { BasePlane } from '@/types/ModelTypes.ts'
|
|
|
|
/**
|
|
* 创建一个矩形的 Shape
|
|
*/
|
|
export function buildRectangle(width: number, height: number, padding: number[] | number = 0, offsetX = 0, offsetY = 0): THREE.Shape {
|
|
let pl = 0,
|
|
pt = 0,
|
|
pr = 0,
|
|
pb = 0
|
|
|
|
if (typeof padding == 'number') {
|
|
pl = padding
|
|
pt = padding
|
|
pr = padding
|
|
pb = padding
|
|
} else if (Array.isArray(padding)) {
|
|
if (padding.length == 1) {
|
|
pl = padding[0]
|
|
pt = padding[0]
|
|
pr = padding[0]
|
|
pb = padding[0]
|
|
} else if (padding.length > 1 && padding.length < 4) {
|
|
pl = padding[0]
|
|
pt = padding[1]
|
|
pr = padding[0]
|
|
pb = padding[1]
|
|
} else if (padding.length >= 4) {
|
|
pl = padding[0]
|
|
pt = padding[1]
|
|
pr = padding[2]
|
|
pb = padding[3]
|
|
}
|
|
}
|
|
const shape = new THREE.Shape()
|
|
shape.moveTo(0 + pl + offsetX, 0 + pb + offsetY)
|
|
shape.lineTo(width - pr + offsetX, 0 + pb + offsetY)
|
|
shape.lineTo(width - pr + offsetX, height - pt + offsetY)
|
|
shape.lineTo(0 + pl + offsetX, height - pt + offsetY)
|
|
shape.closePath()
|
|
return shape
|
|
}
|
|
|
|
|
|
/**
|
|
* 根据自定义的 Shape,通过放样得到一个实体。默认实体的样式是在 front 面放样的。
|
|
*
|
|
* @param {*} shape 自定义的型状
|
|
* @param {*} depth 放样深度(放样后的物体厚度)
|
|
* @param {*} basePlane 放样的基准面。
|
|
* @param {*} x 目标定位x
|
|
* @param {*} y 目标定位y
|
|
* @param {*} z 目标定位z
|
|
* @param {*} euler 旋转到目标位
|
|
* @param {*} anchor 锚点
|
|
* @returns THREE.ExtrudeGeometry
|
|
*/
|
|
export function createExtrudeItem(shape: THREE.Shape, depth: number, basePlane: number,
|
|
x = 0, y = 0, z = 0, euler = null,
|
|
anchor = new THREE.Vector3(0, 0, 0)) {
|
|
const geometry = new THREE.ExtrudeGeometry(shape, {
|
|
steps: 1,
|
|
depth: -depth,
|
|
bevelEnabled: false,
|
|
bevelThickness: 0,
|
|
bevelSize: 0,
|
|
bevelOffset: 0,
|
|
bevelSegments: 0
|
|
})
|
|
|
|
geometry.center()
|
|
const size = geometry.boundingBox.getSize(new THREE.Vector3())
|
|
|
|
let dx, dy, dz
|
|
|
|
switch (basePlane) {
|
|
case BasePlane.LEFT:
|
|
geometry.rotateY(Math.PI / 2)
|
|
dx = size.z / 2
|
|
dy = size.y / 2
|
|
dz = size.x / 2
|
|
break
|
|
case BasePlane.RIGHT:
|
|
geometry.rotateY(-Math.PI / 2)
|
|
dx = size.z / 2
|
|
dy = size.y / 2
|
|
dz = size.x / 2
|
|
break
|
|
case BasePlane.BEHIND:
|
|
geometry.translate(0, 0, size.z)
|
|
dx = size.x / 2
|
|
dy = size.y / 2
|
|
dz = size.z / 2
|
|
break
|
|
case BasePlane.TOP:
|
|
geometry.rotateZ(Math.PI)
|
|
geometry.rotateX(Math.PI / 2)
|
|
geometry.translate(size.x, -size.z, 0)
|
|
dx = size.x / 2
|
|
dy = size.z / 2
|
|
dz = size.y / 2
|
|
break
|
|
case BasePlane.BOTTOM:
|
|
geometry.rotateX(-Math.PI / 2)
|
|
dx = size.x / 2
|
|
dy = size.z / 2
|
|
dz = size.y / 2
|
|
break
|
|
default:
|
|
//BasePlane.FRONT:
|
|
dx = size.x / 2
|
|
dy = size.y / 2
|
|
dz = size.z / 2
|
|
break
|
|
}
|
|
|
|
if (euler != null && euler.isEuler) {
|
|
// 注意,需要先旋转,再平移。
|
|
geometry.rotateX(euler.x)
|
|
geometry.rotateY(euler.y)
|
|
geometry.rotateZ(euler.z)
|
|
}
|
|
|
|
geometry.translate(dx + x + anchor.x, dy + y + anchor.y, -dz + z + anchor.z)
|
|
geometry.center()
|
|
return geometry
|
|
}
|
|
|
|
|
|
|