UNPKG

polygonjs-engine

Version:

node-based webgl 3D engine https://polygonjs.com

206 lines (205 loc) 6.77 kB
import {Vector3 as Vector32} from "three/src/math/Vector3"; import {BufferGeometry as BufferGeometry2} from "three/src/core/BufferGeometry"; import {BufferAttribute as BufferAttribute2} from "three/src/core/BufferAttribute"; import {TypeAssert} from "../../../engine/poly/Assert"; export var PointsCountMode; (function(PointsCountMode2) { PointsCountMode2["SEGMENTS_COUNT"] = "segments count"; PointsCountMode2["SEGMENTS_LENGTH"] = "segments length"; })(PointsCountMode || (PointsCountMode = {})); export const POINTS_COUNT_MODE = [PointsCountMode.SEGMENTS_COUNT, PointsCountMode.SEGMENTS_LENGTH]; export var JoinMode; (function(JoinMode2) { JoinMode2["ABC"] = "abc"; JoinMode2["ACB"] = "acb"; JoinMode2["AB"] = "ab"; JoinMode2["BC"] = "bc"; JoinMode2["AC"] = "ac"; })(JoinMode || (JoinMode = {})); export const JOIN_MODES = [JoinMode.ABC, JoinMode.ACB, JoinMode.AB, JoinMode.AC, JoinMode.BC]; export class Circle3Points { constructor(params) { this.params = params; this.a = new Vector32(); this.b = new Vector32(); this.c = new Vector32(); this.an = new Vector32(); this.bn = new Vector32(); this.cn = new Vector32(); this.ac = new Vector32(); this.ab = new Vector32(); this.ab_x_ac = new Vector32(); this.part0 = new Vector32(); this.part1 = new Vector32(); this.divider = 1; this.a_center = new Vector32(); this.center = new Vector32(); this.normal = new Vector32(); this.radius = 1; this.x = new Vector32(); this.y = new Vector32(); this.z = new Vector32(); this.angle_ab = 1; this.angle_ac = 1; this.angle_bc = 1; this.angle = 2 * Math.PI; this.x_rotated = new Vector32(); this._created_geometries = {}; } created_geometries() { return this._created_geometries; } create(a, b, c) { this.a.copy(a); this.b.copy(b); this.c.copy(c); this._compute_axis(); this._create_arc(); this._create_center(); } _create_arc() { this._compute_angle(); const points_count = this._points_count(); const positions = new Array(points_count * 3); const indices = new Array(points_count); const angle_increment = this.angle / (points_count - 1); this.x_rotated.copy(this.x).multiplyScalar(this.radius); let i = 0; for (i = 0; i < points_count; i++) { this.x_rotated.copy(this.x).applyAxisAngle(this.normal, angle_increment * i).multiplyScalar(this.radius).add(this.center); this.x_rotated.toArray(positions, i * 3); if (i > 0) { indices[(i - 1) * 2] = i - 1; indices[(i - 1) * 2 + 1] = i; } } if (this.params.full) { indices.push(i - 1); indices.push(0); } const geometry = new BufferGeometry2(); geometry.setAttribute("position", new BufferAttribute2(new Float32Array(positions), 3)); geometry.setIndex(indices); if (this.params.addIdAttribute || this.params.addIdnAttribute) { const ids = new Array(points_count); for (let i2 = 0; i2 < ids.length; i2++) { ids[i2] = i2; } if (this.params.addIdAttribute) { geometry.setAttribute("id", new BufferAttribute2(new Float32Array(ids), 1)); } const idns = ids.map((id) => id / (points_count - 1)); if (this.params.addIdnAttribute) { geometry.setAttribute("idn", new BufferAttribute2(new Float32Array(idns), 1)); } } this._created_geometries.arc = geometry; } _create_center() { if (!this.params.center) { return; } const geometry = new BufferGeometry2(); const positions = [this.center.x, this.center.y, this.center.z]; geometry.setAttribute("position", new BufferAttribute2(new Float32Array(positions), 3)); this._created_geometries.center = geometry; } _compute_axis() { this.ac.copy(this.c).sub(this.a); this.ab.copy(this.b).sub(this.a); this.ab_x_ac.copy(this.ab).cross(this.ac); this.divider = 2 * this.ab_x_ac.lengthSq(); this.part0.copy(this.ab_x_ac).cross(this.ab).multiplyScalar(this.ac.lengthSq()); this.part1.copy(this.ac).cross(this.ab_x_ac).multiplyScalar(this.ab.lengthSq()); this.a_center.copy(this.part0).add(this.part1).divideScalar(this.divider); this.radius = this.a_center.length(); this.normal.copy(this.ab_x_ac).normalize(); this.center.copy(this.a).add(this.a_center); } _compute_angle() { if (!this.params.arc) { return; } if (this.params.full) { this.x.copy(this.a).sub(this.center).normalize(); this.angle = 2 * Math.PI; } else { this.an.copy(this.a).sub(this.center).normalize(); this.bn.copy(this.b).sub(this.center).normalize(); this.cn.copy(this.c).sub(this.center).normalize(); this._set_x_from_joinMode(); this.y.copy(this.normal); this.z.copy(this.x).cross(this.y).normalize(); this.angle_ab = this.an.angleTo(this.bn); this.angle_ac = this.an.angleTo(this.cn); this.angle_bc = this.bn.angleTo(this.cn); this._set_angle_from_joinMode(); } } _points_count() { const mode = this.params.pointsCountMode; switch (mode) { case PointsCountMode.SEGMENTS_COUNT: { return this.params.segmentsCount + 1; } case PointsCountMode.SEGMENTS_LENGTH: { let perimeter = Math.PI * this.radius * this.radius; if (!this.params.full) { perimeter *= Math.abs(this.angle) / (Math.PI * 2); } return Math.ceil(perimeter / this.params.segmentsLength); } } TypeAssert.unreachable(mode); } _set_x_from_joinMode() { const joinMode = this.params.joinMode; this.x.copy(this.a).sub(this.center).normalize(); switch (joinMode) { case JoinMode.ABC: { return this.x.copy(this.an); } case JoinMode.ACB: { return this.x.copy(this.an); } case JoinMode.AB: { return this.x.copy(this.an); } case JoinMode.AC: { return this.x.copy(this.an); } case JoinMode.BC: { return this.x.copy(this.bn); } } TypeAssert.unreachable(joinMode); } _set_angle_from_joinMode() { const joinMode = this.params.joinMode; switch (joinMode) { case JoinMode.ABC: { this.angle = this.angle_ab + this.angle_bc; return; } case JoinMode.ACB: { this.angle = this.angle_ac + this.angle_bc; this.angle *= -1; return; } case JoinMode.AB: { this.angle = this.angle_ab; return; } case JoinMode.AC: { this.angle = this.angle_ac; this.angle *= -1; return; } case JoinMode.BC: { this.angle = this.angle_bc; return; } } TypeAssert.unreachable(joinMode); } }