|
|
@ -9,6 +9,10 @@ import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader' |
|
|
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader' |
|
|
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader' |
|
|
import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader' |
|
|
import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader' |
|
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' |
|
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' |
|
|
|
|
|
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2' |
|
|
|
|
|
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' |
|
|
|
|
|
import { Line2 } from 'three/examples/jsm/lines/Line2' |
|
|
|
|
|
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 计算点集凸包(2D) |
|
|
* 计算点集凸包(2D) |
|
|
@ -609,7 +613,6 @@ export function loadTexture(url: string) { |
|
|
|
|
|
|
|
|
export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) { |
|
|
export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) { |
|
|
if (ext.endsWith('.fbx')) { |
|
|
if (ext.endsWith('.fbx')) { |
|
|
system.showLoading() |
|
|
|
|
|
const loader = new FBXLoader() |
|
|
const loader = new FBXLoader() |
|
|
return loader.parse(arrayBuffer, '') |
|
|
return loader.parse(arrayBuffer, '') |
|
|
|
|
|
|
|
|
@ -632,9 +635,8 @@ export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) { |
|
|
/** |
|
|
/** |
|
|
* 根据 ItemJson 数据结构, 构建适合 THREE.js 的变换矩阵 |
|
|
* 根据 ItemJson 数据结构, 构建适合 THREE.js 的变换矩阵 |
|
|
*/ |
|
|
*/ |
|
|
export function getMatrixFromTf(tf: number[][]): THREE.Matrix4 { |
|
|
export function getMatrixFromTf(tf: number[][], matrix = new THREE.Matrix4()): THREE.Matrix4 { |
|
|
const [pos, rot, scale] = tf |
|
|
const [pos, rot, scale] = tf |
|
|
const matrix = new THREE.Matrix4() |
|
|
|
|
|
matrix.compose( |
|
|
matrix.compose( |
|
|
new THREE.Vector3(pos[0], pos[1], pos[2]), |
|
|
new THREE.Vector3(pos[0], pos[1], pos[2]), |
|
|
new THREE.Quaternion().setFromEuler(new THREE.Euler( |
|
|
new THREE.Quaternion().setFromEuler(new THREE.Euler( |
|
|
@ -698,6 +700,74 @@ export function getAABBox(matrix: THREE.Matrix4 | ItemJson): THREE.Vector3[] { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
|
|
|
* 根据变换矩阵绘制 OBB 包围盒, 注意返回 Line2 对象 |
|
|
|
|
|
* @param matrix 物体的变换矩阵或 ItemJson 对象 |
|
|
|
|
|
* @param material LineMaterial 用于绘制线条的材质 |
|
|
|
|
|
* @param padding 包围盒的边距, 默认为 0 |
|
|
|
|
|
*/ |
|
|
|
|
|
export function drawOBBox(matrix: THREE.Matrix4 | ItemJson, material: LineMaterial, padding: number = 0): Line2 { |
|
|
|
|
|
// 定义单位立方体的边对应的顶点索引
|
|
|
|
|
|
const edges = [ |
|
|
|
|
|
[0, 1], [1, 2], [2, 3], [3, 0], |
|
|
|
|
|
[4, 5], [5, 6], [6, 7], [7, 4], |
|
|
|
|
|
// [0, 4], [1, 5], [2, 6], [3, 7]
|
|
|
|
|
|
[0, 4], [4, 5], |
|
|
|
|
|
[5, 1], [1, 2], |
|
|
|
|
|
[2, 6], [6, 7], |
|
|
|
|
|
[7, 3] |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
// 定义单位立方体的8个顶点位置
|
|
|
|
|
|
const verticesParam = [ |
|
|
|
|
|
-0.5 - padding, -0.5, 0.5 + padding, |
|
|
|
|
|
0.5 + padding, -0.5, 0.5 + padding, |
|
|
|
|
|
0.5 + padding, 0.5, 0.5 + padding, |
|
|
|
|
|
-0.5 - padding, 0.5, 0.5 + padding, |
|
|
|
|
|
-0.5 - padding, -0.5, -0.5 - padding, |
|
|
|
|
|
0.5 + padding, -0.5, -0.5 - padding, |
|
|
|
|
|
0.5 + padding, 0.5, -0.5 - padding, |
|
|
|
|
|
-0.5 - padding, 0.5, -0.5 - padding |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
if (!(matrix instanceof THREE.Matrix4)) { |
|
|
|
|
|
// 从 tf 读取的模型, 需要调整Y轴以使底面位于Y=0
|
|
|
|
|
|
matrix = getMatrixFromTf(matrix.tf) |
|
|
|
|
|
for (let i = 1; i < verticesParam.length; i += 3) { |
|
|
|
|
|
verticesParam[i] = verticesParam[i] + 0.5 |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const vertices = new Float32Array(verticesParam) |
|
|
|
|
|
// 将顶点通过变换矩阵转换到世界坐标系中
|
|
|
|
|
|
const transformedVertices = [] |
|
|
|
|
|
for (let i = 0; i < vertices.length; i += 3) { |
|
|
|
|
|
const vec = new THREE.Vector3(vertices[i], vertices[i + 1], vertices[i + 2]) |
|
|
|
|
|
vec.applyMatrix4(matrix) |
|
|
|
|
|
transformedVertices.push(vec.x, vec.y, vec.z) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 合并所有边的顶点信息
|
|
|
|
|
|
const edgePositions = [] |
|
|
|
|
|
edges.forEach(edge => { |
|
|
|
|
|
edgePositions.push( |
|
|
|
|
|
new THREE.Vector3( |
|
|
|
|
|
transformedVertices[edge[0] * 3], |
|
|
|
|
|
transformedVertices[edge[0] * 3 + 1], |
|
|
|
|
|
transformedVertices[edge[0] * 3 + 2] |
|
|
|
|
|
), |
|
|
|
|
|
new THREE.Vector3( |
|
|
|
|
|
transformedVertices[edge[1] * 3], |
|
|
|
|
|
transformedVertices[edge[1] * 3 + 1], |
|
|
|
|
|
transformedVertices[edge[1] * 3 + 2] |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const geometry = new LineGeometry().setFromPoints(edgePositions) |
|
|
|
|
|
return new Line2(geometry, material) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
* 获取物体的 OBB 包围盒顶点 |
|
|
* 获取物体的 OBB 包围盒顶点 |
|
|
* @param matrix 物体的变换矩阵或 ItemJson 对象 |
|
|
* @param matrix 物体的变换矩阵或 ItemJson 对象 |
|
|
*/ |
|
|
*/ |
|
|
@ -706,7 +776,10 @@ export function getOBBox(matrix: THREE.Matrix4 | ItemJson): THREE.Vector3[] { |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
// item.tf = [[0, 0.1, 0], [0, 0, 0], [1, 1, 1]]
|
|
|
// item.tf = [[0, 0.1, 0], [0, 0, 0], [1, 1, 1]]
|
|
|
|
|
|
const height = matrix.tf[0][2] |
|
|
matrix = getMatrixFromTf(matrix.tf) |
|
|
matrix = getMatrixFromTf(matrix.tf) |
|
|
|
|
|
matrix.setPosition(new THREE.Vector3(0, height / 2, 0)) // 确保 OBB 的中心在 (0, height/2, 0)
|
|
|
|
|
|
debugger |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 获取 OOBB 包围盒
|
|
|
// 获取 OOBB 包围盒
|
|
|
@ -732,10 +805,11 @@ export function getOBBox(matrix: THREE.Matrix4 | ItemJson): THREE.Vector3[] { |
|
|
const edges = [ |
|
|
const edges = [ |
|
|
[0, 1], [1, 2], [2, 3], [3, 0], // 侧面
|
|
|
[0, 1], [1, 2], [2, 3], [3, 0], // 侧面
|
|
|
[4, 5], [5, 6], [6, 7], [7, 4], // 右侧面
|
|
|
[4, 5], [5, 6], [6, 7], [7, 4], // 右侧面
|
|
|
// 上面的点 2,3,6,7
|
|
|
[0, 4], [1, 5], [2, 6], [3, 7] |
|
|
[3, 2], [3, 7], [7, 6], [6, 2], |
|
|
// // 上面的点 2,3,6,7
|
|
|
// 下面的点: 0,1,4,5
|
|
|
// [3, 2], [3, 7], [7, 6], [6, 2],
|
|
|
[0, 1], [1, 5], [5, 4], [4, 0] |
|
|
// // 下面的点: 0,1,4,5
|
|
|
|
|
|
// [0, 1], [1, 5], [5, 4], [4, 0]
|
|
|
] |
|
|
] |
|
|
edges.forEach(([a, b]) => { |
|
|
edges.forEach(([a, b]) => { |
|
|
const va = corners[a] |
|
|
const va = corners[a] |
|
|
|