@openhps/core
Version:
Open Hybrid Positioning System - Core component
190 lines (163 loc) • 5.83 kB
JavaScript
;
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;