|
@@ -25396,45 +25396,6 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Text = 3D Text
|
|
|
- *
|
|
|
- * parameters = {
|
|
|
- * font: <THREE.Font>, // font
|
|
|
- *
|
|
|
- * size: <float>, // size of the text
|
|
|
- * height: <float>, // thickness to extrude text
|
|
|
- * curveSegments: <int>, // number of points on the curves
|
|
|
- *
|
|
|
- * bevelEnabled: <bool>, // turn on bevel
|
|
|
- * bevelThickness: <float>, // how deep into text bevel goes
|
|
|
- * bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
|
|
|
- * bevelOffset: <float> // how far from text outline does bevel start
|
|
|
- * }
|
|
|
- */
|
|
|
-
|
|
|
- class TextGeometry extends ExtrudeGeometry {
|
|
|
- constructor(text, parameters = {}) {
|
|
|
- const font = parameters.font;
|
|
|
-
|
|
|
- if (!(font && font.isFont)) {
|
|
|
- console.error('THREE.TextGeometry: font parameter is not an instance of THREE.Font.');
|
|
|
- return new BufferGeometry();
|
|
|
- }
|
|
|
-
|
|
|
- const shapes = font.generateShapes(text, parameters.size); // translate parameters to ExtrudeGeometry API
|
|
|
-
|
|
|
- parameters.depth = parameters.height !== undefined ? parameters.height : 50; // defaults
|
|
|
-
|
|
|
- if (parameters.bevelThickness === undefined) parameters.bevelThickness = 10;
|
|
|
- if (parameters.bevelSize === undefined) parameters.bevelSize = 8;
|
|
|
- if (parameters.bevelEnabled === undefined) parameters.bevelEnabled = false;
|
|
|
- super(shapes, parameters);
|
|
|
- this.type = 'TextGeometry';
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
class TorusGeometry extends BufferGeometry {
|
|
|
constructor(radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2) {
|
|
|
super();
|
|
@@ -25845,8 +25806,6 @@
|
|
|
SphereBufferGeometry: SphereGeometry,
|
|
|
TetrahedronGeometry: TetrahedronGeometry,
|
|
|
TetrahedronBufferGeometry: TetrahedronGeometry,
|
|
|
- TextGeometry: TextGeometry,
|
|
|
- TextBufferGeometry: TextGeometry,
|
|
|
TorusGeometry: TorusGeometry,
|
|
|
TorusBufferGeometry: TorusGeometry,
|
|
|
TorusKnotGeometry: TorusKnotGeometry,
|
|
@@ -30371,400 +30330,50 @@
|
|
|
|
|
|
setOptions(options) {
|
|
|
this.options = options;
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- load(url, onLoad, onProgress, onError) {
|
|
|
- if (url === undefined) url = '';
|
|
|
- if (this.path !== undefined) url = this.path + url;
|
|
|
- url = this.manager.resolveURL(url);
|
|
|
- const scope = this;
|
|
|
- const cached = Cache.get(url);
|
|
|
-
|
|
|
- if (cached !== undefined) {
|
|
|
- scope.manager.itemStart(url);
|
|
|
- setTimeout(function () {
|
|
|
- if (onLoad) onLoad(cached);
|
|
|
- scope.manager.itemEnd(url);
|
|
|
- }, 0);
|
|
|
- return cached;
|
|
|
- }
|
|
|
-
|
|
|
- const fetchOptions = {};
|
|
|
- fetchOptions.credentials = this.crossOrigin === 'anonymous' ? 'same-origin' : 'include';
|
|
|
- fetchOptions.headers = this.requestHeader;
|
|
|
- fetch(url, fetchOptions).then(function (res) {
|
|
|
- return res.blob();
|
|
|
- }).then(function (blob) {
|
|
|
- return createImageBitmap(blob, Object.assign(scope.options, {
|
|
|
- colorSpaceConversion: 'none'
|
|
|
- }));
|
|
|
- }).then(function (imageBitmap) {
|
|
|
- Cache.add(url, imageBitmap);
|
|
|
- if (onLoad) onLoad(imageBitmap);
|
|
|
- scope.manager.itemEnd(url);
|
|
|
- }).catch(function (e) {
|
|
|
- if (onError) onError(e);
|
|
|
- scope.manager.itemError(url);
|
|
|
- scope.manager.itemEnd(url);
|
|
|
- });
|
|
|
- scope.manager.itemStart(url);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- ImageBitmapLoader.prototype.isImageBitmapLoader = true;
|
|
|
-
|
|
|
- class ShapePath {
|
|
|
- constructor() {
|
|
|
- this.type = 'ShapePath';
|
|
|
- this.color = new Color();
|
|
|
- this.subPaths = [];
|
|
|
- this.currentPath = null;
|
|
|
- }
|
|
|
-
|
|
|
- moveTo(x, y) {
|
|
|
- this.currentPath = new Path();
|
|
|
- this.subPaths.push(this.currentPath);
|
|
|
- this.currentPath.moveTo(x, y);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- lineTo(x, y) {
|
|
|
- this.currentPath.lineTo(x, y);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- quadraticCurveTo(aCPx, aCPy, aX, aY) {
|
|
|
- this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
|
|
|
- this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- splineThru(pts) {
|
|
|
- this.currentPath.splineThru(pts);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- toShapes(isCCW, noHoles) {
|
|
|
- function toShapesNoHoles(inSubpaths) {
|
|
|
- const shapes = [];
|
|
|
-
|
|
|
- for (let i = 0, l = inSubpaths.length; i < l; i++) {
|
|
|
- const tmpPath = inSubpaths[i];
|
|
|
- const tmpShape = new Shape();
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
- shapes.push(tmpShape);
|
|
|
- }
|
|
|
-
|
|
|
- return shapes;
|
|
|
- }
|
|
|
-
|
|
|
- function isPointInsidePolygon(inPt, inPolygon) {
|
|
|
- const polyLen = inPolygon.length; // inPt on polygon contour => immediate success or
|
|
|
- // toggling of inside/outside at every single! intersection point of an edge
|
|
|
- // with the horizontal line through inPt, left of inPt
|
|
|
- // not counting lowerY endpoints of edges and whole edges on that line
|
|
|
-
|
|
|
- let inside = false;
|
|
|
-
|
|
|
- for (let p = polyLen - 1, q = 0; q < polyLen; p = q++) {
|
|
|
- let edgeLowPt = inPolygon[p];
|
|
|
- let edgeHighPt = inPolygon[q];
|
|
|
- let edgeDx = edgeHighPt.x - edgeLowPt.x;
|
|
|
- let edgeDy = edgeHighPt.y - edgeLowPt.y;
|
|
|
-
|
|
|
- if (Math.abs(edgeDy) > Number.EPSILON) {
|
|
|
- // not parallel
|
|
|
- if (edgeDy < 0) {
|
|
|
- edgeLowPt = inPolygon[q];
|
|
|
- edgeDx = -edgeDx;
|
|
|
- edgeHighPt = inPolygon[p];
|
|
|
- edgeDy = -edgeDy;
|
|
|
- }
|
|
|
-
|
|
|
- if (inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y) continue;
|
|
|
-
|
|
|
- if (inPt.y === edgeLowPt.y) {
|
|
|
- if (inPt.x === edgeLowPt.x) return true; // inPt is on contour ?
|
|
|
- // continue; // no intersection or edgeLowPt => doesn't count !!!
|
|
|
- } else {
|
|
|
- const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
|
|
|
- if (perpEdge === 0) return true; // inPt is on contour ?
|
|
|
-
|
|
|
- if (perpEdge < 0) continue;
|
|
|
- inside = !inside; // true intersection left of inPt
|
|
|
- }
|
|
|
- } else {
|
|
|
- // parallel or collinear
|
|
|
- if (inPt.y !== edgeLowPt.y) continue; // parallel
|
|
|
- // edge lies on the same horizontal line as inPt
|
|
|
-
|
|
|
- if (edgeHighPt.x <= inPt.x && inPt.x <= edgeLowPt.x || edgeLowPt.x <= inPt.x && inPt.x <= edgeHighPt.x) return true; // inPt: Point on contour !
|
|
|
- // continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return inside;
|
|
|
- }
|
|
|
-
|
|
|
- const isClockWise = ShapeUtils.isClockWise;
|
|
|
- const subPaths = this.subPaths;
|
|
|
- if (subPaths.length === 0) return [];
|
|
|
- if (noHoles === true) return toShapesNoHoles(subPaths);
|
|
|
- let solid, tmpPath, tmpShape;
|
|
|
- const shapes = [];
|
|
|
-
|
|
|
- if (subPaths.length === 1) {
|
|
|
- tmpPath = subPaths[0];
|
|
|
- tmpShape = new Shape();
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
- shapes.push(tmpShape);
|
|
|
- return shapes;
|
|
|
- }
|
|
|
-
|
|
|
- let holesFirst = !isClockWise(subPaths[0].getPoints());
|
|
|
- holesFirst = isCCW ? !holesFirst : holesFirst; // console.log("Holes first", holesFirst);
|
|
|
-
|
|
|
- const betterShapeHoles = [];
|
|
|
- const newShapes = [];
|
|
|
- let newShapeHoles = [];
|
|
|
- let mainIdx = 0;
|
|
|
- let tmpPoints;
|
|
|
- newShapes[mainIdx] = undefined;
|
|
|
- newShapeHoles[mainIdx] = [];
|
|
|
-
|
|
|
- for (let i = 0, l = subPaths.length; i < l; i++) {
|
|
|
- tmpPath = subPaths[i];
|
|
|
- tmpPoints = tmpPath.getPoints();
|
|
|
- solid = isClockWise(tmpPoints);
|
|
|
- solid = isCCW ? !solid : solid;
|
|
|
-
|
|
|
- if (solid) {
|
|
|
- if (!holesFirst && newShapes[mainIdx]) mainIdx++;
|
|
|
- newShapes[mainIdx] = {
|
|
|
- s: new Shape(),
|
|
|
- p: tmpPoints
|
|
|
- };
|
|
|
- newShapes[mainIdx].s.curves = tmpPath.curves;
|
|
|
- if (holesFirst) mainIdx++;
|
|
|
- newShapeHoles[mainIdx] = []; //console.log('cw', i);
|
|
|
- } else {
|
|
|
- newShapeHoles[mainIdx].push({
|
|
|
- h: tmpPath,
|
|
|
- p: tmpPoints[0]
|
|
|
- }); //console.log('ccw', i);
|
|
|
- }
|
|
|
- } // only Holes? -> probably all Shapes with wrong orientation
|
|
|
-
|
|
|
-
|
|
|
- if (!newShapes[0]) return toShapesNoHoles(subPaths);
|
|
|
-
|
|
|
- if (newShapes.length > 1) {
|
|
|
- let ambiguous = false;
|
|
|
- const toChange = [];
|
|
|
-
|
|
|
- for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
|
- betterShapeHoles[sIdx] = [];
|
|
|
- }
|
|
|
-
|
|
|
- for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
|
- const sho = newShapeHoles[sIdx];
|
|
|
-
|
|
|
- for (let hIdx = 0; hIdx < sho.length; hIdx++) {
|
|
|
- const ho = sho[hIdx];
|
|
|
- let hole_unassigned = true;
|
|
|
-
|
|
|
- for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
|
|
|
- if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
|
|
|
- if (sIdx !== s2Idx) toChange.push({
|
|
|
- froms: sIdx,
|
|
|
- tos: s2Idx,
|
|
|
- hole: hIdx
|
|
|
- });
|
|
|
-
|
|
|
- if (hole_unassigned) {
|
|
|
- hole_unassigned = false;
|
|
|
- betterShapeHoles[s2Idx].push(ho);
|
|
|
- } else {
|
|
|
- ambiguous = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (hole_unassigned) {
|
|
|
- betterShapeHoles[sIdx].push(ho);
|
|
|
- }
|
|
|
- }
|
|
|
- } // console.log("ambiguous: ", ambiguous);
|
|
|
-
|
|
|
-
|
|
|
- if (toChange.length > 0) {
|
|
|
- // console.log("to change: ", toChange);
|
|
|
- if (!ambiguous) newShapeHoles = betterShapeHoles;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let tmpHoles;
|
|
|
-
|
|
|
- for (let i = 0, il = newShapes.length; i < il; i++) {
|
|
|
- tmpShape = newShapes[i].s;
|
|
|
- shapes.push(tmpShape);
|
|
|
- tmpHoles = newShapeHoles[i];
|
|
|
-
|
|
|
- for (let j = 0, jl = tmpHoles.length; j < jl; j++) {
|
|
|
- tmpShape.holes.push(tmpHoles[j].h);
|
|
|
- }
|
|
|
- } //console.log("shape", shapes);
|
|
|
-
|
|
|
-
|
|
|
- return shapes;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- class Font {
|
|
|
- constructor(data) {
|
|
|
- this.type = 'Font';
|
|
|
- this.data = data;
|
|
|
- }
|
|
|
-
|
|
|
- generateShapes(text, size = 100) {
|
|
|
- const shapes = [];
|
|
|
- const paths = createPaths(text, size, this.data);
|
|
|
-
|
|
|
- for (let p = 0, pl = paths.length; p < pl; p++) {
|
|
|
- Array.prototype.push.apply(shapes, paths[p].toShapes());
|
|
|
- }
|
|
|
-
|
|
|
- return shapes;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- function createPaths(text, size, data) {
|
|
|
- const chars = Array.from(text);
|
|
|
- const scale = size / data.resolution;
|
|
|
- const line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
|
|
|
- const paths = [];
|
|
|
- let offsetX = 0,
|
|
|
- offsetY = 0;
|
|
|
-
|
|
|
- for (let i = 0; i < chars.length; i++) {
|
|
|
- const char = chars[i];
|
|
|
-
|
|
|
- if (char === '\n') {
|
|
|
- offsetX = 0;
|
|
|
- offsetY -= line_height;
|
|
|
- } else {
|
|
|
- const ret = createPath(char, scale, offsetX, offsetY, data);
|
|
|
- offsetX += ret.offsetX;
|
|
|
- paths.push(ret.path);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return paths;
|
|
|
- }
|
|
|
-
|
|
|
- function createPath(char, scale, offsetX, offsetY, data) {
|
|
|
- const glyph = data.glyphs[char] || data.glyphs['?'];
|
|
|
-
|
|
|
- if (!glyph) {
|
|
|
- console.error('THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.');
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const path = new ShapePath();
|
|
|
- let x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
|
|
|
-
|
|
|
- if (glyph.o) {
|
|
|
- const outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(' '));
|
|
|
-
|
|
|
- for (let i = 0, l = outline.length; i < l;) {
|
|
|
- const action = outline[i++];
|
|
|
-
|
|
|
- switch (action) {
|
|
|
- case 'm':
|
|
|
- // moveTo
|
|
|
- x = outline[i++] * scale + offsetX;
|
|
|
- y = outline[i++] * scale + offsetY;
|
|
|
- path.moveTo(x, y);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'l':
|
|
|
- // lineTo
|
|
|
- x = outline[i++] * scale + offsetX;
|
|
|
- y = outline[i++] * scale + offsetY;
|
|
|
- path.lineTo(x, y);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'q':
|
|
|
- // quadraticCurveTo
|
|
|
- cpx = outline[i++] * scale + offsetX;
|
|
|
- cpy = outline[i++] * scale + offsetY;
|
|
|
- cpx1 = outline[i++] * scale + offsetX;
|
|
|
- cpy1 = outline[i++] * scale + offsetY;
|
|
|
- path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'b':
|
|
|
- // bezierCurveTo
|
|
|
- cpx = outline[i++] * scale + offsetX;
|
|
|
- cpy = outline[i++] * scale + offsetY;
|
|
|
- cpx1 = outline[i++] * scale + offsetX;
|
|
|
- cpy1 = outline[i++] * scale + offsetY;
|
|
|
- cpx2 = outline[i++] * scale + offsetX;
|
|
|
- cpy2 = outline[i++] * scale + offsetY;
|
|
|
- path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- offsetX: glyph.ha * scale,
|
|
|
- path: path
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- Font.prototype.isFont = true;
|
|
|
-
|
|
|
- class FontLoader extends Loader {
|
|
|
- constructor(manager) {
|
|
|
- super(manager);
|
|
|
- }
|
|
|
-
|
|
|
- load(url, onLoad, onProgress, onError) {
|
|
|
- const scope = this;
|
|
|
- const loader = new FileLoader(this.manager);
|
|
|
- loader.setPath(this.path);
|
|
|
- loader.setRequestHeader(this.requestHeader);
|
|
|
- loader.setWithCredentials(scope.withCredentials);
|
|
|
- loader.load(url, function (text) {
|
|
|
- let json;
|
|
|
-
|
|
|
- try {
|
|
|
- json = JSON.parse(text);
|
|
|
- } catch (e) {
|
|
|
- console.warn('THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.');
|
|
|
- json = JSON.parse(text.substring(65, text.length - 2));
|
|
|
- }
|
|
|
-
|
|
|
- const font = scope.parse(json);
|
|
|
- if (onLoad) onLoad(font);
|
|
|
- }, onProgress, onError);
|
|
|
+ return this;
|
|
|
}
|
|
|
|
|
|
- parse(json) {
|
|
|
- return new Font(json);
|
|
|
+ load(url, onLoad, onProgress, onError) {
|
|
|
+ if (url === undefined) url = '';
|
|
|
+ if (this.path !== undefined) url = this.path + url;
|
|
|
+ url = this.manager.resolveURL(url);
|
|
|
+ const scope = this;
|
|
|
+ const cached = Cache.get(url);
|
|
|
+
|
|
|
+ if (cached !== undefined) {
|
|
|
+ scope.manager.itemStart(url);
|
|
|
+ setTimeout(function () {
|
|
|
+ if (onLoad) onLoad(cached);
|
|
|
+ scope.manager.itemEnd(url);
|
|
|
+ }, 0);
|
|
|
+ return cached;
|
|
|
+ }
|
|
|
+
|
|
|
+ const fetchOptions = {};
|
|
|
+ fetchOptions.credentials = this.crossOrigin === 'anonymous' ? 'same-origin' : 'include';
|
|
|
+ fetchOptions.headers = this.requestHeader;
|
|
|
+ fetch(url, fetchOptions).then(function (res) {
|
|
|
+ return res.blob();
|
|
|
+ }).then(function (blob) {
|
|
|
+ return createImageBitmap(blob, Object.assign(scope.options, {
|
|
|
+ colorSpaceConversion: 'none'
|
|
|
+ }));
|
|
|
+ }).then(function (imageBitmap) {
|
|
|
+ Cache.add(url, imageBitmap);
|
|
|
+ if (onLoad) onLoad(imageBitmap);
|
|
|
+ scope.manager.itemEnd(url);
|
|
|
+ }).catch(function (e) {
|
|
|
+ if (onError) onError(e);
|
|
|
+ scope.manager.itemError(url);
|
|
|
+ scope.manager.itemEnd(url);
|
|
|
+ });
|
|
|
+ scope.manager.itemStart(url);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
+ ImageBitmapLoader.prototype.isImageBitmapLoader = true;
|
|
|
+
|
|
|
let _context;
|
|
|
|
|
|
const AudioContext = {
|
|
@@ -34784,6 +34393,218 @@
|
|
|
|
|
|
}
|
|
|
|
|
|
+ class ShapePath {
|
|
|
+ constructor() {
|
|
|
+ this.type = 'ShapePath';
|
|
|
+ this.color = new Color();
|
|
|
+ this.subPaths = [];
|
|
|
+ this.currentPath = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ moveTo(x, y) {
|
|
|
+ this.currentPath = new Path();
|
|
|
+ this.subPaths.push(this.currentPath);
|
|
|
+ this.currentPath.moveTo(x, y);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ lineTo(x, y) {
|
|
|
+ this.currentPath.lineTo(x, y);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ quadraticCurveTo(aCPx, aCPy, aX, aY) {
|
|
|
+ this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
|
|
|
+ this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ splineThru(pts) {
|
|
|
+ this.currentPath.splineThru(pts);
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ toShapes(isCCW, noHoles) {
|
|
|
+ function toShapesNoHoles(inSubpaths) {
|
|
|
+ const shapes = [];
|
|
|
+
|
|
|
+ for (let i = 0, l = inSubpaths.length; i < l; i++) {
|
|
|
+ const tmpPath = inSubpaths[i];
|
|
|
+ const tmpShape = new Shape();
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
+ shapes.push(tmpShape);
|
|
|
+ }
|
|
|
+
|
|
|
+ return shapes;
|
|
|
+ }
|
|
|
+
|
|
|
+ function isPointInsidePolygon(inPt, inPolygon) {
|
|
|
+ const polyLen = inPolygon.length; // inPt on polygon contour => immediate success or
|
|
|
+ // toggling of inside/outside at every single! intersection point of an edge
|
|
|
+ // with the horizontal line through inPt, left of inPt
|
|
|
+ // not counting lowerY endpoints of edges and whole edges on that line
|
|
|
+
|
|
|
+ let inside = false;
|
|
|
+
|
|
|
+ for (let p = polyLen - 1, q = 0; q < polyLen; p = q++) {
|
|
|
+ let edgeLowPt = inPolygon[p];
|
|
|
+ let edgeHighPt = inPolygon[q];
|
|
|
+ let edgeDx = edgeHighPt.x - edgeLowPt.x;
|
|
|
+ let edgeDy = edgeHighPt.y - edgeLowPt.y;
|
|
|
+
|
|
|
+ if (Math.abs(edgeDy) > Number.EPSILON) {
|
|
|
+ // not parallel
|
|
|
+ if (edgeDy < 0) {
|
|
|
+ edgeLowPt = inPolygon[q];
|
|
|
+ edgeDx = -edgeDx;
|
|
|
+ edgeHighPt = inPolygon[p];
|
|
|
+ edgeDy = -edgeDy;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y) continue;
|
|
|
+
|
|
|
+ if (inPt.y === edgeLowPt.y) {
|
|
|
+ if (inPt.x === edgeLowPt.x) return true; // inPt is on contour ?
|
|
|
+ // continue; // no intersection or edgeLowPt => doesn't count !!!
|
|
|
+ } else {
|
|
|
+ const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
|
|
|
+ if (perpEdge === 0) return true; // inPt is on contour ?
|
|
|
+
|
|
|
+ if (perpEdge < 0) continue;
|
|
|
+ inside = !inside; // true intersection left of inPt
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // parallel or collinear
|
|
|
+ if (inPt.y !== edgeLowPt.y) continue; // parallel
|
|
|
+ // edge lies on the same horizontal line as inPt
|
|
|
+
|
|
|
+ if (edgeHighPt.x <= inPt.x && inPt.x <= edgeLowPt.x || edgeLowPt.x <= inPt.x && inPt.x <= edgeHighPt.x) return true; // inPt: Point on contour !
|
|
|
+ // continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return inside;
|
|
|
+ }
|
|
|
+
|
|
|
+ const isClockWise = ShapeUtils.isClockWise;
|
|
|
+ const subPaths = this.subPaths;
|
|
|
+ if (subPaths.length === 0) return [];
|
|
|
+ if (noHoles === true) return toShapesNoHoles(subPaths);
|
|
|
+ let solid, tmpPath, tmpShape;
|
|
|
+ const shapes = [];
|
|
|
+
|
|
|
+ if (subPaths.length === 1) {
|
|
|
+ tmpPath = subPaths[0];
|
|
|
+ tmpShape = new Shape();
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
+ shapes.push(tmpShape);
|
|
|
+ return shapes;
|
|
|
+ }
|
|
|
+
|
|
|
+ let holesFirst = !isClockWise(subPaths[0].getPoints());
|
|
|
+ holesFirst = isCCW ? !holesFirst : holesFirst; // console.log("Holes first", holesFirst);
|
|
|
+
|
|
|
+ const betterShapeHoles = [];
|
|
|
+ const newShapes = [];
|
|
|
+ let newShapeHoles = [];
|
|
|
+ let mainIdx = 0;
|
|
|
+ let tmpPoints;
|
|
|
+ newShapes[mainIdx] = undefined;
|
|
|
+ newShapeHoles[mainIdx] = [];
|
|
|
+
|
|
|
+ for (let i = 0, l = subPaths.length; i < l; i++) {
|
|
|
+ tmpPath = subPaths[i];
|
|
|
+ tmpPoints = tmpPath.getPoints();
|
|
|
+ solid = isClockWise(tmpPoints);
|
|
|
+ solid = isCCW ? !solid : solid;
|
|
|
+
|
|
|
+ if (solid) {
|
|
|
+ if (!holesFirst && newShapes[mainIdx]) mainIdx++;
|
|
|
+ newShapes[mainIdx] = {
|
|
|
+ s: new Shape(),
|
|
|
+ p: tmpPoints
|
|
|
+ };
|
|
|
+ newShapes[mainIdx].s.curves = tmpPath.curves;
|
|
|
+ if (holesFirst) mainIdx++;
|
|
|
+ newShapeHoles[mainIdx] = []; //console.log('cw', i);
|
|
|
+ } else {
|
|
|
+ newShapeHoles[mainIdx].push({
|
|
|
+ h: tmpPath,
|
|
|
+ p: tmpPoints[0]
|
|
|
+ }); //console.log('ccw', i);
|
|
|
+ }
|
|
|
+ } // only Holes? -> probably all Shapes with wrong orientation
|
|
|
+
|
|
|
+
|
|
|
+ if (!newShapes[0]) return toShapesNoHoles(subPaths);
|
|
|
+
|
|
|
+ if (newShapes.length > 1) {
|
|
|
+ let ambiguous = false;
|
|
|
+ const toChange = [];
|
|
|
+
|
|
|
+ for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
|
+ betterShapeHoles[sIdx] = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
|
|
|
+ const sho = newShapeHoles[sIdx];
|
|
|
+
|
|
|
+ for (let hIdx = 0; hIdx < sho.length; hIdx++) {
|
|
|
+ const ho = sho[hIdx];
|
|
|
+ let hole_unassigned = true;
|
|
|
+
|
|
|
+ for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
|
|
|
+ if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
|
|
|
+ if (sIdx !== s2Idx) toChange.push({
|
|
|
+ froms: sIdx,
|
|
|
+ tos: s2Idx,
|
|
|
+ hole: hIdx
|
|
|
+ });
|
|
|
+
|
|
|
+ if (hole_unassigned) {
|
|
|
+ hole_unassigned = false;
|
|
|
+ betterShapeHoles[s2Idx].push(ho);
|
|
|
+ } else {
|
|
|
+ ambiguous = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hole_unassigned) {
|
|
|
+ betterShapeHoles[sIdx].push(ho);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } // console.log("ambiguous: ", ambiguous);
|
|
|
+
|
|
|
+
|
|
|
+ if (toChange.length > 0) {
|
|
|
+ // console.log("to change: ", toChange);
|
|
|
+ if (!ambiguous) newShapeHoles = betterShapeHoles;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let tmpHoles;
|
|
|
+
|
|
|
+ for (let i = 0, il = newShapes.length; i < il; i++) {
|
|
|
+ tmpShape = newShapes[i].s;
|
|
|
+ shapes.push(tmpShape);
|
|
|
+ tmpHoles = newShapeHoles[i];
|
|
|
+
|
|
|
+ for (let j = 0, jl = tmpHoles.length; j < jl; j++) {
|
|
|
+ tmpShape.holes.push(tmpHoles[j].h);
|
|
|
+ }
|
|
|
+ } //console.log("shape", shapes);
|
|
|
+
|
|
|
+
|
|
|
+ return shapes;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
const _floatView = new Float32Array(1);
|
|
|
|
|
|
const _int32View = new Int32Array(_floatView.buffer);
|
|
@@ -36088,6 +35909,21 @@
|
|
|
|
|
|
function LensFlare() {
|
|
|
console.error('THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js');
|
|
|
+ } //
|
|
|
+
|
|
|
+ function ParametricGeometry() {
|
|
|
+ console.error('THREE.ParametricGeometry has been moved to /examples/jsm/geometries/ParametricGeometry.js');
|
|
|
+ return new BufferGeometry();
|
|
|
+ }
|
|
|
+ function TextGeometry() {
|
|
|
+ console.error('THREE.TextGeometry has been moved to /examples/jsm/geometries/TextGeometry.js');
|
|
|
+ return new BufferGeometry();
|
|
|
+ }
|
|
|
+ function FontLoader() {
|
|
|
+ console.error('THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js');
|
|
|
+ }
|
|
|
+ function Font() {
|
|
|
+ console.error('THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js');
|
|
|
}
|
|
|
|
|
|
if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
|
|
@@ -36374,6 +36210,7 @@
|
|
|
exports.PCFShadowMap = PCFShadowMap;
|
|
|
exports.PCFSoftShadowMap = PCFSoftShadowMap;
|
|
|
exports.PMREMGenerator = PMREMGenerator;
|
|
|
+ exports.ParametricGeometry = ParametricGeometry;
|
|
|
exports.Particle = Particle;
|
|
|
exports.ParticleBasicMaterial = ParticleBasicMaterial;
|
|
|
exports.ParticleSystem = ParticleSystem;
|
|
@@ -36509,7 +36346,6 @@
|
|
|
exports.TangentSpaceNormalMap = TangentSpaceNormalMap;
|
|
|
exports.TetrahedronBufferGeometry = TetrahedronGeometry;
|
|
|
exports.TetrahedronGeometry = TetrahedronGeometry;
|
|
|
- exports.TextBufferGeometry = TextGeometry;
|
|
|
exports.TextGeometry = TextGeometry;
|
|
|
exports.Texture = Texture;
|
|
|
exports.TextureLoader = TextureLoader;
|