@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
222 lines (196 loc) • 6.57 kB
text/typescript
import {Vector3, Vector4, Line3, BufferAttribute} from 'three';
import {QuadObject} from '../QuadObject';
import {Attribute} from '../../../Attribute';
import {closestPointsBetweenLines, ClosestPoints} from '../../../../LineUtils';
const _v4 = new Vector4();
const _p0 = new Vector3();
const _p1 = new Vector3();
const _p2 = new Vector3();
const _p3 = new Vector3();
const _center = new Vector3();
const _line01 = new Line3();
const _line12 = new Line3();
const _line23 = new Line3();
const _line30 = new Line3();
const _line0p = new Vector3();
const _line1p = new Vector3();
const _line2p = new Vector3();
const _line3p = new Vector3();
const _delta0 = new Vector3();
const _delta1 = new Vector3();
const _delta2 = new Vector3();
const _delta3 = new Vector3();
const _closestPoints: ClosestPoints = {
pointOnLine1: new Vector3(),
pointOnLine2: new Vector3(),
};
export function quadInnerRadius(quadObject: QuadObject, i: number) {
const quadGeometry = quadObject.geometry;
const indices = quadGeometry.index;
const srcPositions = quadGeometry.attributes.position.array;
_v4.fromArray(indices, i * 4);
_p0.fromArray(srcPositions, _v4.x * 3);
_p1.fromArray(srcPositions, _v4.y * 3);
_p2.fromArray(srcPositions, _v4.z * 3);
_p3.fromArray(srcPositions, _v4.w * 3);
_center.copy(_p0).add(_p1).add(_p2).add(_p3).multiplyScalar(0.25);
_line01.start.copy(_p0);
_line01.end.copy(_p1);
_line12.start.copy(_p1);
_line12.end.copy(_p2);
_line23.start.copy(_p2);
_line23.end.copy(_p3);
_line30.start.copy(_p3);
_line30.end.copy(_p0);
_line01.closestPointToPoint(_center, false, _line0p);
_line12.closestPointToPoint(_center, false, _line1p);
_line23.closestPointToPoint(_center, false, _line2p);
_line30.closestPointToPoint(_center, false, _line3p);
const dist0 = _line0p.distanceTo(_center);
const dist1 = _line1p.distanceTo(_center);
const dist2 = _line2p.distanceTo(_center);
const dist3 = _line3p.distanceTo(_center);
let innerRadius = dist0;
if (innerRadius > dist1) {
innerRadius = dist1;
}
if (innerRadius > dist2) {
innerRadius = dist2;
}
if (innerRadius > dist3) {
innerRadius = dist3;
}
return innerRadius;
}
export function quadOuterRadius(quadObject: QuadObject, i: number) {
const quadGeometry = quadObject.geometry;
const indices = quadGeometry.index;
const srcPositions = quadGeometry.attributes.position.array;
_v4.fromArray(indices, i * 4);
_p0.fromArray(srcPositions, _v4.x * 3);
_p1.fromArray(srcPositions, _v4.y * 3);
_p2.fromArray(srcPositions, _v4.z * 3);
_p3.fromArray(srcPositions, _v4.w * 3);
_center.copy(_p0).add(_p1).add(_p2).add(_p3).multiplyScalar(0.25);
const dist0 = _p0.distanceTo(_center);
const dist1 = _p1.distanceTo(_center);
const dist2 = _p2.distanceTo(_center);
const dist3 = _p3.distanceTo(_center);
let outerRadius = 0;
if (outerRadius < dist0) {
outerRadius = dist0;
}
if (outerRadius < dist1) {
outerRadius = dist1;
}
if (outerRadius < dist2) {
outerRadius = dist2;
}
if (outerRadius < dist3) {
outerRadius = dist3;
}
return outerRadius;
}
export interface QuadPrimitivePointPositions {
p0: Vector3;
p1: Vector3;
p2: Vector3;
p3: Vector3;
}
export interface QuadPrimitivePointIndices {
i0: number;
i1: number;
i2: number;
i3: number;
}
const _indexIndices: QuadPrimitivePointIndices = {
i0: 0,
i1: 0,
i2: 0,
i3: 0,
};
const _indices: QuadPrimitivePointIndices = {
i0: 0,
i1: 0,
i2: 0,
i3: 0,
};
const stride = 4;
export function quadPrimitivePointIndexIndices(primitiveIndex: number, target: QuadPrimitivePointIndices) {
target.i0 = primitiveIndex * stride + 0;
target.i1 = primitiveIndex * stride + 1;
target.i2 = primitiveIndex * stride + 2;
target.i3 = primitiveIndex * stride + 3;
}
export function quadPrimitivePointIndices(
quadObject: QuadObject,
primitiveIndex: number,
target: QuadPrimitivePointIndices
) {
quadPrimitivePointIndexIndices(primitiveIndex, _indexIndices);
const quadGeometry = quadObject.geometry;
const index = quadGeometry.index;
target.i0 = index[_indexIndices.i0];
target.i1 = index[_indexIndices.i1];
target.i2 = index[_indexIndices.i2];
target.i3 = index[_indexIndices.i3];
}
export function quadPrimitivePointPositions(
quadObject: QuadObject,
primitiveIndex: number,
target: QuadPrimitivePointPositions
) {
const quadGeometry = quadObject.geometry;
const positionAttribute = quadGeometry.attributes[Attribute.POSITION] as BufferAttribute | undefined;
if (!positionAttribute) {
return target;
}
quadPrimitivePointIndices(quadObject, primitiveIndex, _indices);
const positionArray = positionAttribute.array;
target.p0.fromArray(positionArray, _indices.i0 * 3);
target.p1.fromArray(positionArray, _indices.i1 * 3);
target.p2.fromArray(positionArray, _indices.i2 * 3);
target.p3.fromArray(positionArray, _indices.i3 * 3);
}
function _prepareLine(line: Line3, start: Vector3, end: Vector3) {
line.start.copy(start);
line.end.copy(end);
}
export function quadPointInset(
points: QuadPrimitivePointPositions,
unclampedInset: number,
target: QuadPrimitivePointPositions
) {
_prepareLine(_line01, points.p0, points.p1);
_prepareLine(_line12, points.p1, points.p2);
_prepareLine(_line23, points.p2, points.p3);
_prepareLine(_line30, points.p3, points.p0);
_center.copy(points.p0).add(points.p1).add(points.p2).add(points.p3).multiplyScalar(0.25);
_line01.closestPointToPoint(_center, false, _line0p);
_line12.closestPointToPoint(_center, false, _line1p);
_line23.closestPointToPoint(_center, false, _line2p);
_line30.closestPointToPoint(_center, false, _line3p);
_delta0.copy(_center).sub(_line0p);
_delta1.copy(_center).sub(_line1p);
_delta2.copy(_center).sub(_line2p);
_delta3.copy(_center).sub(_line3p);
const maxInset = Math.min(_delta0.length(), _delta1.length(), _delta2.length(), _delta3.length());
const inset = Math.min(unclampedInset, maxInset);
const _offsetLine = (line: Line3, delta: Vector3) => {
delta.normalize().multiplyScalar(inset);
line.start.add(delta);
line.end.add(delta);
};
_offsetLine(_line01, _delta0);
_offsetLine(_line12, _delta1);
_offsetLine(_line23, _delta2);
_offsetLine(_line30, _delta3);
const _getIntersect = (line0: Line3, line1: Line3, target: Vector3) => {
closestPointsBetweenLines(line0, line1, _closestPoints);
target.copy(_closestPoints.pointOnLine1).add(_closestPoints.pointOnLine2).multiplyScalar(0.5);
};
_getIntersect(_line01, _line30, target.p0);
_getIntersect(_line12, _line01, target.p1);
_getIntersect(_line23, _line12, target.p2);
_getIntersect(_line30, _line23, target.p3);
}