@mcolabs/threebox-plugin 4.0.0
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.
- package/LICENSE.txt +97 -0
- package/README.md +199 -0
- package/dist/threebox.cjs +2 -0
- package/dist/threebox.cjs.map +1 -0
- package/dist/threebox.iife.js +2 -0
- package/dist/threebox.iife.js.map +1 -0
- package/dist/threebox.js +3521 -0
- package/dist/threebox.js.map +1 -0
- package/package.json +57 -0
- package/src/Threebox.js +1201 -0
- package/src/animation/AnimationManager.js +482 -0
- package/src/camera/CameraSync.js +298 -0
- package/src/index.js +8 -0
- package/src/objects/CSS2DRenderer.js +236 -0
- package/src/objects/LabelRenderer.js +70 -0
- package/src/objects/Object3D.js +32 -0
- package/src/objects/effects/BuildingShadows.js +163 -0
- package/src/objects/extrusion.js +59 -0
- package/src/objects/fflate.min.js +6 -0
- package/src/objects/label.js +25 -0
- package/src/objects/line.js +45 -0
- package/src/objects/loadObj.js +139 -0
- package/src/objects/objects.js +1111 -0
- package/src/objects/sphere.js +22 -0
- package/src/objects/tooltip.js +26 -0
- package/src/objects/tube.js +28 -0
- package/src/utils/ValueGenerator.js +11 -0
- package/src/utils/constants.js +23 -0
- package/src/utils/material.js +52 -0
- package/src/utils/suncalc.js +311 -0
- package/src/utils/utils.js +420 -0
- package/src/utils/validate.js +114 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import Constants from './constants.js';
|
|
3
|
+
import Validate from './validate.js';
|
|
4
|
+
|
|
5
|
+
var utils = {
|
|
6
|
+
|
|
7
|
+
prettyPrintMatrix: function (uglymatrix) {
|
|
8
|
+
for (var s = 0; s < 4; s++) {
|
|
9
|
+
var quartet = [uglymatrix[s],
|
|
10
|
+
uglymatrix[s + 4],
|
|
11
|
+
uglymatrix[s + 8],
|
|
12
|
+
uglymatrix[s + 12]];
|
|
13
|
+
console.log(quartet.map(function (num) { return num.toFixed(4) }))
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
makePerspectiveMatrix: function (fovy, aspect, near, far) {
|
|
18
|
+
|
|
19
|
+
var out = new THREE.Matrix4();
|
|
20
|
+
var f = 1.0 / Math.tan(fovy / 2),
|
|
21
|
+
nf = 1 / (near - far);
|
|
22
|
+
|
|
23
|
+
var newMatrix = [
|
|
24
|
+
f / aspect, 0, 0, 0,
|
|
25
|
+
0, f, 0, 0,
|
|
26
|
+
0, 0, (far + near) * nf, -1,
|
|
27
|
+
0, 0, (2 * far * near) * nf, 0
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
out.elements = newMatrix
|
|
31
|
+
return out;
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
//[jscastro] new orthographic matrix calculations https://en.wikipedia.org/wiki/Orthographic_projection and validated with https://bit.ly/3rPvB9Y
|
|
35
|
+
makeOrthographicMatrix: function (left, right, top, bottom, near, far) {
|
|
36
|
+
var out = new THREE.Matrix4();
|
|
37
|
+
|
|
38
|
+
const w = 1.0 / (right - left);
|
|
39
|
+
const h = 1.0 / (top - bottom);
|
|
40
|
+
const p = 1.0 / (far - near);
|
|
41
|
+
|
|
42
|
+
const x = (right + left) * w;
|
|
43
|
+
const y = (top + bottom) * h;
|
|
44
|
+
const z = near * p;
|
|
45
|
+
|
|
46
|
+
var newMatrix = [
|
|
47
|
+
2 * w, 0, 0, 0,
|
|
48
|
+
0, 2 * h, 0, 0,
|
|
49
|
+
0, 0, - 1 * p, 0,
|
|
50
|
+
- x, -y, -z, 1
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
out.elements = newMatrix
|
|
54
|
+
return out;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
//gimme radians
|
|
58
|
+
radify: function (deg) {
|
|
59
|
+
|
|
60
|
+
function convert(degrees) {
|
|
61
|
+
degrees = degrees || 0;
|
|
62
|
+
return Math.PI * 2 * degrees / 360
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof deg === 'object') {
|
|
66
|
+
|
|
67
|
+
//if [x,y,z] array of rotations
|
|
68
|
+
if (deg.length > 0) {
|
|
69
|
+
return deg.map(function (degree) {
|
|
70
|
+
return convert(degree)
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// if {x: y: z:} rotation object
|
|
75
|
+
else {
|
|
76
|
+
return [convert(deg.x), convert(deg.y), convert(deg.z)]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//if just a number
|
|
81
|
+
else return convert(deg)
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
//gimme degrees
|
|
85
|
+
degreeify: function (rad) {
|
|
86
|
+
function convert(radians) {
|
|
87
|
+
radians = radians || 0;
|
|
88
|
+
return radians * 360 / (Math.PI * 2)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (typeof rad === 'object') {
|
|
92
|
+
return [convert(rad.x), convert(rad.y), convert(rad.z)]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
else return convert(rad)
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
projectToWorld: function (coords) {
|
|
99
|
+
|
|
100
|
+
// Spherical mercator forward projection, re-scaling to WORLD_SIZE
|
|
101
|
+
|
|
102
|
+
var projected = [
|
|
103
|
+
-Constants.MERCATOR_A * Constants.DEG2RAD * coords[0] * Constants.PROJECTION_WORLD_SIZE,
|
|
104
|
+
-Constants.MERCATOR_A * Math.log(Math.tan((Math.PI * 0.25) + (0.5 * Constants.DEG2RAD * coords[1]))) * Constants.PROJECTION_WORLD_SIZE
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
//z dimension, defaulting to 0 if not provided
|
|
108
|
+
|
|
109
|
+
if (!coords[2]) projected.push(0)
|
|
110
|
+
else {
|
|
111
|
+
var pixelsPerMeter = this.projectedUnitsPerMeter(coords[1]);
|
|
112
|
+
projected.push(coords[2] * pixelsPerMeter);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var result = new THREE.Vector3(projected[0], projected[1], projected[2]);
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
projectedUnitsPerMeter: function (latitude) {
|
|
121
|
+
return Math.abs(Constants.WORLD_SIZE / Math.cos(Constants.DEG2RAD * latitude) / Constants.EARTH_CIRCUMFERENCE);
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
_circumferenceAtLatitude: function (latitude) {
|
|
125
|
+
return Constants.EARTH_CIRCUMFERENCE * Math.cos(latitude * Math.PI / 180);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
mercatorZfromAltitude: function (altitude, lat) {
|
|
129
|
+
return altitude / this._circumferenceAtLatitude(lat);
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
_scaleVerticesToMeters: function (centerLatLng, vertices) {
|
|
133
|
+
var pixelsPerMeter = this.projectedUnitsPerMeter(centerLatLng[1]);
|
|
134
|
+
var centerProjected = this.projectToWorld(centerLatLng);
|
|
135
|
+
|
|
136
|
+
for (var i = 0; i < vertices.length; i++) {
|
|
137
|
+
vertices[i].multiplyScalar(pixelsPerMeter);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return vertices;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
projectToScreen: function (coords) {
|
|
144
|
+
console.log("WARNING: Projecting to screen coordinates is not yet implemented");
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
unprojectFromScreen: function (pixel) {
|
|
148
|
+
console.log("WARNING: unproject is not yet implemented");
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
//world units to lnglat
|
|
152
|
+
unprojectFromWorld: function (worldUnits) {
|
|
153
|
+
|
|
154
|
+
var unprojected = [
|
|
155
|
+
-worldUnits.x / (Constants.MERCATOR_A * Constants.DEG2RAD * Constants.PROJECTION_WORLD_SIZE),
|
|
156
|
+
2 * (Math.atan(Math.exp(worldUnits.y / (Constants.PROJECTION_WORLD_SIZE * (-Constants.MERCATOR_A)))) - Math.PI / 4) / Constants.DEG2RAD
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
var pixelsPerMeter = this.projectedUnitsPerMeter(unprojected[1]);
|
|
160
|
+
|
|
161
|
+
//z dimension
|
|
162
|
+
var height = worldUnits.z || 0;
|
|
163
|
+
unprojected.push(height / pixelsPerMeter);
|
|
164
|
+
|
|
165
|
+
return unprojected;
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
toScreenPosition: function (obj, camera) {
|
|
169
|
+
var vector = new THREE.Vector3();
|
|
170
|
+
|
|
171
|
+
var widthHalf = 0.5 * renderer.context.canvas.width;
|
|
172
|
+
var heightHalf = 0.5 * renderer.context.canvas.height;
|
|
173
|
+
|
|
174
|
+
obj.updateMatrixWorld();
|
|
175
|
+
vector.setFromMatrixPosition(obj.matrixWorld);
|
|
176
|
+
vector.project(camera);
|
|
177
|
+
|
|
178
|
+
vector.x = (vector.x * widthHalf) + widthHalf;
|
|
179
|
+
vector.y = - (vector.y * heightHalf) + heightHalf;
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
x: vector.x,
|
|
183
|
+
y: vector.y
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
//get the center point of a feature
|
|
189
|
+
getFeatureCenter: function getFeatureCenter(feature, model, level) {
|
|
190
|
+
let center = [];
|
|
191
|
+
let latitude = 0;
|
|
192
|
+
let longitude = 0;
|
|
193
|
+
let height = 0;
|
|
194
|
+
//deep copy to avoid modifying the original array
|
|
195
|
+
let coordinates = [...feature.geometry.coordinates[0]];
|
|
196
|
+
if (feature.geometry.type === "Point") {
|
|
197
|
+
center = [...coordinates[0]];//deep copy
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
//features in mapbox repeat the first coordinates at the end. We remove it.
|
|
201
|
+
if (feature.geometry.type === "MultiPolygon") coordinates = coordinates[0];
|
|
202
|
+
coordinates.splice(-1, 1);
|
|
203
|
+
coordinates.forEach(function (c) {
|
|
204
|
+
latitude += c[0];
|
|
205
|
+
longitude += c[1];
|
|
206
|
+
});
|
|
207
|
+
center = [latitude / coordinates.length, longitude / coordinates.length];
|
|
208
|
+
}
|
|
209
|
+
height = this.getObjectHeightOnFloor(feature, model, level);
|
|
210
|
+
|
|
211
|
+
(center.length < 3 ? center.push(height) : center[2] = height);
|
|
212
|
+
|
|
213
|
+
return center;
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
getObjectHeightOnFloor: function (feature, obj, level = feature.properties.level || 0) {
|
|
217
|
+
let floorHeightMin = (level * (feature.properties.levelHeight || 0));
|
|
218
|
+
//object height is modelSize.z + base_height or min_height configured for this object
|
|
219
|
+
let base = (feature.properties.base_height || feature.properties.min_height || 0);
|
|
220
|
+
//let height = ((obj && obj.model) ? obj.modelSize.z : (feature.properties.height - base));
|
|
221
|
+
let height = ((obj && obj.model) ? 0 : (feature.properties.height - base));
|
|
222
|
+
let objectHeight = height + base;
|
|
223
|
+
let modelHeightFloor = floorHeightMin + objectHeight;
|
|
224
|
+
return modelHeightFloor;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
_flipMaterialSides: function (obj) {
|
|
228
|
+
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
// to improve precision, normalize a series of vector3's to their collective center, and move the resultant mesh to that center
|
|
232
|
+
normalizeVertices(vertices) {
|
|
233
|
+
|
|
234
|
+
let geometry = new THREE.BufferGeometry();
|
|
235
|
+
let positions = [];
|
|
236
|
+
|
|
237
|
+
for (var j = 0; j < vertices.length; j++) {
|
|
238
|
+
let p = vertices[j];
|
|
239
|
+
positions.push(p.x, p.y, p.z);
|
|
240
|
+
positions.push(p.x, p.y, p.z);
|
|
241
|
+
}
|
|
242
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
|
|
243
|
+
geometry.computeBoundingSphere();
|
|
244
|
+
var center = geometry.boundingSphere.center;
|
|
245
|
+
|
|
246
|
+
var scaled = vertices.map(function (v3) {
|
|
247
|
+
var normalized = v3.sub(center);
|
|
248
|
+
return normalized;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return { vertices: scaled, position: center }
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
//flatten an array of Vector3's into a shallow array of values in x-y-z order, for bufferGeometry
|
|
255
|
+
flattenVectors(vectors) {
|
|
256
|
+
var flattenedArray = [];
|
|
257
|
+
for (let vertex of vectors) {
|
|
258
|
+
flattenedArray.push(vertex.x, vertex.y, vertex.z);
|
|
259
|
+
}
|
|
260
|
+
return flattenedArray
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
//convert a line/polygon to Vector3's
|
|
264
|
+
|
|
265
|
+
lnglatsToWorld: function (coords) {
|
|
266
|
+
|
|
267
|
+
var vector3 = coords.map(
|
|
268
|
+
function (pt) {
|
|
269
|
+
var p = utils.projectToWorld(pt);
|
|
270
|
+
var v3 = new THREE.Vector3(p.x, p.y, p.z);
|
|
271
|
+
return v3
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
return vector3
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
extend: function (original, addition) {
|
|
279
|
+
for (let key in addition) original[key] = addition[key];
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
clone: function (original) {
|
|
283
|
+
var clone = {};
|
|
284
|
+
for (let key in original) clone[key] = original[key];
|
|
285
|
+
return clone;
|
|
286
|
+
},
|
|
287
|
+
|
|
288
|
+
clamp: function(n, min, max) {
|
|
289
|
+
return Math.min(max, Math.max(min, n));
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
// retrieve object parameters from an options object
|
|
293
|
+
types: {
|
|
294
|
+
|
|
295
|
+
rotation: function (r, currentRotation) {
|
|
296
|
+
|
|
297
|
+
//[jscastro] rotation default 0
|
|
298
|
+
if (!r) { r = 0; };
|
|
299
|
+
|
|
300
|
+
// if number provided, rotate only in Z by that amount
|
|
301
|
+
if (typeof r === 'number') r = { z: r };
|
|
302
|
+
|
|
303
|
+
var degrees = this.applyDefault([r.x, r.y, r.z], currentRotation);
|
|
304
|
+
var radians = utils.radify(degrees);
|
|
305
|
+
return radians;
|
|
306
|
+
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
scale: function (s, currentScale) {
|
|
310
|
+
//[jscastro] scale default 1
|
|
311
|
+
if (!s) { s = 1; };
|
|
312
|
+
if (typeof s === 'number') return s = [s, s, s];
|
|
313
|
+
else return this.applyDefault([s.x, s.y, s.z], currentScale);
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
applyDefault: function (array, current) {
|
|
317
|
+
|
|
318
|
+
var output = array.map(function (item, index) {
|
|
319
|
+
item = item || current[index];
|
|
320
|
+
return item
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
return output
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
toDecimal: function (n, d) {
|
|
329
|
+
return Number(n.toFixed(d));
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
equal: function (obj1, obj2) {
|
|
333
|
+
const keys1 = Object.keys(obj1);
|
|
334
|
+
const keys2 = Object.keys(obj2);
|
|
335
|
+
|
|
336
|
+
if (keys1.length !== keys2.length) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
if (keys1.length == 0 && keys2.length == 0 && keys1 !== keys2) {
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
for (const key of keys1) {
|
|
344
|
+
const val1 = obj1[key];
|
|
345
|
+
const val2 = obj2[key];
|
|
346
|
+
const areObjects = this.isObject(val1) && this.isObject(val2);
|
|
347
|
+
if (
|
|
348
|
+
areObjects && !equal(val1, val2) ||
|
|
349
|
+
!areObjects && val1 !== val2
|
|
350
|
+
) {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return true;
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
isObject: function (object) {
|
|
359
|
+
return object != null && typeof object === 'object';
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
curveToLine: (curve, params) => {
|
|
363
|
+
let { width, color } = params;
|
|
364
|
+
let geometry = new THREE.BufferGeometry().setFromPoints(
|
|
365
|
+
curve.getPoints(100)
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
let material = new THREE.LineBasicMaterial({
|
|
369
|
+
color: color,
|
|
370
|
+
linewidth: width,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
let line = new THREE.Line(geometry, material);
|
|
374
|
+
|
|
375
|
+
return line;
|
|
376
|
+
},
|
|
377
|
+
|
|
378
|
+
curvesToLines: (curves) => {
|
|
379
|
+
var colors = [0xff0000, 0x1eff00, 0x2600ff];
|
|
380
|
+
var lines = curves.map((curve, i) => {
|
|
381
|
+
let params = {
|
|
382
|
+
width: 3,
|
|
383
|
+
color: colors[i] || 'purple',
|
|
384
|
+
};
|
|
385
|
+
let curveline = curveToLine(curve, params);
|
|
386
|
+
|
|
387
|
+
return curveline;
|
|
388
|
+
});
|
|
389
|
+
return lines;
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
_validate: function (userInputs, defaults) {
|
|
393
|
+
|
|
394
|
+
userInputs = userInputs || {};
|
|
395
|
+
var validatedOutput = {};
|
|
396
|
+
utils.extend(validatedOutput, userInputs);
|
|
397
|
+
|
|
398
|
+
for (let key of Object.keys(defaults)) {
|
|
399
|
+
|
|
400
|
+
if (userInputs[key] === undefined) {
|
|
401
|
+
//make sure required params are present
|
|
402
|
+
if (defaults[key] === null) {
|
|
403
|
+
console.error(key + ' is required')
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
else validatedOutput[key] = defaults[key]
|
|
408
|
+
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
else validatedOutput[key] = userInputs[key]
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return validatedOutput
|
|
415
|
+
},
|
|
416
|
+
Validator: new Validate(),
|
|
417
|
+
exposedMethods: ['projectToWorld', 'projectedUnitsPerMeter', 'extend', 'unprojectFromWorld']
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export default utils;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Type validator
|
|
2
|
+
|
|
3
|
+
function Validate(){
|
|
4
|
+
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
Validate.prototype = {
|
|
8
|
+
|
|
9
|
+
Coords: function(input) {
|
|
10
|
+
|
|
11
|
+
if (input.constructor !== Array) {
|
|
12
|
+
console.error("Coords must be an array")
|
|
13
|
+
return
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (input.length < 2) {
|
|
17
|
+
console.error("Coords length must be at least 2")
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (const member of input) {
|
|
22
|
+
if (member.constructor !== Number) {
|
|
23
|
+
console.error("Coords values must be numbers")
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (Math.abs(input[1]) > 90) {
|
|
29
|
+
console.error("Latitude must be between -90 and 90")
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return input
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
Line: function(input) {
|
|
37
|
+
|
|
38
|
+
var scope = this;
|
|
39
|
+
|
|
40
|
+
if (input.constructor !== Array) {
|
|
41
|
+
console.error("Line must be an array")
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (const coord of input){
|
|
46
|
+
if (!scope.Coords(coord)) {
|
|
47
|
+
console.error("Each coordinate in a line must be a valid Coords type")
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return input
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
Rotation: function(input) {
|
|
57
|
+
|
|
58
|
+
if (input.constructor === Number) input = {z: input}
|
|
59
|
+
|
|
60
|
+
else if (input.constructor === Object) {
|
|
61
|
+
|
|
62
|
+
for (const key of Object.keys(input)){
|
|
63
|
+
|
|
64
|
+
if (!['x', 'y', 'z'].includes(key)) {
|
|
65
|
+
console.error('Rotation parameters must be x, y, or z')
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if (input[key].constructor !== Number) {
|
|
69
|
+
console.error('Individual rotation values must be numbers')
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
else {
|
|
76
|
+
console.error('Rotation must be an object or a number')
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return input
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
Scale: function(input) {
|
|
84
|
+
|
|
85
|
+
if (input.constructor === Number) {
|
|
86
|
+
input = {x:input, y:input, z: input}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
else if (input.constructor === Object) {
|
|
90
|
+
|
|
91
|
+
for (const key of Object.keys(input)){
|
|
92
|
+
|
|
93
|
+
if (!['x', 'y', 'z'].includes(key)) {
|
|
94
|
+
console.error('Scale parameters must be x, y, or z')
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
if (input[key].constructor !== Number) {
|
|
98
|
+
console.error('Individual scale values must be numbers')
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
else {
|
|
105
|
+
console.error('Scale must be an object or a number')
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return input
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export default Validate;
|