import { Utils, Mesh } from '@uino/thing';
/**
* 体积网格。
* @class VolumeMesh
* @public
* @memberof THING
* @example
* let volumeMesh = new THING.VolumeMesh({
* data: {
* position: [x, y, z, x1, y1, y2, .... ],
* index: [1 ,2, 3, ...]
* },
* alphaThreshold: 0.1,
* opacity: 0.5,
* unitDistanceOpacity: 0.1,
* mixType: 'mix',
* colorRampTexture: new THING.ImageTexture({ url: 'http://xxx.png' }),
* ValueAffectsOpacity: true,
* volumeSize: [x, y, z],
* volumeOffset: [x, y, z],
* volumeRotation: [x, y, z],
* particleRadius: 0.7,
* particleDensity: 1.6,
* isParticleBased: true
* });
*/
class VolumeMesh extends Mesh {
/**
* @constructor
* @public
* @summary 构造函数
* @param {object} param
* @param {object} param.data 剪辑形状数据 {position: [x, y, z, x1, y1, y2, .... ], index: [1 ,2, 3, ...]}
* @param {number} param.alphaThreshold 默认值 0 范围 0 - 1
* @param {number} param.opacity 默认值 0 范围 0 - 1
* @param {number} param.unitDistanceOpacity 默认值 1.2 范围 0 - 10
* @param {string} param.mixType 混合类型 "mix" 或 "normal" 默认值 "normal"
* @param {ImageTexture} param.colorRampTexture 颜色渐变纹理
* @param {boolean} param.ValueAffectsOpacity 值是否影响透明度 默认值 true
* @param {Array} param.volumeSize 体积大小 [x, y, z]
* @param {Array} param.volumeOffset 体积偏移 [x, y, z]
* @param {Array} param.volumeRotation 体积旋转 [x, y, z]
* @param {number} param.particleRadius 粒子半径 默认值 0.7
* @param {number} param.particleDensity 粒子密度 默认值 1.6
* @param {boolean} param.isParticleBased 是否粒子化 默认值 true
**/
constructor(param) {
super(param);
}
/**
* @private
**/
_createCustomNode(param) {
super._loadGeometryResource(param)
let geometryResource = this.geometry;
return Utils.createObject('VolumeEffectNode', { external: { node: this.node, camera: this.app.camera, view: this.app.view, param: param, geometryResource }});
}
/**
* @private
**/
onLoadResource(options, resolve, reject) {
let dynamic = Utils.parseValue(options['dynamic'], false);
if (!dynamic) {
Utils.setTimeout(() => {
if (this.destroyed) {
reject(`The object had been destroyed, skip to load resources`);
}
else {
let node = this._createCustomNode(options);
this.body.setNode(node);
resolve();
}
});
}
}
/**
* 网格不透明度(默认值 1,范围 0 - 1)。
* @type {boolean}
* @public
*/
set opacity(opacity) {
this.node.setOpacity(opacity);
}
get opacity() {
return this.node.getOpacity();
}
/**
* 此对象与场景颜色的混合方法(混合类型为 mix 或 "normal",默认值为 "normal")
* @type {string}
* @public
*/
set mixType(value) {
this.node.setMixType(value);
}
get mixType() {
return this.node.getMixType();
}
/**
* Alpha 阈值,低于此值的项将被裁剪(默认值 0,范围 0 - 1)
* @type {number}
* @public
*/
set alphaThreshold(value) {
this.node.setAlphaThreshold(value);
}
get alphaThreshold() {
return this.node.getAlphaThreshold();
}
/**
* 每单位距离内的透明度(默认值 1.2,范围 0 - 10)
* @type {number}
* @public
*/
set unitDistanceOpacity(value) {
this.node.setUnitDistanceOpacity(value);
}
get unitDistanceOpacity() {
return this.node.getUnitDistanceOpacity();
}
/**
* 对象渲染数据是否影响透明度(默认值为 true)
* @type {boolean}
* @public
*/
set valueOpacityEnable(value) {
this.node.setValueAffectsOpacity(value);
}
get valueOpacityEnable() {
return this.node.getValueAffectsOpacity();
}
set particleRadius(value) {
this.node.setParticleRadius(value);
}
get particleRadius() {
return this.node.getParticleRadius();
}
set isParticleBased(value) {
this.node.setIsParticleBased(value);
}
get isParticleBased() {
return this.node.getIsParticleBased();
}
set particleDensity(value) {
this.node.setParticleDensity(value);
}
get particleDensity() {
return this.node.getParticleDensity();
}
set maskIntensity(value) {
this.node.setMaskIntensity(value);
}
get maskIntensity() {
return this.node.getMaskIntensity();
}
set lightDirection(value) {
this.node.setLightDirection(value);
}
get lightDirection() {
return this.node.getLightDirection();
}
/**
* Set HeatAtPoint
* @param {object} object
* @param {object} object.data
* @param {object} object.data.size data format{ x, y, z }
* @param {Array} object.data.points data format[[x,y,z,value],[x,y,z,value]]
* @param {Array} object.data.range data format[x,y,z]The data range starts from the data center [0, 0, 0] and points within the positive and negative range radius,
* @param {number} object.data.radius Data radius
* @param {object} object.textureSize [Size, Size, Size], if it is a 3D texture, the texture size needs to be set
* @example
* heatCloudData = {
* size: { x: 256, y: 256, z: 256 },
* points: [[x, y, z, value], [x, y, z, value]],
* range: [x, y, z],
* radius: 10
* }
* volumeMesh.setHeatAtPoint({ data: heatCloudData, textureSize: [SIZE, SIZE, SIZE]});
* @private
*/
_setHeatAtPoint(object) {
if (this.node._children.length > 0) {
this.node._children[0].setHeatAtPoint(object);
}
else {
this.node.setHeatAtPoint(object);
}
}
/**
* Set HeatAtPoint
* @param {object} object
* @param {object} object.data
* @param {object} object.data.size data format{ x, y, z }
* @param {Array} object.data.points data format[[x,y,z,value],[x,y,z,value]]
* @param {Array} object.data.range data format[x,y,z]The data range starts from the data center [0, 0, 0] and points within the positive and negative range radius,
* @param {number} object.data.radius Data radius
* @param {number} object.data.type Data type
* @param {object} object.textureSize [Size, Size, Size], if it is a 3D texture, the texture size needs to be set
* @example
* heatCloudData = {
* size: { x: 256, y: 256, z: 256 },
* points: [[x, y, z, value], [x, y, z, value]],
* range: [x, y, z],
* radius: 10
* type: 'temperature'
* }
* volumeMesh.setHeatAtPoint({ data: heatCloudData, textureSize: [SIZE, SIZE, SIZE]});
* @private
*/
_setTemperatureAtPoint(object) {
if (this.node._children.length > 0) {
this.node._children[0].setTemperatureAtPoint(object);
}
else {
this.node.setTemperatureAtPoint(object);
}
}
/**
* Set Texture
* @param {object} object
* @param {ImageTexture} object.data 3DTexture ImageTexture
* @param {number} object.ZSLICEX,
* @param {number} object.ZSLICEY,
* @param {number} object.ZSLICENUM,
* @param {object} object.textureSize [SIZE, SIZE,SIZE],
* @example
* let texture = new THING.ImageTexture({ url: 'http://xxx.png' });
* volumeMesh.setTexture({ data: texture, ZSLICEX:16, ZSLICEY:16, ZSLICENUM:256});
* @private
*/
_setTexture(object) {
this.node.setTexture(object);
}
/**
* Set ArrayBuffer
* @param {object} object
* @param {Uint8Array} object.data 3DTexture ArrayBuffer
* @param {object} object.textureSize [SIZE, SIZE, SIZE]
* @example
* let arrayBuffer = new Uint8Array(data);
* volumeMesh.setArrayBuffer({ data: arrayBuffer, textureSize: [SIZE, SIZE, SIZE]});
* @private
*/
_setArrayBuffer(object) {
this.node.setArrayBuffer(object);
}
/**
* 设置体积数据
* @param {object} object - 体积数据对象
* @param {object} object.data - 包含体积数据的详细信息
* @param {number} object.data.radius - 体积的半径
* @param {string} object.data.type - 体积数据的类型,支持 'temperature' 和其他类型
* @public
*/
setData(object) {
if (object.data.radius) {
if (object.data.type == 'temperature') {
this._setTemperatureAtPoint(object);
}
else {
this._setHeatAtPoint(object);
}
}
else if (object.data.isImageTexture) {
this._setTexture(object);
}
else {
this._setArrayBuffer(object);
}
}
}
export { VolumeMesh };