UNPKG

21.3 kBJavaScriptView Raw
1import { Vector3 } from '../math/Vector3.js';
2import { Box3 } from '../math/Box3.js';
3import { EventDispatcher } from './EventDispatcher.js';
4import { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute } from './BufferAttribute.js';
5import { Sphere } from '../math/Sphere.js';
6import { DirectGeometry } from './DirectGeometry.js';
7import { Object3D } from './Object3D.js';
8import { Matrix4 } from '../math/Matrix4.js';
9import { Matrix3 } from '../math/Matrix3.js';
10import { _Math } from '../math/Math.js';
11import { arrayMax } from '../utils.js';
12
13/**
14 * @author alteredq / http://alteredqualia.com/
15 * @author mrdoob / http://mrdoob.com/
16 */
17
18var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
19
20function BufferGeometry() {
21
22 Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } );
23
24 this.uuid = _Math.generateUUID();
25
26 this.name = '';
27 this.type = 'BufferGeometry';
28
29 this.index = null;
30 this.attributes = {};
31
32 this.morphAttributes = {};
33
34 this.groups = [];
35
36 this.boundingBox = null;
37 this.boundingSphere = null;
38
39 this.drawRange = { start: 0, count: Infinity };
40
41}
42
43BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
44
45 constructor: BufferGeometry,
46
47 isBufferGeometry: true,
48
49 getIndex: function () {
50
51 return this.index;
52
53 },
54
55 setIndex: function ( index ) {
56
57 if ( Array.isArray( index ) ) {
58
59 this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
60
61 } else {
62
63 this.index = index;
64
65 }
66
67 },
68
69 addAttribute: function ( name, attribute ) {
70
71 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
72
73 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
74
75 this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
76
77 return;
78
79 }
80
81 if ( name === 'index' ) {
82
83 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
84 this.setIndex( attribute );
85
86 return;
87
88 }
89
90 this.attributes[ name ] = attribute;
91
92 return this;
93
94 },
95
96 getAttribute: function ( name ) {
97
98 return this.attributes[ name ];
99
100 },
101
102 removeAttribute: function ( name ) {
103
104 delete this.attributes[ name ];
105
106 return this;
107
108 },
109
110 addGroup: function ( start, count, materialIndex ) {
111
112 this.groups.push( {
113
114 start: start,
115 count: count,
116 materialIndex: materialIndex !== undefined ? materialIndex : 0
117
118 } );
119
120 },
121
122 clearGroups: function () {
123
124 this.groups = [];
125
126 },
127
128 setDrawRange: function ( start, count ) {
129
130 this.drawRange.start = start;
131 this.drawRange.count = count;
132
133 },
134
135 applyMatrix: function ( matrix ) {
136
137 var position = this.attributes.position;
138
139 if ( position !== undefined ) {
140
141 matrix.applyToBufferAttribute( position );
142 position.needsUpdate = true;
143
144 }
145
146 var normal = this.attributes.normal;
147
148 if ( normal !== undefined ) {
149
150 var normalMatrix = new Matrix3().getNormalMatrix( matrix );
151
152 normalMatrix.applyToBufferAttribute( normal );
153 normal.needsUpdate = true;
154
155 }
156
157 if ( this.boundingBox !== null ) {
158
159 this.computeBoundingBox();
160
161 }
162
163 if ( this.boundingSphere !== null ) {
164
165 this.computeBoundingSphere();
166
167 }
168
169 return this;
170
171 },
172
173 rotateX: function () {
174
175 // rotate geometry around world x-axis
176
177 var m1 = new Matrix4();
178
179 return function rotateX( angle ) {
180
181 m1.makeRotationX( angle );
182
183 this.applyMatrix( m1 );
184
185 return this;
186
187 };
188
189 }(),
190
191 rotateY: function () {
192
193 // rotate geometry around world y-axis
194
195 var m1 = new Matrix4();
196
197 return function rotateY( angle ) {
198
199 m1.makeRotationY( angle );
200
201 this.applyMatrix( m1 );
202
203 return this;
204
205 };
206
207 }(),
208
209 rotateZ: function () {
210
211 // rotate geometry around world z-axis
212
213 var m1 = new Matrix4();
214
215 return function rotateZ( angle ) {
216
217 m1.makeRotationZ( angle );
218
219 this.applyMatrix( m1 );
220
221 return this;
222
223 };
224
225 }(),
226
227 translate: function () {
228
229 // translate geometry
230
231 var m1 = new Matrix4();
232
233 return function translate( x, y, z ) {
234
235 m1.makeTranslation( x, y, z );
236
237 this.applyMatrix( m1 );
238
239 return this;
240
241 };
242
243 }(),
244
245 scale: function () {
246
247 // scale geometry
248
249 var m1 = new Matrix4();
250
251 return function scale( x, y, z ) {
252
253 m1.makeScale( x, y, z );
254
255 this.applyMatrix( m1 );
256
257 return this;
258
259 };
260
261 }(),
262
263 lookAt: function () {
264
265 var obj = new Object3D();
266
267 return function lookAt( vector ) {
268
269 obj.lookAt( vector );
270
271 obj.updateMatrix();
272
273 this.applyMatrix( obj.matrix );
274
275 };
276
277 }(),
278
279 center: function () {
280
281 var offset = new Vector3();
282
283 return function center() {
284
285 this.computeBoundingBox();
286
287 this.boundingBox.getCenter( offset ).negate();
288
289 this.translate( offset.x, offset.y, offset.z );
290
291 return this;
292
293 };
294
295 }(),
296
297 setFromObject: function ( object ) {
298
299 // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
300
301 var geometry = object.geometry;
302
303 if ( object.isPoints || object.isLine ) {
304
305 var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
306 var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
307
308 this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
309 this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
310
311 if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
312
313 var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
314
315 this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
316
317 }
318
319 if ( geometry.boundingSphere !== null ) {
320
321 this.boundingSphere = geometry.boundingSphere.clone();
322
323 }
324
325 if ( geometry.boundingBox !== null ) {
326
327 this.boundingBox = geometry.boundingBox.clone();
328
329 }
330
331 } else if ( object.isMesh ) {
332
333 if ( geometry && geometry.isGeometry ) {
334
335 this.fromGeometry( geometry );
336
337 }
338
339 }
340
341 return this;
342
343 },
344
345 setFromPoints: function ( points ) {
346
347 var position = [];
348
349 for ( var i = 0, l = points.length; i < l; i ++ ) {
350
351 var point = points[ i ];
352 position.push( point.x, point.y, point.z || 0 );
353
354 }
355
356 this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
357
358 return this;
359
360 },
361
362 updateFromObject: function ( object ) {
363
364 var geometry = object.geometry;
365
366 if ( object.isMesh ) {
367
368 var direct = geometry.__directGeometry;
369
370 if ( geometry.elementsNeedUpdate === true ) {
371
372 direct = undefined;
373 geometry.elementsNeedUpdate = false;
374
375 }
376
377 if ( direct === undefined ) {
378
379 return this.fromGeometry( geometry );
380
381 }
382
383 direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
384 direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
385 direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
386 direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
387 direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
388
389 geometry.verticesNeedUpdate = false;
390 geometry.normalsNeedUpdate = false;
391 geometry.colorsNeedUpdate = false;
392 geometry.uvsNeedUpdate = false;
393 geometry.groupsNeedUpdate = false;
394
395 geometry = direct;
396
397 }
398
399 var attribute;
400
401 if ( geometry.verticesNeedUpdate === true ) {
402
403 attribute = this.attributes.position;
404
405 if ( attribute !== undefined ) {
406
407 attribute.copyVector3sArray( geometry.vertices );
408 attribute.needsUpdate = true;
409
410 }
411
412 geometry.verticesNeedUpdate = false;
413
414 }
415
416 if ( geometry.normalsNeedUpdate === true ) {
417
418 attribute = this.attributes.normal;
419
420 if ( attribute !== undefined ) {
421
422 attribute.copyVector3sArray( geometry.normals );
423 attribute.needsUpdate = true;
424
425 }
426
427 geometry.normalsNeedUpdate = false;
428
429 }
430
431 if ( geometry.colorsNeedUpdate === true ) {
432
433 attribute = this.attributes.color;
434
435 if ( attribute !== undefined ) {
436
437 attribute.copyColorsArray( geometry.colors );
438 attribute.needsUpdate = true;
439
440 }
441
442 geometry.colorsNeedUpdate = false;
443
444 }
445
446 if ( geometry.uvsNeedUpdate ) {
447
448 attribute = this.attributes.uv;
449
450 if ( attribute !== undefined ) {
451
452 attribute.copyVector2sArray( geometry.uvs );
453 attribute.needsUpdate = true;
454
455 }
456
457 geometry.uvsNeedUpdate = false;
458
459 }
460
461 if ( geometry.lineDistancesNeedUpdate ) {
462
463 attribute = this.attributes.lineDistance;
464
465 if ( attribute !== undefined ) {
466
467 attribute.copyArray( geometry.lineDistances );
468 attribute.needsUpdate = true;
469
470 }
471
472 geometry.lineDistancesNeedUpdate = false;
473
474 }
475
476 if ( geometry.groupsNeedUpdate ) {
477
478 geometry.computeGroups( object.geometry );
479 this.groups = geometry.groups;
480
481 geometry.groupsNeedUpdate = false;
482
483 }
484
485 return this;
486
487 },
488
489 fromGeometry: function ( geometry ) {
490
491 geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
492
493 return this.fromDirectGeometry( geometry.__directGeometry );
494
495 },
496
497 fromDirectGeometry: function ( geometry ) {
498
499 var positions = new Float32Array( geometry.vertices.length * 3 );
500 this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
501
502 if ( geometry.normals.length > 0 ) {
503
504 var normals = new Float32Array( geometry.normals.length * 3 );
505 this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
506
507 }
508
509 if ( geometry.colors.length > 0 ) {
510
511 var colors = new Float32Array( geometry.colors.length * 3 );
512 this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
513
514 }
515
516 if ( geometry.uvs.length > 0 ) {
517
518 var uvs = new Float32Array( geometry.uvs.length * 2 );
519 this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
520
521 }
522
523 if ( geometry.uvs2.length > 0 ) {
524
525 var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
526 this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
527
528 }
529
530 // groups
531
532 this.groups = geometry.groups;
533
534 // morphs
535
536 for ( var name in geometry.morphTargets ) {
537
538 var array = [];
539 var morphTargets = geometry.morphTargets[ name ];
540
541 for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
542
543 var morphTarget = morphTargets[ i ];
544
545 var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 );
546
547 array.push( attribute.copyVector3sArray( morphTarget ) );
548
549 }
550
551 this.morphAttributes[ name ] = array;
552
553 }
554
555 // skinning
556
557 if ( geometry.skinIndices.length > 0 ) {
558
559 var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
560 this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
561
562 }
563
564 if ( geometry.skinWeights.length > 0 ) {
565
566 var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
567 this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
568
569 }
570
571 //
572
573 if ( geometry.boundingSphere !== null ) {
574
575 this.boundingSphere = geometry.boundingSphere.clone();
576
577 }
578
579 if ( geometry.boundingBox !== null ) {
580
581 this.boundingBox = geometry.boundingBox.clone();
582
583 }
584
585 return this;
586
587 },
588
589 computeBoundingBox: function () {
590
591 if ( this.boundingBox === null ) {
592
593 this.boundingBox = new Box3();
594
595 }
596
597 var position = this.attributes.position;
598
599 if ( position !== undefined ) {
600
601 this.boundingBox.setFromBufferAttribute( position );
602
603 } else {
604
605 this.boundingBox.makeEmpty();
606
607 }
608
609 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
610
611 console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
612
613 }
614
615 },
616
617 computeBoundingSphere: function () {
618
619 var box = new Box3();
620 var vector = new Vector3();
621
622 return function computeBoundingSphere() {
623
624 if ( this.boundingSphere === null ) {
625
626 this.boundingSphere = new Sphere();
627
628 }
629
630 var position = this.attributes.position;
631
632 if ( position ) {
633
634 var center = this.boundingSphere.center;
635
636 box.setFromBufferAttribute( position );
637 box.getCenter( center );
638
639 // hoping to find a boundingSphere with a radius smaller than the
640 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
641
642 var maxRadiusSq = 0;
643
644 for ( var i = 0, il = position.count; i < il; i ++ ) {
645
646 vector.x = position.getX( i );
647 vector.y = position.getY( i );
648 vector.z = position.getZ( i );
649 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
650
651 }
652
653 this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
654
655 if ( isNaN( this.boundingSphere.radius ) ) {
656
657 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
658
659 }
660
661 }
662
663 };
664
665 }(),
666
667 computeFaceNormals: function () {
668
669 // backwards compatibility
670
671 },
672
673 computeVertexNormals: function () {
674
675 var index = this.index;
676 var attributes = this.attributes;
677 var groups = this.groups;
678
679 if ( attributes.position ) {
680
681 var positions = attributes.position.array;
682
683 if ( attributes.normal === undefined ) {
684
685 this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
686
687 } else {
688
689 // reset existing normals to zero
690
691 var array = attributes.normal.array;
692
693 for ( var i = 0, il = array.length; i < il; i ++ ) {
694
695 array[ i ] = 0;
696
697 }
698
699 }
700
701 var normals = attributes.normal.array;
702
703 var vA, vB, vC;
704 var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
705 var cb = new Vector3(), ab = new Vector3();
706
707 // indexed elements
708
709 if ( index ) {
710
711 var indices = index.array;
712
713 if ( groups.length === 0 ) {
714
715 this.addGroup( 0, indices.length );
716
717 }
718
719 for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
720
721 var group = groups[ j ];
722
723 var start = group.start;
724 var count = group.count;
725
726 for ( var i = start, il = start + count; i < il; i += 3 ) {
727
728 vA = indices[ i + 0 ] * 3;
729 vB = indices[ i + 1 ] * 3;
730 vC = indices[ i + 2 ] * 3;
731
732 pA.fromArray( positions, vA );
733 pB.fromArray( positions, vB );
734 pC.fromArray( positions, vC );
735
736 cb.subVectors( pC, pB );
737 ab.subVectors( pA, pB );
738 cb.cross( ab );
739
740 normals[ vA ] += cb.x;
741 normals[ vA + 1 ] += cb.y;
742 normals[ vA + 2 ] += cb.z;
743
744 normals[ vB ] += cb.x;
745 normals[ vB + 1 ] += cb.y;
746 normals[ vB + 2 ] += cb.z;
747
748 normals[ vC ] += cb.x;
749 normals[ vC + 1 ] += cb.y;
750 normals[ vC + 2 ] += cb.z;
751
752 }
753
754 }
755
756 } else {
757
758 // non-indexed elements (unconnected triangle soup)
759
760 for ( var i = 0, il = positions.length; i < il; i += 9 ) {
761
762 pA.fromArray( positions, i );
763 pB.fromArray( positions, i + 3 );
764 pC.fromArray( positions, i + 6 );
765
766 cb.subVectors( pC, pB );
767 ab.subVectors( pA, pB );
768 cb.cross( ab );
769
770 normals[ i ] = cb.x;
771 normals[ i + 1 ] = cb.y;
772 normals[ i + 2 ] = cb.z;
773
774 normals[ i + 3 ] = cb.x;
775 normals[ i + 4 ] = cb.y;
776 normals[ i + 5 ] = cb.z;
777
778 normals[ i + 6 ] = cb.x;
779 normals[ i + 7 ] = cb.y;
780 normals[ i + 8 ] = cb.z;
781
782 }
783
784 }
785
786 this.normalizeNormals();
787
788 attributes.normal.needsUpdate = true;
789
790 }
791
792 },
793
794 merge: function ( geometry, offset ) {
795
796 if ( ! ( geometry && geometry.isBufferGeometry ) ) {
797
798 console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
799 return;
800
801 }
802
803 if ( offset === undefined ) {
804
805 offset = 0;
806
807 console.warn(
808 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
809 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
810 );
811
812 }
813
814 var attributes = this.attributes;
815
816 for ( var key in attributes ) {
817
818 if ( geometry.attributes[ key ] === undefined ) continue;
819
820 var attribute1 = attributes[ key ];
821 var attributeArray1 = attribute1.array;
822
823 var attribute2 = geometry.attributes[ key ];
824 var attributeArray2 = attribute2.array;
825
826 var attributeSize = attribute2.itemSize;
827
828 for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
829
830 attributeArray1[ j ] = attributeArray2[ i ];
831
832 }
833
834 }
835
836 return this;
837
838 },
839
840 normalizeNormals: function () {
841
842 var vector = new Vector3();
843
844 return function normalizeNormals() {
845
846 var normals = this.attributes.normal;
847
848 for ( var i = 0, il = normals.count; i < il; i ++ ) {
849
850 vector.x = normals.getX( i );
851 vector.y = normals.getY( i );
852 vector.z = normals.getZ( i );
853
854 vector.normalize();
855
856 normals.setXYZ( i, vector.x, vector.y, vector.z );
857
858 }
859
860 };
861
862 }(),
863
864 toNonIndexed: function () {
865
866 if ( this.index === null ) {
867
868 console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
869 return this;
870
871 }
872
873 var geometry2 = new BufferGeometry();
874
875 var indices = this.index.array;
876 var attributes = this.attributes;
877
878 for ( var name in attributes ) {
879
880 var attribute = attributes[ name ];
881
882 var array = attribute.array;
883 var itemSize = attribute.itemSize;
884
885 var array2 = new array.constructor( indices.length * itemSize );
886
887 var index = 0, index2 = 0;
888
889 for ( var i = 0, l = indices.length; i < l; i ++ ) {
890
891 index = indices[ i ] * itemSize;
892
893 for ( var j = 0; j < itemSize; j ++ ) {
894
895 array2[ index2 ++ ] = array[ index ++ ];
896
897 }
898
899 }
900
901 geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) );
902
903 }
904
905 var groups = this.groups;
906
907 for ( var i = 0, l = groups.length; i < l; i ++ ) {
908
909 var group = groups[ i ];
910 geometry2.addGroup( group.start, group.count, group.materialIndex );
911
912 }
913
914 return geometry2;
915
916 },
917
918 toJSON: function () {
919
920 var data = {
921 metadata: {
922 version: 4.5,
923 type: 'BufferGeometry',
924 generator: 'BufferGeometry.toJSON'
925 }
926 };
927
928 // standard BufferGeometry serialization
929
930 data.uuid = this.uuid;
931 data.type = this.type;
932 if ( this.name !== '' ) data.name = this.name;
933
934 if ( this.parameters !== undefined ) {
935
936 var parameters = this.parameters;
937
938 for ( var key in parameters ) {
939
940 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
941
942 }
943
944 return data;
945
946 }
947
948 data.data = { attributes: {} };
949
950 var index = this.index;
951
952 if ( index !== null ) {
953
954 var array = Array.prototype.slice.call( index.array );
955
956 data.data.index = {
957 type: index.array.constructor.name,
958 array: array
959 };
960
961 }
962
963 var attributes = this.attributes;
964
965 for ( var key in attributes ) {
966
967 var attribute = attributes[ key ];
968
969 var array = Array.prototype.slice.call( attribute.array );
970
971 data.data.attributes[ key ] = {
972 itemSize: attribute.itemSize,
973 type: attribute.array.constructor.name,
974 array: array,
975 normalized: attribute.normalized
976 };
977
978 }
979
980 var groups = this.groups;
981
982 if ( groups.length > 0 ) {
983
984 data.data.groups = JSON.parse( JSON.stringify( groups ) );
985
986 }
987
988 var boundingSphere = this.boundingSphere;
989
990 if ( boundingSphere !== null ) {
991
992 data.data.boundingSphere = {
993 center: boundingSphere.center.toArray(),
994 radius: boundingSphere.radius
995 };
996
997 }
998
999 return data;
1000
1001 },
1002
1003 clone: function () {
1004
1005 /*
1006 // Handle primitives
1007
1008 var parameters = this.parameters;
1009
1010 if ( parameters !== undefined ) {
1011
1012 var values = [];
1013
1014 for ( var key in parameters ) {
1015
1016 values.push( parameters[ key ] );
1017
1018 }
1019
1020 var geometry = Object.create( this.constructor.prototype );
1021 this.constructor.apply( geometry, values );
1022 return geometry;
1023
1024 }
1025
1026 return new this.constructor().copy( this );
1027 */
1028
1029 return new BufferGeometry().copy( this );
1030
1031 },
1032
1033 copy: function ( source ) {
1034
1035 var name, i, l;
1036
1037 // reset
1038
1039 this.index = null;
1040 this.attributes = {};
1041 this.morphAttributes = {};
1042 this.groups = [];
1043 this.boundingBox = null;
1044 this.boundingSphere = null;
1045
1046 // name
1047
1048 this.name = source.name;
1049
1050 // index
1051
1052 var index = source.index;
1053
1054 if ( index !== null ) {
1055
1056 this.setIndex( index.clone() );
1057
1058 }
1059
1060 // attributes
1061
1062 var attributes = source.attributes;
1063
1064 for ( name in attributes ) {
1065
1066 var attribute = attributes[ name ];
1067 this.addAttribute( name, attribute.clone() );
1068
1069 }
1070
1071 // morph attributes
1072
1073 var morphAttributes = source.morphAttributes;
1074
1075 for ( name in morphAttributes ) {
1076
1077 var array = [];
1078 var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
1079
1080 for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
1081
1082 array.push( morphAttribute[ i ].clone() );
1083
1084 }
1085
1086 this.morphAttributes[ name ] = array;
1087
1088 }
1089
1090 // groups
1091
1092 var groups = source.groups;
1093
1094 for ( i = 0, l = groups.length; i < l; i ++ ) {
1095
1096 var group = groups[ i ];
1097 this.addGroup( group.start, group.count, group.materialIndex );
1098
1099 }
1100
1101 // bounding box
1102
1103 var boundingBox = source.boundingBox;
1104
1105 if ( boundingBox !== null ) {
1106
1107 this.boundingBox = boundingBox.clone();
1108
1109 }
1110
1111 // bounding sphere
1112
1113 var boundingSphere = source.boundingSphere;
1114
1115 if ( boundingSphere !== null ) {
1116
1117 this.boundingSphere = boundingSphere.clone();
1118
1119 }
1120
1121 // draw range
1122
1123 this.drawRange.start = source.drawRange.start;
1124 this.drawRange.count = source.drawRange.count;
1125
1126 return this;
1127
1128 },
1129
1130 dispose: function () {
1131
1132 this.dispatchEvent( { type: 'dispose' } );
1133
1134 }
1135
1136} );
1137
1138
1139export { BufferGeometry };