poly-extrude 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.eslintignore +12 -0
  2. package/.eslintrc.js +34 -0
  3. package/.vscode/settings.json +3 -0
  4. package/LICENSE +21 -0
  5. package/babel.config.js +12 -0
  6. package/dist/poly-extrude.js +1317 -0
  7. package/dist/poly-extrude.js.map +1 -0
  8. package/dist/poly-extrude.min.js +4 -0
  9. package/dist/poly-extrude.mjs +1305 -0
  10. package/index.js +3 -0
  11. package/package.json +42 -0
  12. package/pnpm-lock.yaml +3054 -0
  13. package/rollup.config.js +108 -0
  14. package/src/polygon.js +148 -0
  15. package/src/polyline.js +190 -0
  16. package/src/util.js +205 -0
  17. package/test/buildings.html +77 -0
  18. package/test/data/a.png +0 -0
  19. package/test/data/building-texture-dark.jpg +0 -0
  20. package/test/data/building.geojson +1118 -0
  21. package/test/data/buildings-ny.geojson +2845 -0
  22. package/test/data/buildings.geojson +1 -0
  23. package/test/data/free-line.geojson +1 -0
  24. package/test/data/line.geojson +1 -0
  25. package/test/data/polygon.geojson +1 -0
  26. package/test/data/simple-hole.geojson +1 -0
  27. package/test/data/simple-line.geojson +45 -0
  28. package/test/data/simple.geojson +1 -0
  29. package/test/data/street.geojson +1 -0
  30. package/test/data//345/244/252/346/271/226.geojson +8 -0
  31. package/test/data//350/210/237/345/261/261/345/270/202.geojson +1 -0
  32. package/test/data//350/213/217/345/267/236.geojson +1 -0
  33. package/test/data//351/204/261/351/230/263/346/271/226.geojson +1 -0
  34. package/test/line-draw.html +100 -0
  35. package/test/line-uv.html +69 -0
  36. package/test/line.html +56 -0
  37. package/test/multi-polygon.html +53 -0
  38. package/test/ny-building.html +67 -0
  39. package/test/simple.html +61 -0
  40. package/test/street.html +52 -0
  41. package/test/util.js +131 -0
  42. package/test/uv.html +77 -0
@@ -0,0 +1,108 @@
1
+ // Rollup plugins
2
+
3
+ import { nodeResolve } from '@rollup/plugin-node-resolve';
4
+ import { babel } from '@rollup/plugin-babel';
5
+ import commonjs from '@rollup/plugin-commonjs';
6
+ import json from '@rollup/plugin-json';
7
+ import { terser } from 'rollup-plugin-terser';
8
+ // import swc from 'rollup-plugin-swc';
9
+ import pkg from './package.json';
10
+ const path = require('path');
11
+
12
+ const product = process.env.NODE_ENV.trim() === 'prd';
13
+ const FILEMANE = pkg.name;
14
+ const sourceMap = !product;
15
+
16
+ const banner = `/*!\n * ${pkg.name} v${pkg.version}\n */`;
17
+ let outro = pkg.name + ' v' + pkg.version;
18
+ outro = `typeof console !== 'undefined' && console.log('${outro}');`;
19
+ const plugins = [
20
+ json(),
21
+ nodeResolve(),
22
+ commonjs(),
23
+ // swc({
24
+ // // rollup: {
25
+ // // exclude: 'path/to/exclude/',
26
+ // // },
27
+ // jsc: {
28
+ // parser: {
29
+ // syntax: 'ecmascript'
30
+ // },
31
+ // target: 'es5'
32
+ // },
33
+ // 'sourceMaps': true
34
+ // })
35
+ babel({
36
+ babelHelpers: 'bundled'
37
+ // exclude: ['node_modules/**']
38
+ })
39
+ ];
40
+ const external = [];
41
+ const globals = {
42
+
43
+ };
44
+ const name = 'polyextrude';
45
+ export default [
46
+ {
47
+ input: path.join(__dirname, './index.js'),
48
+ plugins: plugins,
49
+ // sourceMap: true,
50
+ external,
51
+ output:
52
+ {
53
+ 'format': 'umd',
54
+ 'name': name,
55
+ 'file': `dist/${FILEMANE}.js`,
56
+ 'sourcemap': sourceMap,
57
+ 'extend': true,
58
+ 'banner': banner,
59
+ 'outro': outro,
60
+ 'globals': globals
61
+ }
62
+ },
63
+ {
64
+ input: path.join(__dirname, './index.js'),
65
+ plugins: plugins.concat([terser()]),
66
+ // sourceMap: true,
67
+ external,
68
+ output:
69
+ {
70
+ 'format': 'umd',
71
+ 'name': name,
72
+ 'file': `dist/${FILEMANE}.min.js`,
73
+ 'sourcemap': false,
74
+ 'extend': true,
75
+ 'banner': banner,
76
+ 'outro': outro,
77
+ 'globals': globals
78
+ }
79
+ },
80
+ {
81
+ input: path.join(__dirname, './index.js'),
82
+ plugins: plugins,
83
+ // sourceMap: true,
84
+ external,
85
+ output:
86
+ {
87
+ 'format': 'es',
88
+ 'name': name,
89
+ 'file': `dist/${FILEMANE}.mjs`,
90
+ 'sourcemap': false,
91
+ 'extend': true,
92
+ 'banner': banner,
93
+ 'outro': outro,
94
+ 'globals': globals
95
+ }
96
+ }
97
+ // {
98
+ // 'sourcemap': false,
99
+ // 'format': 'es',
100
+ // // banner,
101
+ // 'file': `dist/${FILEMANE}.es.js`,
102
+ // 'extend': true,
103
+ // 'banner': banner,
104
+ // 'globals': {
105
+ // 'YY': 'YY'
106
+ // }
107
+ // }
108
+ ];
package/src/polygon.js ADDED
@@ -0,0 +1,148 @@
1
+
2
+ import earcut from 'earcut';
3
+ import { generateNormal, generateSideWallUV, isClockwise, merge } from './util';
4
+
5
+ export function extrudePolygons(polygons, options) {
6
+ options = Object.assign({}, { depth: 2 }, options);
7
+ const results = polygons.map(polygon => {
8
+ if (!isClockwise(polygon[0])) {
9
+ polygon[0] = polygon[0].reverse();
10
+ }
11
+ polygon.slice(1, Infinity).forEach((coordinates, index) => {
12
+ if (isClockwise(coordinates)) {
13
+ polygon[index + 1] = coordinates.reverse();
14
+ }
15
+ });
16
+ polygon.forEach(ring => {
17
+ const len = ring.length;
18
+ const [x1, y1] = ring[0], [x2, y2] = ring[len - 1];
19
+ if (x1 === x2 && y1 === y2) {
20
+ ring.splice(len - 1, 1);
21
+ }
22
+ });
23
+ const result = flatVertices(polygon, options);
24
+ result.polygon = polygon;
25
+ const time = 'earcut';
26
+ console.time(time);
27
+ const triangles = earcut(result.flatVertices, result.holes, 2);
28
+ console.timeEnd(time);
29
+ generateTopAndBottom(result, triangles);
30
+ generateSides(result, options);
31
+ result.position = new Float32Array(result.points);
32
+ result.indices = new Uint32Array(result.index);
33
+ result.uv = new Float32Array(result.uvs);
34
+ result.normal = generateNormal(result.indices, result.position);
35
+ return result;
36
+ });
37
+ const result = merge(results);
38
+ result.polygons = polygons;
39
+ return result;
40
+
41
+ }
42
+
43
+ function generateTopAndBottom(result, triangles) {
44
+ const index = [];
45
+ const { count } = result;
46
+ for (let i = 0, len = triangles.length; i < len; i += 3) {
47
+ // top
48
+ const a = triangles[i], b = triangles[i + 1], c = triangles[i + 2];
49
+ index[i] = a;
50
+ index[i + 1] = b;
51
+ index[i + 2] = c;
52
+ // bottom
53
+ const idx = len + i;
54
+ const a1 = count + a, b1 = count + b, c1 = count + c;
55
+ index[idx] = a1;
56
+ index[idx + 1] = b1;
57
+ index[idx + 2] = c1;
58
+ }
59
+ result.index = index;
60
+ }
61
+
62
+ function generateSides(result, options) {
63
+ const { points, index, polygon, uvs } = result;
64
+ const z = options.depth;
65
+ for (let i = 0, len = polygon.length; i < len; i++) {
66
+ const ring = polygon[i];
67
+ for (let j = 0, len1 = ring.length; j < len1; j++) {
68
+ const v1 = ring[j];
69
+ let v2 = ring[j + 1];
70
+ if (j === len1 - 1) {
71
+ v2 = ring[0];
72
+ }
73
+ // const p1 = [v1[0], v1[1], options.depth],
74
+ // p2 = [v2[0], v2[1], options.depth],
75
+ // p3 = [v1[0], v1[1], 0],
76
+ // p4 = [v2[0], v2[1], 0];
77
+ const idx = points.length / 3;
78
+ points.push(v1[0], v1[1], 0, v2[0], v2[1], 0, v1[0], v1[1], z, v2[0], v2[1], z);
79
+ const a = idx, b = idx + 1, c = idx + 2, d = idx + 3;
80
+ // points.push(p3, p4, p1, p2);
81
+ index.push(a, c, b);
82
+ index.push(c, d, b);
83
+
84
+ generateSideWallUV(uvs, points, a, b, c, d);
85
+ }
86
+ }
87
+ }
88
+
89
+ function calPolygonPointsCount(polygon) {
90
+ let count = 0;
91
+ let i = 0;
92
+ const len = polygon.length;
93
+ while (i < len) {
94
+ count += (polygon[i].length);
95
+ i++;
96
+ }
97
+ return count;
98
+ }
99
+
100
+ function flatVertices(polygon, options) {
101
+ const count = calPolygonPointsCount(polygon);
102
+ const len = polygon.length;
103
+ const holes = [], flatVertices = new Float32Array(count * 2), points = [], uvs = [];
104
+ const pOffset = count * 3, uOffset = count * 2;
105
+ const z = options.depth;
106
+
107
+ let idx0 = 0, idx1 = 0, idx2 = 0;
108
+ for (let i = 0; i < len; i++) {
109
+ const ring = polygon[i];
110
+ if (i > 0) {
111
+ holes.push(idx0 / 2);
112
+ }
113
+ for (let j = 0, len1 = ring.length; j < len1; j++) {
114
+ const c = ring[j];
115
+ const x = c[0], y = c[1];
116
+
117
+ flatVertices[idx0++] = x;
118
+ flatVertices[idx0++] = y;
119
+
120
+ // top vertices
121
+ points[idx1] = x;
122
+ points[idx1 + 1] = y;
123
+ points[idx1 + 2] = z;
124
+
125
+ // bottom vertices
126
+ points[pOffset + idx1] = x;
127
+ points[pOffset + idx1 + 1] = y;
128
+ points[pOffset + idx1 + 2] = 0;
129
+
130
+ uvs[idx2] = x;
131
+ uvs[idx2 + 1] = y;
132
+
133
+ uvs[uOffset + idx2] = x;
134
+ uvs[uOffset + idx2 + 1] = y;
135
+
136
+ idx1 += 3;
137
+ idx2 += 2;
138
+ }
139
+ }
140
+ return {
141
+ flatVertices,
142
+ holes,
143
+ points,
144
+ count,
145
+ uvs
146
+ };
147
+
148
+ }
@@ -0,0 +1,190 @@
1
+ import { degToRad, generateNormal, generateSideWallUV, merge, radToDeg } from './util';
2
+
3
+ export function extrudePolylines(lines, options) {
4
+ options = Object.assign({}, { depth: 2, lineWidth: 1 }, options);
5
+ const results = lines.map(line => {
6
+ const result = expandLine(line, options);
7
+ result.line = line;
8
+ generateTopAndBottom(result, options);
9
+ generateSides(result, options);
10
+ result.position = new Float32Array(result.points);
11
+ result.indices = new Uint32Array(result.index);
12
+ result.uv = new Float32Array(result.uvs);
13
+ result.normal = generateNormal(result.indices, result.position);
14
+ return result;
15
+ });
16
+ const result = merge(results);
17
+ result.lines = lines;
18
+ return result;
19
+ }
20
+
21
+ function generateTopAndBottom(result, options) {
22
+ const z = options.depth;
23
+ const points = [], index = [], uvs = [];
24
+ const { leftPoints, rightPoints } = result;
25
+ for (let i = 0, len = leftPoints.length; i < len; i++) {
26
+ // top left
27
+ const idx0 = i * 3;
28
+ const [x1, y1] = leftPoints[i];
29
+ points[idx0] = x1;
30
+ points[idx0 + 1] = y1;
31
+ points[idx0 + 2] = z;
32
+
33
+ // top right
34
+ const [x2, y2] = rightPoints[i];
35
+ const idx1 = len * 3 + idx0;
36
+ points[idx1] = x2;
37
+ points[idx1 + 1] = y2;
38
+ points[idx1 + 2] = z;
39
+
40
+ // bottom left
41
+ const idx2 = (len * 2) * 3 + idx0;
42
+ points[idx2] = x1;
43
+ points[idx2 + 1] = y1;
44
+ points[idx2 + 2] = 0;
45
+
46
+ // bottom right
47
+ const idx3 = (len * 2) * 3 + len * 3 + idx0;
48
+ points[idx3] = x2;
49
+ points[idx3 + 1] = y2;
50
+ points[idx3 + 2] = 0;
51
+ }
52
+ for (let i = 0, len = points.length; i < len; i += 3) {
53
+ const x = points[i], y = points[i + 1];
54
+ uvs.push(x, y);
55
+ }
56
+ for (let i = 0, len = leftPoints.length; i < len - 1; i++) {
57
+ // top
58
+ // left1 left2 right1,right2
59
+ const a1 = i, b1 = i + 1, c1 = a1 + len, d1 = b1 + len;
60
+ index.push(a1, c1, b1);
61
+ index.push(c1, d1, b1);
62
+
63
+ // bottom
64
+ // left1 left2 right1,right2
65
+ const len2 = len * 2;
66
+ const a2 = i + len2, b2 = a2 + 1, c2 = a2 + len, d2 = b2 + len;
67
+ index.push(a2, c2, b2);
68
+ index.push(c2, d2, b2);
69
+ }
70
+ result.index = index;
71
+ result.points = points;
72
+ result.uvs = uvs;
73
+ }
74
+
75
+ function generateSides(result, options) {
76
+ const { points, index, leftPoints, rightPoints, uvs } = result;
77
+ const z = options.depth;
78
+ const rings = [leftPoints, rightPoints];
79
+ function addOneSideIndex(v1, v2) {
80
+ const idx = points.length / 3;
81
+ points.push(v1[0], v1[1], 0, v2[0], v2[1], 0, v1[0], v1[1], z, v2[0], v2[1], z);
82
+ const a = idx, b = idx + 1, c = idx + 2, d = idx + 3;
83
+ // points.push(p3, p4, p1, p2);
84
+ index.push(a, c, b);
85
+ index.push(c, d, b);
86
+ generateSideWallUV(uvs, points, a, b, c, d);
87
+ }
88
+
89
+ for (let i = 0, len = rings.length; i < len; i++) {
90
+ let ring = rings[i];
91
+ if (i > 0) {
92
+ ring = ring.map(p => {
93
+ return p;
94
+ });
95
+ ring = ring.reverse();
96
+ }
97
+ for (let j = 0, len1 = ring.length - 1; j < len1; j++) {
98
+ const v1 = ring[j];
99
+ const v2 = ring[j + 1];
100
+ addOneSideIndex(v1, v2);
101
+ }
102
+ }
103
+ const len = leftPoints.length;
104
+ const vs = [rightPoints[0], leftPoints[0], leftPoints[len - 1], rightPoints[len - 1]];
105
+ for (let i = 0; i < vs.length; i += 2) {
106
+ const v1 = vs[i], v2 = vs[i + 1];
107
+ addOneSideIndex(v1, v2);
108
+ }
109
+ }
110
+
111
+ const TEMPV1 = { x: 0, y: 0 }, TEMPV2 = { x: 0, y: 0 };
112
+
113
+ function expandLine(line, options) {
114
+ let preAngle = 0;
115
+ const radius = options.lineWidth / 2;
116
+ const points = [], leftPoints = [], rightPoints = [];
117
+ const len = line.length;
118
+ for (let i = 0; i < len - 1; i++) {
119
+ const p1 = line[i],
120
+ p2 = line[i + 1];
121
+ const dy = p2[1] - p1[1],
122
+ dx = p2[0] - p1[0];
123
+ let rAngle = 0;
124
+ const rad = Math.atan(dy / dx);
125
+ const angle = radToDeg(rad);
126
+ preAngle = angle;
127
+ if (i === 0) {
128
+ rAngle = angle;
129
+ rAngle -= 90;
130
+ } else {
131
+ const p0 = line[i - 1];
132
+ TEMPV1.x = p0[0] - p1[0];
133
+ TEMPV1.y = p0[1] - p1[1];
134
+ TEMPV2.x = p2[0] - p1[0];
135
+ TEMPV2.y = p2[1] - p1[1];
136
+ const vAngle = getAngle(TEMPV1, TEMPV2);
137
+ rAngle = angle - vAngle / 2;
138
+ }
139
+ const rRad = degToRad(rAngle);
140
+ const [op1, op2] = calOffsetPoint(rRad, radius, p1);
141
+ points.push(op1, op2);
142
+ if (leftOnLine(op1, p1, p2)) {
143
+ leftPoints.push(op1);
144
+ rightPoints.push(op2);
145
+ } else {
146
+ leftPoints.push(op2);
147
+ rightPoints.push(op1);
148
+ }
149
+ }
150
+ let rAngle = preAngle;
151
+ rAngle -= 90;
152
+ const rRad = degToRad(rAngle);
153
+ const p1 = line[len - 2];
154
+ const p2 = line[len - 1];
155
+ const [op1, op2] = calOffsetPoint(rRad, radius, p2);
156
+ points.push(op1, op2);
157
+ if (leftOnLine(op1, p1, p2)) {
158
+ leftPoints.push(op1);
159
+ rightPoints.push(op2);
160
+ } else {
161
+ leftPoints.push(op2);
162
+ rightPoints.push(op1);
163
+ }
164
+
165
+ return { offsetPoints: points, leftPoints, rightPoints };
166
+ }
167
+
168
+ function calOffsetPoint(rad, radius, p) {
169
+ const [x, y] = p;
170
+ const x1 = Math.cos(rad) * radius, y1 = Math.sin(rad) * radius;
171
+ const p1 = [x + x1, y + y1];
172
+ const rad1 = rad += Math.PI;
173
+ const x2 = Math.cos(rad1) * radius, y2 = Math.sin(rad1) * radius;
174
+ const p2 = [x + x2, y + y2];
175
+ return [p1, p2];
176
+ }
177
+
178
+ const getAngle = ({ x: x1, y: y1 }, { x: x2, y: y2 }) => {
179
+ const dot = x1 * x2 + y1 * y2;
180
+ const det = x1 * y2 - y1 * x2;
181
+ const angle = Math.atan2(det, dot) / Math.PI * 180;
182
+ return (angle + 360) % 360;
183
+ };
184
+
185
+ function leftOnLine(p, p1, p2) {
186
+ const [x1, y1] = p1;
187
+ const [x2, y2] = p2;
188
+ const [x, y] = p;
189
+ return (y1 - y2) * x + (x2 - x1) * y + x1 * y2 - x2 * y1 > 0;
190
+ }
package/src/util.js ADDED
@@ -0,0 +1,205 @@
1
+ /**
2
+ * https://github.com/Turfjs/turf/blob/master/packages/turf-boolean-clockwise/index.ts
3
+ * @param {*} ring
4
+ * @returns
5
+ */
6
+ export function isClockwise(ring) {
7
+ let sum = 0;
8
+ let i = 1;
9
+ let prev;
10
+ let cur;
11
+ const len = ring.length;
12
+
13
+ while (i < len) {
14
+ prev = cur || ring[0];
15
+ cur = ring[i];
16
+ sum += (cur[0] - prev[0]) * (cur[1] + prev[1]);
17
+ i++;
18
+ }
19
+ return sum > 0;
20
+ }
21
+
22
+ function v3Sub(out, v1, v2) {
23
+ out[0] = v1[0] - v2[0];
24
+ out[1] = v1[1] - v2[1];
25
+ out[2] = v1[2] - v2[2];
26
+ return out;
27
+ }
28
+
29
+ function v3Normalize(out, v) {
30
+ const x = v[0];
31
+ const y = v[1];
32
+ const z = v[2];
33
+ const d = Math.sqrt(x * x + y * y + z * z) || 1;
34
+ out[0] = x / d;
35
+ out[1] = y / d;
36
+ out[2] = z / d;
37
+ return out;
38
+ }
39
+
40
+ function v3Cross(out, v1, v2) {
41
+ const ax = v1[0], ay = v1[1], az = v1[2],
42
+ bx = v2[0], by = v2[1], bz = v2[2];
43
+
44
+ out[0] = ay * bz - az * by;
45
+ out[1] = az * bx - ax * bz;
46
+ out[2] = ax * by - ay * bx;
47
+ return out;
48
+ }
49
+
50
+ export function generateNormal(indices, position) {
51
+
52
+ function v3Set(p, a, b, c) {
53
+ p[0] = a; p[1] = b; p[2] = c;
54
+ }
55
+
56
+ const p1 = [];
57
+ const p2 = [];
58
+ const p3 = [];
59
+
60
+ const v21 = [];
61
+ const v32 = [];
62
+
63
+ const n = [];
64
+
65
+ const len = indices.length;
66
+ const normals = new Float32Array(position.length);
67
+
68
+ for (let f = 0; f < len; f += 3) {
69
+ // const i1 = indices[f++] * 3;
70
+ // const i2 = indices[f++] * 3;
71
+ // const i3 = indices[f++] * 3;
72
+ // const i1 = indices[f];
73
+ // const i2 = indices[f + 1];
74
+ // const i3 = indices[f + 2];
75
+ const a = indices[f], b = indices[f + 1], c = indices[f + 2];
76
+ const i1 = a * 3, i2 = b * 3, i3 = c * 3;
77
+
78
+ v3Set(p1, position[i1], position[i1 + 1], position[i1 + 2]);
79
+ v3Set(p2, position[i2], position[i2 + 1], position[i2 + 2]);
80
+ v3Set(p3, position[i3], position[i3 + 1], position[i3 + 2]);
81
+
82
+ // pA.fromBufferAttribute(positionAttribute, vA);
83
+ // pB.fromBufferAttribute(positionAttribute, vB);
84
+ // pC.fromBufferAttribute(positionAttribute, vC);
85
+
86
+ // cb.subVectors(pC, pB);
87
+ // ab.subVectors(pA, pB);
88
+ // cb.cross(ab);
89
+ v3Sub(v32, p3, p2);
90
+ v3Sub(v21, p1, p2);
91
+ v3Cross(n, v32, v21);
92
+ // Already be weighted by the triangle area
93
+ for (let i = 0; i < 3; i++) {
94
+ normals[i1 + i] += n[i];
95
+ normals[i2 + i] += n[i];
96
+ normals[i3 + i] += n[i];
97
+ }
98
+ }
99
+
100
+ for (let i = 0; i < normals.length; i += 3) {
101
+ v3Set(n, normals[i], normals[i + 1], normals[i + 2]);
102
+ v3Normalize(n, n);
103
+ normals[i] = n[0] || 1;
104
+ normals[i + 1] = n[1] || 1;
105
+ normals[i + 2] = n[2] || 1;
106
+
107
+ }
108
+
109
+ return normals;
110
+ }
111
+
112
+ export function merge(results) {
113
+ if (results.length === 1) {
114
+ const result = {
115
+ position: results[0].position,
116
+ normal: results[0].normal,
117
+ uv: results[0].uv,
118
+ indices: results[0].indices,
119
+ results
120
+ };
121
+ return result;
122
+ }
123
+ let plen = 0, ilen = 0;
124
+ for (let i = 0, len = results.length; i < len; i++) {
125
+ const { position, indices } = results[i];
126
+ plen += position.length;
127
+ ilen += indices.length;
128
+ }
129
+ const result = {
130
+ position: new Float32Array(plen),
131
+ normal: new Float32Array(plen),
132
+ uv: new Float32Array(plen / 3 * 2),
133
+ indices: new Uint32Array(ilen),
134
+ results
135
+ };
136
+ let pOffset = 0, pCount = 0, iIdx = 0, uvOffset = 0;
137
+ for (let i = 0, len = results.length; i < len; i++) {
138
+ const { position, indices, normal, uv } = results[i];
139
+ result.position.set(position, pOffset);
140
+ result.normal.set(normal, pOffset);
141
+ result.uv.set(uv, uvOffset);
142
+ for (let j = 0, len1 = indices.length; j < len1; j++) {
143
+ const pIndex = indices[j] + pCount;
144
+ result.indices[iIdx] = pIndex;
145
+ iIdx++;
146
+ }
147
+ uvOffset += uv.length;
148
+ pOffset += position.length;
149
+ pCount += position.length / 3;
150
+ }
151
+ return result;
152
+ }
153
+
154
+ export function radToDeg(rad) {
155
+ return rad * 180 / Math.PI;
156
+ }
157
+
158
+ export function degToRad(angle) {
159
+ return angle / 180 * Math.PI;
160
+ }
161
+
162
+ // https://github.com/mrdoob/three.js/blob/16f13e3b07e31d0e9a00df7c3366bbe0e464588c/src/geometries/ExtrudeGeometry.js?_pjax=%23js-repo-pjax-container#L736
163
+ export function generateSideWallUV(uvs, vertices, indexA, indexB, indexC, indexD) {
164
+
165
+ const a_x = vertices[indexA * 3];
166
+ const a_y = vertices[indexA * 3 + 1];
167
+ const a_z = vertices[indexA * 3 + 2];
168
+ const b_x = vertices[indexB * 3];
169
+ const b_y = vertices[indexB * 3 + 1];
170
+ const b_z = vertices[indexB * 3 + 2];
171
+ const c_x = vertices[indexC * 3];
172
+ const c_y = vertices[indexC * 3 + 1];
173
+ const c_z = vertices[indexC * 3 + 2];
174
+ const d_x = vertices[indexD * 3];
175
+ const d_y = vertices[indexD * 3 + 1];
176
+ const d_z = vertices[indexD * 3 + 2];
177
+
178
+ if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) {
179
+
180
+ uvs.push(a_x, 1 - a_z);
181
+ uvs.push(b_x, 1 - b_z);
182
+ uvs.push(c_x, 1 - c_z);
183
+ uvs.push(d_x, 1 - d_z);
184
+ // return [
185
+ // new Vector2(a_x, 1 - a_z),
186
+ // new Vector2(b_x, 1 - b_z),
187
+ // new Vector2(c_x, 1 - c_z),
188
+ // new Vector2(d_x, 1 - d_z)
189
+ // ];
190
+
191
+ } else {
192
+ uvs.push(a_y, 1 - a_z);
193
+ uvs.push(b_y, 1 - b_z);
194
+ uvs.push(c_y, 1 - c_z);
195
+ uvs.push(d_y, 1 - d_z);
196
+ // return [
197
+ // new Vector2(a_y, 1 - a_z),
198
+ // new Vector2(b_y, 1 - b_z),
199
+ // new Vector2(c_y, 1 - c_z),
200
+ // new Vector2(d_y, 1 - d_z)
201
+ // ];
202
+
203
+ }
204
+
205
+ }