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

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
}