@damienmortini/three 0.1.164 → 0.1.167

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.
@@ -48,6 +48,13 @@ class BasisTextureLoader extends Loader {
48
48
  this.workerSourceURL = '';
49
49
  this.workerConfig = null;
50
50
 
51
+ console.warn(
52
+
53
+ 'THREE.BasisTextureLoader: This loader is deprecated, and will be removed in a future release. '
54
+ + 'Instead, use Basis Universal compression in KTX2 (.ktx2) files with THREE.KTX2Loader.'
55
+
56
+ );
57
+
51
58
  }
52
59
 
53
60
  setTranscoderPath( path ) {
@@ -47,7 +47,6 @@ import {
47
47
  PropertyBinding,
48
48
  Quaternion,
49
49
  QuaternionKeyframeTrack,
50
- RGBFormat,
51
50
  RepeatWrapping,
52
51
  Skeleton,
53
52
  SkinnedMesh,
@@ -627,7 +626,7 @@ class GLTFMaterialsUnlitExtension {
627
626
 
628
627
  if ( metallicRoughness.baseColorTexture !== undefined ) {
629
628
 
630
- pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
629
+ pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, sRGBEncoding ) );
631
630
 
632
631
  }
633
632
 
@@ -781,7 +780,7 @@ class GLTFMaterialsSheenExtension {
781
780
 
782
781
  if ( extension.sheenColorTexture !== undefined ) {
783
782
 
784
- pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture ) );
783
+ pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, sRGBEncoding ) );
785
784
 
786
785
  }
787
786
 
@@ -1014,11 +1013,7 @@ class GLTFMaterialsSpecularExtension {
1014
1013
 
1015
1014
  if ( extension.specularColorTexture !== undefined ) {
1016
1015
 
1017
- pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture ).then( function ( texture ) {
1018
-
1019
- texture.encoding = sRGBEncoding;
1020
-
1021
- } ) );
1016
+ pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, sRGBEncoding ) );
1022
1017
 
1023
1018
  }
1024
1019
 
@@ -1056,7 +1051,6 @@ class GLTFTextureBasisUExtension {
1056
1051
  }
1057
1052
 
1058
1053
  const extension = textureDef.extensions[ this.name ];
1059
- const source = json.images[ extension.source ];
1060
1054
  const loader = parser.options.ktx2Loader;
1061
1055
 
1062
1056
  if ( ! loader ) {
@@ -1074,7 +1068,7 @@ class GLTFTextureBasisUExtension {
1074
1068
 
1075
1069
  }
1076
1070
 
1077
- return parser.loadTextureImage( textureIndex, source, loader );
1071
+ return parser.loadTextureImage( textureIndex, extension.source, loader );
1078
1072
 
1079
1073
  }
1080
1074
 
@@ -1478,7 +1472,6 @@ class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
1478
1472
  'vec3 specularFactor = specular;',
1479
1473
  '#ifdef USE_SPECULARMAP',
1480
1474
  ' vec4 texelSpecular = texture2D( specularMap, vUv );',
1481
- ' texelSpecular = sRGBToLinear( texelSpecular );',
1482
1475
  ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
1483
1476
  ' specularFactor *= texelSpecular.rgb;',
1484
1477
  '#endif'
@@ -1667,8 +1660,7 @@ class GLTFMaterialsPbrSpecularGlossinessExtension {
1667
1660
  'glossiness',
1668
1661
  'alphaMap',
1669
1662
  'envMap',
1670
- 'envMapIntensity',
1671
- 'refractionRatio',
1663
+ 'envMapIntensity'
1672
1664
  ];
1673
1665
 
1674
1666
  }
@@ -1699,7 +1691,7 @@ class GLTFMaterialsPbrSpecularGlossinessExtension {
1699
1691
 
1700
1692
  if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
1701
1693
 
1702
- pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) );
1694
+ pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, sRGBEncoding ) );
1703
1695
 
1704
1696
  }
1705
1697
 
@@ -1717,7 +1709,7 @@ class GLTFMaterialsPbrSpecularGlossinessExtension {
1717
1709
 
1718
1710
  const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
1719
1711
  pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
1720
- pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) );
1712
+ pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef, sRGBEncoding ) );
1721
1713
 
1722
1714
  }
1723
1715
 
@@ -1767,8 +1759,6 @@ class GLTFMaterialsPbrSpecularGlossinessExtension {
1767
1759
  material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
1768
1760
  material.envMapIntensity = 1.0;
1769
1761
 
1770
- material.refractionRatio = 0.98;
1771
-
1772
1762
  return material;
1773
1763
 
1774
1764
  }
@@ -2054,6 +2044,7 @@ function addMorphTargets( geometry, targets, parser ) {
2054
2044
 
2055
2045
  let hasMorphPosition = false;
2056
2046
  let hasMorphNormal = false;
2047
+ let hasMorphColor = false;
2057
2048
 
2058
2049
  for ( let i = 0, il = targets.length; i < il; i ++ ) {
2059
2050
 
@@ -2061,15 +2052,17 @@ function addMorphTargets( geometry, targets, parser ) {
2061
2052
 
2062
2053
  if ( target.POSITION !== undefined ) hasMorphPosition = true;
2063
2054
  if ( target.NORMAL !== undefined ) hasMorphNormal = true;
2055
+ if ( target.COLOR_0 !== undefined ) hasMorphColor = true;
2064
2056
 
2065
- if ( hasMorphPosition && hasMorphNormal ) break;
2057
+ if ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;
2066
2058
 
2067
2059
  }
2068
2060
 
2069
- if ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry );
2061
+ if ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );
2070
2062
 
2071
2063
  const pendingPositionAccessors = [];
2072
2064
  const pendingNormalAccessors = [];
2065
+ const pendingColorAccessors = [];
2073
2066
 
2074
2067
  for ( let i = 0, il = targets.length; i < il; i ++ ) {
2075
2068
 
@@ -2095,18 +2088,31 @@ function addMorphTargets( geometry, targets, parser ) {
2095
2088
 
2096
2089
  }
2097
2090
 
2091
+ if ( hasMorphColor ) {
2092
+
2093
+ const pendingAccessor = target.COLOR_0 !== undefined
2094
+ ? parser.getDependency( 'accessor', target.COLOR_0 )
2095
+ : geometry.attributes.color;
2096
+
2097
+ pendingColorAccessors.push( pendingAccessor );
2098
+
2099
+ }
2100
+
2098
2101
  }
2099
2102
 
2100
2103
  return Promise.all( [
2101
2104
  Promise.all( pendingPositionAccessors ),
2102
- Promise.all( pendingNormalAccessors )
2105
+ Promise.all( pendingNormalAccessors ),
2106
+ Promise.all( pendingColorAccessors )
2103
2107
  ] ).then( function ( accessors ) {
2104
2108
 
2105
2109
  const morphPositions = accessors[ 0 ];
2106
2110
  const morphNormals = accessors[ 1 ];
2111
+ const morphColors = accessors[ 2 ];
2107
2112
 
2108
2113
  if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
2109
2114
  if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
2115
+ if ( hasMorphColor ) geometry.morphAttributes.color = morphColors;
2110
2116
  geometry.morphTargetsRelative = true;
2111
2117
 
2112
2118
  return geometry;
@@ -2221,6 +2227,15 @@ function getNormalizedComponentScale( constructor ) {
2221
2227
 
2222
2228
  }
2223
2229
 
2230
+ function getImageURIMimeType( uri ) {
2231
+
2232
+ if ( uri.search( /\.jpe?g($|\?)/i ) > 0 || uri.search( /^data\:image\/jpeg/ ) === 0 ) return 'image/jpeg';
2233
+ if ( uri.search( /\.webp($|\?)/i ) > 0 || uri.search( /^data\:image\/webp/ ) === 0 ) return 'image/webp';
2234
+
2235
+ return 'image/png';
2236
+
2237
+ }
2238
+
2224
2239
  /* GLTF PARSER */
2225
2240
 
2226
2241
  class GLTFParser {
@@ -2246,6 +2261,7 @@ class GLTFParser {
2246
2261
  this.cameraCache = { refs: {}, uses: {} };
2247
2262
  this.lightCache = { refs: {}, uses: {} };
2248
2263
 
2264
+ this.sourceCache = {};
2249
2265
  this.textureCache = {};
2250
2266
 
2251
2267
  // Track node names, to ensure no duplicates
@@ -2253,7 +2269,7 @@ class GLTFParser {
2253
2269
 
2254
2270
  // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
2255
2271
  // expensive work of uploading a texture to the GPU off the main thread.
2256
- if ( typeof createImageBitmap !== 'undefined' && /Firefox|Safari/.test( navigator.userAgent ) === false ) {
2272
+ if ( typeof createImageBitmap !== 'undefined' && /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === false ) {
2257
2273
 
2258
2274
  this.textureLoader = new ImageBitmapLoader( this.options.manager );
2259
2275
 
@@ -2810,30 +2826,31 @@ class GLTFParser {
2810
2826
  const json = this.json;
2811
2827
  const options = this.options;
2812
2828
  const textureDef = json.textures[ textureIndex ];
2813
- const source = json.images[ textureDef.source ];
2829
+ const sourceIndex = textureDef.source;
2830
+ const sourceDef = json.images[ sourceIndex ];
2814
2831
 
2815
2832
  let loader = this.textureLoader;
2816
2833
 
2817
- if ( source.uri ) {
2834
+ if ( sourceDef.uri ) {
2818
2835
 
2819
- const handler = options.manager.getHandler( source.uri );
2836
+ const handler = options.manager.getHandler( sourceDef.uri );
2820
2837
  if ( handler !== null ) loader = handler;
2821
2838
 
2822
2839
  }
2823
2840
 
2824
- return this.loadTextureImage( textureIndex, source, loader );
2841
+ return this.loadTextureImage( textureIndex, sourceIndex, loader );
2825
2842
 
2826
2843
  }
2827
2844
 
2828
- loadTextureImage( textureIndex, source, loader ) {
2845
+ loadTextureImage( textureIndex, sourceIndex, loader ) {
2829
2846
 
2830
2847
  const parser = this;
2831
2848
  const json = this.json;
2832
- const options = this.options;
2833
2849
 
2834
2850
  const textureDef = json.textures[ textureIndex ];
2851
+ const sourceDef = json.images[ sourceIndex ];
2835
2852
 
2836
- const cacheKey = ( source.uri || source.bufferView ) + ':' + textureDef.sampler;
2853
+ const cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;
2837
2854
 
2838
2855
  if ( this.textureCache[ cacheKey ] ) {
2839
2856
 
@@ -2842,27 +2859,71 @@ class GLTFParser {
2842
2859
 
2843
2860
  }
2844
2861
 
2862
+ const promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {
2863
+
2864
+ texture.flipY = false;
2865
+
2866
+ if ( textureDef.name ) texture.name = textureDef.name;
2867
+
2868
+ const samplers = json.samplers || {};
2869
+ const sampler = samplers[ textureDef.sampler ] || {};
2870
+
2871
+ texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;
2872
+ texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;
2873
+ texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;
2874
+ texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;
2875
+
2876
+ parser.associations.set( texture, { textures: textureIndex } );
2877
+
2878
+ return texture;
2879
+
2880
+ } ).catch( function () {
2881
+
2882
+ return null;
2883
+
2884
+ } );
2885
+
2886
+ this.textureCache[ cacheKey ] = promise;
2887
+
2888
+ return promise;
2889
+
2890
+ }
2891
+
2892
+ loadImageSource( sourceIndex, loader ) {
2893
+
2894
+ const parser = this;
2895
+ const json = this.json;
2896
+ const options = this.options;
2897
+
2898
+ if ( this.sourceCache[ sourceIndex ] !== undefined ) {
2899
+
2900
+ return this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );
2901
+
2902
+ }
2903
+
2904
+ const sourceDef = json.images[ sourceIndex ];
2905
+
2845
2906
  const URL = self.URL || self.webkitURL;
2846
2907
 
2847
- let sourceURI = source.uri || '';
2908
+ let sourceURI = sourceDef.uri || '';
2848
2909
  let isObjectURL = false;
2849
2910
 
2850
- if ( source.bufferView !== undefined ) {
2911
+ if ( sourceDef.bufferView !== undefined ) {
2851
2912
 
2852
2913
  // Load binary image data from bufferView, if provided.
2853
2914
 
2854
- sourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {
2915
+ sourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {
2855
2916
 
2856
2917
  isObjectURL = true;
2857
- const blob = new Blob( [ bufferView ], { type: source.mimeType } );
2918
+ const blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );
2858
2919
  sourceURI = URL.createObjectURL( blob );
2859
2920
  return sourceURI;
2860
2921
 
2861
2922
  } );
2862
2923
 
2863
- } else if ( source.uri === undefined ) {
2924
+ } else if ( sourceDef.uri === undefined ) {
2864
2925
 
2865
- throw new Error( 'THREE.GLTFLoader: Image ' + textureIndex + ' is missing URI and bufferView' );
2926
+ throw new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );
2866
2927
 
2867
2928
  }
2868
2929
 
@@ -2899,31 +2960,18 @@ class GLTFParser {
2899
2960
 
2900
2961
  }
2901
2962
 
2902
- texture.flipY = false;
2903
-
2904
- if ( textureDef.name ) texture.name = textureDef.name;
2905
-
2906
- const samplers = json.samplers || {};
2907
- const sampler = samplers[ textureDef.sampler ] || {};
2908
-
2909
- texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || LinearFilter;
2910
- texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || LinearMipmapLinearFilter;
2911
- texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || RepeatWrapping;
2912
- texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || RepeatWrapping;
2913
-
2914
- parser.associations.set( texture, { textures: textureIndex } );
2963
+ texture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri );
2915
2964
 
2916
2965
  return texture;
2917
2966
 
2918
- } ).catch( function () {
2967
+ } ).catch( function ( error ) {
2919
2968
 
2920
2969
  console.error( 'THREE.GLTFLoader: Couldn\'t load texture', sourceURI );
2921
- return null;
2970
+ throw error;
2922
2971
 
2923
2972
  } );
2924
2973
 
2925
- this.textureCache[ cacheKey ] = promise;
2926
-
2974
+ this.sourceCache[ sourceIndex ] = promise;
2927
2975
  return promise;
2928
2976
 
2929
2977
  }
@@ -2935,7 +2983,7 @@ class GLTFParser {
2935
2983
  * @param {Object} mapDef
2936
2984
  * @return {Promise<Texture>}
2937
2985
  */
2938
- assignTexture( materialParams, mapName, mapDef ) {
2986
+ assignTexture( materialParams, mapName, mapDef, encoding ) {
2939
2987
 
2940
2988
  const parser = this;
2941
2989
 
@@ -2963,6 +3011,12 @@ class GLTFParser {
2963
3011
 
2964
3012
  }
2965
3013
 
3014
+ if ( encoding !== undefined ) {
3015
+
3016
+ texture.encoding = encoding;
3017
+
3018
+ }
3019
+
2966
3020
  materialParams[ mapName ] = texture;
2967
3021
 
2968
3022
  return texture;
@@ -3134,7 +3188,7 @@ class GLTFParser {
3134
3188
 
3135
3189
  if ( metallicRoughness.baseColorTexture !== undefined ) {
3136
3190
 
3137
- pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
3191
+ pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, sRGBEncoding ) );
3138
3192
 
3139
3193
  }
3140
3194
 
@@ -3179,7 +3233,6 @@ class GLTFParser {
3179
3233
 
3180
3234
  } else {
3181
3235
 
3182
- materialParams.format = RGBFormat;
3183
3236
  materialParams.transparent = false;
3184
3237
 
3185
3238
  if ( alphaMode === ALPHA_MODES.MASK ) {
@@ -3226,7 +3279,7 @@ class GLTFParser {
3226
3279
 
3227
3280
  if ( materialDef.emissiveTexture !== undefined && materialType !== MeshBasicMaterial ) {
3228
3281
 
3229
- pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
3282
+ pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, sRGBEncoding ) );
3230
3283
 
3231
3284
  }
3232
3285
 
@@ -3246,10 +3299,6 @@ class GLTFParser {
3246
3299
 
3247
3300
  if ( materialDef.name ) material.name = materialDef.name;
3248
3301
 
3249
- // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
3250
- if ( material.map ) material.map.encoding = sRGBEncoding;
3251
- if ( material.emissiveMap ) material.emissiveMap.encoding = sRGBEncoding;
3252
-
3253
3302
  assignExtrasToUserData( material, materialDef );
3254
3303
 
3255
3304
  parser.associations.set( material, { materials: materialIndex } );
@@ -106,15 +106,6 @@ class KTX2Loader extends Loader {
106
106
 
107
107
  }
108
108
 
109
- dispose() {
110
-
111
- this.workerPool.dispose();
112
- if ( this.workerSourceURL ) URL.revokeObjectURL( this.workerSourceURL );
113
-
114
- return this;
115
-
116
- }
117
-
118
109
  init() {
119
110
 
120
111
  if ( ! this.transcoderPending ) {
@@ -270,8 +261,8 @@ class KTX2Loader extends Loader {
270
261
 
271
262
  dispose() {
272
263
 
273
- URL.revokeObjectURL( this.workerSourceURL );
274
264
  this.workerPool.dispose();
265
+ if ( this.workerSourceURL ) URL.revokeObjectURL( this.workerSourceURL );
275
266
 
276
267
  _activeLoaders --;
277
268
 
@@ -8,11 +8,11 @@ import {
8
8
  InterleavedBufferAttribute,
9
9
  Mesh,
10
10
  MeshBasicMaterial,
11
- RGBFormat,
12
11
  RawShaderMaterial,
13
12
  Vector2,
14
13
  Vector3,
15
- Vector4
14
+ Vector4,
15
+ RGBAFormat
16
16
  } from '../../../../three/src/Three.js';
17
17
 
18
18
  class Lensflare extends Mesh {
@@ -32,8 +32,8 @@ class Lensflare extends Mesh {
32
32
 
33
33
  // textures
34
34
 
35
- const tempMap = new FramebufferTexture( 16, 16, RGBFormat );
36
- const occlusionMap = new FramebufferTexture( 16, 16, RGBFormat );
35
+ const tempMap = new FramebufferTexture( 16, 16, RGBAFormat );
36
+ const occlusionMap = new FramebufferTexture( 16, 16, RGBAFormat );
37
37
 
38
38
  // material
39
39
 
@@ -4,25 +4,91 @@ import {
4
4
  Float32BufferAttribute,
5
5
  InterleavedBuffer,
6
6
  InterleavedBufferAttribute,
7
+ MathUtils,
7
8
  TriangleFanDrawMode,
8
9
  TriangleStripDrawMode,
9
10
  TrianglesDrawMode,
10
- Vector3
11
+ Vector3,
11
12
  } from '../../../../three/src/Three.js';
13
+ import { generateTangents } from '../libs/mikktspace.module.js';
12
14
 
13
15
 
14
- function computeTangents( geometry ) {
16
+ function computeTangents( geometry, negateSign = true ) {
15
17
 
16
- geometry.computeTangents();
17
- console.warn( 'THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.' );
18
+ function getAttributeArray( attribute ) {
19
+
20
+ if ( attribute.normalized || attribute.isInterleavedBufferAttribute ) {
21
+
22
+ const srcArray = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array;
23
+ const dstArray = new Float32Array( attribute.getCount() * attribute.itemSize );
24
+
25
+ for ( let i = 0, j = 0; i < attribute.getCount(); i ++ ) {
26
+
27
+ dstArray[ j ++ ] = MathUtils.denormalize( attribute.getX( i ), srcArray );
28
+ dstArray[ j ++ ] = MathUtils.denormalize( attribute.getY( i ), srcArray );
29
+
30
+ if ( attribute.itemSize > 2 ) {
31
+
32
+ dstArray[ j ++ ] = MathUtils.denormalize( attribute.getZ( i ), srcArray );
33
+
34
+ }
35
+
36
+ }
37
+
38
+ return dstArray;
39
+
40
+ }
41
+
42
+ if ( attribute.array instanceof Float32Array ) {
43
+
44
+ return attribute.array;
45
+
46
+ }
47
+
48
+ return new Float32Array( attribute.array );
49
+
50
+ }
51
+
52
+ // MikkTSpace algorithm requires non-indexed input.
53
+
54
+ const _geometry = geometry.index ? geometry.toNonIndexed() : geometry;
55
+
56
+ // Compute vertex tangents.
57
+
58
+ const tangents = generateTangents(
59
+
60
+ getAttributeArray( _geometry.attributes.position ),
61
+ getAttributeArray( _geometry.attributes.normal ),
62
+ getAttributeArray( _geometry.attributes.uv )
63
+
64
+ );
65
+
66
+ // Texture coordinate convention of glTF differs from the apparent
67
+ // default of the MikkTSpace library; .w component must be flipped.
68
+
69
+ if ( negateSign ) {
70
+
71
+ for ( let i = 3; i < tangents.length; i += 4 ) {
72
+
73
+ tangents[ i ] *= - 1;
74
+
75
+ }
76
+
77
+ }
78
+
79
+ //
80
+
81
+ _geometry.setAttribute( 'tangent', new BufferAttribute( tangents, 4 ) );
82
+
83
+ return geometry.copy( _geometry );
18
84
 
19
85
  }
20
86
 
21
87
  /**
22
- * @param {Array<BufferGeometry>} geometries
23
- * @param {Boolean} useGroups
24
- * @return {BufferGeometry}
25
- */
88
+ * @param {Array<BufferGeometry>} geometries
89
+ * @param {Boolean} useGroups
90
+ * @return {BufferGeometry}
91
+ */
26
92
  function mergeBufferGeometries( geometries, useGroups = false ) {
27
93
 
28
94
  const isIndexed = geometries[ 0 ].index !== null;
@@ -834,7 +900,7 @@ function computeMorphedAttributes( object ) {
834
900
 
835
901
  }
836
902
 
837
- } else if ( positionAttribute !== undefined ) {
903
+ } else {
838
904
 
839
905
  // non-indexed buffer geometry
840
906
 
@@ -929,7 +995,107 @@ function computeMorphedAttributes( object ) {
929
995
 
930
996
  }
931
997
 
998
+ function mergeGroups( geometry ) {
999
+
1000
+ if ( geometry.groups.length === 0 ) {
1001
+
1002
+ console.warn( 'THREE.BufferGeometryUtils.mergeGroups(): No groups are defined. Nothing to merge.' );
1003
+ return geometry;
1004
+
1005
+ }
1006
+
1007
+ let groups = geometry.groups;
1008
+
1009
+ // sort groups by material index
1010
+
1011
+ groups = groups.sort( ( a, b ) => {
1012
+
1013
+ if ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;
1014
+
1015
+ return a.start - b.start;
932
1016
 
1017
+ } );
1018
+
1019
+ // create index for non-indexed geometries
1020
+
1021
+ if ( geometry.getIndex() === null ) {
1022
+
1023
+ const positionAttribute = geometry.getAttribute( 'position' );
1024
+ const indices = [];
1025
+
1026
+ for ( let i = 0; i < positionAttribute.count; i += 3 ) {
1027
+
1028
+ indices.push( i, i + 1, i + 2 );
1029
+
1030
+ }
1031
+
1032
+ geometry.setIndex( indices );
1033
+
1034
+ }
1035
+
1036
+ // sort index
1037
+
1038
+ const index = geometry.getIndex();
1039
+
1040
+ const newIndices = [];
1041
+
1042
+ for ( let i = 0; i < groups.length; i ++ ) {
1043
+
1044
+ const group = groups[ i ];
1045
+
1046
+ const groupStart = group.start;
1047
+ const groupLength = groupStart + group.count;
1048
+
1049
+ for ( let j = groupStart; j < groupLength; j ++ ) {
1050
+
1051
+ newIndices.push( index.getX( j ) );
1052
+
1053
+ }
1054
+
1055
+ }
1056
+
1057
+ geometry.dispose(); // Required to force buffer recreation
1058
+ geometry.setIndex( newIndices );
1059
+
1060
+ // update groups indices
1061
+
1062
+ let start = 0;
1063
+
1064
+ for ( let i = 0; i < groups.length; i ++ ) {
1065
+
1066
+ const group = groups[ i ];
1067
+
1068
+ group.start = start;
1069
+ start += group.count;
1070
+
1071
+ }
1072
+
1073
+ // merge groups
1074
+
1075
+ let currentGroup = groups[ 0 ];
1076
+
1077
+ geometry.groups = [ currentGroup ];
1078
+
1079
+ for ( let i = 1; i < groups.length; i ++ ) {
1080
+
1081
+ const group = groups[ i ];
1082
+
1083
+ if ( currentGroup.materialIndex === group.materialIndex ) {
1084
+
1085
+ currentGroup.count += group.count;
1086
+
1087
+ } else {
1088
+
1089
+ currentGroup = group;
1090
+ geometry.groups.push( currentGroup );
1091
+
1092
+ }
1093
+
1094
+ }
1095
+
1096
+ return geometry;
1097
+
1098
+ }
933
1099
 
934
1100
  export {
935
1101
  computeTangents,
@@ -940,4 +1106,5 @@ export {
940
1106
  mergeVertices,
941
1107
  toTrianglesDrawMode,
942
1108
  computeMorphedAttributes,
1109
+ mergeGroups
943
1110
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damienmortini/three",
3
- "version": "0.1.164",
3
+ "version": "0.1.167",
4
4
  "description": "Three.js helpers",
5
5
  "scripts": {
6
6
  "install": "npm run copyexamples",
@@ -25,9 +25,9 @@
25
25
  "bugs": "https://github.com/damienmortini/lib/issues",
26
26
  "homepage": "https://github.com/damienmortini/lib/tree/main/packages/three",
27
27
  "dependencies": {
28
- "@damienmortini/core": "^0.2.129",
29
- "fs-extra": "^10.0.0",
30
- "three": "0.136.0"
28
+ "@damienmortini/core": "^0.2.131",
29
+ "fs-extra": "^10.0.1",
30
+ "three": "0.139.0"
31
31
  },
32
- "gitHead": "5d6d7bc792737ff3f3861c41f8d452e52d26d1a3"
32
+ "gitHead": "212228c077e3dd31b65117e24ec84c80a9bfb984"
33
33
  }