import { MathUtils } from '../math/MathUtils';
import { Utils } from '../common/Utils';
import { BaseComponent } from './BaseComponent';
const __ = {
private: Symbol('private'),
}
/**
* @class SpaceHelperComponent
* The space helper component.
* @memberof THING
* @extends THING.BaseComponent
* @public
*/
class SpaceHelperComponent extends BaseComponent {
/**
* The space relation component of object.
*/
constructor(param) {
super(param);
this[__.private] = {};
let _private = this[__.private];
_private.lines = null;
_private.box = null;
_private.linesColor = [1, 1, 1];
_private.boxColor = [0, 1, 0];
_private.boxOpacity = 0.3;
_private.points = [];
_private.colors = [];
_private.initHalfSize = [];
_private.initOffset = [];
}
onRemove() {
let _private = this[__.private];
if (_private.box) {
_private.box.dispose();
_private.box = null;
_private.lines = null;
}
super.onRemove();
}
/**
* show bounding
* @param {Boolean} value The value
* @example
* space.showBounding();
* @public
*/
showBounding(value = true) {
let _private = this[__.private];
if (_private.box) {
_private.box.setVisible(value);
}
else if (value) {
this._initBoundingBox();
}
}
async _initBoundingBox() {
await this.object.loaded;
this._initOrientedBoxData()
this._begin();
let _private = this[__.private];
const size = _private.initHalfSize;
const boxPoints = {
// TOP
tlt: this._getRealPoint([-size[0], size[1], -size[2]]), // 0
trt: this._getRealPoint([size[0], size[1], -size[2]]), // 1
trb: this._getRealPoint([size[0], size[1], size[2]]), // 2
tlb: this._getRealPoint([-size[0], size[1], size[2]]), // 3
// BOTTOM
blt: this._getRealPoint([-size[0], -size[1], -size[2]]), // 4
brt: this._getRealPoint([size[0], -size[1], -size[2]]), // 5
brb: this._getRealPoint([size[0], -size[1], size[2]]), // 6
blb: this._getRealPoint([-size[0], -size[1], size[2]]), // 7
};
// Insert line
this._insertLine(boxPoints.tlt, boxPoints.trt);
this._insertLine(boxPoints.trt, boxPoints.trb);
this._insertLine(boxPoints.trb, boxPoints.tlb);
this._insertLine(boxPoints.tlb, boxPoints.tlt);
this._insertLine(boxPoints.blt, boxPoints.brt);
this._insertLine(boxPoints.brt, boxPoints.brb);
this._insertLine(boxPoints.brb, boxPoints.blb);
this._insertLine(boxPoints.blb, boxPoints.blt);
this._insertLine(boxPoints.tlt, boxPoints.blt);
this._insertLine(boxPoints.trt, boxPoints.brt);
this._insertLine(boxPoints.trb, boxPoints.brb);
this._insertLine(boxPoints.tlb, boxPoints.blb);
this._end();
}
_initOrientedBoxData() {
let _private = this[__.private];
const object = this.object;
const orientedBox = object.getOBB(false);
_private.initHalfSize = MathUtils.divideVector(MathUtils.divideVector(orientedBox.size, object.scale), 2);
_private.initOffset = MathUtils.divideVector(
MathUtils.vec3ApplyQuat(MathUtils.subVector(orientedBox.center, object.position),
MathUtils.quat.invert([], object.quaternion)), object.scale);
}
_begin() {
let _private = this[__.private];
// Line
let lines = Utils.createObject('LineSegments');
lines.setAttribute('Pickable', false);
_private.lines = lines;
// Box
let box = this.object.app.resourceManager.parseModel('Box');
box.setAttribute('Pickable', false);
box.setScale(MathUtils.scaleVector(_private.initHalfSize, 2));
let style = box.getStyle();
style.setColorOp(() => { return _private.boxColor; });
style.setOpacityOp(() => { return _private.boxOpacity; });
_private.box = box;
}
_end() {
let _private = this[__.private];
// Update lines
_private.lines.setSize(_private.points.length);
// Let line's position is center of points
let center = MathUtils.getCenterFromPoints(_private.points);
// Make points to relative position
let relativePoints = _private.points.map(point => {
return MathUtils.subVector(point, center);
});
_private.lines.setPoints(relativePoints);
_private.lines.setColors(_private.colors);
_private.box.add(_private.lines);
this.object.body.createRootNode();
this.object.node.add(_private.box);
_private.lines.setWorldQuaternion([0, 0, 0, 1]);
_private.lines.setWorldScale([1, 1, 1]);
}
_getRealPoint(point) {
let _private = this[__.private];
return MathUtils.addVector(_private.initOffset, this.object.selfToWorld(point));
}
_insertLine(p0, p1) {
let _private = this[__.private];
_private.points.push(p0);
_private.colors.push(_private.linesColor);
_private.points.push(p1);
_private.colors.push(_private.linesColor);
}
/**
* @private
*/
setColor(val) {
let _private = this[__.private];
if (_private.lines) {
let style = _private.lines.getStyle();
style.setColorOp(() => { return val || _private.linesColor; });
}
}
}
export { SpaceHelperComponent }