-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmyObject.js
More file actions
657 lines (495 loc) · 27.8 KB
/
myObject.js
File metadata and controls
657 lines (495 loc) · 27.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
/**
* @module myObject
* @description Base class for my threejs objects.
* @author [Andrej Hristoliubov]{@link https://github.com/anhr}
*
* @copyright 2011 Data Arts Team, Google Creative Lab
*
* @license under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*/
import three from './three.js'
import Player from './player/player.js'
const sMyObject = 'MyObject';
/**
* @class Base class for my threejs objects.
* <pre>
* Examples of child classes:
* <a href="../../getShaderMaterialPoints/jsdoc/module-getShaderMaterialPoints-getShaderMaterialPoints.html" target="_blank">getShaderMaterialPoints</a>,
* <a href="../../HyperSphere/jsdoc/module-HyperSphere-HyperSphere.html" target="_blank">HyperSphere</a>,
* <a href="../../myPoints/jsdoc/module-MyPoints-MyPoints.html" target="_blank">MyPoints</a>,
* <a href="../../nD/jsdoc/module-ND-ND.html" target="_blank">ND</a>.
* </pre>
*/
class MyObject {
/**
*
* @param {object} settings See child class (<a href="../../nD/jsdoc/module-ND-ND.html" target="_blank">ND</a>, <a href="../../myPoints/jsdoc/module-MyPoints-MyPoints.html" target="_blank">MyPoints</a>) <b>settings.
* @param {any} vertices
*/
constructor(settings={}, vertices) {
const _this = this;
//иммитация наследования классов
//settings.overriddenProperties ||= {};uncompatible with myThree.js → ./build/myThree.js, ./ build / myThree.module.js...
if (!settings.overriddenProperties) settings.overriddenProperties = {};
//settings.overriddenProperties.setDrawRange ||= (start, count) => { }uncompatible with myThree.js → ./build/myThree.js, ./ build / myThree.module.js...
if (!settings.overriddenProperties.setDrawRange) settings.overriddenProperties.setDrawRange = (start, count) => { }
settings.overriddenProperties.getPlayerTimesLength = () => { return 1; }
if (!settings.overriddenProperties.positionOffsetId) settings.overriddenProperties.positionOffsetId = (positionId) => { return positionId; }
if (settings.guiPoints) this.guiPoints = settings.guiPoints;
settings.object = settings.object || {};
settings.object.geometry = settings.object.geometry || {};
this.isSetPosition = settings.isSetPosition;
const timeId = (settings.options && settings.options.player) ? settings.options.player.getTimeId() : 0, geometry = settings.object.geometry,
geometryPosition = geometry.position;
if (
//(timeId === 0) && если оставить эту строку, то не смогу изменять положение вершины в nD.
//Для проверки открыть http://localhost/anhr/commonNodeJS/master/nD/Examples/
//сделать 3D на весь экран
//В gui выбрать Mesh\nD\Faces\Edges\Vertices и поменять одну из координат
//Положение ыбанной вершины должно меняться
(!geometryPosition || !geometryPosition.isPositionProxy)
) {
geometry.position = new Proxy(geometryPosition || [], {
get: (positions, name) => {
const positionId = parseInt(name);
if (!isNaN(positionId)) {
return new Proxy(positions[positionId], {
set: (position, name, value) => {
const axisId = parseInt(name);
if (!isNaN(axisId)) {
position[axisId] = value;
settings.bufferGeometry.userData.position[positionId][axisId] = value;
return true;
}
position[name] = value;
return true;
}
});
}
switch (name) {
case 'isPositionProxy': return true;
}
return positions[name];
},
});
}
const THREE = three.THREE;
if (!settings.bufferGeometry) {
settings.bufferGeometry = new THREE.BufferGeometry();
Object.defineProperty(settings.bufferGeometry.userData, 'timeId', {
get: () => { return 0; },
set: (timeIdNew) => { },//ignore timeIdNew
configurable: true,//https://stackoverflow.com/a/25518045/5175935
});
}
/**
* [BufferGeometry]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry} of the child graphical object.
*/
this.bufferGeometry = settings.bufferGeometry;
if (vertices)
//for for compatibility with ND
//Что бы можно было менять позицию и цвет вершины
if (!settings.object.geometry.position) settings.object.geometry.position = vertices;
//Эту строку нельзя использовать потому что во вселенной будет ошибка
//TypeError: classSettings.overriddenProperties.position0.angles[verticeId].middleVertice is not a function
//если:
//Открыть http://localhost/anhr/universe/main/hyperSphere/Examples/ что бы не было видно ребер classSettings.edges.project = true
//Сделать один шаг проигрывателя: нажать →
//Сделать ребра невидимыми: Поставить галочку Гиперсфера\Ребро\Отображать.
//Сделать один шаг проигрывателя: нажать →
//Это происходить потому что когда проигрыватель находится не в начальном положении timeId > 0, то в settings.object.geometry.position попадают вершины не из начального времени
// settings.object.geometry.position = settings.object.geometry.position || vertices;
/**
* Determines the part of the child graphical object geometry to render. See [BufferGeometry.drawRange]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry.drawRange}.
* @param {number} start Identifier of the start vertice to render.
* @param {number} count Count of vertices to render.
*/
this.setVerticesRange = (start, count) => {
const bufferGeometry = settings.bufferGeometry, position = bufferGeometry.attributes.position;
//Когда bufferGeometry.index != null, и отображаются вершины,
//то в drawRange задается диапазон видимых вершин без учета размера каждой вершины bufferGeometry.attributes.positionю.itemSize
const itemSize = ((position && (bufferGeometry.index != null)) ? position.itemSize : 1);
this.setDrawRange(start * itemSize, count * itemSize, bufferGeometry.drawRange.types.vertices);//https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry.setDrawRange
}
/**
* Determines the part of edges of the child graphical object geometry to render. See [BufferGeometry.drawRange]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry.drawRange}.
* @param {number} [start=0] Identifier of the start edge to render.
* @param {number} [timeId] Time identifier of the <a href="../../player/jsdoc/module-Player-Player.html" target="_blank">player</a> that determines of the end edge to render.
*/
this.setEdgesRange = (start = 0, timeId) => {
const drawRange = settings.bufferGeometry.drawRange;
start = start != undefined ? start : drawRange.start;
const timeEdgesLength = settings.object.geometry.indices[0].timeEdgesCount * 2;
this.setDrawRange(timeEdgesLength * start, timeEdgesLength * (((timeId != undefined) ? timeId : settings.options.player.getTimeId() + 1) - start), drawRange.types.edges);
}
/**
* Determines the part of vertices or edges of the child graphical object geometry to render. See [BufferGeometry.drawRange]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry.drawRange}.
* @param {number} start Identifier of the start vertice or edge to render.
* @param {number} count Count of vertices or edges to render.
* @param {number} type For debug. 0 - vertices draw range. 1 - edge's draw range.
*/
this.setDrawRange = (start, count, type) => {
if (settings.debug) {
if (type != undefined) settings.bufferGeometry.drawRange.type = type;
else console.error(sMyObject + ': setDrawRange(...). Invalid type = ' + type);
if (!Number.isInteger(start) || ((count != Infinity) && !Number.isInteger(count))) console.error(sMyObject + ': setDrawRange(...). Invalid drawRange = { start: ' + start + ', count: ' + count + ' }');
}
settings.overriddenProperties.setDrawRange(start, count);
}
const getPlayerTimesLength = () => { return settings.overriddenProperties.getPlayerTimesLength(); }
//Для отладки
const setDrawRangeTypes = () => {
settings.bufferGeometry.drawRange.types = { vertices: 0, edges: 1 };
//settings.bufferGeometry.drawRange.type = settings.bufferGeometry.drawRange.types.vertices Установлен диапазон видимых вершин
//settings.bufferGeometry.drawRange.type = settings.bufferGeometry.drawRange.types.edges Установлен диапазон видимых ребер
}
const createPositionAttribute = (pointLength, pointsLength) => {
//https://stackoverflow.com/questions/31399856/drawing-a-line-with-three-js-dynamically/31411794#31411794
const isRCount = settings.object.geometry.rCount != undefined, MAX_POINTS = isRCount ?
//резервирую место для вершин, которые появятся по мере проигрывания player.
//Это случается когда во вселенной вычисляется очередной шаг по времени. Тоесть пользователь нажал ► или →
pointLength * pointsLength * settings.object.geometry.rCount :
settings.object.geometry.MAX_POINTS;
setDrawRangeTypes();
if (MAX_POINTS != undefined) this.setVerticesRange(0, isRCount ?
pointLength * pointsLength * getPlayerTimesLength()://зарезервировано место для вершин вселенной с разным радиусом
//Имеются ребра. В этом случае settings.bufferGeometry.drawRange.count определяет количество отображаемых ребер
//Сейчас ребра еще не созданы. Поэтому settings.bufferGeometry.drawRange будет установлено после вызова this.setDrawRange
Infinity//pointsLength * 2 - 1
);
if (isRCount) settings.bufferGeometry.userData.drawRange = () => { return settings.bufferGeometry.drawRange; }
const positions = new Float32Array((MAX_POINTS != undefined ? MAX_POINTS : pointsLength) * pointLength);
settings.bufferGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, pointLength));
settings.bufferGeometry.userData.positionOffsetId = (positionId) => { return this.positionOffsetId(positionId) }
settings.bufferGeometry.userData.position = new Proxy(settings.bufferGeometry.attributes.position, {
get: (position, name) => {
const positionId = parseInt(name);
if (!isNaN(positionId)) {
const positionOffset = this.positionOffset(position, positionId),
array = position.array;
const verticeProxy = new Proxy([], {
get: (vertice, name) => {
const axisId = parseInt(name);
if (!isNaN(axisId)) {
if (axisId >= position.itemSize) {
//console.error(sMyObject + ': get position axis failed. Invalid axisId = ' + axisId);
return;
}
return array[positionOffset + axisId];
}
switch (name) {
case 'forEach': return (item) => {
for (let axisId = 0; axisId < position.itemSize; axisId++) item(array[positionOffset + axisId], axisId);
}
case 'length': return position.itemSize;
case 'toJSON': return (item) => {
let res = '[';
verticeProxy.forEach(axis => { res += axis + ', ' });
return res.substring(0, res.length-2) + ']';
}
case 'x': return array[positionOffset + 0];
case 'y': return array[positionOffset + 1];
case 'z': return array[positionOffset + 2];
case 'w': {
if (position.itemSize < 4) return;
return array[positionOffset + 3];
}
//для вывода углов на консоль
//Если оставить эту строку, то будет исключение в строке
//return new Proxy(timeAngles[verticeId]
//в файле hyperSphere.js потому что в массиве timeAngles нет углов с индексом verticeId
//Для проверки открыть http://localhost/anhr/universe/main/hyperSphere/Examples/
//Нажать ► проигрывателя
case 'angles': return settings.object.geometry.times[vertice.timeId][positionId];
case 'edges': return settings.object.geometry.times[0][positionId].edges;
case 'vector':
const vector = vertice.vector;
if (vector) {
console.error('Under constraction');
return vector;
}
{//hide vertice
//для совместимости с Player.getPoints.
//Открыть вселенную http://localhost/anhr/universe/main/hyperSphere/Examples/ с отображением ребер classSettings.edges.project != false
//Сделать один шаг проигрывателя. Появятся ребра для вселенной с новым временем.
//Убрать галочку "Гиперсфера.Вершины.Ребро.Отображать"classSettings.edges.project = false что бы реьа заменить на вершины
const vertice = verticeProxy;
switch(vertice.length){
case 3: return new THREE.Vector3(vertice[0], vertice[1], vertice[2]);
case 4: return new THREE.Vector4(vertice[0], vertice[1], vertice[2], vertice[3]);
}
console.error(sMyObject + ': get vertice.vector failed. Invalid vertice.length = ' + vertice.length);
}
return vertice[name];
}
if (_this.getPositionItem) {
const res = _this.getPositionItem(verticeProxy, name);
if (res != undefined) return res;
}
return vertice[name];
},
set: (vertice, name, value) => {
//edit vertice in http://localhost/anhr/commonNodeJS/master/nD/Examples/ for testing
const axisId = name === 'x' ? 0 : name === 'y' ? 1 : name === 'z' ? 2 : name === 'w' ? 3 : parseInt(name);
if (!isNaN(axisId)) {
array[positionOffset + axisId] = value;
return true;
}
vertice[name] = value;
return true;
}
});
return verticeProxy;
}
switch (name) {
case 'length': return position.count;
case 'itemSize': return position.itemSize;
}
console.error(sMyObject + ': get settings.bufferGeometry.userData.position. Invalid name: ' + name);
return position[name];
}
});
//color
if (_this.setW) _this.setW();
const itemSize = settings.object.geometry.opacity ? 4 : 3, colors = new Float32Array((MAX_POINTS != undefined ? MAX_POINTS : pointsLength) * itemSize);
if (itemSize === 4){
let colorId = itemSize - 1;
const opacity = settings.object.geometry.opacity;
//set opacity
while(colorId < colors.length) {
colors[colorId] = opacity;
colorId += itemSize;
}
}
settings.bufferGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, itemSize));
}
/**
* Sets the [BufferGeometry]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry} position attribute from <b>points</b> array.
* @param {Array} points Points array.
* @param {boolean} boCreatePositionAttribute true - replace old position attribute to new if it exists.
*/
this.setPositionAttributeFromPoints = (points, boCreatePositionAttribute) => {
const bufferAttributes = settings.bufferAttributes, bufferGeometry = settings.bufferGeometry;
if (bufferAttributes) {
Object.keys(bufferAttributes).forEach((key) => {
if (bufferGeometry.attributes[key]) console.error(sMyObject + '.setPositionAttributeFromPoints: Duplicated attribute: ' + key);
bufferGeometry.setAttribute(key, bufferAttributes[key]);
} );
settings.overriddenProperties.setTracesIndices(bufferGeometry);
setDrawRangeTypes();
return;
}
if (boCreatePositionAttribute) delete bufferGeometry.attributes.position;
if (!bufferGeometry.attributes.position) {
createPositionAttribute(
this.pointLength ? this.pointLength() :
points[0].w === undefined ? 3 : 4,
points.length);
const boLog = this.classSettings && (this.classSettings.debug != undefined) && (this.classSettings.debug != false) && (this.classSettings.debug.log != false);
for (let timeId = 0; timeId < getPlayerTimesLength(); timeId++) {
if (boLog) console.log('timeId = ' + timeId);
for (let i = 0; i < points.length; i++) {
const vertice = this.setPositionAttributeFromPoint(i, undefined, timeId);
if (boLog) console.log('\tvertice[' + i + '] = ' + JSON.stringify(vertice));
}
if (boLog) console.log('');
}
}
return bufferGeometry;
}
/**
* Vertice color.
* @param {number} i Vertice identifier.
* @param {Array} vertice Vertice axis array.
* @param {number} timeId Time identifier of the <a href="../../player/jsdoc/module-Player-Player.html" target="_blank">player</a> that determines current vertice color.
*/
this.verticeColor = (i, vertice, timeId) => {
const colors = settings.object.geometry.colors;
if (colors) {
const colorsId = i * 3;
if (colors[colorsId] != undefined)
return [colors[colorsId], colors[colorsId + 1], colors[colorsId + 2]];
}
const color = settings.object.color;
if (typeof color === "function") return color(timeId);
if ((color != undefined) && (typeof color != 'object')) return new THREE.Color(_this.color());
//Вершина не имеет 4 координаты. Установить цвет вершины по умолчанию
const getDefaultColor = () => { return new THREE.Color(_this.color()); }
let w
if (vertice) w = vertice.w;
else if (!_this.getPoint) {
const position = _this.bufferGeometry.attributes.position;
if (position.itemSize != 4) return getDefaultColor();
w = new THREE.Vector4().fromBufferAttribute(position, i).w;
}
else w = _this.getPoint(i).w;
if (w === undefined) return getDefaultColor();
return w;
}
/**
* Gets a position data.
* @param {number} i Vertice identifier for <b>timeId</b> = 0.
* @param {number} timeId Time identifier of the <a href="../../player/jsdoc/module-Player-Player.html" target="_blank">player</a> that determines current position data.
* @return position data object. Object properties:
* <pre>
* verticeId: Vertice identifier for current <b>timeId</b>.
* itemSize: Size of the position axis array.
* positionBlockLength: Positions count for current time.
* positionId: <b>verticeId</b> * <b>itemSize</b>.
* <pre>
*/
this.getPositionData = (i, timeId) => {
//Во вселенной, когда пользователь щелкает по вершине, то индекс вершины i будет равен положению вершины в attributes.position
//а должен быть равен индексу вершины для текущего времени.
if (_this.guiPoints && _this.guiPoints.verticeId) {
i = _this.guiPoints.verticeId;
timeId = _this.guiPoints.timeId;
}
i = parseInt(i);
if (timeId === undefined) timeId = 0;
if (i === undefined) console.error(sMyObject + '.getPositionData. Invalid i = ' + i);
const userData = settings.bufferGeometry.userData,
positionBlockLength = userData.positionBlockLength === undefined ? 0 : userData.positionBlockLength,
itemSize = settings.bufferGeometry.attributes.position.itemSize,
verticeId = positionBlockLength * timeId + i;
return {
verticeId: verticeId,
itemSize: itemSize,
positionBlockLength: positionBlockLength,
positionId: verticeId * itemSize,
}
}
/**
* Sets the [BufferGeometry]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry} position attribute from <b>vertice</b>.
* @param {number} i Vertice identifier for <b>timeId</b> = 0.
* @param {Array} [vertice] Vertice axis array for current <b>timeId</b>.
* @param {number} timeId Time identifier of the <a href="../../player/jsdoc/module-Player-Player.html" target="_blank">player</a> that determines current vertice.
*/
this.setPositionAttributeFromPoint = (i, vertice, timeId) => {
//Position attribute
vertice = vertice || _this.getPoint(i, timeId);
const attributes = settings.bufferGeometry.attributes, positionData = this.getPositionData(i, timeId),
positionBlockLength = positionData.positionBlockLength;
let itemSize = positionData.itemSize, positionId = positionData.positionId, array = attributes.position.array;
array [positionId] = vertice.x != undefined ? vertice.x : vertice[0] != undefined ? vertice[0] : 0;
if (itemSize > 1) array [++positionId] = vertice.y != undefined ? vertice.y : vertice[1] != undefined ? vertice[1] : 0;
if (itemSize > 2) array [++positionId] = vertice.z != undefined ? vertice.z : vertice[2] != undefined ? vertice[2] : 0;
const w = vertice.w != undefined ? vertice.w : vertice[3];
if (itemSize > 3) array [++positionId] = w;
if (this.onSetPositionAttributeFromPoint) this.onSetPositionAttributeFromPoint(i);
const drawRange = settings.bufferGeometry.drawRange;
if ((drawRange.count === Infinity) || (((drawRange.start + drawRange.count) * ((settings.bufferGeometry.index === null) ? itemSize : 1)) < positionId)){
this.setVerticesRange(drawRange.start, (positionId + 1) / itemSize - drawRange.start);
if (!Number.isInteger(drawRange.count) && (drawRange.count != Infinity)) console.error(sMyObject + '.setPositionAttributeFromPoint failed. Invalid drawRange.count = ' + drawRange.count);
}
//gui
const guiSelectPoint = settings.options.guiSelectPoint,
object3D = this.object3D;
if (guiSelectPoint && (guiSelectPoint.getSelectedPointIndexShort() === i) && guiSelectPoint.isSelectedMesh(object3D)) {
guiSelectPoint.setPosition( { index: i, nearestEdgeVerticeId: i, object: object3D });
if (object3D && object3D.userData.gui) object3D.userData.gui.reset()//в hyperSphere обновить выделенные ребра, среднюю вершину и плоскости вращения углов
}
//Color attribute
itemSize = attributes.color.itemSize;
let colorId = i * itemSize + (timeId === undefined ? 0 : positionBlockLength * timeId * itemSize);
array = attributes.color.array;
const verticeColor = this.verticeColor(i, vertice, timeId);
if (typeof verticeColor === 'number'){
if (settings.options) {
const wScale = settings.options.scales.w;
Player.setColorAttribute(attributes, i + (timeId === undefined ? 0 : positionBlockLength * timeId), settings.options.palette.toColor(verticeColor, wScale.min, wScale.max));
}
colorId += attributes.color.itemSize - 1;
} else if (Array.isArray(verticeColor)) verticeColor.forEach(item => array[colorId++] = item);
else if (verticeColor instanceof THREE.Color) {
array [colorId++] = verticeColor.r;
array [colorId++] = verticeColor.g;
array [colorId++] = verticeColor.b;
}
else console.error(sMyObject + '.setPositionAttributeFromPoint: Invalid verticeColor = ' + verticeColor);
//opacity
if (attributes.color.itemSize > 3) this.verticeOpacity(i);
//Необходимо для того, что бы отоборажалась информация о вершине при наведении на нее мышки
//Внимание. Иногда эта функция работает и без удаления boundingSphere
delete settings.bufferGeometry.boundingSphere;
settings.bufferGeometry.boundingSphere = null;
return vertice;
}
/**
* Vertice opacity.
* @param {number} i Vertice identifier.
* @param {Boolean} [transparent] See [transparent]{@link https://threejs.org/docs/index.html?q=LineBasicMaterial#api/en/materials/Material.transparent}.
* @param {number} [opacity] See [opacity]{@link https://threejs.org/docs/index.html?q=LineBasicMaterial#api/en/materials/Material.opacity}.
*/
this.verticeOpacity = (i, transparent, opacity) => {
const color = settings.bufferGeometry.attributes.color;
if (color.itemSize != 4) {
console.error(sMyObject + '.verticeOpacity: Invalid color.itemSize = ' + color.itemSize);
return;
}
const array = color.array;
const verticeOpacity = settings.object.geometry.opacity ? settings.object.geometry.opacity[i] : undefined;
array[color.itemSize * i + 3] = transparent ? opacity : verticeOpacity === undefined ? 1 : verticeOpacity;
color.needsUpdate = true;
}
/**
* Opacity for all vertices.
* @param {Array} [transparent] See [transparent]{@link https://threejs.org/docs/index.html?q=LineBasicMaterial#api/en/materials/Material.transparent}.
* @param {number} [opacity] See [opacity]{@link https://threejs.org/docs/index.html?q=LineBasicMaterial#api/en/materials/Material.opacity}.
*/
this.verticesOpacity = (transparent, opacity) => {
const color = settings.bufferGeometry.attributes.color;
if ( color && ( color.itemSize > 3 ) ) {
for ( let i = 0; i < color.count; i++ ) { this.verticeOpacity(i, transparent, opacity); }
} else {
const object3D = _this.object3D;
if (object3D) {
object3D.material.transparent = transparent;
object3D.material.opacity = transparent ? opacity : 1;
object3D.material.needsUpdate = true;//for THREE.REVISION = "145dev"
} else console.error(sMyObject + '.verticesOpacity: Invalid object3D');
}
}
/**
* @return The child graphical object color or <a href="../../player/jsdoc/module-Player-Player.html" target="_blank">player</a> time if graphical object color is not defined.
*/
this.color = () => {
const color = settings.object.color != undefined ? settings.object.color : settings.pointsOptions != undefined ? settings.pointsOptions.color : undefined;
return (color != undefined) ?
(typeof color === "function") ? color() : color :
this.defaultColor;//'lime';
}
/**
* @param {number} positionId Position identifier for start time.
* @returns Offset of the position identifier for current time.
*/
this.positionOffsetId = (positionId) => { return settings.overriddenProperties.positionOffsetId(positionId); }
}
//base methods
/**
* Returns 'white'.
*/
get defaultColor() { return 'white'; }
/**
* Returns <b>true</b> if a child graphical object can be transparent.
*/
get isOpacity() {
if (this.bufferGeometry.attributes.color && (this.bufferGeometry.attributes.color.itemSize > 3)) {
if (!this.object3D.material.transparent) console.error(sMyObject + '.isOpacity: invalid this.object3D.material.transparent = ' + this.object3D.material.transparent);
return true;
}
return false;
}
/**
* @param {object} position [BufferGeometry]{@link https://threejs.org/docs/index.html?q=BufferGeometry#api/en/core/BufferGeometry} <b>position</b> attribute of the child graphical object.
* @param {number} positionId Position identifier for start time.
* @returns Offset of the position in the <b>position</b> attribute for current time.
*/
positionOffset(position, positionId) { return this.positionOffsetId(positionId) * position.itemSize; }
}
export default MyObject;