UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

190 lines (163 loc) 5.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LatheGeometry = void 0; var _BufferAttribute = require("../core/BufferAttribute.js"); var _BufferGeometry = require("../core/BufferGeometry.js"); var _Vector = require("../math/Vector3.js"); var _Vector2 = require("../math/Vector2.js"); var _MathUtils = require("../math/MathUtils.js"); /** * Creates meshes with axial symmetry like vases. The lathe rotates around the Y axis. * * ```js * const points = []; * for ( let i = 0; i < 10; i ++ ) { * points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) ); * } * const geometry = new THREE.LatheGeometry( points ); * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } ); * const lathe = new THREE.Mesh( geometry, material ); * scene.add( lathe ); * ``` * * @augments BufferGeometry */ class LatheGeometry extends _BufferGeometry.BufferGeometry { /** * Constructs a new lathe geometry. * * @param {Array<Vector2|Vector3>} [points] - An array of points in 2D space. The x-coordinate of each point * must be greater than zero. * @param {number} [segments=12] - The number of circumference segments to generate. * @param {number} [phiStart=0] - The starting angle in radians. * @param {number} [phiLength=Math.PI*2] - The radian (0 to 2PI) range of the lathed section 2PI is a * closed lathe, less than 2PI is a portion. */ constructor(points = [new _Vector2.Vector2(0, -0.5), new _Vector2.Vector2(0.5, 0), new _Vector2.Vector2(0, 0.5)], segments = 12, phiStart = 0, phiLength = Math.PI * 2) { super(); this.type = 'LatheGeometry'; /** * Holds the constructor parameters that have been * used to generate the geometry. Any modification * after instantiation does not change the geometry. * * @type {Object} */ this.parameters = { points: points, segments: segments, phiStart: phiStart, phiLength: phiLength }; segments = Math.floor(segments); // clamp phiLength so it's in range of [ 0, 2PI ] phiLength = (0, _MathUtils.clamp)(phiLength, 0, Math.PI * 2); // buffers const indices = []; const vertices = []; const uvs = []; const initNormals = []; const normals = []; // helper variables const inverseSegments = 1.0 / segments; const vertex = new _Vector.Vector3(); const uv = new _Vector2.Vector2(); const normal = new _Vector.Vector3(); const curNormal = new _Vector.Vector3(); const prevNormal = new _Vector.Vector3(); let dx = 0; let dy = 0; // pre-compute normals for initial "meridian" for (let j = 0; j <= points.length - 1; j++) { switch (j) { case 0: // special handling for 1st vertex on path dx = points[j + 1].x - points[j].x; dy = points[j + 1].y - points[j].y; normal.x = dy * 1.0; normal.y = -dx; normal.z = dy * 0.0; prevNormal.copy(normal); normal.normalize(); initNormals.push(normal.x, normal.y, normal.z); break; case points.length - 1: // special handling for last Vertex on path initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z); break; default: // default handling for all vertices in between dx = points[j + 1].x - points[j].x; dy = points[j + 1].y - points[j].y; normal.x = dy * 1.0; normal.y = -dx; normal.z = dy * 0.0; curNormal.copy(normal); normal.x += prevNormal.x; normal.y += prevNormal.y; normal.z += prevNormal.z; normal.normalize(); initNormals.push(normal.x, normal.y, normal.z); prevNormal.copy(curNormal); } } // generate vertices, uvs and normals for (let i = 0; i <= segments; i++) { const phi = phiStart + i * inverseSegments * phiLength; const sin = Math.sin(phi); const cos = Math.cos(phi); for (let j = 0; j <= points.length - 1; j++) { // vertex vertex.x = points[j].x * sin; vertex.y = points[j].y; vertex.z = points[j].x * cos; vertices.push(vertex.x, vertex.y, vertex.z); // uv uv.x = i / segments; uv.y = j / (points.length - 1); uvs.push(uv.x, uv.y); // normal const x = initNormals[3 * j + 0] * sin; const y = initNormals[3 * j + 1]; const z = initNormals[3 * j + 0] * cos; normals.push(x, y, z); } } // indices for (let i = 0; i < segments; i++) { for (let j = 0; j < points.length - 1; j++) { const base = j + i * points.length; const a = base; const b = base + points.length; const c = base + points.length + 1; const d = base + 1; // faces indices.push(a, b, d); indices.push(c, d, b); } } // build geometry this.setIndex(indices); this.setAttribute('position', new _BufferAttribute.Float32BufferAttribute(vertices, 3)); this.setAttribute('uv', new _BufferAttribute.Float32BufferAttribute(uvs, 2)); this.setAttribute('normal', new _BufferAttribute.Float32BufferAttribute(normals, 3)); } copy(source) { super.copy(source); this.parameters = Object.assign({}, source.parameters); return this; } /** * Factory method for creating an instance of this class from the given * JSON object. * * @param {Object} data - A JSON object representing the serialized geometry. * @return {LatheGeometry} A new instance. */ static fromJSON(data) { return new LatheGeometry(data.points, data.segments, data.phiStart, data.phiLength); } } exports.LatheGeometry = LatheGeometry;