TkAstral3D/packages/sdk/lib/utils/scene/index.ts
2025-10-04 23:36:07 +08:00

139 lines
3.5 KiB
TypeScript

import { Object3D,InstancedMesh,Mesh,Matrix4,AnimationAction,AnimationClip } from "three";
import App from "@/core/app/App";
export * from "./material";
export * from "./Stats";
export * from "./controls";
/**
* 获取对象到父对象的路径(结果不包含parentObject)
* @param parentObject
* @param object
* @param attr 对象属性名
* @param splitter 路径分隔符
*/
export function getParentPath(parentObject:Object3D,object:Object3D,attr = 'name',splitter = '/'){
if(!parentObject || !object) return '';
if(parentObject === object) return object[attr];
let path = [object[attr]];
const getPath = (obj) => {
if(!obj.parent) return;
if(obj.parent === parentObject) return;
path.unshift(obj.parent[attr]);
getPath(obj.parent);
}
getPath(object);
return path.join(splitter);
}
/**
* 获取鼠标按下的位置
* @param dom
* @param x
* @param y
*/
export function getMousePosition(dom: HTMLElement, x: number, y: number) {
const rect = dom.getBoundingClientRect();
return [(x - rect.left) / rect.width, (y - rect.top) / rect.height];
}
/**
* InstancedMesh 解出所有 mesh
*/
export function getMeshByInstancedMesh(instancedMesh:InstancedMesh){
const meshes:Mesh[] = [];
// if (instancedMesh.material === undefined) return meshes;
const matrixWorld = instancedMesh.matrixWorld;
const count = instancedMesh.count;
for (let instanceId = 0; instanceId < count; instanceId++) {
const _mesh = new Mesh();
const _instanceLocalMatrix = new Matrix4();
const _instanceWorldMatrix = new Matrix4();
_mesh.geometry = instancedMesh.geometry;
_mesh.material = instancedMesh.material;
// 计算每个实例的世界矩阵
instancedMesh.getMatrixAt(instanceId, _instanceLocalMatrix);
_instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix);
// 网格表示这个单一实例
_mesh.matrixWorld = _instanceWorldMatrix;
meshes.push(_mesh);
}
return meshes;
}
/**
* 判断是否是group,因为导入有可能存在被定义为Object3D类型的group
*/
export function isGroup(object3D:Object3D){
return (object3D.isGroup || object3D.children.length > 0)
}
/**
* 判断是否是代理粒子发射器的3D对象
*/
export function isParticleObject(object:Object3D | null){
return object && object.type === "Particle" && object.emitter;
}
/**
* 判断是否是Billboard 3D对象
*/
export function isBillboardObject(object:Object3D | null){
return object && object.type === "Billboard" && object.options;
}
/**
* 判断是否是HtmlPanel 3D对象
*/
export function isHtmlPanelObject(object:Object3D | null){
return object && (object.isHtmlPanel || object.isHtmlSprite) && object.element;
}
/**
* 获取场景/物体中的所有动画
*/
export function getAnimations(object = App.scene) {
const animations: any = [];
object.traverse(function (object) {
animations.push(...object.animations);
});
return animations;
}
/**
* 获取场景/物体中的所有动画剪辑
*/
export function getAnimationClips(object:Object3D = App.scene) {
const animations: any = [];
object.traverse(function (object) {
object.animations.forEach(animation => {
if(animation instanceof AnimationAction){
animations.push(animation.getClip());
}
if(animation instanceof AnimationClip){
animations.push(animation);
}
})
});
return animations;
}