/**
* author luocharming
* use to create sector
* @export
* @class Sector
* @extends {THING.Mesh}
*/
module.exports = class Sector extends THING.Mesh{
#degree = 0;
#degreeDown = 0;
#segment = 4;
#radius = 1;
#height = 0;
#shape = null;
constructor(params) {
let shape = {data:{
position: [0, 0, 0, 1, 0, 0, 0, 0, 1],
normal: [0, 1, 0, 0, 1, 0, 0, 1, 0],
uv: [0, 0, 0, 1, 1, 0],
uv2: [0, 0, 0, 1, 1, 0],
index: [0, 1, 2]
}};
if(params && params.material) {
shape.material = params.material;
}
super(shape);
this.#degree = THING.Math.clamp(THING.Utils.parseValue(params && params['degree'], 30), 0, 360);
this.#degreeDown = THING.Math.clamp(THING.Utils.parseValue(params && params['degreeDown'], 0), 0, 89);
this.#segment = THING.Math.max(THING.Utils.parseValue(params && params['segment'], 10), 4);
this.#radius = THING.Math.max(THING.Utils.parseValue(params && params['radius'], 1), 0);
this.#height = THING.Math.max(THING.Utils.parseValue(params && params['height'], 0),0);
this.geometry.resource.setVertexData(this.#generateVertexData());
this.node.$markRenderStateDirty();
}
set degree(value) {
this.#degree = THING.Math.clamp(value, 0, 360);
this.#updateMesh();
}
get degree() {
return this.#degree;
}
set radius(value) {
this.#radius = THING.Math.max(value,0);
this.#updateMesh();
}
get radius() {
return this.#radius;
}
set degreeDown(value) {
this.#degreeDown = THING.Math.clamp(value, 0, 89);
this.#updateMesh();
}
get degreeDown() {
return this.#degreeDown;
}
set height(value) {
if(value * this.#height === 0){
this.#height = THING.Math.max(value, 0);
this.#updateMesh(true);
}else{
this.#height = THING.Math.max(value, 0);
this.#updateMesh();
}
}
get height() {
return this.#height;
}
#updateMesh(rebuildMesh = false){
if(rebuildMesh){
//TODO 后续支持修改Segment,重置网格
}else{
this.#updatePoints();
this.setPosition(this.#shape.position);
}
this.node.$markRenderStateDirty();
}
#generateVertexData() {
if(this.#height === 0){
this.#shape = this.#createSection([0,1,0],0);
}else{
//TODO 后续支持设置厚度
// shapeData = $createSection(params,false,shapeData);
// shapeData = $createSection(params,true,shapeData);
// shapeData = $createSide(params,shapeData);
}
let vertexData = {attributes:{},vertexBuffer:[],indices:[]};
vertexData.attributes = {positions:0,normals:1,uvs:2,uvs2:3};
let offset = this.#shape.index.length / 3;
vertexData.vertexBuffer.push(this.#getVertexBuffer(this.#shape.position,offset),this.#getVertexBuffer(this.#shape.normal,offset),this.#getVertexBuffer(this.#shape.uv,offset),this.#getVertexBuffer(this.#shape.uv2,offset));
vertexData.indices = [...this.#shape.index];
return vertexData;
}
#getVertexBuffer(data,offset){
return {array:[...data], stride: data.length / offset};
}
#createSection(axis,height) {
let shape = {position:[],normal:[],uv:[],uv2:[],index:[]};
let startQuat = THING.Math.multiplyQuat(THING.Math.getQuatFromUnitVectors([0,0,0],[0,0,1]),THING.Math.getQuatFromAxisAngle(axis,-this.#degree / 2));
let unitDegree = this.#degree / this.#segment;
for (let i = 0; i <= this.#segment; i++) {
this.#generatePoints(startQuat,axis,i*unitDegree,height,shape);
this.#generateUvs(i/this.#segment, shape.uv)
}
this.#computeNormals(0, shape);
this.#generateSectionIndices(0, shape);
shape.uv2 = shape.uv;
return shape;
}
#generatePoints(startQuat,axis,degree,height,out) {
out.position.push(0,0,0);
let startDir = [0,0,1];
let quat = THING.Math.multiplyQuat(startQuat, THING.Math.getQuatFromAxisAngle(axis, degree));
let dir = THING.Math.vec3ApplyQuat(startDir,quat);
dir = THING.Math.normalizeVector(dir);
let point = THING.Math.scaleVector(dir,this.#radius);
point = [point[0], point[1] + height - this.#radius * THING.Math.tan(THING.Math.degToRad(this.#degreeDown)), point[2]];
out.position.push(...point);
}
#generateUvs(offset, out) {
out.push(offset,0,offset,1);
}
#computeNormals(startIndex, out) {
out.normal = [];
let index = startIndex;
for (let i = 0; i <= this.#segment; i++) {
if(i == this.#segment){
let n = [out.normal[out.normal.length - 3],out.normal[out.normal.length - 2],out.normal[out.normal.length - 1]];
out.normal.push(...n,...n);
continue;
}
let o = [out.position[index],out.position[index + 1],out.position[index + 2]];
let a = [out.position[index + 3],out.position[index + 4],out.position[index + 5]];
let b = [out.position[index + 9],out.position[index + 10],out.position[index + 11]];
let oa = THING.Math.subVector(a,o);
let ob = THING.Math.subVector(b,o);
let n = THING.Math.crossVector(oa,ob);
n = THING.Math.normalizeVector(n);
out.normal.push(...n,...n);
index += 6;
}
}
#generateSectionIndices(startIndex, out) {
for (let i = 0; i < this.#segment; i++) {
out.index.push(startIndex, startIndex+1, startIndex+3);
startIndex+=2;
}
}
#updatePoints() {
//TODO 目前不考虑厚度
let axis = [0,1,0];
let height = 0;
let startQuat = THING.Math.multiplyQuat(THING.Math.getQuatFromUnitVectors([0,0,0],[0,0,1]),THING.Math.getQuatFromAxisAngle(axis,-this.#degree / 2));
let unitDegree = this.#degree / this.#segment;
this.#shape.position = [];
for (let i = 0; i <= this.#segment; i++) {
this.#generatePoints(startQuat,axis,i*unitDegree,height,this.#shape);
}
this.#computeNormals(0,this.#shape);
}
}