import { Utils } from '../common/Utils'
import { BasePlanePoints } from './BasePlanePoints';
/**
* Water - 水体
*
* 模拟水面效果,支持波浪、扰动、反射和流动等视觉效果。
*
* @class Water
* @memberof THING
* @extends THING.BasePlanePoints
* @public
*
* @example
* const water = new THING.Water({
* points: [[-10, 0, -10], [10, 0, -10], [10, 0, 10], [-10, 0, 10]],
* flowSpeed: [0.01, 0.01],
* flowWeight: 0.5,
* });
*/
class Water extends BasePlanePoints {
static defaultTagArray = ['Region'];
/**
* 构造函数
* @param {object} param 初始参数。
* @param {number[][]} [param.points] 世界坐标系下(3D)区域外轮廓坐标
* @param {number[][][]} [param.holes] 世界坐标系下(3D)区域内空洞的坐标(支持多个空洞)
* @param {number[][]} [param.selfPoints] 自身坐标系下(3D)区域外轮廓坐标
* @param {number[][][]} [param.selfHoles] 自身坐标系下(3D)区域空洞坐标
* @param {number[][]} [param.selfPlanePoints] 自身平面坐标系下(2D)区域外轮廓坐标
* @param {number[][][]} [param.selfPlaneHoles] 自身平面坐标系下(2D)区域空洞坐标
* @param {number[]} [param.flowSpeed=[0,0]] 流速(数组,分别代表x,y方向的流速)
* @param {number} [param.flowWeight=0.5] 波浪强度
* @param {number} [param.reflectDistortion=2] 反射变形系数
* @param {number} [param.noiseTimeScale=1] 水流动态效果(噪声系数)
* @param {object} param.style 物体样式
* @constructor
* @public
*/
constructor(param = {}) {
super(param);
// Set default normal map
let normalMap = this.app.global.cache.images['water_normal_image'];
this.style.normalMap = normalMap;
}
// #region Overrides
onSetupResource(param) {
this._flowOffset = param['flowOffset'] || [0, 0];
this._flowSpeed = param['flowSpeed'] || [0, 0];
this._flowWeight = param['flowWeight'] || 0.5;
this._reflectDistortion = param['reflectDistortion'] || 2;
this._noiseTimeScale = param['noiseTimeScale'] || 1;
this._radialFlow = param['radialFlow'] || false;
super.onSetupResource(param);
}
onCreateBodyNode() {
let water = Utils.createObject('Water', { app: this.app });
return water;
}
onSetupBodyNode(node) {
super.onSetupBodyNode(node);
node.setFlowWeight(this._flowWeight);
node.setReflectDistortion(this._reflectDistortion);
node.setNoiseTimeScale(this._noiseTimeScale);
node.setRadialFlow(this._radialFlow);
}
onRefreshAttributes() {
let bodyNode = this.bodyNode;
bodyNode.setFlowWeight(this._flowWeight);
bodyNode.setReflectDistortion(this._reflectDistortion);
bodyNode.setNoiseTimeScale(this._noiseTimeScale);
bodyNode.setRadialFlow(this._radialFlow);
}
onUpdate(deltaTime) {
if (this._flowSpeed[0] || this._flowSpeed[1]) {
let factor = deltaTime;
let flowOffset = this._flowOffset;
let flowSpeed = this._flowSpeed;
let offset = [flowSpeed[0] * factor, flowSpeed[1] * factor];
flowOffset[0] += offset[0];
flowOffset[1] += offset[1];
this.bodyNode.setFlowOffset(flowOffset);
}
this.bodyNode.update(deltaTime);
}
onCreate(options) {
super.onCreate(options);
this.onAddTickableObject();
}
// #endregion
destroy() {
if (this.app.objectManager.isKeepAliveObject(this)) {
return false;
}
this.onRemoveTickableObject();
return super.destroy();
}
onExportExternalData() {
let external = Object.assign({}, super.onExportExternalData());
Utils.setAttributeIfExist(external, 'flowSpeed', this);
Utils.setAttributeIfExist(external, 'flowWeight', this);
Utils.setAttributeIfExist(external, 'noiseTimeScale', this);
Utils.setAttributeIfExist(external, 'radialFlow', this);
return external;
}
// #region Accessor
/**
* 获取/设置流速 数组分别代表x和y方向流速
* @type {Array<number>}
* @public
*/
get flowSpeed() {
return this._flowSpeed;
}
set flowSpeed(value) {
this._flowSpeed = value.concat();
}
/**
* 获取/设置 波浪强度
* @type {number}
* @public
*/
get flowWeight() {
return this._flowWeight;
}
set flowWeight(value) {
this._flowWeight = value;
this.bodyNode.setFlowWeight(value);
}
/**
* 获取/设置水面反射物体的变形系数(扰动)
* @type {number}
* @public
*/
get reflectDistortion() {
return this._reflectDistortion;
}
set reflectDistortion(value) {
this._reflectDistortion = value;
this.bodyNode.setReflectDistortion(value);
}
/**
* 获取/设置 水流动态效果(噪声系数,暂时还没看到效果是什么)
* @type {number}
* @public
*/
get noiseTimeScale() {
return this._noiseTimeScale;
}
set noiseTimeScale(value) {
this._noiseTimeScale = value;
this.bodyNode.setNoiseTimeScale(value);
}
/**
* 获取/设置 是否开启径向流动
* @type {boolean}
* @public
*/
get radialFlow() {
return this.bodyNode.getRadialFlow();
}
set radialFlow(value) {
this.bodyNode.setRadialFlow(value);
}
// #endregion
get isWater() {
return true;
}
}
export { Water }