import { Component, IComponentOption } from "../../core/component"; import { Vec3, Mat4, Quat, Euler, Vec2, Mat3 } from 'xtorcga'; import { MetaEntity } from "../entity/metaentity"; /* * @Description : * @Author : 赵耀圣 * @QQ : 549184003 * @Date : 2021-09-09 08:53:12 * @LastEditTime : 2021-09-15 16:23:21 * @FilePath : \object_frame\src\extends\components\transform.ts * * set 设置 在现有基础上改变 * make 设置新数据 创建一个新对象 * */ const _v1 = new Vec3(); const _q1 = new Quat(); const _m1 = new Mat4(); const _target = new Vec3(); const _position = new Vec3(); const _scale = new Vec3(); const _quaternion = new Quat(); const _xAxis = Vec3.UnitX; const _yAxis = Vec3.UnitY; const _zAxis = Vec3.UnitZ; export class TransformComponent extends Component { _position: Vec3 = new Vec3; _rotation: Euler = new Euler; _scale: Vec3 = new Vec3(1, 1, 1); _quat: Quat = new Quat; _mat: Mat4 = new Mat4; _matWorld: Mat4 = new Mat4; _modelViewMat: Mat4 = new Mat4; _normalMat: Mat3 = new Mat3; _matWorldInverse: Mat4 = new Mat4; up: Vec3 = new Vec3(0, 1, 0); right: Vec3 = new Vec3(1, 0, 0); front: Vec3 = new Vec3(0, 0, 1); /** * 物体是否需要更新世界矩阵 */ matWorldNeedsUpdate: boolean = true; /** * 自动更新矩阵 */ matAutoUpdate: boolean = true; [key: string]: any; constructor(options: IComponentOption) { super(options) this.descriptors = [ { name: 'position', type: 'Vector', label: '位置' }, { name: 'rotation', type: 'Vector', label: '旋转' }, { name: 'scale', type: 'Vector', label: '缩放' }, ]; this.isSingle = true; this.label = '方位'; this.buildAccessors(this.descriptors, this); this._rotation.on('change', () => { this._quat.setFromEuler(this._rotation, false); this.entity?.fire('change', this); }) this._position.on('change', () => { this.entity?.fire('change', this); }) this._scale.on('change', () => { this.entity?.fire('change', this); }) this._quat.on('change', () => { this._rotation.setFromQuat(this._quat, undefined, false); this.entity?.fire('change', this); }); } /** * 更新自身矩阵 */ updateMat() { this._mat.compose(this._position, this._quat, this._scale); this.matWorldNeedsUpdate = true; } /** * 更新整体层次的世界矩阵 * @param force 是否强制更新 */ updateMatWorld(force: boolean = false) { if (this.matAutoUpdate) this.updateMat(); if (this.matWorldNeedsUpdate || force) { if (this.entity?.parent === null) { this._matWorld.copy(this._mat); } else { if (this.entity && this.entity.parent) this._matWorld.multiplyMats((this.entity.parent as MetaEntity).transfrom._matWorld, this._mat); } this.matWorldNeedsUpdate = false; force = true; } // update children if (this.entity) { const children: MetaEntity[] = this.entity.children as MetaEntity[]; for (let i = 0, l = children.length; i < l; i++) { children[i].transfrom.updateMatWorld(force); } } } /** * @description : 更新当前 世界矩阵 * @param {boolean} updateParents 是否更新父节点 * @param {boolean} updateChildren 是否更新子节点 * @return {*} * @example : */ updateWorldMat(updateParents: boolean, updateChildren: boolean) { const parent = this.entity!.parent as MetaEntity; if (updateParents === true && parent !== null) { parent.transfrom.updateWorldMat(true, false); } if (this.matAutoUpdate) this.updateMat(); if (this.entity!.parent === null) { this._matWorld.copy(this._mat); } else { this._matWorld.multiplyMats((this.entity!.parent as MetaEntity).transfrom._matWorld, this._mat); } // update children if (updateChildren === true && this.entity) { const children = this.entity.children as MetaEntity[]; for (let i = 0, l = children.length; i < l; i++) { children[i].transfrom.updateWorldMat(false, true); } } } /** * 响应其他矩阵 * @param mat4 */ applyMat4(mat4: Mat4) { if (this.matAutoUpdate) this.updateMat(); this._mat.premultiply(mat4); this._mat.decompose(this._position, this._quat, this._scale); } applyQuaternion(q: Quat) { this._quat.premultiply(q); return this; } setRotationFromAxisAngle(axis: Vec3, angle: number) { this._quat.setFromAxisAngle(axis, angle); } setRotationFromEuler(euler: Euler) { this._quat.setFromEuler(euler, true); } setRotationFromMat(m: Mat4) { // assumes the upper 3x3 of m is a pure rotation _mat (i.e, unscaled) this._quat.setFromRotationMat(m); } setRotationFromQuaternion(q: Quat) { // 假定q已经正交化 this._quat.copy(q); } /** * 在本地坐标旋转 * @param axis 正交化的旋转轴 * @param angle 旋转角度 * @returns */ rotateOnAxis(axis: Vec3, angle: number) { _q1.setFromAxisAngle(axis, angle); this._quat.multiply(_q1); return this; } /** * 在世界坐标旋转 不旋转父节点 * @param axis 正交化的旋转轴 * @param angle 旋转角度 * @returns */ rotateOnWorldAxis(axis: Vec3, angle: number) { _q1.setFromAxisAngle(axis, angle); this._quat.premultiply(_q1); return this; } rotateX(angle: any) { return this.rotateOnAxis(_xAxis, angle); } rotateY(angle: any) { return this.rotateOnAxis(_yAxis, angle); } rotateZ(angle: any) { return this.rotateOnAxis(_zAxis, angle); } translateOnAxis(axis: Vec3, distance: number) { // translate object by distance along axis in object space // axis is assumed to be normalized _v1.copy(axis).applyQuat(this._quat); this._position.add(_v1.multiplyScalar(distance)); return this; } translateX(distance: number) { return this.translateOnAxis(_xAxis, distance); } translateY(distance: number) { return this.translateOnAxis(_yAxis, distance); } translateZ(distance: number) { return this.translateOnAxis(_zAxis, distance); } localToWorld(vector: { applyMat4: (arg0: Mat4) => any; }) { return vector.applyMat4(this._matWorld); } worldToLocal(vector: { applyMat4: (arg0: Mat4) => any; }) { return vector.applyMat4(_m1.copy(this._matWorld).invert()); } lookAt(x: number | Vec3, y?: number, z?: number) { // This method does not support objects having non-uniformly-scaled parent(s) if (x instanceof Vec3) { _target.copy(x); } else if (y !== undefined && z !== undefined) { _target.set(x, y, z); } const parent = this.entity!.parent; this.updateWorldMat(true, false); _position.setFromMatPosition(this._matWorld); // if (this.isCamera || this.isLight) { // _m1.lookAt(_position, _target, this.up); // } else { _m1.lookAt(_target, _position, this.up); // } this._quat.setFromRotationMat(_m1); if (parent) { _m1.extractRotation((parent).transfrom._matWorld); _q1.setFromRotationMat(_m1); this._quat.premultiply(_q1.inverse()); } } update(entity: MetaEntity) { } }