import { Utils } from '../common/Utils'
import { GeometryResource } from '../resources/GeometryResource';
import { MaterialResource } from '../resources/MaterialResource';
import { Object3D } from './Object3D';
/**
* Mesh - 三维网格物体
*
* 用于创建自定义三维网格物体(带材质),支持传入顶点数据和材质属性。
* @class Mesh
* @memberof THING
* @extends THING.Object3D
* @public
* @example
const mesh = new THING.Mesh({
data: {
position: [0, 0, 0, 1, 0, 0, 0, 1, 0],
index: [0, 1, 2],
},
material: {
color:[1,0,0],
transparent:true,
opacity:0.5,
}
});
*/
class Mesh extends Object3D {
static defaultTagArray = ['Geometry'];
/**
三维网格物体(带材质)
* @param {object} param 初始化参数列表
* @param {object} param.data 存放模型的顶点信息,包括顶点位置(position)、法向量(normal)、贴图坐标(uv)、索引(index)等
* @param {object} param.material 材质属性
* @constructor
* @public
*/
constructor(param = {}) {
super(param);
}
// #region Private
_createCustomNode() {
let geometryResource = this._geometry.resource;
let materialResource = this._material.resource;
return Utils.createObject('CustomNode', { app: this.app, geometryResource, materialResource });
}
_loadGeometryResource(param) {
let data = param['data'];
if (data) {
this._geometry = new GeometryResource(data);
}
else if (param['geometry']) {
this._geometry = param['geometry'];
this._geometry.addRef();
}
}
_loadMaterialResource(param) {
let material = param['material'];
if (material) {
if (material.isMaterialResource) {
this._material = material;
this._material.addRef();
}
else {
this._material = new MaterialResource(material);
}
}
else {
this._material = new MaterialResource();
}
}
// #endregion
// #region Overrides
onDestroy() {
if (this._geometry) {
this._geometry.release();
this._geometry = null;
}
if (this._material) {
this._material.release();
this._material = null;
}
super.onDestroy();
}
onTaskExecutorComplete(callback, error) {
if (this.taskExecutor.length) {
this.taskExecutor.then(callback, error);
}
else {
callback();
}
}
onLoadResource(options, resolve, reject) {
// 如果动态加载直接返回
const dynamic = Utils.parseValue(options['dynamic'], false);
if (dynamic) {
resolve();
return;
}
if (this.destroyed) {
return;
}
this._resourceState = Object3D.ResourceState.Loading;
this._loadGeometryResource(this.options);
this._loadMaterialResource(this.options);
// 再加载unode
if (this._geometry) {
let node = this._createCustomNode();
this.body.setNode(node);
}
// 最后加载图片资源
if (this._material.loaded) {
resolve();
}
else {
this._material.waitForComplete().then(() => {
resolve();
});
}
}
onCopy(object) {
super.onCopy(object);
let resource = object.geometry.resource;
if (!this.geometry) {
this.geometry = new GeometryResource({ array: resource._vertexData });
}
else {
this.setNormal(resource.getAttribute('a_Normal'));
this.setPosition(resource.getAttribute('a_Position'));
this.setUv(resource.getAttribute('a_Uv'));
this.setUv2(resource.getAttribute('a_Uv2'));
}
}
/**
设置顶点位置信息 当 geometry 仅被当前 Mesh 引用时,使用此接口设置 Mesh 顶点。
* @param {Array<number>|Float32Array} array 顶点位置信息。
* @public
*/
setPosition(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Position', array);
}
}
/**
* 获取顶点位置信息
* @returns {Float32Array} 顶点位置信息。
* @public
*/
getPosition() {
return this.geometry.resource.getAttribute('a_Position');
}
/**
* 设置顶点贴图坐标信息 当 geometry 仅被当前 Mesh 引用时,使用此接口设置 UV。
* @param {Array<number>|Float32Array} array 顶点贴图坐标信息。
* @public
*/
setUv(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Uv', array);
}
}
/**
获取顶点贴图坐标信息
* @returns {Float32Array} 顶点贴图坐标信息。
* @public
*/
getUv() {
return this.geometry.resource.getAttribute('a_Uv');
}
/**
设置顶点第二套贴图坐标信息
* @param {Array<number>|Float32Array} array 顶点第二套贴图坐标信息。
* @private
*/
setUv2(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Uv2', array);
}
}
/**
设置顶点法线信息 当 geometry 仅被当前 Mesh 引用时,使用此接口设置法线。
* @param {Array<number>|Float32Array} array 顶点法线信息。
* @public
*/
setNormal(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setAttribute('a_Normal', array);
}
}
/**
获取顶点法线信息
* @returns {Float32Array} 顶点法线信息。
* @public
*/
getNormal() {
return this.geometry.resource.getAttribute('a_Normal');
}
setIndices(array) {
if (this.geometry.refCount == 1) {
if (array instanceof Array) {
array = new Float32Array(array);
}
this.geometry.resource.setIndices(array);
}
}
getIndices() {
return this.geometry.resource.getIndices();
}
// #endregion
// #region Accessor
/**
获取Mesh的数据
* @type {object}
* @public
*/
get data() {
return {
geometryData: this._geometry ? this._geometry.vertexData : null,
materialData: this._material ? this._material.data : null,
}
}
/**
Get geometry. 获取Mesh的几何数据
* @type {GeometryResource}
* @private
*/
get geometry() {
return this._geometry;
}
set geometry(value) {
this._geometry = value;
}
// #endregion
/**
检查是否为Mesh类型或继承自Mesh。
* @type {boolean}
* @public
*/
get isMesh() {
return true;
}
}
export { Mesh }